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

Commit c5dc0d0c authored by Jorim Jaggi's avatar Jorim Jaggi
Browse files

Zoom notifications on lockscreen after tapping.

For the double tap interaction, this change introduces a new cue
that the notifications must be double-tapped: With the first tap,
the tapped notifications gets larger and the others fade out a bit.

Change-Id: Ib48ff0291aee1a5ec083b9e7ed1021bc420514cf
parent 18769204
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -14,7 +14,8 @@
  ~ limitations under the License
  -->

<FrameLayout
<!-- Extends FrameLayout -->
<com.android.systemui.statusbar.NotificationOverflowContainer
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
@@ -48,4 +49,4 @@
            android:layout_height="wrap_content"
            />
    </com.android.systemui.statusbar.LatestItemView>
</FrameLayout>
</com.android.systemui.statusbar.NotificationOverflowContainer>
+2 −2
Original line number Diff line number Diff line
@@ -83,7 +83,7 @@
    <dimen name="notification_mid_height">128dp</dimen>

    <!-- Height of a small notification in the status bar plus glow, padding, etc -->
    <dimen name="notification_row_min_height">70dp</dimen>
    <dimen name="notification_row_min_height">68dp</dimen>

    <!-- Height of a large notification in the status bar plus glow, padding, etc -->
    <dimen name="notification_row_max_height">260dp</dimen>
@@ -98,7 +98,7 @@
    <dimen name="status_bar_icon_padding">0dp</dimen>

    <!-- half the distance between notifications in the panel -->
    <dimen name="notification_divider_height">3dp</dimen>
    <dimen name="notification_divider_height">2dp</dimen>

    <!-- Notification drawer tuning parameters (phone UI) -->
    <!-- Initial velocity of the shade when expanding on its own -->
+42 −6
Original line number Diff line number Diff line
@@ -83,7 +83,7 @@ import java.util.ArrayList;
import java.util.Locale;

public abstract class BaseStatusBar extends SystemUI implements
        CommandQueue.Callbacks {
        CommandQueue.Callbacks, LatestItemView.OnActivatedListener {
    public static final String TAG = "StatusBar";
    public static final boolean DEBUG = false;
    public static final boolean MULTIUSER_DEBUG = false;
@@ -169,8 +169,7 @@ public abstract class BaseStatusBar extends SystemUI implements
    protected int mZenMode;

    protected boolean mOnKeyguard;
    protected View mKeyguardIconOverflowContainer;
    protected NotificationOverflowIconsView mOverflowIconsView;
    protected NotificationOverflowContainer mKeyguardIconOverflowContainer;

    public boolean isDeviceProvisioned() {
        return mDeviceProvisioned;
@@ -882,6 +881,7 @@ public abstract class BaseStatusBar extends SystemUI implements
        }
        entry.row = row;
        entry.row.setHeightRange(mRowMinHeight, mRowMaxHeight);
        entry.row.setOnActivatedListener(this);
        entry.content = content;
        entry.expanded = contentViewLocal;
        entry.expandedPublic = publicViewLocal;
@@ -1067,7 +1067,7 @@ public abstract class BaseStatusBar extends SystemUI implements
     */
    protected void updateRowStates() {
        int maxKeyguardNotifications = getMaxKeyguardNotifications();
        mOverflowIconsView.removeAllViews();
        mKeyguardIconOverflowContainer.getIconsView().removeAllViews();
        int n = mNotificationData.size();
        int visibleNotifications = 0;
        for (int i = n-1; i >= 0; i--) {
@@ -1087,7 +1087,7 @@ public abstract class BaseStatusBar extends SystemUI implements
                    || !showOnKeyguard)) {
                entry.row.setVisibility(View.GONE);
                if (showOnKeyguard) {
                    mOverflowIconsView.addNotification(entry);
                    mKeyguardIconOverflowContainer.getIconsView().addNotification(entry);
                }
            } else {
                entry.row.setVisibility(View.VISIBLE);
@@ -1095,13 +1095,49 @@ public abstract class BaseStatusBar extends SystemUI implements
            }
        }

        if (mOnKeyguard && mOverflowIconsView.getChildCount() > 0) {
        if (mOnKeyguard && mKeyguardIconOverflowContainer.getIconsView().getChildCount() > 0) {
            mKeyguardIconOverflowContainer.setVisibility(View.VISIBLE);
        } else {
            mKeyguardIconOverflowContainer.setVisibility(View.GONE);
        }
    }

    @Override
    public void onActivated(View view) {
        int n = mNotificationData.size();
        for (int i = 0; i < n; i++) {
            NotificationData.Entry entry = mNotificationData.get(i);
            if (entry.row.getVisibility() != View.GONE) {
                if (view == entry.row) {
                    entry.row.getActivator().activate();
                } else {
                    entry.row.getActivator().activateInverse();
                }
            }
        }
        if (mKeyguardIconOverflowContainer.getVisibility() != View.GONE) {
            if (view == mKeyguardIconOverflowContainer) {
                mKeyguardIconOverflowContainer.getActivator().activate();
            } else {
                mKeyguardIconOverflowContainer.getActivator().activateInverse();
            }
        }
    }

    @Override
    public void onReset(View view) {
        int n = mNotificationData.size();
        for (int i = 0; i < n; i++) {
            NotificationData.Entry entry = mNotificationData.get(i);
            if (entry.row.getVisibility() != View.GONE) {
                entry.row.getActivator().reset();
            }
        }
        if (mKeyguardIconOverflowContainer.getVisibility() != View.GONE) {
            mKeyguardIconOverflowContainer.getActivator().reset();
        }
    }

    private boolean shouldShowOnKeyguard(StatusBarNotification sbn) {
        return sbn.getNotification().priority >= Notification.PRIORITY_LOW;
    }
+30 −2
Original line number Diff line number Diff line
@@ -25,7 +25,8 @@ import android.widget.FrameLayout;
import com.android.internal.widget.SizeAdaptiveLayout;
import com.android.systemui.R;

public class ExpandableNotificationRow extends FrameLayout {
public class ExpandableNotificationRow extends FrameLayout
        implements LatestItemView.OnActivatedListener {
    private int mRowMinHeight;
    private int mRowMaxHeight;

@@ -51,6 +52,8 @@ public class ExpandableNotificationRow extends FrameLayout {
    private SizeAdaptiveLayout mPrivateLayout;
    private int mMaxExpandHeight;
    private boolean mMaxHeightNeedsUpdate;
    private NotificationActivator mActivator;
    private LatestItemView.OnActivatedListener mOnActivatedListener;

    public ExpandableNotificationRow(Context context, AttributeSet attrs) {
        super(context, attrs);
@@ -62,8 +65,10 @@ public class ExpandableNotificationRow extends FrameLayout {
        mPublicLayout = (SizeAdaptiveLayout) findViewById(R.id.expandedPublic);
        mPrivateLayout = (SizeAdaptiveLayout) findViewById(R.id.expanded);
        mLatestItemView = (LatestItemView) findViewById(R.id.container);
    }

        mActivator = new NotificationActivator(this);
        mLatestItemView.setOnActivatedListener(this);
    }

    public void setHeightRange(int rowMinHeight, int rowMaxHeight) {
        mRowMinHeight = rowMinHeight;
@@ -202,6 +207,7 @@ public class ExpandableNotificationRow extends FrameLayout {
     */
    public void setDimmed(boolean dimmed) {
        mLatestItemView.setDimmed(dimmed);
        mActivator.setDimmed(dimmed);
    }

    public int getMaxExpandHeight() {
@@ -220,6 +226,28 @@ public class ExpandableNotificationRow extends FrameLayout {
        mLatestItemView.setLocked(locked);
    }

    public void setOnActivatedListener(LatestItemView.OnActivatedListener listener) {
        mOnActivatedListener = listener;
    }

    public NotificationActivator getActivator() {
        return mActivator;
    }

    @Override
    public void onActivated(View view) {
        if (mOnActivatedListener != null) {
            mOnActivatedListener.onActivated(this);
        }
    }

    @Override
    public void onReset(View view) {
        if (mOnActivatedListener != null) {
            mOnActivatedListener.onReset(this);
        }
    }

    /**
     * Sets the resource id for the background of this notification.
     *
+30 −11
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@
package com.android.systemui.statusbar;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
@@ -46,7 +45,8 @@ public class LatestItemView extends FrameLayout {
    private float mDownX;
    private float mDownY;
    private final float mTouchSlop;
    private boolean mHotspotActive;

    private OnActivatedListener mOnActivatedListener;

    public LatestItemView(Context context, AttributeSet attrs) {
        super(context, attrs);
@@ -90,14 +90,17 @@ public class LatestItemView extends FrameLayout {

    private boolean handleTouchEventLocked(MotionEvent event) {
        int action = event.getActionMasked();
        Drawable background = getBackground();
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                mDownX = event.getX();
                mDownY = event.getY();
                if (!mActivated) {
                    background.setHotspot(0, event.getX(), event.getY());
                    mHotspotActive = true;

                // 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
                // animation, which is cancellable without jarring effects when swiping away
                // notifications.
                if (mOnActivatedListener != null) {
                    mOnActivatedListener.onActivated(this);
                }
                break;
            case MotionEvent.ACTION_MOVE:
@@ -109,7 +112,7 @@ public class LatestItemView extends FrameLayout {
            case MotionEvent.ACTION_UP:
                if (isWithinTouchSlop(event)) {
                    if (!mActivated) {
                        mActivated = true;
                        makeActive(event.getX(), event.getY());
                        postDelayed(mTapTimeoutRunnable, DOUBLETAP_TIMEOUT_MS);
                    } else {
                        performClick();
@@ -128,17 +131,24 @@ public class LatestItemView extends FrameLayout {
        return true;
    }

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

    /**
     * Cancels the hotspot and makes the notification inactive.
     */
    private void makeInactive() {
        if (mHotspotActive) {
        if (mActivated) {
            // Make sure that we clear the hotspot from the center.
            getBackground().setHotspot(0, getWidth() / 2, getHeight() / 2);
            getBackground().removeHotspot(0);
            mHotspotActive = false;
        }
            mActivated = false;
        }
        if (mOnActivatedListener != null) {
            mOnActivatedListener.onReset(this);
        }
        removeCallbacks(mTapTimeoutRunnable);
    }

@@ -180,4 +190,13 @@ public class LatestItemView extends FrameLayout {
    private void updateBackgroundResource() {
        setBackgroundResource(mDimmed ? mDimmedBgResId : mBgResId);
    }

    public void setOnActivatedListener(OnActivatedListener onActivatedListener) {
        mOnActivatedListener = onActivatedListener;
    }

    public interface OnActivatedListener {
        void onActivated(View view);
        void onReset(View view);
    }
}
Loading