From c26185bb7b30508a1940eb452af64b6d8661915f Mon Sep 17 00:00:00 2001 From: Daniel Sandler Date: Wed, 29 Aug 2012 15:49:53 -0400 Subject: [PATCH] Expand the navbar dead zone briefly after touches elsewhere. For now, each time the dead zone captures a touch, it will flash to let you know that's what happened. We should probably turn this off before shipping. Note also that this currently only expands the navbar on ACTION_DOWN elsewhere in the UI (because this is the only time ACTION_OUTSIDE is generated); this isn't perfect and we'll need to do some mucking about with the input system to get information about ongoing drags or additional pointers down, but this CL is a good start and introduces the general mechanism for expanding and contracting the dead zone. Change-Id: I43e63aed1e541fd07d83fde4d66bcb5be89b69d2 --- .../res/layout-sw600dp/navigation_bar.xml | 14 +- .../SystemUI/res/layout/navigation_bar.xml | 16 ++- packages/SystemUI/res/values/attrs.xml | 12 ++ packages/SystemUI/res/values/config.xml | 4 + packages/SystemUI/res/values/dimens.xml | 2 + .../statusbar/phone/NavigationBarView.java | 20 +-- .../statusbar/phone/PhoneStatusBar.java | 1 + .../systemui/statusbar/policy/DeadZone.java | 125 +++++++++++++++++- 8 files changed, 177 insertions(+), 17 deletions(-) diff --git a/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml b/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml index 67e13eb7af960..fbbd7e5f76509 100644 --- a/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml +++ b/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml @@ -143,8 +143,13 @@ @@ -269,8 +274,13 @@ diff --git a/packages/SystemUI/res/layout/navigation_bar.xml b/packages/SystemUI/res/layout/navigation_bar.xml index d41040d13f2e7..33b5dbb7b52e8 100644 --- a/packages/SystemUI/res/layout/navigation_bar.xml +++ b/packages/SystemUI/res/layout/navigation_bar.xml @@ -147,8 +147,13 @@ @@ -276,9 +281,14 @@ diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml index 48fb21f76dffb..047570f088987 100644 --- a/packages/SystemUI/res/values/attrs.xml +++ b/packages/SystemUI/res/values/attrs.xml @@ -35,5 +35,17 @@ + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 1cd7904d0ffd7..333757333d9af 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -72,5 +72,9 @@ 90 + + + 333 + 333 diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 94465e2f38907..0d7cdb1656508 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -63,6 +63,8 @@ 12dp + + 32dp @*android:dimen/status_bar_icon_size diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java index 33973b6ec7c2f..dcc2e570aa72e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java @@ -45,13 +45,12 @@ import com.android.internal.statusbar.IStatusBarService; import com.android.systemui.R; import com.android.systemui.statusbar.BaseStatusBar; import com.android.systemui.statusbar.DelegateViewHelper; +import com.android.systemui.statusbar.policy.DeadZone; public class NavigationBarView extends LinearLayout { final static boolean DEBUG = false; final static String TAG = "PhoneStatusBar/NavigationBarView"; - final static boolean DEBUG_DEADZONE = false; - final static boolean NAVBAR_ALWAYS_AT_RIGHT = true; final static boolean ANIMATE_HIDE_TRANSITION = false; // turned off because it introduces unsightly delay when videos goes to full screen @@ -71,6 +70,7 @@ public class NavigationBarView extends LinearLayout { private Drawable mBackIcon, mBackLandIcon, mBackAltIcon, mBackAltLandIcon; private DelegateViewHelper mDelegateHelper; + private DeadZone mDeadZone; // workaround for LayoutTransitions leaving the nav buttons in a weird state (bug 5549288) final static boolean WORKAROUND_INVALID_LAYOUT = true; @@ -109,10 +109,14 @@ public class NavigationBarView extends LinearLayout { @Override public boolean onTouchEvent(MotionEvent event) { - if (mDelegateHelper != null) { - mDelegateHelper.onInterceptTouchEvent(event); + if (mDeadZone != null && event.getAction() == MotionEvent.ACTION_OUTSIDE) { + mDeadZone.poke(event); } - return true; + if (mDelegateHelper != null) { + boolean ret = mDelegateHelper.onInterceptTouchEvent(event); + if (ret) return true; + } + return super.onTouchEvent(event); } @Override @@ -335,15 +339,13 @@ public class NavigationBarView extends LinearLayout { mCurrentView = mRotatedViews[rot]; mCurrentView.setVisibility(View.VISIBLE); + mDeadZone = (DeadZone) mCurrentView.findViewById(R.id.deadzone); + // force the low profile & disabled states into compliance setLowProfile(mLowProfile, false, true /* force */); setDisabledFlags(mDisabledFlags, true /* force */); setMenuVisibility(mShowMenu, true /* force */); - if (DEBUG_DEADZONE) { - mCurrentView.findViewById(R.id.deadzone).setBackgroundColor(0x808080FF); - } - if (DEBUG) { Slog.d(TAG, "reorient(): rot=" + mDisplay.getRotation()); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index 9d2678a7b1cb3..9b4ee38f9e381 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -639,6 +639,7 @@ public class PhoneStatusBar extends BaseStatusBar { | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL + | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, PixelFormat.OPAQUE); // this will allow the navbar to run in an overlay on devices that support this diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java index 19fbe9636c0d5..6ffca2a9f0ad3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java @@ -16,26 +16,145 @@ package com.android.systemui.statusbar.policy; +import android.animation.ObjectAnimator; import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.os.SystemClock; import android.util.AttributeSet; +import android.util.Slog; import android.view.MotionEvent; import android.view.View; import com.android.systemui.R; public class DeadZone extends View { + public static final String TAG = "DeadZone"; + + public static final boolean DEBUG = false; + public static final int HORIZONTAL = 0; + public static final int VERTICAL = 1; + + private boolean mShouldFlash; + private float mFlashFrac = 0f; + + private int mSizeMax; + private int mSizeMin; + // Upon activity elsewhere in the UI, the dead zone will hold steady for + // mHold ms, then move back over the course of mDecay ms + private int mHold, mDecay; + private boolean mVertical; + private long mLastPokeTime; + + private final Runnable mDebugFlash = new Runnable() { + @Override + public void run() { + ObjectAnimator.ofFloat(DeadZone.this, "flash", 1f, 0f).setDuration(150).start(); + } + }; + public DeadZone(Context context, AttributeSet attrs) { this(context, attrs, 0); } public DeadZone(Context context, AttributeSet attrs, int defStyle) { super(context, attrs); + + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DeadZone, + defStyle, 0); + + mHold = a.getInteger(R.styleable.DeadZone_holdTime, 0); + mDecay = a.getInteger(R.styleable.DeadZone_decayTime, 0); + + mSizeMin = a.getDimensionPixelSize(R.styleable.DeadZone_minSize, 0); + mSizeMax = a.getDimensionPixelSize(R.styleable.DeadZone_maxSize, 0); + + int index = a.getInt(R.styleable.DeadZone_orientation, -1); + mVertical = (index == VERTICAL); + + if (DEBUG) + Slog.v(TAG, this + " size=[" + mSizeMin + "-" + mSizeMax + "] hold=" + mHold + + (mVertical ? " vertical" : " horizontal")); + + setFlashOnTouchCapture(true); + } + + static float lerp(float a, float b, float f) { + return (b - a) * f + a; + } + + private float getSize(long now) { + if (mSizeMax == 0) + return 0; + long dt = (now - mLastPokeTime); + if (dt > mHold + mDecay) + return mSizeMin; + if (dt < mHold) + return mSizeMax; + return (int) lerp(mSizeMax, mSizeMin, (float) (dt - mHold) / mDecay); + } + + public void setFlashOnTouchCapture(boolean dbg) { + mShouldFlash = dbg; + mFlashFrac = 0f; + postInvalidate(); } // I made you a touch event @Override - public boolean onTouchEvent (MotionEvent event) { - return true; // but I eated it + public boolean onTouchEvent(MotionEvent event) { + if (DEBUG) + Slog.v(TAG, this + " onTouch: " + MotionEvent.actionToString(event.getAction())); + + final int action = event.getAction(); + if (action == MotionEvent.ACTION_OUTSIDE) { + poke(event); + } else if (action == MotionEvent.ACTION_DOWN) { + if (DEBUG) + Slog.v(TAG, this + " ACTION_DOWN: " + event.getX() + "," + event.getY()); + int size = (int) getSize(event.getEventTime()); + if ((mVertical && event.getX() < size) || event.getY() < size) { + if (DEBUG) + Slog.v(TAG, "eating click!"); + if (mShouldFlash) { + post(mDebugFlash); + postInvalidate(); + } + return true; // but I eated it + } + } + return false; + } + + public void poke(MotionEvent event) { + mLastPokeTime = event.getEventTime(); + if (DEBUG) + Slog.v(TAG, "poked! size=" + getSize(mLastPokeTime)); + postInvalidate(); + } + + public void setFlash(float f) { + mFlashFrac = f; + postInvalidate(); + } + + public float getFlash() { + return mFlashFrac; + } + + @Override + public void onDraw(Canvas can) { + if (!mShouldFlash || mFlashFrac <= 0f) { + return; + } + + final int size = (int) getSize(SystemClock.uptimeMillis()); + can.clipRect(0, 0, mVertical ? size : can.getWidth(), mVertical ? can.getHeight() : size); + final float frac = DEBUG ? (mFlashFrac - 0.5f) + 0.5f : mFlashFrac; + can.drawARGB((int) (frac * 0xFF), 0xDD, 0xEE, 0xAA); + + if (DEBUG && size > mSizeMin) + // crazy aggressive redrawing here, for debugging only + postInvalidateDelayed(100); } } -