Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 04dd9d00 authored by Jason Monk's avatar Jason Monk
Browse files

Extract QS animations to QSContainer

Move some of the logic for QS animations into QSContainer with a
stable interface for NotificationPanelView to call.

This also moves the QSPanel out of the scroll container and up
to live in with the header (QSContainer is the parent of both
the header and the QSPanel now).

Change-Id: I197b93bab05c336a8a8debea781e7ad3053b0b1d
parent ff25528a
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -19,12 +19,15 @@
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/qs_background_primary"
        android:paddingBottom="8dp"
        android:elevation="2dp">
        android:paddingBottom="8dp">

    <com.android.systemui.qs.QSPanel
            android:id="@+id/quick_settings_panel"
            android:background="#0000"
            android:layout_marginTop="@dimen/status_bar_header_height"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

    <include layout="@layout/quick_status_bar_expanded_header" />

</com.android.systemui.qs.QSContainer>
+6 −11
Original line number Diff line number Diff line
@@ -31,6 +31,12 @@
        android:layout_height="wrap_content"
        android:visibility="gone" />

    <include
        layout="@layout/qs_panel"
        android:layout_width="@dimen/notification_panel_width"
        android:layout_height="wrap_content"
        android:layout_gravity="@integer/notification_panel_layout_gravity" />

    <com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer
        android:layout_width="match_parent"
        android:layout_height="match_parent"
@@ -51,11 +57,6 @@
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">
                <include
                    layout="@layout/qs_panel"
                    android:layout_marginTop="@dimen/status_bar_header_height_expanded"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content" />

                <!-- A view to reserve space for the collapsed stack -->
                <!-- Layout height: notification_min_height + bottom_stack_peek_amount -->
@@ -90,12 +91,6 @@
            layout="@layout/keyguard_bottom_area"
            android:visibility="gone" />

    <ViewStub
        android:id="@+id/status_bar_header"
        android:layout_width="@dimen/notification_panel_width"
        android:layout_height="@dimen/status_bar_header_height"
        android:layout_gravity="@integer/notification_panel_layout_gravity" />

    <com.android.systemui.statusbar.AlphaOptimizedView
        android:id="@+id/qs_navbar_scrim"
        android:layout_height="96dp"
+143 −4
Original line number Diff line number Diff line
@@ -16,19 +16,38 @@

package com.android.systemui.qs;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;

import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.statusbar.phone.BaseStatusBarHeader;
import com.android.systemui.statusbar.stack.StackStateAnimator;

/**
 * Wrapper view with background which contains {@link QSPanel}
 * Wrapper view with background which contains {@link QSPanel} and {@link BaseStatusBarHeader}
 *
 * Also manages animations for the QS Header and Panel.
 */
public class QSContainer extends FrameLayout {
    private static final String TAG = "QSContainer";
    private static final boolean DEBUG = false;

    private int mHeightOverride = -1;
    private QSPanel mQSPanel;
    protected BaseStatusBarHeader mHeader;
    private float mQsExpansion;
    private boolean mQsExpanded;
    private boolean mHeaderAnimating;
    private boolean mKeyguardShowing;
    private boolean mStackScrollerOverscrolling;

    private long mDelay;

    public QSContainer(Context context, AttributeSet attrs) {
        super(context, attrs);
@@ -38,6 +57,7 @@ public class QSContainer extends FrameLayout {
    protected void onFinishInflate() {
        super.onFinishInflate();
        mQSPanel = (QSPanel) findViewById(R.id.quick_settings_panel);
        mHeader = (BaseStatusBarHeader) findViewById(R.id.header);
    }

    @Override
@@ -63,14 +83,133 @@ public class QSContainer extends FrameLayout {
     */
    public int getDesiredHeight() {
        if (mQSPanel.isClosingDetail()) {
            return mQSPanel.getGridHeight() + getPaddingTop() + getPaddingBottom();
            return mQSPanel.getGridHeight() + mHeader.getCollapsedHeight() + getPaddingBottom();
        } else {
            return getMeasuredHeight();
        }
    }

    private void updateBottom() {
        int height = mHeightOverride != -1 ? mHeightOverride : getMeasuredHeight();
        int heightOverride = mHeightOverride != -1 ? mHeightOverride : getMeasuredHeight();
        int height = (int) (mQsExpansion * (heightOverride - mHeader.getCollapsedHeight()))
                + mHeader.getCollapsedHeight();
        setBottom(getTop() + height);
    }

    private void updateQsState() {
        boolean expandVisually = mQsExpanded || mStackScrollerOverscrolling || mHeaderAnimating;
        mQSPanel.setExpanded(mQsExpanded);
        mHeader.setVisibility((mQsExpanded || !mKeyguardShowing || mHeaderAnimating)
                ? View.VISIBLE
                : View.INVISIBLE);
        mHeader.setExpanded((mKeyguardShowing && !mHeaderAnimating)
                || (mQsExpanded && !mStackScrollerOverscrolling));
        mQSPanel.setVisibility(expandVisually ? View.VISIBLE : View.INVISIBLE);
        setVisibility(mKeyguardShowing && !expandVisually ? View.INVISIBLE : View.VISIBLE);
    }

    public BaseStatusBarHeader getHeader() {
        return mHeader;
    }

    public QSPanel getQsPanel() {
        return mQSPanel;
    }

    public void setHeaderClickable(boolean clickable) {
        if (DEBUG) Log.d(TAG, "setHeaderClickable " + clickable);
        mHeader.setClickable(clickable);
    }

    public void setExpanded(boolean expanded) {
        if (DEBUG) Log.d(TAG, "setExpanded " + expanded);
        mQsExpanded = expanded;
        updateQsState();
    }

    public void setKeyguardShowing(boolean keyguardShowing) {
        if (DEBUG) Log.d(TAG, "setKeyguardShowing " + keyguardShowing);
        mKeyguardShowing = keyguardShowing;
        updateQsState();
    }

    public void setOverscrolling(boolean stackScrollerOverscrolling) {
        if (DEBUG) Log.d(TAG, "setOverscrolling " + stackScrollerOverscrolling);
        mStackScrollerOverscrolling = stackScrollerOverscrolling;
        updateQsState();
    }

    public void setListening(boolean listening) {
        if (DEBUG) Log.d(TAG, "setListening " + listening);
        mQSPanel.setListening(listening);
        mHeader.setListening(listening);
    }

    public void setQsExpansion(float expansion, float headerTranslation) {
        if (DEBUG) Log.d(TAG, "setQSExpansion " + expansion + " " + headerTranslation);
        mQsExpansion = expansion;
        final float translationScaleY = expansion - 1;
        if (!mHeaderAnimating) {
            setTranslationY(mKeyguardShowing ? (translationScaleY * mHeader.getHeight())
                    : headerTranslation);
        }
        mHeader.setExpansion(mKeyguardShowing ? 1 : expansion);
        mQSPanel.setTranslationY(translationScaleY * mQSPanel.getHeight());
        updateBottom();
    }

    public void animateHeaderSlidingIn(long delay) {
        if (DEBUG) Log.d(TAG, "animateHeaderSlidingIn");
        // If the QS is already expanded we don't need to slide in the header as it's already
        // visible.
        if (!mQsExpanded) {
            mHeaderAnimating = true;
            mDelay = delay;
            getViewTreeObserver().addOnPreDrawListener(mStartHeaderSlidingIn);
        }
    }

    public void animateHeaderSlidingOut() {
        if (DEBUG) Log.d(TAG, "animateHeaderSlidingOut");
        mHeaderAnimating = true;
        animate().y(-mHeader.getHeight())
                .setStartDelay(0)
                .setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD)
                .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
                .setListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        animate().setListener(null);
                        mHeaderAnimating = false;
                        updateQsState();
                    }
                })
                .start();
    }

    private final ViewTreeObserver.OnPreDrawListener mStartHeaderSlidingIn
            = new ViewTreeObserver.OnPreDrawListener() {
        @Override
        public boolean onPreDraw() {
            getViewTreeObserver().removeOnPreDrawListener(this);
            animate()
                    .translationY(0f)
                    .setStartDelay(mDelay)
                    .setDuration(StackStateAnimator.ANIMATION_DURATION_GO_TO_FULL_SHADE)
                    .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
                    .setListener(mAnimateHeaderSlidingInListener)
                    .start();
            setY(-mHeader.getHeight());
            return true;
        }
    };

    private final Animator.AnimatorListener mAnimateHeaderSlidingInListener
            = new AnimatorListenerAdapter() {
        @Override
        public void onAnimationEnd(Animator animation) {
            mHeaderAnimating = false;
            updateQsState();
        }
    };
}
+37 −168

File changed.

Preview size limit exceeded, changes collapsed.