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

Commit b9606993 authored by Daniel Sandler's avatar Daniel Sandler
Browse files

Improve hide/show animations in status bar.

This cleans up the lights out experience so you can clearly
see that the "shadows" along the bottom of the bar
correspond to invisible (but still available) UI elements.

Bug: 3203171
Change-Id: I635394d625bf97bbbe7260c1ae9320b616ea7aec
parent a8bbc11a
Loading
Loading
Loading
Loading
+60 −57
Original line number Diff line number Diff line
@@ -25,7 +25,6 @@
        android:id="@+id/bar_contents"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:animateLayoutChanges="false"
        >

        <!-- notification icons & panel access -->
@@ -105,7 +104,6 @@
            android:layout_height="match_parent"
            android:layout_alignParentLeft="true"
            android:orientation="horizontal"
            android:animateLayoutChanges="false"
            >

            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
@@ -178,6 +176,11 @@
        </LinearLayout>

        <!-- lights out mode: "shadow" views -->
        <RelativeLayout
            android:id="@+id/shadows"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            >
            <ImageView
                android:id="@+id/notification_shadow"
                android:layout_width="176dip"
@@ -234,6 +237,7 @@
                android:src="@drawable/ic_sysbar_shadow"
                android:visibility="gone"
                />
        </RelativeLayout>

        <!-- ticker: transient incoming notification information -->
        <FrameLayout
@@ -244,7 +248,6 @@
            android:layout_toRightOf="@+id/systemInfo"
            android:paddingLeft="6dip"
            android:gravity="center_vertical"
            android:animateLayoutChanges="true"
            />
            
    </RelativeLayout>
+98 −60
Original line number Diff line number Diff line
@@ -19,9 +19,12 @@ package com.android.systemui.statusbar.tablet;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Map;
import java.util.IdentityHashMap;

import android.animation.LayoutTransition;
import android.animation.ObjectAnimator;
import android.animation.AnimatorSet;
import android.app.ActivityManagerNative;
import android.app.PendingIntent;
import android.app.Notification;
@@ -257,21 +260,6 @@ public class TabletStatusBar extends StatusBar {

        mBarContents = sb.findViewById(R.id.bar_contents);

        // "shadows" of the status bar features, for lights-out mode
        mBackShadow = sb.findViewById(R.id.back_shadow);
        mHomeShadow = sb.findViewById(R.id.home_shadow);
        mRecentShadow = sb.findViewById(R.id.recent_shadow);
        mMenuShadow = sb.findViewById(R.id.menu_shadow);
        mNotificationShadow = sb.findViewById(R.id.notification_shadow);

        mShadowController = new ShadowController(false);

        mBackShadow.setOnTouchListener(mShadowController.makeTouchListener());
        mHomeShadow.setOnTouchListener(mShadowController.makeTouchListener());
        mRecentShadow.setOnTouchListener(mShadowController.makeTouchListener());
        mMenuShadow.setOnTouchListener(mShadowController.makeTouchListener());
        mNotificationShadow.setOnTouchListener(mShadowController.makeTouchListener());

        // the whole right-hand side of the bar
        mNotificationArea = sb.findViewById(R.id.notificationArea);

@@ -310,6 +298,20 @@ public class TabletStatusBar extends StatusBar {
        // The bar contents buttons
        mInputMethodButton = (InputMethodButton) sb.findViewById(R.id.imeButton);

        // "shadows" of the status bar features, for lights-out mode
        mBackShadow = sb.findViewById(R.id.back_shadow);
        mHomeShadow = sb.findViewById(R.id.home_shadow);
        mRecentShadow = sb.findViewById(R.id.recent_shadow);
        mMenuShadow = sb.findViewById(R.id.menu_shadow);
        mNotificationShadow = sb.findViewById(R.id.notification_shadow);

        mShadowController = new ShadowController(false);
        mShadowController.add(mBackButton, mBackShadow);
        mShadowController.add(mHomeButton, mHomeShadow);
        mShadowController.add(mRecentButton, mRecentShadow);
        mShadowController.add(mMenuButton, mMenuShadow);
        mShadowController.add(mNotificationArea, mNotificationShadow);

        // set the initial view visibility
        setAreThereNotifications();
        refreshNotificationTrigger();
@@ -386,8 +388,8 @@ public class TabletStatusBar extends StatusBar {

                        mNotificationPanel.setVisibility(View.VISIBLE);

                        // XXX: need to synchronize with shadows here
                        mNotificationArea.setVisibility(View.GONE);
                        // synchronize with current shadow state
                        mShadowController.hideElement(mNotificationArea);
                    }
                    break;
                case MSG_CLOSE_NOTIFICATION_PANEL:
@@ -395,8 +397,8 @@ public class TabletStatusBar extends StatusBar {
                    if (mNotificationPanel.getVisibility() == View.VISIBLE) {
                        mNotificationPanel.setVisibility(View.GONE);

                        // XXX: need to synchronize with shadows here
                        mNotificationArea.setVisibility(View.VISIBLE);
                        // synchronize with current shadow state
                        mShadowController.showElement(mNotificationArea);
                    }
                    break;
                case MSG_OPEN_RECENTS_PANEL:
@@ -576,11 +578,13 @@ public class TabletStatusBar extends StatusBar {
        if ((diff & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
            if ((state & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
                Slog.d(TAG, "DISABLE_NOTIFICATION_ICONS: yes");
                mNotificationIconArea.setVisibility(View.GONE);
                // synchronize with current shadow state
                mShadowController.hideElement(mNotificationArea);
                mTicker.halt();
            } else {
                Slog.d(TAG, "DISABLE_NOTIFICATION_ICONS: no");
                mNotificationIconArea.setVisibility(View.VISIBLE);
                // synchronize with current shadow state
                mShadowController.showElement(mNotificationArea);
            }
        } else if ((diff & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) {
            if ((state & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) {
@@ -1047,11 +1051,57 @@ public class TabletStatusBar extends StatusBar {

    public class ShadowController {
        boolean mShowShadows;
        Map<View, View> mShadowsForElements = new IdentityHashMap<View, View>(7);
        Map<View, View> mElementsForShadows = new IdentityHashMap<View, View>(7);
        LayoutTransition mElementTransition, mShadowTransition;

        View mTouchTarget;

        ShadowController(boolean showShadows) {
            mShowShadows = showShadows;
            mTouchTarget = null;

            mElementTransition = new LayoutTransition();
//            AnimatorSet s = new AnimatorSet();
//            s.play(ObjectAnimator.ofInt(null, "top", 48, 0))
//                .with(ObjectAnimator.ofFloat(null, "scaleY", 0.5f, 1f))
//                .with(ObjectAnimator.ofFloat(null, "alpha", 0.5f, 1f))
//                ;
            mElementTransition.setAnimator(LayoutTransition.APPEARING, //s);
                   ObjectAnimator.ofInt(null, "top", 48, 0));
            mElementTransition.setDuration(LayoutTransition.APPEARING, 100);
            mElementTransition.setStartDelay(LayoutTransition.APPEARING, 0);

//            s = new AnimatorSet();
//            s.play(ObjectAnimator.ofInt(null, "top", 0, 48))
//                .with(ObjectAnimator.ofFloat(null, "scaleY", 1f, 0.5f))
//                .with(ObjectAnimator.ofFloat(null, "alpha", 1f, 0.5f))
//                ;
            mElementTransition.setAnimator(LayoutTransition.DISAPPEARING, //s);
                    ObjectAnimator.ofInt(null, "top", 0, 48));
            mElementTransition.setDuration(LayoutTransition.DISAPPEARING, 400);

            mShadowTransition = new LayoutTransition();
            mShadowTransition.setAnimator(LayoutTransition.APPEARING, 
                    ObjectAnimator.ofFloat(null, "alpha", 0f, 1f));
            mShadowTransition.setDuration(LayoutTransition.APPEARING, 200);
            mShadowTransition.setStartDelay(LayoutTransition.APPEARING, 100);
            mShadowTransition.setAnimator(LayoutTransition.DISAPPEARING, 
                    ObjectAnimator.ofFloat(null, "alpha", 1f, 0f));
            mShadowTransition.setDuration(LayoutTransition.DISAPPEARING, 100);

            ViewGroup bar = (ViewGroup) TabletStatusBar.this.mBarContents;
            bar.setLayoutTransition(mElementTransition);
            ViewGroup nav = (ViewGroup) TabletStatusBar.this.mNavigationArea;
            nav.setLayoutTransition(mElementTransition);
            ViewGroup shadowGroup = (ViewGroup) bar.findViewById(R.id.shadows);
            shadowGroup.setLayoutTransition(mShadowTransition);
        }

        public void add(View element, View shadow) {
            shadow.setOnTouchListener(makeTouchListener());
            mShadowsForElements.put(element, shadow);
            mElementsForShadows.put(shadow, element);
        }

        public boolean getShadowState() {
@@ -1067,17 +1117,7 @@ public class TabletStatusBar extends StatusBar {

                    // currently redirecting events?
                    if (mTouchTarget == null) {
                        if (v == mBackShadow) {
                            mTouchTarget = mBackButton;
                        } else if (v == mHomeShadow) {
                            mTouchTarget = mHomeButton;
                        } else if (v == mMenuShadow) {
                            mTouchTarget = mMenuButton;
                        } else if (v == mRecentShadow) {
                            mTouchTarget = mRecentButton;
                        } else if (v == mNotificationShadow) {
                            mTouchTarget = mNotificationArea;
                        }
                        mTouchTarget = mElementsForShadows.get(v);
                    }

                    if (mTouchTarget != null && mTouchTarget.getVisibility() != View.GONE) {
@@ -1094,7 +1134,7 @@ public class TabletStatusBar extends StatusBar {
                                break;
                            case MotionEvent.ACTION_DOWN:
                                mHandler.removeMessages(MSG_RESTORE_SHADOWS);
                                setShadowForButton(mTouchTarget, false);
                                setElementShadow(mTouchTarget, false);
                                break;
                        }
                        mTouchTarget.dispatchTouchEvent(ev);
@@ -1108,11 +1148,9 @@ public class TabletStatusBar extends StatusBar {
        }

        public void refresh() {
            setShadowForButton(mBackButton, mShowShadows);
            setShadowForButton(mHomeButton, mShowShadows);
            setShadowForButton(mRecentButton, mShowShadows);
            setShadowForButton(mMenuButton, mShowShadows);
            setShadowForButton(mNotificationArea, mShowShadows);
            for (View element : mShadowsForElements.keySet()) {
                setElementShadow(element, mShowShadows);
            }
        }

        public void showAllShadows() {
@@ -1127,19 +1165,8 @@ public class TabletStatusBar extends StatusBar {

        // Use View.INVISIBLE for things hidden due to shadowing, and View.GONE for things that are
        // disabled (and should not be shadowed or re-shown)
        public void setShadowForButton(View button, boolean shade) {
            View shadow = null;
            if (button == mBackButton) {
                shadow = mBackShadow;
            } else if (button == mHomeButton) {
                shadow = mHomeShadow;
            } else if (button == mMenuButton) {
                shadow = mMenuShadow;
            } else if (button == mRecentButton) {
                shadow = mRecentShadow;
            } else if (button == mNotificationArea) {
                shadow = mNotificationShadow;
            }
        public void setElementShadow(View button, boolean shade) {
            View shadow = mShadowsForElements.get(button);
            if (shadow != null) {
                if (button.getVisibility() != View.GONE) {
                    shadow.setVisibility(shade ? View.VISIBLE : View.INVISIBLE);
@@ -1147,6 +1174,26 @@ public class TabletStatusBar extends StatusBar {
                }
            }
        }

        // Hide both element and shadow, using default layout animations.
        public void hideElement(View button) {
            Slog.d(TAG, "hiding: " + button);
            View shadow = mShadowsForElements.get(button);
            if (shadow != null) {
                shadow.setVisibility(View.GONE);
            }
            button.setVisibility(View.GONE);
        }

        // Honoring the current shadow state.
        public void showElement(View button) {
            Slog.d(TAG, "showing: " + button);
            View shadow = mShadowsForElements.get(button);
            if (shadow != null) {
                shadow.setVisibility(mShowShadows ? View.VISIBLE : View.INVISIBLE);
            }
            button.setVisibility(mShowShadows ? View.INVISIBLE : View.VISIBLE);
        }
    }

    public class TouchOutsideListener implements View.OnTouchListener {
@@ -1171,15 +1218,6 @@ public class TabletStatusBar extends StatusBar {
        }
    }

    private void setViewVisibility(View v, int vis, int anim) {
        if (v.getVisibility() != vis) {
            //Slog.d(TAG, "setViewVisibility vis=" + (vis == View.VISIBLE) + " v=" + v);
            v.setAnimation(AnimationUtils.loadAnimation(mContext, anim));
            v.setVisibility(vis);
        }
    }


    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        pw.print("mDisabled=0x");
        pw.println(Integer.toHexString(mDisabled));