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

Commit 1c7c0287 authored by Roman Birg's avatar Roman Birg
Browse files

SystemUI: improve qs tile scroll handling



  - place detail view within bounds of expanded panel when it
   goes beyond the bottom of the screen

  - collapse qs panel when scrolling detail view (and letting go),
    disallowing it to get stuck at weird states that cut off the detail view

Change-Id: I775c0bb0022893a6a79fab93fb6cd92ba67b7213
Signed-off-by: default avatarRoman Birg <roman@cyngn.com>
parent cffcdc5e
Loading
Loading
Loading
Loading
+47 −5
Original line number Diff line number Diff line
@@ -23,9 +23,9 @@ import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Point;
import android.os.Handler;
import android.os.Message;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.AttributeSet;
import android.view.LayoutInflater;
@@ -68,6 +68,7 @@ public class QSPanel extends ViewGroup {
    private int mPanelPaddingBottom;
    private int mDualTileUnderlap;
    private int mBrightnessPaddingTop;
    private int mTranslationTop;
    private boolean mExpanded;
    private boolean mListening;

@@ -81,6 +82,9 @@ public class QSPanel extends ViewGroup {

    private boolean mUseMainTiles = false;

    private DetailCallback mDetailCallback;
    private int mContainerTop;

    public QSPanel(Context context) {
        this(context, null);
    }
@@ -153,6 +157,14 @@ public class QSPanel extends ViewGroup {
        mCallback = callback;
    }

    public void setDetailCallback(DetailCallback callback) {
        mDetailCallback = callback;
    }

    public void setTopOfContainer(int t) {
        mContainerTop = t;
    }

    public void setHost(QSTileHost host) {
        mHost = host;
        mFooter.setHost(host);
@@ -363,7 +375,7 @@ public class QSPanel extends ViewGroup {
        }
        int x = r.tileView.getLeft() + r.tileView.getWidth() / 2;
        int y = r.tileView.getTop() + r.tileView.getHeight() / 2;
        handleShowDetailImpl(r, show, x, y);
        handleShowDetailImpl(r, show, x, y - mTranslationTop);
    }

    private void handleShowDetailImpl(Record r, boolean show, int x, int y) {
@@ -447,9 +459,22 @@ public class QSPanel extends ViewGroup {
        if (mFooter.hasFooter()) {
            h += mFooter.getView().getMeasuredHeight();
        }

        mDetail.measure(exactly(width), MeasureSpec.UNSPECIFIED);
        if (mDetail.getMeasuredHeight() < h) {
            mDetail.measure(exactly(width), exactly(h));
        if (isShowingDetail()) {
            Point size = new Point();
            getDisplay().getSize(size);
            final int panelBottom = (mContainerTop - mTranslationTop + h);
            final int detailMinHeight = size.y - mContainerTop - mPanelPaddingBottom;

            if (size.y > panelBottom) {
                int delta = size.y - panelBottom;
                // panel is smaller than screen size
                mDetail.measure(exactly(width), exactly(detailMinHeight - delta));
            } else {
                // panel is hanging below the screen
                mDetail.measure(exactly(width), exactly(detailMinHeight));
            }
        }
        setMeasuredDimension(width, Math.max(h, mDetail.getMeasuredHeight()));
    }
@@ -483,7 +508,7 @@ public class QSPanel extends ViewGroup {
            record.tileView.layout(left, top, right, top + record.tileView.getMeasuredHeight());
        }
        final int dh = Math.max(mDetail.getMeasuredHeight(), getMeasuredHeight());
        mDetail.layout(0, 0, mDetail.getMeasuredWidth(), dh);
        mDetail.layout(0, mTranslationTop, mDetail.getMeasuredWidth(), dh + mTranslationTop);
        if (mFooter.hasFooter()) {
            View footer = mFooter.getView();
            footer.layout(0, getMeasuredHeight() - footer.getMeasuredHeight(),
@@ -511,6 +536,10 @@ public class QSPanel extends ViewGroup {
        if (mCallback != null) {
            mCallback.onShowingDetail(detail);
        }
        if (mDetailCallback != null && detail != null) {
            // don't notify when hiding, wait for animation to finish
            mDetailCallback.onDetailChanged(true);
        }
    }

    private void fireToggleStateChanged(boolean state) {
@@ -533,6 +562,12 @@ public class QSPanel extends ViewGroup {
        fireScanStateChanged(scanState);
    }

    public void setDetailOffset(int translationY) {
        if (!isShowingDetail()) {
            mTranslationTop = translationY;
        }
    }

    private class H extends Handler {
        private static final int SHOW_DETAIL = 1;
        private static final int SET_TILE_VISIBILITY = 2;
@@ -563,6 +598,9 @@ public class QSPanel extends ViewGroup {
        public void onAnimationEnd(Animator animation) {
            mDetailContent.removeAllViews();
            setDetailRecord(null);
            if (mDetailCallback != null) {
                mDetailCallback.onDetailChanged(false);
            }
        };
    };

@@ -579,6 +617,10 @@ public class QSPanel extends ViewGroup {
        }
    };

    public interface DetailCallback {
        void onDetailChanged(boolean showing);
    }

    public interface Callback {
        void onShowingDetail(QSTile.DetailAdapter detail);
        void onToggleStateChanged(boolean state);
+38 −2
Original line number Diff line number Diff line
@@ -26,7 +26,6 @@ import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.net.Uri;
import android.os.Handler;
import android.os.PowerManager;
import android.os.UserHandle;
@@ -212,6 +211,16 @@ public class NotificationPanelView extends PanelView implements
        mKeyguardStatusView = (KeyguardStatusView) findViewById(R.id.keyguard_status_view);
        mQsContainer = findViewById(R.id.quick_settings_container);
        mQsPanel = (QSPanel) findViewById(R.id.quick_settings_panel);
        mQsPanel.setDetailCallback(new QSPanel.DetailCallback() {
            @Override
            public void onDetailChanged(boolean showing) {
                mQsPanel.setTopOfContainer(mQsContainer.getTop());
                mQsPanel.setDetailOffset(mScrollView.getScrollY());
                if (!showing) {
                    mHandler.removeCallbacks(mCloseQsRunnable);
                }
            }
        });
        mClockView = (TextView) findViewById(R.id.clock_view);
        mScrollView = (ObservableScrollView) findViewById(R.id.scroll_view);
        mScrollView.setListener(this);
@@ -585,6 +594,9 @@ public class NotificationPanelView extends PanelView implements
    }

    private boolean flingExpandsQs(float vel) {
        if (isQsDetailShowing() && mStatusBarState == StatusBarState.SHADE) {
            return false;
        }
        if (isBelowFalsingThreshold()) {
            return false;
        }
@@ -701,6 +713,9 @@ public class NotificationPanelView extends PanelView implements
        if (mQsExpansionAnimator != null) {
            expands = true;
        }
        if (isQsDetailShowing()) {
            expands = false;
        }
        return expands;
    }

@@ -1565,9 +1580,30 @@ public class NotificationPanelView extends PanelView implements
    public void onReset(ExpandableView view) {
    }

    private Runnable mCloseQsRunnable = new Runnable() {
        @Override
        public void run() {
            if (isQsDetailShowing()
                    && !mTracking
                    && (!mQsTracking || mStatusBarState == StatusBarState.KEYGUARD)
                    && !mIntercepting
                    && mQsExpansionAnimator == null) {
                if (mStatusBarState == StatusBarState.SHADE) {
                    closeQsDetail();
                }
                animateCloseQs();
            }
        }
    };

    @Override
    public void onScrollChanged() {
        mQsPanel.setDetailOffset(mScrollView.getScrollY());
        if (mQsExpanded) {
            if (isQsDetailShowing()) {
                mHandler.removeCallbacks(mCloseQsRunnable);
                mHandler.postDelayed(mCloseQsRunnable, 200);
            }
            requestScrollerTopPaddingUpdate(false /* animate */);
            requestPanelHeightUpdate();
        }