From 0b69b59877896e4cab448cef9e12ff4c29a4252e Mon Sep 17 00:00:00 2001 From: Daniel Sandler Date: Mon, 23 Jan 2012 21:08:36 -0500 Subject: [PATCH] Detect and repair invalid layouts in the navigation bar. It seems that something (probably layout transitions) occasionally leaves the navigation bar layout in a weird state such that most of the buttons are offscreen. For example, the portrait nav bar might have buttons with widths matching the nav bar's old width from landscape; the clickable regions will therefore be far off the right edge of the display. The navigation bar now looks for this situation when the size of the view changes and corrects for it. Bug: 5549288 Change-Id: I8464ac9fd64cb64ec18baf51478dd0f6564a2284 --- .../statusbar/phone/NavigationBarView.java | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) 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 97a18555e4323..005d12f1bdb67 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java @@ -21,6 +21,8 @@ import android.animation.AnimatorListenerAdapter; import android.content.Context; import android.content.res.Resources; import android.graphics.Rect; +import android.os.Handler; +import android.os.Message; import android.os.ServiceManager; import android.util.AttributeSet; import android.util.Slog; @@ -62,6 +64,35 @@ public class NavigationBarView extends LinearLayout { boolean mHidden, mLowProfile, mShowMenu; int mDisabledFlags = 0; + // workaround for LayoutTransitions leaving the nav buttons in a weird state (bug 5549288) + final static boolean WORKAROUND_INVALID_LAYOUT = true; + final static int MSG_CHECK_INVALID_LAYOUT = 8686; + + private class H extends Handler { + public void handleMessage(Message m) { + switch (m.what) { + case MSG_CHECK_INVALID_LAYOUT: + final String how = "" + m.obj; + final int w = getWidth(); + final int h = getHeight(); + final int vw = mCurrentView.getWidth(); + final int vh = mCurrentView.getHeight(); + + if (h != vh || w != vw) { + Slog.w(TAG, String.format( + "*** Invalid layout in navigation bar (%s this=%dx%d cur=%dx%d)", + how, w, h, vw, vh)); + if (WORKAROUND_INVALID_LAYOUT) { + requestLayout(); + } + } + break; + } + } + } + + private H mHandler = new H(); + public View getRecentsButton() { return mCurrentView.findViewById(R.id.recent_apps); } @@ -243,6 +274,36 @@ public class NavigationBarView extends LinearLayout { } } + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + if (DEBUG) Slog.d(TAG, String.format( + "onSizeChanged: (%dx%d) old: (%dx%d)", w, h, oldw, oldh)); + postCheckForInvalidLayout("sizeChanged"); + super.onSizeChanged(w, h, oldw, oldh); + } + + /* + @Override + protected void onLayout (boolean changed, int left, int top, int right, int bottom) { + if (DEBUG) Slog.d(TAG, String.format( + "onLayout: %s (%d,%d,%d,%d)", + changed?"changed":"notchanged", left, top, right, bottom)); + super.onLayout(changed, left, top, right, bottom); + } + + // uncomment this for extra defensiveness in WORKAROUND_INVALID_LAYOUT situations: if all else + // fails, any touch on the display will fix the layout. + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + if (DEBUG) Slog.d(TAG, "onInterceptTouchEvent: " + ev.toString()); + if (ev.getAction() == MotionEvent.ACTION_DOWN) { + postCheckForInvalidLayout("touch"); + } + return super.onInterceptTouchEvent(ev); + } + */ + + private String getResourceName(int resId) { if (resId != 0) { final android.content.res.Resources res = mContext.getResources(); @@ -256,6 +317,10 @@ public class NavigationBarView extends LinearLayout { } } + private void postCheckForInvalidLayout(final String how) { + mHandler.obtainMessage(MSG_CHECK_INVALID_LAYOUT, 0, 0, how).sendToTarget(); + } + private static String visibilityToString(int vis) { switch (vis) { case View.INVISIBLE: