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

Commit be565dfc authored by Jorim Jaggi's avatar Jorim Jaggi Committed by Selim Cinek
Browse files

Refactored the layout of a notifications

Notifications now consist of ExpandableViews instead of SizeAdaptiveLayouts
to avoid layout passes during the resizing. The StackScrollAlgorithm and its
States are also refactored in order to support the new behaviour. In addition,
the generation of the outline is moved to the notification views instead of
the container which contains them.

Change-Id: I1ac1292a6520f5951610039bfa204c204be9d640
parent 2e9c300b
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -18,10 +18,9 @@
<com.android.systemui.statusbar.NotificationOverflowContainer
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_height="32dp"
    android:focusable="true"
    android:clickable="true"
    android:background="@*android:drawable/notification_quantum_bg_dim"
    >
    <TextView
        android:id="@+id/more_text"
+2 −3
Original line number Diff line number Diff line
@@ -4,14 +4,13 @@
    android:layout_height="wrap_content"
    android:focusable="true"
    android:clickable="true"
    android:background="@*android:drawable/notification_quantum_bg"
    >

    <com.android.internal.widget.SizeAdaptiveLayout android:id="@+id/expanded"
    <com.android.systemui.statusbar.NotificationContentView android:id="@+id/expanded"
       android:layout_width="match_parent"
       android:layout_height="wrap_content" />

    <com.android.internal.widget.SizeAdaptiveLayout android:id="@+id/expandedPublic"
    <com.android.systemui.statusbar.NotificationContentView android:id="@+id/expandedPublic"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

+30 −45
Original line number Diff line number Diff line
@@ -31,8 +31,9 @@ import android.view.ScaleGestureDetector.OnScaleGestureListener;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewConfiguration;
import android.view.ViewGroup;

import com.android.systemui.statusbar.ExpandableView;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.policy.ScrollAdapter;

public class ExpandHelper implements Gefingerpoken, OnClickListener {
@@ -115,9 +116,7 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
            float focusY = detector.getFocusY();

            final View underFocus = findView(focusX, focusY);
            if (underFocus != null) {
            startExpanding(underFocus, STRETCH);
            }
            return mExpanding;
        }

@@ -133,41 +132,21 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
    };

    private class ViewScaler {
        View mView;
        ExpandableView mView;

        public ViewScaler() {}
        public void setView(View v) {
        public void setView(ExpandableView v) {
            mView = v;
        }
        public void setHeight(float h) {
            if (DEBUG_SCALE) Log.v(TAG, "SetHeight: setting to " + h);
            ViewGroup.LayoutParams lp = mView.getLayoutParams();
            lp.height = (int)h;
            mView.setLayoutParams(lp);
            mView.requestLayout();
            mView.setActualHeight((int) h);
        }
        public float getHeight() {
            int height = mView.getLayoutParams().height;
            if (height < 0) {
                height = mView.getMeasuredHeight();
            }
            return height;
            return mView.getActualHeight();
        }
        public int getNaturalHeight(int maximum) {
            ViewGroup.LayoutParams lp = mView.getLayoutParams();
            if (DEBUG_SCALE) Log.v(TAG, "Inspecting a child of type: " +
                    mView.getClass().getName());
            int oldHeight = lp.height;
            lp.height = ViewGroup.LayoutParams.WRAP_CONTENT;
            mView.setLayoutParams(lp);
            mView.measure(
                    View.MeasureSpec.makeMeasureSpec(mView.getMeasuredWidth(),
                                                     View.MeasureSpec.EXACTLY),
                    View.MeasureSpec.makeMeasureSpec(maximum,
                                                     View.MeasureSpec.AT_MOST));
            lp.height = oldHeight;
            mView.setLayoutParams(lp);
            return mView.getMeasuredHeight();
            return Math.min(maximum, mView.getMaxHeight());
        }
    }

@@ -189,12 +168,6 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
        mGravity = Gravity.TOP;
        mScaleAnimation = ObjectAnimator.ofFloat(mScaler, "height", 0f);
        mScaleAnimation.setDuration(EXPAND_DURATION);
        mScaleAnimation.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                mCallback.setUserLockedChild(mCurrView, false);
            }
        });
        mPopLimit = mContext.getResources().getDimension(R.dimen.blinds_pop_threshold);
        mPopDuration = mContext.getResources().getInteger(R.integer.blinds_pop_duration_ms);
        mPullGestureMinXSpan = mContext.getResources().getDimension(R.dimen.pull_span_min);
@@ -341,9 +314,7 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
                if (DEBUG_SCALE) Log.v(TAG, "got pull gesture (xspan=" + xspan + "px)");

                final View underFocus = findView(x, y);
                if (underFocus != null) {
                startExpanding(underFocus, PULL);
                }
                return true;
            }
            if (mScrollAdapter != null && !mScrollAdapter.isScrolledToTop()) {
@@ -358,8 +329,7 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
                        if (DEBUG) Log.v(TAG, "got venetian gesture (dy=" + yDiff + "px)");
                        mLastMotionY = y;
                        final View underFocus = findView(x, y);
                        if (underFocus != null) {
                            startExpanding(underFocus, BLINDS);
                        if (startExpanding(underFocus, BLINDS)) {
                            mInitialTouchY = mLastMotionY;
                            mHasPopped = false;
                        }
@@ -459,16 +429,22 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
        return true;
    }

    private void startExpanding(View v, int expandType) {
    /**
     * @return True if the view is expandable, false otherwise.
     */
    private boolean startExpanding(View v, int expandType) {
        if (!(v instanceof ExpandableNotificationRow)) {
            return false;
        }
        mExpansionStyle = expandType;
        if (mExpanding && v == mCurrView) {
            return;
            return true;
        }
        mExpanding = true;
        if (DEBUG) Log.d(TAG, "scale type " + expandType + " beginning on view: " + v);
        mCallback.setUserLockedChild(v, true);
        setView(v);
        mScaler.setView(v);
        mScaler.setView((ExpandableView) v);
        mOldHeight = mScaler.getHeight();
        if (mCallback.canChildBeExpanded(v)) {
            if (DEBUG) Log.d(TAG, "working on an expandable child");
@@ -480,6 +456,7 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
        if (DEBUG) Log.d(TAG, "got mOldHeight: " + mOldHeight +
                    " mNaturalHeight: " + mNaturalHeight);
        v.getParent().requestDisallowInterceptTouchEvent(true);
        return true;
    }

    private void finishExpanding(boolean force) {
@@ -499,10 +476,18 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
        if (mScaleAnimation.isRunning()) {
            mScaleAnimation.cancel();
        }
        mCallback.setUserExpandedChild(mCurrView, h == mNaturalHeight);
        mCallback.setUserExpandedChild(mCurrView, targetHeight == mNaturalHeight);
        if (targetHeight != currentHeight) {
            mScaleAnimation.setFloatValues(targetHeight);
            mScaleAnimation.setupStartValues();
            final View scaledView = mCurrView;
            mScaleAnimation.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    mCallback.setUserLockedChild(scaledView, false);
                    mScaleAnimation.removeListener(this);
                }
            });
            mScaleAnimation.start();
        } else {
            mCallback.setUserLockedChild(mCurrView, false);
+21 −5
Original line number Diff line number Diff line
@@ -29,7 +29,7 @@ import com.android.internal.R;
 * Base class for both {@link ExpandableNotificationRow} and {@link NotificationOverflowContainer}
 * to implement dimming/activating on Keyguard for the double-tap gesture
 */
public class ActivatableNotificationView extends FrameLayout {
public abstract class ActivatableNotificationView extends ExpandableOutlineView {

    private static final long DOUBLETAP_TIMEOUT_MS = 1000;

@@ -54,6 +54,7 @@ public class ActivatableNotificationView extends FrameLayout {
    public ActivatableNotificationView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
        updateBackgroundResource();
    }


@@ -84,6 +85,9 @@ public class ActivatableNotificationView extends FrameLayout {
            case MotionEvent.ACTION_DOWN:
                mDownX = event.getX();
                mDownY = event.getY();
                if (mDownY > getActualHeight()) {
                    return false;
                }

                // Call the listener tentatively directly, even if we don't know whether the user
                // will stay within the touch slop, as the listener is implemented as a scale
@@ -122,7 +126,7 @@ public class ActivatableNotificationView extends FrameLayout {
    }

    private void makeActive(float x, float y) {
        getBackground().setHotspot(0, x, y);
        mCustomBackground.setHotspot(0, x, y);
        mActivated = true;
    }

@@ -132,8 +136,8 @@ public class ActivatableNotificationView extends FrameLayout {
    private void makeInactive() {
        if (mActivated) {
            // Make sure that we clear the hotspot from the center.
            getBackground().setHotspot(0, getWidth() / 2, getHeight() / 2);
            getBackground().removeHotspot(0);
            mCustomBackground.setHotspot(0, getWidth() / 2, getActualHeight() / 2);
            mCustomBackground.removeHotspot(0);
            mActivated = false;
        }
        if (mOnActivatedListener != null) {
@@ -178,7 +182,19 @@ public class ActivatableNotificationView extends FrameLayout {
    }

    private void updateBackgroundResource() {
        setBackgroundResource(mDimmed ? mDimmedBgResId : mBgResId);
        setCustomBackgroundResource(mDimmed ? mDimmedBgResId : mBgResId);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        setPivotX(getWidth()/2);
    }

    @Override
    public void setActualHeight(int actualHeight) {
        super.setActualHeight(actualHeight);
        setPivotY(actualHeight/2);
    }

    public void setOnActivatedListener(OnActivatedListener onActivatedListener) {
+8 −18
Original line number Diff line number Diff line
@@ -760,9 +760,10 @@ public abstract class BaseStatusBar extends SystemUI implements
        // NB: the large icon is now handled entirely by the template

        // bind the click event to the content area
        SizeAdaptiveLayout expanded = (SizeAdaptiveLayout)row.findViewById(R.id.expanded);
        SizeAdaptiveLayout expandedPublic
                = (SizeAdaptiveLayout)row.findViewById(R.id.expandedPublic);
        NotificationContentView expanded =
                (NotificationContentView) row.findViewById(R.id.expanded);
        NotificationContentView expandedPublic =
                (NotificationContentView) row.findViewById(R.id.expandedPublic);

        row.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);

@@ -794,19 +795,11 @@ public abstract class BaseStatusBar extends SystemUI implements

        if (contentViewLocal != null) {
            contentViewLocal.setIsRootNamespace(true);
            SizeAdaptiveLayout.LayoutParams params =
                    new SizeAdaptiveLayout.LayoutParams(contentViewLocal.getLayoutParams());
            params.minHeight = minHeight;
            params.maxHeight = minHeight;
            expanded.addView(contentViewLocal, params);
            expanded.setContractedChild(contentViewLocal);
        }
        if (bigContentViewLocal != null) {
            bigContentViewLocal.setIsRootNamespace(true);
            SizeAdaptiveLayout.LayoutParams params =
                    new SizeAdaptiveLayout.LayoutParams(bigContentViewLocal.getLayoutParams());
            params.minHeight = minHeight+1;
            params.maxHeight = maxHeight;
            expanded.addView(bigContentViewLocal, params);
            expanded.setExpandedChild(bigContentViewLocal);
        }

        PackageManager pm = mContext.getPackageManager();
@@ -820,11 +813,7 @@ public abstract class BaseStatusBar extends SystemUI implements

                if (publicViewLocal != null) {
                    publicViewLocal.setIsRootNamespace(true);
                    SizeAdaptiveLayout.LayoutParams params =
                            new SizeAdaptiveLayout.LayoutParams(publicViewLocal.getLayoutParams());
                    params.minHeight = minHeight;
                    params.maxHeight = minHeight;
                    expandedPublic.addView(publicViewLocal, params);
                    expandedPublic.setContractedChild(publicViewLocal);
                }
            }
            catch (RuntimeException e) {
@@ -1352,6 +1341,7 @@ public abstract class BaseStatusBar extends SystemUI implements
        } else {
            entry.row.setOnClickListener(null);
        }
        entry.row.notifyContentUpdated();
    }

    protected void notifyHeadsUpScreenOn(boolean screenOn) {
Loading