From ae4f155e090bf387b989fb738ee34ab045585711 Mon Sep 17 00:00:00 2001 From: Adam Cohen Date: Thu, 20 Oct 2011 00:15:42 -0700 Subject: Fixing AllAppsCustomize Keyboard Accessibility / NPE (issue 5483485) Change-Id: I841823e28bf419028afea2a57352c4ad45c7c4a0 --- .../android/launcher2/AppsCustomizePagedView.java | 5 + .../android/launcher2/AppsCustomizeTabHost.java | 1 + src/com/android/launcher2/FocusHelper.java | 134 ++++++++++++--------- src/com/android/launcher2/PagedView.java | 8 +- src/com/android/launcher2/PagedViewIcon.java | 4 +- src/com/android/launcher2/PagedViewWidget.java | 4 +- 6 files changed, 93 insertions(+), 63 deletions(-) (limited to 'src/com/android') diff --git a/src/com/android/launcher2/AppsCustomizePagedView.java b/src/com/android/launcher2/AppsCustomizePagedView.java index 4718b31c4..5ed20a7fe 100644 --- a/src/com/android/launcher2/AppsCustomizePagedView.java +++ b/src/com/android/launcher2/AppsCustomizePagedView.java @@ -1200,6 +1200,11 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen return getChildAt(getChildCount() - index - 1); } + @Override + protected int indexToPage(int index) { + return getChildCount() - index - 1; + } + // In apps customize, we have a scrolling effect which emulates pulling cards off of a stack. @Override protected void screenScrolled(int screenCenter) { diff --git a/src/com/android/launcher2/AppsCustomizeTabHost.java b/src/com/android/launcher2/AppsCustomizeTabHost.java index 404b088dc..593712a74 100644 --- a/src/com/android/launcher2/AppsCustomizeTabHost.java +++ b/src/com/android/launcher2/AppsCustomizeTabHost.java @@ -224,6 +224,7 @@ public class AppsCustomizeTabHost extends TabHost implements LauncherTransitiona } mAppsCustomizePane.loadAssociatedPages( mAppsCustomizePane.getCurrentPage()); + mAppsCustomizePane.requestFocus(); } }); AnimatorSet animSet = new AnimatorSet(); diff --git a/src/com/android/launcher2/FocusHelper.java b/src/com/android/launcher2/FocusHelper.java index 967b02ff4..1a7416a99 100644 --- a/src/com/android/launcher2/FocusHelper.java +++ b/src/com/android/launcher2/FocusHelper.java @@ -124,6 +124,18 @@ public class FocusHelper { return v.getVisibility() == View.VISIBLE; } + /** + * Returns the Viewgroup containing page contents for the page at the index specified. + */ + private static ViewGroup getAppsCustomizePage(ViewGroup container, int index) { + ViewGroup page = (ViewGroup) ((PagedView) container).getPageAt(index); + if (page instanceof PagedViewCellLayout) { + // There are two layers, a PagedViewCellLayout and PagedViewCellLayoutChildren + page = (ViewGroup) page.getChildAt(0); + } + return page; + } + /** * Handles key events in a PageViewExtendedLayout containing PagedViewWidgets. */ @@ -131,12 +143,12 @@ public class FocusHelper { KeyEvent e) { final PagedViewGridLayout parent = (PagedViewGridLayout) w.getParent(); - final ViewGroup container = (ViewGroup) parent.getParent(); + final PagedView container = (PagedView) parent.getParent(); final TabHost tabHost = findTabHostParent(container); final TabWidget tabs = (TabWidget) tabHost.findViewById(com.android.internal.R.id.tabs); final int widgetIndex = parent.indexOfChild(w); final int widgetCount = parent.getChildCount(); - final int pageIndex = container.indexOfChild(parent); + final int pageIndex = ((PagedView) container).indexToPage(container.indexOfChild(parent)); final int pageCount = container.getChildCount(); final int cellCountX = parent.getCellCountX(); final int cellCountY = parent.getCellCountY(); @@ -145,7 +157,7 @@ public class FocusHelper { final int action = e.getAction(); final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP); - PagedViewGridLayout newParent = null; + ViewGroup newParent = null; // Now that we load items in the bg asynchronously, we can't just focus // child siblings willy-nilly View child = null; @@ -158,10 +170,11 @@ public class FocusHelper { parent.getChildAt(widgetIndex - 1).requestFocus(); } else { if (pageIndex > 0) { - newParent = (PagedViewGridLayout) - container.getChildAt(pageIndex - 1); - child = newParent.getChildAt(newParent.getChildCount() - 1); - if (child != null) child.requestFocus(); + newParent = getAppsCustomizePage(container, pageIndex - 1); + if (newParent != null) { + child = newParent.getChildAt(newParent.getChildCount() - 1); + if (child != null) child.requestFocus(); + } } } } @@ -174,10 +187,11 @@ public class FocusHelper { parent.getChildAt(widgetIndex + 1).requestFocus(); } else { if (pageIndex < (pageCount - 1)) { - newParent = (PagedViewGridLayout) - container.getChildAt(pageIndex + 1); - child = newParent.getChildAt(0); - if (child != null) child.requestFocus(); + newParent = getAppsCustomizePage(container, pageIndex + 1); + if (newParent != null) { + child = newParent.getChildAt(0); + if (child != null) child.requestFocus(); + } } } } @@ -221,8 +235,10 @@ public class FocusHelper { // Select the first item on the previous page, or the first item on this page // if there is no previous page if (pageIndex > 0) { - newParent = (PagedViewGridLayout) container.getChildAt(pageIndex - 1); - child = newParent.getChildAt(0); + newParent = getAppsCustomizePage(container, pageIndex - 1); + if (newParent != null) { + child = newParent.getChildAt(0); + } } else { child = parent.getChildAt(0); } @@ -235,8 +251,10 @@ public class FocusHelper { // Select the first item on the next page, or the last item on this page // if there is no next page if (pageIndex < (pageCount - 1)) { - newParent = (PagedViewGridLayout) container.getChildAt(pageIndex + 1); - child = newParent.getChildAt(0); + newParent = getAppsCustomizePage(container, pageIndex + 1); + if (newParent != null) { + child = newParent.getChildAt(0); + } } else { child = parent.getChildAt(widgetCount - 1); } @@ -264,39 +282,41 @@ public class FocusHelper { return wasHandled; } - /** - * Private helper method to get the PagedViewCellLayoutChildren given a PagedViewCellLayout - * index. - */ - private static PagedViewCellLayoutChildren getPagedViewCellLayoutChildrenForIndex( - ViewGroup container, int i) { - ViewGroup parent = (ViewGroup) container.getChildAt(i); - return (PagedViewCellLayoutChildren) parent.getChildAt(0); - } - /** * Handles key events in a PageViewCellLayout containing PagedViewIcons. */ - static boolean handlePagedViewIconKeyEvent(PagedViewIcon v, int keyCode, KeyEvent e) { - final PagedViewCellLayoutChildren parent = (PagedViewCellLayoutChildren) v.getParent(); - final PagedViewCellLayout parentLayout = (PagedViewCellLayout) parent.getParent(); + static boolean handleAppsCustomizeKeyEvent(View v, int keyCode, KeyEvent e) { + ViewGroup parentLayout; + ViewGroup itemContainer; + int countX; + int countY; + if (v.getParent() instanceof PagedViewCellLayoutChildren) { + itemContainer = (ViewGroup) v.getParent(); + parentLayout = (ViewGroup) itemContainer.getParent(); + countX = ((PagedViewCellLayout) parentLayout).getCellCountX(); + countY = ((PagedViewCellLayout) parentLayout).getCellCountY(); + } else { + itemContainer = parentLayout = (ViewGroup) v.getParent(); + countX = ((PagedViewGridLayout) parentLayout).getCellCountX(); + countY = ((PagedViewGridLayout) parentLayout).getCellCountY(); + } + // Note we have an extra parent because of the // PagedViewCellLayout/PagedViewCellLayoutChildren relationship - final ViewGroup container = (ViewGroup) parentLayout.getParent(); + final PagedView container = (PagedView) parentLayout.getParent(); final TabHost tabHost = findTabHostParent(container); final TabWidget tabs = (TabWidget) tabHost.findViewById(com.android.internal.R.id.tabs); - final int iconIndex = parent.indexOfChild(v); - final int widgetCount = parent.getChildCount(); - final int pageIndex = container.indexOfChild(parentLayout); + final int iconIndex = itemContainer.indexOfChild(v); + final int itemCount = itemContainer.getChildCount(); + final int pageIndex = ((PagedView) container).indexToPage(container.indexOfChild(parentLayout)); final int pageCount = container.getChildCount(); - final int cellCountX = parentLayout.getCellCountX(); - final int cellCountY = parentLayout.getCellCountY(); - final int x = iconIndex % cellCountX; - final int y = iconIndex / cellCountX; + + final int x = iconIndex % countX; + final int y = iconIndex / countX; final int action = e.getAction(); final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP); - PagedViewCellLayoutChildren newParent = null; + ViewGroup newParent = null; // Side pages do not always load synchronously, so check before focusing child siblings // willy-nilly View child = null; @@ -306,12 +326,12 @@ public class FocusHelper { if (handleKeyEvent) { // Select the previous icon or the last icon on the previous page if (iconIndex > 0) { - parent.getChildAt(iconIndex - 1).requestFocus(); + itemContainer.getChildAt(iconIndex - 1).requestFocus(); } else { if (pageIndex > 0) { - newParent = getPagedViewCellLayoutChildrenForIndex(container, - pageIndex - 1); + newParent = getAppsCustomizePage(container, pageIndex - 1); if (newParent != null) { + container.snapToPage(pageIndex - 1); child = newParent.getChildAt(newParent.getChildCount() - 1); if (child != null) child.requestFocus(); } @@ -323,13 +343,13 @@ public class FocusHelper { case KeyEvent.KEYCODE_DPAD_RIGHT: if (handleKeyEvent) { // Select the next icon or the first icon on the next page - if (iconIndex < (widgetCount - 1)) { - parent.getChildAt(iconIndex + 1).requestFocus(); + if (iconIndex < (itemCount - 1)) { + itemContainer.getChildAt(iconIndex + 1).requestFocus(); } else { if (pageIndex < (pageCount - 1)) { - newParent = getPagedViewCellLayoutChildrenForIndex(container, - pageIndex + 1); + newParent = getAppsCustomizePage(container, pageIndex + 1); if (newParent != null) { + container.snapToPage(pageIndex + 1); child = newParent.getChildAt(0); if (child != null) child.requestFocus(); } @@ -342,8 +362,8 @@ public class FocusHelper { if (handleKeyEvent) { // Select the closest icon in the previous row, otherwise select the tab bar if (y > 0) { - int newiconIndex = ((y - 1) * cellCountX) + x; - parent.getChildAt(newiconIndex).requestFocus(); + int newiconIndex = ((y - 1) * countX) + x; + itemContainer.getChildAt(newiconIndex).requestFocus(); } else { tabs.requestFocus(); } @@ -353,9 +373,9 @@ public class FocusHelper { case KeyEvent.KEYCODE_DPAD_DOWN: if (handleKeyEvent) { // Select the closest icon in the previous row, otherwise do nothing - if (y < (cellCountY - 1)) { - int newiconIndex = Math.min(widgetCount - 1, ((y + 1) * cellCountX) + x); - parent.getChildAt(newiconIndex).requestFocus(); + if (y < (countY - 1)) { + int newiconIndex = Math.min(itemCount - 1, ((y + 1) * countX) + x); + itemContainer.getChildAt(newiconIndex).requestFocus(); } } wasHandled = true; @@ -374,14 +394,14 @@ public class FocusHelper { // Select the first icon on the previous page, or the first icon on this page // if there is no previous page if (pageIndex > 0) { - newParent = getPagedViewCellLayoutChildrenForIndex(container, - pageIndex - 1); + newParent = getAppsCustomizePage(container, pageIndex - 1); if (newParent != null) { + container.snapToPage(pageIndex - 1); child = newParent.getChildAt(0); if (child != null) child.requestFocus(); } } else { - parent.getChildAt(0).requestFocus(); + itemContainer.getChildAt(0).requestFocus(); } } wasHandled = true; @@ -391,14 +411,14 @@ public class FocusHelper { // Select the first icon on the next page, or the last icon on this page // if there is no next page if (pageIndex < (pageCount - 1)) { - newParent = getPagedViewCellLayoutChildrenForIndex(container, - pageIndex + 1); + newParent = getAppsCustomizePage(container, pageIndex + 1); if (newParent != null) { + container.snapToPage(pageIndex + 1); child = newParent.getChildAt(0); if (child != null) child.requestFocus(); } } else { - parent.getChildAt(widgetCount - 1).requestFocus(); + itemContainer.getChildAt(itemCount - 1).requestFocus(); } } wasHandled = true; @@ -406,14 +426,14 @@ public class FocusHelper { case KeyEvent.KEYCODE_MOVE_HOME: if (handleKeyEvent) { // Select the first icon on this page - parent.getChildAt(0).requestFocus(); + itemContainer.getChildAt(0).requestFocus(); } wasHandled = true; break; case KeyEvent.KEYCODE_MOVE_END: if (handleKeyEvent) { // Select the last icon on this page - parent.getChildAt(widgetCount - 1).requestFocus(); + itemContainer.getChildAt(itemCount - 1).requestFocus(); } wasHandled = true; break; diff --git a/src/com/android/launcher2/PagedView.java b/src/com/android/launcher2/PagedView.java index 8121d3b9d..7be19bf23 100644 --- a/src/com/android/launcher2/PagedView.java +++ b/src/com/android/launcher2/PagedView.java @@ -270,6 +270,10 @@ public abstract class PagedView extends ViewGroup { return getChildAt(index); } + protected int indexToPage(int index) { + return index; + } + /** * Updates the scroll of the current page immediately to its final scroll position. We use this * in CustomizePagedView to allow tabs to share the same PagedView while resetting the scroll of @@ -714,7 +718,7 @@ public abstract class PagedView extends ViewGroup { @Override public boolean requestChildRectangleOnScreen(View child, Rect rectangle, boolean immediate) { - int page = indexOfChild(child); + int page = indexToPage(indexOfChild(child)); if (page != mCurrentPage || !mScroller.isFinished()) { snapToPage(page); return true; @@ -1287,7 +1291,7 @@ public abstract class PagedView extends ViewGroup { @Override public void requestChildFocus(View child, View focused) { super.requestChildFocus(child, focused); - int page = indexOfChild(child); + int page = indexToPage(indexOfChild(child)); if (page >= 0 && page != getCurrentPage() && !isInTouchMode()) { snapToPage(page); } diff --git a/src/com/android/launcher2/PagedViewIcon.java b/src/com/android/launcher2/PagedViewIcon.java index 3ae978d19..3cc7786cc 100644 --- a/src/com/android/launcher2/PagedViewIcon.java +++ b/src/com/android/launcher2/PagedViewIcon.java @@ -156,13 +156,13 @@ public class PagedViewIcon extends CachedTextView implements Checkable { @Override public boolean onKeyDown(int keyCode, KeyEvent event) { - return FocusHelper.handlePagedViewIconKeyEvent(this, keyCode, event) + return FocusHelper.handleAppsCustomizeKeyEvent(this, keyCode, event) || super.onKeyDown(keyCode, event); } @Override public boolean onKeyUp(int keyCode, KeyEvent event) { - return FocusHelper.handlePagedViewIconKeyEvent(this, keyCode, event) + return FocusHelper.handleAppsCustomizeKeyEvent(this, keyCode, event) || super.onKeyUp(keyCode, event); } diff --git a/src/com/android/launcher2/PagedViewWidget.java b/src/com/android/launcher2/PagedViewWidget.java index 4d5fd7b38..12c98b292 100644 --- a/src/com/android/launcher2/PagedViewWidget.java +++ b/src/com/android/launcher2/PagedViewWidget.java @@ -167,13 +167,13 @@ public class PagedViewWidget extends LinearLayout implements Checkable { @Override public boolean onKeyDown(int keyCode, KeyEvent event) { - return FocusHelper.handlePagedViewGridLayoutWidgetKeyEvent(this, keyCode, event) + return FocusHelper.handleAppsCustomizeKeyEvent(this, keyCode, event) || super.onKeyDown(keyCode, event); } @Override public boolean onKeyUp(int keyCode, KeyEvent event) { - return FocusHelper.handlePagedViewGridLayoutWidgetKeyEvent(this, keyCode, event) + return FocusHelper.handleAppsCustomizeKeyEvent(this, keyCode, event) || super.onKeyUp(keyCode, event); } -- cgit v1.2.3