197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung/* 297d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung * Copyright (C) 2011 The Android Open Source Project 397d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung * 497d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung * Licensed under the Apache License, Version 2.0 (the "License"); 597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung * you may not use this file except in compliance with the License. 697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung * You may obtain a copy of the License at 797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung * 897d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung * http://www.apache.org/licenses/LICENSE-2.0 997d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung * 1097d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung * Unless required by applicable law or agreed to in writing, software 1197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung * distributed under the License is distributed on an "AS IS" BASIS, 1297d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1397d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung * See the License for the specific language governing permissions and 1497d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung * limitations under the License. 1597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung */ 1697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung 17325dc23624160689e59fbac708cf6f222b20d025Daniel Sandlerpackage com.android.launcher3; 1897d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung 194e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chungimport android.content.res.Configuration; 20b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyalimport android.util.Log; 2197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chungimport android.view.KeyEvent; 22b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyalimport android.view.SoundEffectConstants; 2397d85d23b013347bead4e2f5fa430a79ce69431eWinson Chungimport android.view.View; 2497d85d23b013347bead4e2f5fa430a79ce69431eWinson Chungimport android.view.ViewGroup; 2597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chungimport android.view.ViewParent; 26a1f133de788823603a2c62aba5dc5d84c5a39cc6Winson Chungimport android.widget.ScrollView; 2797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung 28faa13255de0fb1d581ec7a583ed6ef0b661dbea0Winson Chungimport java.util.ArrayList; 29faa13255de0fb1d581ec7a583ed6ef0b661dbea0Winson Chungimport java.util.Collections; 30faa13255de0fb1d581ec7a583ed6ef0b661dbea0Winson Chungimport java.util.Comparator; 31faa13255de0fb1d581ec7a583ed6ef0b661dbea0Winson Chung 3297d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung/** 334d279d94ade1c0d455404312b3c9cfde0078c547Winson Chung * A keyboard listener we set on all the workspace icons. 344d279d94ade1c0d455404312b3c9cfde0078c547Winson Chung */ 35ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohenclass IconKeyEventListener implements View.OnKeyListener { 364d279d94ade1c0d455404312b3c9cfde0078c547Winson Chung public boolean onKey(View v, int keyCode, KeyEvent event) { 37ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen return FocusHelper.handleIconKeyEvent(v, keyCode, event); 38ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen } 39ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen} 40ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen 41ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen/** 42ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen * A keyboard listener we set on all the workspace icons. 43ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen */ 44ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohenclass FolderKeyEventListener implements View.OnKeyListener { 45ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen public boolean onKey(View v, int keyCode, KeyEvent event) { 46ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen return FocusHelper.handleFolderKeyEvent(v, keyCode, event); 474d279d94ade1c0d455404312b3c9cfde0078c547Winson Chung } 484d279d94ade1c0d455404312b3c9cfde0078c547Winson Chung} 494d279d94ade1c0d455404312b3c9cfde0078c547Winson Chung 504d279d94ade1c0d455404312b3c9cfde0078c547Winson Chung/** 513d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung * A keyboard listener we set on all the hotseat buttons. 524e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung */ 53ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohenclass HotseatIconKeyEventListener implements View.OnKeyListener { 544e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung public boolean onKey(View v, int keyCode, KeyEvent event) { 554e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung final Configuration configuration = v.getResources().getConfiguration(); 563d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung return FocusHelper.handleHotseatButtonKeyEvent(v, keyCode, event, configuration.orientation); 574e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung } 584e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung} 594e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung 6097d85d23b013347bead4e2f5fa430a79ce69431eWinson Chungpublic class FocusHelper { 6197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung /** 6297d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung * Private helper to get the parent TabHost in the view hiearchy. 6397d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung */ 64c956cbaee26c173ff3f9ec6625822b92dd07766fAdam Cohen private static AppsCustomizeTabHost findTabHostParent(View v) { 6597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung ViewParent p = v.getParent(); 66c956cbaee26c173ff3f9ec6625822b92dd07766fAdam Cohen while (p != null && !(p instanceof AppsCustomizeTabHost)) { 6797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung p = p.getParent(); 6897d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 69c956cbaee26c173ff3f9ec6625822b92dd07766fAdam Cohen return (AppsCustomizeTabHost) p; 7097d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 7197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung 7297d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung /** 73ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen * Returns the Viewgroup containing page contents for the page at the index specified. 74ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen */ 75ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen private static ViewGroup getAppsCustomizePage(ViewGroup container, int index) { 76ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen ViewGroup page = (ViewGroup) ((PagedView) container).getPageAt(index); 77c58497ee619416c4949b16eb43486c11618b69e5Winson Chung if (page instanceof CellLayout) { 78ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen // There are two layers, a PagedViewCellLayout and PagedViewCellLayoutChildren 79c58497ee619416c4949b16eb43486c11618b69e5Winson Chung page = ((CellLayout) page).getShortcutsAndWidgets(); 80ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen } 81ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen return page; 82ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen } 83ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen 84ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen /** 8597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung * Handles key events in a PageViewExtendedLayout containing PagedViewWidgets. 864e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung */ 874e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung static boolean handlePagedViewGridLayoutWidgetKeyEvent(PagedViewWidget w, int keyCode, 884e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung KeyEvent e) { 894e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung 904e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung final PagedViewGridLayout parent = (PagedViewGridLayout) w.getParent(); 91ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen final PagedView container = (PagedView) parent.getParent(); 924e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung final int widgetIndex = parent.indexOfChild(w); 934e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung final int widgetCount = parent.getChildCount(); 94ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen final int pageIndex = ((PagedView) container).indexToPage(container.indexOfChild(parent)); 954e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung final int pageCount = container.getChildCount(); 964e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung final int cellCountX = parent.getCellCountX(); 974e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung final int cellCountY = parent.getCellCountY(); 984e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung final int x = widgetIndex % cellCountX; 994e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung final int y = widgetIndex / cellCountX; 1004e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung 1014e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung final int action = e.getAction(); 1024e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP); 103ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen ViewGroup newParent = null; 1043b0b46af5dd09ae00cd0ff7fcce6cff17447acadWinson Chung // Now that we load items in the bg asynchronously, we can't just focus 1053b0b46af5dd09ae00cd0ff7fcce6cff17447acadWinson Chung // child siblings willy-nilly 1063b0b46af5dd09ae00cd0ff7fcce6cff17447acadWinson Chung View child = null; 1074e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung boolean wasHandled = false; 1084e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung switch (keyCode) { 1094e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung case KeyEvent.KEYCODE_DPAD_LEFT: 1104e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung if (handleKeyEvent) { 1114e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung // Select the previous widget or the last widget on the previous page 1124e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung if (widgetIndex > 0) { 1134e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung parent.getChildAt(widgetIndex - 1).requestFocus(); 1144e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung } else { 1154e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung if (pageIndex > 0) { 116ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen newParent = getAppsCustomizePage(container, pageIndex - 1); 117ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen if (newParent != null) { 118ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen child = newParent.getChildAt(newParent.getChildCount() - 1); 119ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen if (child != null) child.requestFocus(); 120ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen } 1214e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung } 1224e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung } 1234e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung } 1244e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung wasHandled = true; 1254e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung break; 1264e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung case KeyEvent.KEYCODE_DPAD_RIGHT: 1274e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung if (handleKeyEvent) { 1284e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung // Select the next widget or the first widget on the next page 1294e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung if (widgetIndex < (widgetCount - 1)) { 1304e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung parent.getChildAt(widgetIndex + 1).requestFocus(); 1314e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung } else { 1324e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung if (pageIndex < (pageCount - 1)) { 133ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen newParent = getAppsCustomizePage(container, pageIndex + 1); 134ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen if (newParent != null) { 135ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen child = newParent.getChildAt(0); 136ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen if (child != null) child.requestFocus(); 137ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen } 1384e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung } 1394e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung } 1404e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung } 1414e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung wasHandled = true; 1424e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung break; 1434e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung case KeyEvent.KEYCODE_DPAD_UP: 1444e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung if (handleKeyEvent) { 1454e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung // Select the closest icon in the previous row, otherwise select the tab bar 1464e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung if (y > 0) { 1474e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung int newWidgetIndex = ((y - 1) * cellCountX) + x; 1483b0b46af5dd09ae00cd0ff7fcce6cff17447acadWinson Chung child = parent.getChildAt(newWidgetIndex); 1493b0b46af5dd09ae00cd0ff7fcce6cff17447acadWinson Chung if (child != null) child.requestFocus(); 1504e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung } 1514e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung } 1524e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung wasHandled = true; 1534e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung break; 1544e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung case KeyEvent.KEYCODE_DPAD_DOWN: 1554e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung if (handleKeyEvent) { 1564e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung // Select the closest icon in the previous row, otherwise do nothing 1574e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung if (y < (cellCountY - 1)) { 1584e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung int newWidgetIndex = Math.min(widgetCount - 1, ((y + 1) * cellCountX) + x); 1593b0b46af5dd09ae00cd0ff7fcce6cff17447acadWinson Chung child = parent.getChildAt(newWidgetIndex); 1603b0b46af5dd09ae00cd0ff7fcce6cff17447acadWinson Chung if (child != null) child.requestFocus(); 1614e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung } 1624e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung } 1634e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung wasHandled = true; 1644e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung break; 1654e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung case KeyEvent.KEYCODE_ENTER: 1664e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung case KeyEvent.KEYCODE_DPAD_CENTER: 1674e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung if (handleKeyEvent) { 1684e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung // Simulate a click on the widget 1694e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung View.OnClickListener clickListener = (View.OnClickListener) container; 1704e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung clickListener.onClick(w); 1714e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung } 1724e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung wasHandled = true; 1734e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung break; 1744e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung case KeyEvent.KEYCODE_PAGE_UP: 1754e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung if (handleKeyEvent) { 1764e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung // Select the first item on the previous page, or the first item on this page 1774e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung // if there is no previous page 1784e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung if (pageIndex > 0) { 179ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen newParent = getAppsCustomizePage(container, pageIndex - 1); 180ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen if (newParent != null) { 181ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen child = newParent.getChildAt(0); 182ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen } 1834e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung } else { 1843b0b46af5dd09ae00cd0ff7fcce6cff17447acadWinson Chung child = parent.getChildAt(0); 1854e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung } 1863b0b46af5dd09ae00cd0ff7fcce6cff17447acadWinson Chung if (child != null) child.requestFocus(); 1874e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung } 1884e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung wasHandled = true; 1894e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung break; 1904e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung case KeyEvent.KEYCODE_PAGE_DOWN: 1914e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung if (handleKeyEvent) { 1924e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung // Select the first item on the next page, or the last item on this page 1934e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung // if there is no next page 1944e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung if (pageIndex < (pageCount - 1)) { 195ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen newParent = getAppsCustomizePage(container, pageIndex + 1); 196ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen if (newParent != null) { 197ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen child = newParent.getChildAt(0); 198ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen } 1994e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung } else { 2003b0b46af5dd09ae00cd0ff7fcce6cff17447acadWinson Chung child = parent.getChildAt(widgetCount - 1); 2014e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung } 2023b0b46af5dd09ae00cd0ff7fcce6cff17447acadWinson Chung if (child != null) child.requestFocus(); 2034e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung } 2044e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung wasHandled = true; 2054e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung break; 2064e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung case KeyEvent.KEYCODE_MOVE_HOME: 2074e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung if (handleKeyEvent) { 2084e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung // Select the first item on this page 2093b0b46af5dd09ae00cd0ff7fcce6cff17447acadWinson Chung child = parent.getChildAt(0); 2103b0b46af5dd09ae00cd0ff7fcce6cff17447acadWinson Chung if (child != null) child.requestFocus(); 2114e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung } 2124e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung wasHandled = true; 2134e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung break; 2144e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung case KeyEvent.KEYCODE_MOVE_END: 2154e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung if (handleKeyEvent) { 2164e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung // Select the last item on this page 2174e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung parent.getChildAt(widgetCount - 1).requestFocus(); 2184e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung } 2194e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung wasHandled = true; 2204e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung break; 2214e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung default: break; 2224e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung } 2234e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung return wasHandled; 2244e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung } 2254e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung 2264e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung /** 22797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung * Handles key events in a PageViewCellLayout containing PagedViewIcons. 22897d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung */ 229ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen static boolean handleAppsCustomizeKeyEvent(View v, int keyCode, KeyEvent e) { 230ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen ViewGroup parentLayout; 231ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen ViewGroup itemContainer; 232ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen int countX; 233ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen int countY; 234c58497ee619416c4949b16eb43486c11618b69e5Winson Chung if (v.getParent() instanceof ShortcutAndWidgetContainer) { 235ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen itemContainer = (ViewGroup) v.getParent(); 236ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen parentLayout = (ViewGroup) itemContainer.getParent(); 237c58497ee619416c4949b16eb43486c11618b69e5Winson Chung countX = ((CellLayout) parentLayout).getCountX(); 238c58497ee619416c4949b16eb43486c11618b69e5Winson Chung countY = ((CellLayout) parentLayout).getCountY(); 239ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen } else { 240ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen itemContainer = parentLayout = (ViewGroup) v.getParent(); 241ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen countX = ((PagedViewGridLayout) parentLayout).getCellCountX(); 242ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen countY = ((PagedViewGridLayout) parentLayout).getCellCountY(); 243ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen } 244ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen 24597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung // Note we have an extra parent because of the 24697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung // PagedViewCellLayout/PagedViewCellLayoutChildren relationship 247ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen final PagedView container = (PagedView) parentLayout.getParent(); 248ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen final int iconIndex = itemContainer.indexOfChild(v); 249ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen final int itemCount = itemContainer.getChildCount(); 250ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen final int pageIndex = ((PagedView) container).indexToPage(container.indexOfChild(parentLayout)); 25197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung final int pageCount = container.getChildCount(); 252ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen 253ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen final int x = iconIndex % countX; 254ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen final int y = iconIndex / countX; 25597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung 256b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal final int action = e.getAction(); 25797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP); 258ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen ViewGroup newParent = null; 25990576b5f095371e1ba4fedcb775f43715adf9634Winson Chung // Side pages do not always load synchronously, so check before focusing child siblings 26090576b5f095371e1ba4fedcb775f43715adf9634Winson Chung // willy-nilly 26190576b5f095371e1ba4fedcb775f43715adf9634Winson Chung View child = null; 26297d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung boolean wasHandled = false; 26397d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung switch (keyCode) { 26497d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung case KeyEvent.KEYCODE_DPAD_LEFT: 26597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (handleKeyEvent) { 26697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung // Select the previous icon or the last icon on the previous page 26790576b5f095371e1ba4fedcb775f43715adf9634Winson Chung if (iconIndex > 0) { 268ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen itemContainer.getChildAt(iconIndex - 1).requestFocus(); 269b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal v.playSoundEffect(SoundEffectConstants.NAVIGATION_LEFT); 27097d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } else { 27197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (pageIndex > 0) { 272ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen newParent = getAppsCustomizePage(container, pageIndex - 1); 27390576b5f095371e1ba4fedcb775f43715adf9634Winson Chung if (newParent != null) { 274ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen container.snapToPage(pageIndex - 1); 27590576b5f095371e1ba4fedcb775f43715adf9634Winson Chung child = newParent.getChildAt(newParent.getChildCount() - 1); 276b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal if (child != null) { 277b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal child.requestFocus(); 278b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal v.playSoundEffect(SoundEffectConstants.NAVIGATION_LEFT); 279b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal } 28090576b5f095371e1ba4fedcb775f43715adf9634Winson Chung } 28197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 28297d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 28397d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 28497d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung wasHandled = true; 28597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung break; 28697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung case KeyEvent.KEYCODE_DPAD_RIGHT: 28797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (handleKeyEvent) { 28897d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung // Select the next icon or the first icon on the next page 289ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen if (iconIndex < (itemCount - 1)) { 290ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen itemContainer.getChildAt(iconIndex + 1).requestFocus(); 291b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal v.playSoundEffect(SoundEffectConstants.NAVIGATION_RIGHT); 29297d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } else { 29397d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (pageIndex < (pageCount - 1)) { 294ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen newParent = getAppsCustomizePage(container, pageIndex + 1); 29590576b5f095371e1ba4fedcb775f43715adf9634Winson Chung if (newParent != null) { 296ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen container.snapToPage(pageIndex + 1); 29790576b5f095371e1ba4fedcb775f43715adf9634Winson Chung child = newParent.getChildAt(0); 298b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal if (child != null) { 299b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal child.requestFocus(); 300b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal v.playSoundEffect(SoundEffectConstants.NAVIGATION_RIGHT); 301b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal } 30290576b5f095371e1ba4fedcb775f43715adf9634Winson Chung } 30397d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 30497d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 30597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 30697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung wasHandled = true; 30797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung break; 30897d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung case KeyEvent.KEYCODE_DPAD_UP: 30997d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (handleKeyEvent) { 31097d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung // Select the closest icon in the previous row, otherwise select the tab bar 31197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (y > 0) { 312ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen int newiconIndex = ((y - 1) * countX) + x; 313ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen itemContainer.getChildAt(newiconIndex).requestFocus(); 314b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal v.playSoundEffect(SoundEffectConstants.NAVIGATION_UP); 31597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 31697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 31797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung wasHandled = true; 31897d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung break; 31997d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung case KeyEvent.KEYCODE_DPAD_DOWN: 32097d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (handleKeyEvent) { 321b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal // Select the closest icon in the next row, otherwise do nothing 322ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen if (y < (countY - 1)) { 323ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen int newiconIndex = Math.min(itemCount - 1, ((y + 1) * countX) + x); 324b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal int newIconY = newiconIndex / countX; 325b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal if (newIconY != y) { 326b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal itemContainer.getChildAt(newiconIndex).requestFocus(); 327b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal v.playSoundEffect(SoundEffectConstants.NAVIGATION_DOWN); 328b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal } 32997d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 33097d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 33197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung wasHandled = true; 33297d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung break; 33397d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung case KeyEvent.KEYCODE_PAGE_UP: 33497d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (handleKeyEvent) { 33597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung // Select the first icon on the previous page, or the first icon on this page 33697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung // if there is no previous page 33797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (pageIndex > 0) { 338ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen newParent = getAppsCustomizePage(container, pageIndex - 1); 33990576b5f095371e1ba4fedcb775f43715adf9634Winson Chung if (newParent != null) { 340ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen container.snapToPage(pageIndex - 1); 34190576b5f095371e1ba4fedcb775f43715adf9634Winson Chung child = newParent.getChildAt(0); 342b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal if (child != null) { 343b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal child.requestFocus(); 344b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal v.playSoundEffect(SoundEffectConstants.NAVIGATION_UP); 345b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal } 34690576b5f095371e1ba4fedcb775f43715adf9634Winson Chung } 34797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } else { 348ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen itemContainer.getChildAt(0).requestFocus(); 349b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal v.playSoundEffect(SoundEffectConstants.NAVIGATION_UP); 35097d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 35197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 35297d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung wasHandled = true; 35397d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung break; 35497d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung case KeyEvent.KEYCODE_PAGE_DOWN: 35597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (handleKeyEvent) { 35697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung // Select the first icon on the next page, or the last icon on this page 35797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung // if there is no next page 35897d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (pageIndex < (pageCount - 1)) { 359ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen newParent = getAppsCustomizePage(container, pageIndex + 1); 36090576b5f095371e1ba4fedcb775f43715adf9634Winson Chung if (newParent != null) { 361ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen container.snapToPage(pageIndex + 1); 36290576b5f095371e1ba4fedcb775f43715adf9634Winson Chung child = newParent.getChildAt(0); 363b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal if (child != null) { 364b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal child.requestFocus(); 365b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal v.playSoundEffect(SoundEffectConstants.NAVIGATION_DOWN); 366b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal } 36790576b5f095371e1ba4fedcb775f43715adf9634Winson Chung } 36897d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } else { 369ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen itemContainer.getChildAt(itemCount - 1).requestFocus(); 370b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal v.playSoundEffect(SoundEffectConstants.NAVIGATION_DOWN); 37197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 37297d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 37397d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung wasHandled = true; 37497d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung break; 37597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung case KeyEvent.KEYCODE_MOVE_HOME: 37697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (handleKeyEvent) { 37797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung // Select the first icon on this page 378ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen itemContainer.getChildAt(0).requestFocus(); 379b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal v.playSoundEffect(SoundEffectConstants.NAVIGATION_UP); 38097d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 38197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung wasHandled = true; 38297d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung break; 38397d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung case KeyEvent.KEYCODE_MOVE_END: 38497d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (handleKeyEvent) { 38597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung // Select the last icon on this page 386ae4f155e090bf387b989fb738ee34ab045585711Adam Cohen itemContainer.getChildAt(itemCount - 1).requestFocus(); 387b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal v.playSoundEffect(SoundEffectConstants.NAVIGATION_DOWN); 38897d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 38997d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung wasHandled = true; 39097d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung break; 39197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung default: break; 39297d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 39397d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung return wasHandled; 39497d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 39597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung 39697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung /** 39797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung * Handles key events in the tab widget. 39897d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung */ 39997d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung static boolean handleTabKeyEvent(AccessibleTabView v, int keyCode, KeyEvent e) { 400e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler if (!LauncherAppState.getInstance().isScreenLarge()) return false; 40197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung 40297d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung final FocusOnlyTabWidget parent = (FocusOnlyTabWidget) v.getParent(); 403c956cbaee26c173ff3f9ec6625822b92dd07766fAdam Cohen final AppsCustomizeTabHost tabHost = findTabHostParent(parent); 404c956cbaee26c173ff3f9ec6625822b92dd07766fAdam Cohen final ViewGroup contents = tabHost.getContent(); 40597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung final int tabCount = parent.getTabCount(); 40697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung final int tabIndex = parent.getChildTabIndex(v); 40797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung 40897d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung final int action = e.getAction(); 40997d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP); 41097d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung boolean wasHandled = false; 41197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung switch (keyCode) { 41297d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung case KeyEvent.KEYCODE_DPAD_LEFT: 41397d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (handleKeyEvent) { 41497d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung // Select the previous tab 41597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (tabIndex > 0) { 41697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung parent.getChildTabViewAt(tabIndex - 1).requestFocus(); 41797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 41897d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 41997d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung wasHandled = true; 42097d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung break; 42197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung case KeyEvent.KEYCODE_DPAD_RIGHT: 42297d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (handleKeyEvent) { 42397d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung // Select the next tab, or if the last tab has a focus right id, select that 42497d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (tabIndex < (tabCount - 1)) { 42597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung parent.getChildTabViewAt(tabIndex + 1).requestFocus(); 42697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } else { 42797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (v.getNextFocusRightId() != View.NO_ID) { 42897d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung tabHost.findViewById(v.getNextFocusRightId()).requestFocus(); 42997d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 43097d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 43197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 43297d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung wasHandled = true; 43397d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung break; 43497d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung case KeyEvent.KEYCODE_DPAD_UP: 43597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung // Do nothing 43697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung wasHandled = true; 43797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung break; 43897d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung case KeyEvent.KEYCODE_DPAD_DOWN: 43997d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (handleKeyEvent) { 44097d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung // Select the content view 44197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung contents.requestFocus(); 44297d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 44397d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung wasHandled = true; 44497d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung break; 44597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung default: break; 44697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 44797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung return wasHandled; 44897d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 44997d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung 45097d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung /** 4513d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung * Handles key events in the workspace hotseat (bottom of the screen). 4524e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung */ 4533d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung static boolean handleHotseatButtonKeyEvent(View v, int keyCode, KeyEvent e, int orientation) { 454b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal ShortcutAndWidgetContainer parent = (ShortcutAndWidgetContainer) v.getParent(); 455b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal final CellLayout layout = (CellLayout) parent.getParent(); 4564e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung 4574e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung // NOTE: currently we don't special case for the phone UI in different 458b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal // orientations, even though the hotseat is on the side in landscape mode. This 4594e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung // is to ensure that accessibility consistency is maintained across rotations. 4604e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung final int action = e.getAction(); 4614e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP); 4624e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung boolean wasHandled = false; 4634e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung switch (keyCode) { 4644e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung case KeyEvent.KEYCODE_DPAD_LEFT: 4654e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung if (handleKeyEvent) { 466b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal ArrayList<View> views = getCellLayoutChildrenSortedSpatially(layout, parent); 467b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal int myIndex = views.indexOf(v); 468b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal // Select the previous button, otherwise do nothing 469b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal if (myIndex > 0) { 470b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal views.get(myIndex - 1).requestFocus(); 471b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal v.playSoundEffect(SoundEffectConstants.NAVIGATION_LEFT); 4724e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung } 4734e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung } 4744e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung wasHandled = true; 4754e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung break; 4764e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung case KeyEvent.KEYCODE_DPAD_RIGHT: 4774e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung if (handleKeyEvent) { 478b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal ArrayList<View> views = getCellLayoutChildrenSortedSpatially(layout, parent); 479b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal int myIndex = views.indexOf(v); 480b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal // Select the next button, otherwise do nothing 481b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal if (myIndex < views.size() - 1) { 482b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal views.get(myIndex + 1).requestFocus(); 483b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal v.playSoundEffect(SoundEffectConstants.NAVIGATION_RIGHT); 4844e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung } 4854e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung } 4864e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung wasHandled = true; 4874e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung break; 4884e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung case KeyEvent.KEYCODE_DPAD_UP: 4894e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung if (handleKeyEvent) { 490b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal final Workspace workspace = (Workspace) 491b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal v.getRootView().findViewById(R.id.workspace); 492b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal if (workspace != null) { 493b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal int pageIndex = workspace.getCurrentPage(); 494b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal CellLayout topLayout = (CellLayout) workspace.getChildAt(pageIndex); 495b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal ShortcutAndWidgetContainer children = topLayout.getShortcutsAndWidgets(); 496b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal final View newIcon = getIconInDirection(layout, children, -1, 1); 497b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal // Select the first bubble text view in the current page of the workspace 498b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal if (newIcon != null) { 499b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal newIcon.requestFocus(); 500b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal v.playSoundEffect(SoundEffectConstants.NAVIGATION_UP); 501b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal } else { 502b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal workspace.requestFocus(); 503b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal } 5044e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung } 5054e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung } 5064e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung wasHandled = true; 5074e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung break; 5084e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung case KeyEvent.KEYCODE_DPAD_DOWN: 5094e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung // Do nothing 5104e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung wasHandled = true; 5114e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung break; 5124e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung default: break; 5134e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung } 5144e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung return wasHandled; 5154e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung } 5164e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung 5174e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung /** 51897d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung * Private helper method to get the CellLayoutChildren given a CellLayout index. 51997d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung */ 520a52570f8f9ad65b85e33a2f2e87722f9edd6c6f4Michael Jurka private static ShortcutAndWidgetContainer getCellLayoutChildrenForIndex( 521a52570f8f9ad65b85e33a2f2e87722f9edd6c6f4Michael Jurka ViewGroup container, int i) { 522b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal CellLayout parent = (CellLayout) container.getChildAt(i); 523b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal return parent.getShortcutsAndWidgets(); 52497d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 52597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung 52697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung /** 52797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung * Private helper method to sort all the CellLayout children in order of their (x,y) spatially 52897d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung * from top left to bottom right. 52997d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung */ 53097d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung private static ArrayList<View> getCellLayoutChildrenSortedSpatially(CellLayout layout, 53197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung ViewGroup parent) { 53297d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung // First we order each the CellLayout children by their x,y coordinates 53397d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung final int cellCountX = layout.getCountX(); 53497d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung final int count = parent.getChildCount(); 53597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung ArrayList<View> views = new ArrayList<View>(); 53697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung for (int j = 0; j < count; ++j) { 53797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung views.add(parent.getChildAt(j)); 53897d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 53997d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung Collections.sort(views, new Comparator<View>() { 54097d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung @Override 54197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung public int compare(View lhs, View rhs) { 54297d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung CellLayout.LayoutParams llp = (CellLayout.LayoutParams) lhs.getLayoutParams(); 54397d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung CellLayout.LayoutParams rlp = (CellLayout.LayoutParams) rhs.getLayoutParams(); 54497d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung int lvIndex = (llp.cellY * cellCountX) + llp.cellX; 54597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung int rvIndex = (rlp.cellY * cellCountX) + rlp.cellX; 54697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung return lvIndex - rvIndex; 54797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 54897d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung }); 54997d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung return views; 55097d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 55197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung /** 552ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen * Private helper method to find the index of the next BubbleTextView or FolderIcon in the 553ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen * direction delta. 554ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen * 55597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung * @param delta either -1 or 1 depending on the direction we want to search 55697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung */ 557ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen private static View findIndexOfIcon(ArrayList<View> views, int i, int delta) { 55897d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung // Then we find the next BubbleTextView offset by delta from i 55997d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung final int count = views.size(); 56097d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung int newI = i + delta; 56197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung while (0 <= newI && newI < count) { 56297d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung View newV = views.get(newI); 563ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen if (newV instanceof BubbleTextView || newV instanceof FolderIcon) { 56497d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung return newV; 56597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 56697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung newI += delta; 56797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 56897d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung return null; 56997d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 570ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen private static View getIconInDirection(CellLayout layout, ViewGroup parent, int i, 57197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung int delta) { 57297d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung final ArrayList<View> views = getCellLayoutChildrenSortedSpatially(layout, parent); 573ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen return findIndexOfIcon(views, i, delta); 57497d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 575ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen private static View getIconInDirection(CellLayout layout, ViewGroup parent, View v, 57697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung int delta) { 57797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung final ArrayList<View> views = getCellLayoutChildrenSortedSpatially(layout, parent); 578ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen return findIndexOfIcon(views, views.indexOf(v), delta); 57997d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 58097d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung /** 581ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen * Private helper method to find the next closest BubbleTextView or FolderIcon in the direction 582ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen * delta on the next line. 583ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen * 58497d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung * @param delta either -1 or 1 depending on the line and direction we want to search 58597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung */ 586ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen private static View getClosestIconOnLine(CellLayout layout, ViewGroup parent, View v, 58797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung int lineDelta) { 58897d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung final ArrayList<View> views = getCellLayoutChildrenSortedSpatially(layout, parent); 58997d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung final CellLayout.LayoutParams lp = (CellLayout.LayoutParams) v.getLayoutParams(); 59097d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung final int cellCountY = layout.getCountY(); 59197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung final int row = lp.cellY; 59297d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung final int newRow = row + lineDelta; 59397d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (0 <= newRow && newRow < cellCountY) { 59497d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung float closestDistance = Float.MAX_VALUE; 59597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung int closestIndex = -1; 59697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung int index = views.indexOf(v); 59797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung int endIndex = (lineDelta < 0) ? -1 : views.size(); 59897d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung while (index != endIndex) { 59997d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung View newV = views.get(index); 60097d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung CellLayout.LayoutParams tmpLp = (CellLayout.LayoutParams) newV.getLayoutParams(); 60197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung boolean satisfiesRow = (lineDelta < 0) ? (tmpLp.cellY < row) : (tmpLp.cellY > row); 602ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen if (satisfiesRow && 603ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen (newV instanceof BubbleTextView || newV instanceof FolderIcon)) { 60497d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung float tmpDistance = (float) Math.sqrt(Math.pow(tmpLp.cellX - lp.cellX, 2) + 60597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung Math.pow(tmpLp.cellY - lp.cellY, 2)); 60697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (tmpDistance < closestDistance) { 60797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung closestIndex = index; 60897d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung closestDistance = tmpDistance; 60997d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 61097d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 61197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (index <= endIndex) { 61297d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung ++index; 61397d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } else { 61497d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung --index; 61597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 61697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 61797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (closestIndex > -1) { 61897d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung return views.get(closestIndex); 61997d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 62097d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 62197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung return null; 62297d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 62397d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung 62497d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung /** 625ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen * Handles key events in a Workspace containing. 62697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung */ 627ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen static boolean handleIconKeyEvent(View v, int keyCode, KeyEvent e) { 628a52570f8f9ad65b85e33a2f2e87722f9edd6c6f4Michael Jurka ShortcutAndWidgetContainer parent = (ShortcutAndWidgetContainer) v.getParent(); 62997d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung final CellLayout layout = (CellLayout) parent.getParent(); 63097d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung final Workspace workspace = (Workspace) layout.getParent(); 63197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung final ViewGroup launcher = (ViewGroup) workspace.getParent(); 63224ce0b3708b44e738d6ee52477aa4dd917b547e7Adam Cohen final ViewGroup tabs = (ViewGroup) launcher.findViewById(R.id.search_drop_target_bar); 6334d279d94ade1c0d455404312b3c9cfde0078c547Winson Chung final ViewGroup hotseat = (ViewGroup) launcher.findViewById(R.id.hotseat); 63497d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung int pageIndex = workspace.indexOfChild(layout); 63597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung int pageCount = workspace.getChildCount(); 63697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung 63797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung final int action = e.getAction(); 63897d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP); 63997d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung boolean wasHandled = false; 64097d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung switch (keyCode) { 64197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung case KeyEvent.KEYCODE_DPAD_LEFT: 64297d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (handleKeyEvent) { 64397d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung // Select the previous icon or the last icon on the previous page if possible 644ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen View newIcon = getIconInDirection(layout, parent, v, -1); 64597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (newIcon != null) { 64697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung newIcon.requestFocus(); 647b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal v.playSoundEffect(SoundEffectConstants.NAVIGATION_LEFT); 64897d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } else { 64997d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (pageIndex > 0) { 65097d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung parent = getCellLayoutChildrenForIndex(workspace, pageIndex - 1); 651ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen newIcon = getIconInDirection(layout, parent, 65297d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung parent.getChildCount(), -1); 65397d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (newIcon != null) { 65497d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung newIcon.requestFocus(); 65597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } else { 65697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung // Snap to the previous page 65797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung workspace.snapToPage(pageIndex - 1); 65897d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 659b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal v.playSoundEffect(SoundEffectConstants.NAVIGATION_LEFT); 66097d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 66197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 66297d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 66397d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung wasHandled = true; 66497d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung break; 66597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung case KeyEvent.KEYCODE_DPAD_RIGHT: 66697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (handleKeyEvent) { 66797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung // Select the next icon or the first icon on the next page if possible 668ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen View newIcon = getIconInDirection(layout, parent, v, 1); 66997d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (newIcon != null) { 67097d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung newIcon.requestFocus(); 671b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal v.playSoundEffect(SoundEffectConstants.NAVIGATION_RIGHT); 67297d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } else { 67397d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (pageIndex < (pageCount - 1)) { 67497d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung parent = getCellLayoutChildrenForIndex(workspace, pageIndex + 1); 675ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen newIcon = getIconInDirection(layout, parent, -1, 1); 67697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (newIcon != null) { 67797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung newIcon.requestFocus(); 67897d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } else { 67997d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung // Snap to the next page 68097d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung workspace.snapToPage(pageIndex + 1); 68197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 682b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal v.playSoundEffect(SoundEffectConstants.NAVIGATION_RIGHT); 68397d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 68497d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 68597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 68697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung wasHandled = true; 68797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung break; 68897d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung case KeyEvent.KEYCODE_DPAD_UP: 68997d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (handleKeyEvent) { 69097d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung // Select the closest icon in the previous line, otherwise select the tab bar 691ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen View newIcon = getClosestIconOnLine(layout, parent, v, -1); 69297d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (newIcon != null) { 69397d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung newIcon.requestFocus(); 69497d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung wasHandled = true; 69597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } else { 69697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung tabs.requestFocus(); 69797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 698b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal v.playSoundEffect(SoundEffectConstants.NAVIGATION_UP); 69997d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 70097d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung break; 70197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung case KeyEvent.KEYCODE_DPAD_DOWN: 70297d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (handleKeyEvent) { 7034d279d94ade1c0d455404312b3c9cfde0078c547Winson Chung // Select the closest icon in the next line, otherwise select the button bar 704ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen View newIcon = getClosestIconOnLine(layout, parent, v, 1); 70597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (newIcon != null) { 70697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung newIcon.requestFocus(); 707b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal v.playSoundEffect(SoundEffectConstants.NAVIGATION_DOWN); 70897d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung wasHandled = true; 7094d279d94ade1c0d455404312b3c9cfde0078c547Winson Chung } else if (hotseat != null) { 7104d279d94ade1c0d455404312b3c9cfde0078c547Winson Chung hotseat.requestFocus(); 711b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal v.playSoundEffect(SoundEffectConstants.NAVIGATION_DOWN); 71297d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 71397d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 71497d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung break; 71597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung case KeyEvent.KEYCODE_PAGE_UP: 71697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (handleKeyEvent) { 71797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung // Select the first icon on the previous page or the first icon on this page 71897d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung // if there is no previous page 71997d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (pageIndex > 0) { 72097d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung parent = getCellLayoutChildrenForIndex(workspace, pageIndex - 1); 721ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen View newIcon = getIconInDirection(layout, parent, -1, 1); 72297d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (newIcon != null) { 72397d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung newIcon.requestFocus(); 72497d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } else { 72597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung // Snap to the previous page 72697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung workspace.snapToPage(pageIndex - 1); 72797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 728b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal v.playSoundEffect(SoundEffectConstants.NAVIGATION_UP); 72997d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } else { 730ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen View newIcon = getIconInDirection(layout, parent, -1, 1); 73197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (newIcon != null) { 73297d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung newIcon.requestFocus(); 733b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal v.playSoundEffect(SoundEffectConstants.NAVIGATION_UP); 73497d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 73597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 73697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 73797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung wasHandled = true; 73897d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung break; 73997d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung case KeyEvent.KEYCODE_PAGE_DOWN: 74097d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (handleKeyEvent) { 74197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung // Select the first icon on the next page or the last icon on this page 74297d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung // if there is no previous page 74397d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (pageIndex < (pageCount - 1)) { 74497d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung parent = getCellLayoutChildrenForIndex(workspace, pageIndex + 1); 745ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen View newIcon = getIconInDirection(layout, parent, -1, 1); 74697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (newIcon != null) { 74797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung newIcon.requestFocus(); 74897d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } else { 74997d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung // Snap to the next page 75097d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung workspace.snapToPage(pageIndex + 1); 75197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 752b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal v.playSoundEffect(SoundEffectConstants.NAVIGATION_DOWN); 75397d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } else { 754ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen View newIcon = getIconInDirection(layout, parent, 75597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung parent.getChildCount(), -1); 75697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (newIcon != null) { 75797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung newIcon.requestFocus(); 758b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal v.playSoundEffect(SoundEffectConstants.NAVIGATION_DOWN); 75997d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 76097d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 76197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 76297d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung wasHandled = true; 76397d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung break; 76497d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung case KeyEvent.KEYCODE_MOVE_HOME: 76597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (handleKeyEvent) { 76697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung // Select the first icon on this page 767ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen View newIcon = getIconInDirection(layout, parent, -1, 1); 768ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen if (newIcon != null) { 769ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen newIcon.requestFocus(); 770b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal v.playSoundEffect(SoundEffectConstants.NAVIGATION_UP); 771ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen } 772ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen } 773ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen wasHandled = true; 774ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen break; 775ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen case KeyEvent.KEYCODE_MOVE_END: 776ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen if (handleKeyEvent) { 777ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen // Select the last icon on this page 778ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen View newIcon = getIconInDirection(layout, parent, 779ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen parent.getChildCount(), -1); 780ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen if (newIcon != null) { 781ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen newIcon.requestFocus(); 782b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal v.playSoundEffect(SoundEffectConstants.NAVIGATION_DOWN); 783ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen } 784ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen } 785ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen wasHandled = true; 786ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen break; 787ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen default: break; 788ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen } 789ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen return wasHandled; 790ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen } 791ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen 792ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen /** 793ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen * Handles key events for items in a Folder. 794ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen */ 795ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen static boolean handleFolderKeyEvent(View v, int keyCode, KeyEvent e) { 796a52570f8f9ad65b85e33a2f2e87722f9edd6c6f4Michael Jurka ShortcutAndWidgetContainer parent = (ShortcutAndWidgetContainer) v.getParent(); 797ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen final CellLayout layout = (CellLayout) parent.getParent(); 798a1f133de788823603a2c62aba5dc5d84c5a39cc6Winson Chung final ScrollView scrollView = (ScrollView) layout.getParent(); 799a1f133de788823603a2c62aba5dc5d84c5a39cc6Winson Chung final Folder folder = (Folder) scrollView.getParent(); 800ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen View title = folder.mFolderName; 801ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen 802ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen final int action = e.getAction(); 803ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP); 804ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen boolean wasHandled = false; 805ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen switch (keyCode) { 806ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen case KeyEvent.KEYCODE_DPAD_LEFT: 807ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen if (handleKeyEvent) { 808ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen // Select the previous icon 809ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen View newIcon = getIconInDirection(layout, parent, v, -1); 810ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen if (newIcon != null) { 811ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen newIcon.requestFocus(); 812b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal v.playSoundEffect(SoundEffectConstants.NAVIGATION_LEFT); 813ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen } 814ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen } 815ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen wasHandled = true; 816ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen break; 817ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen case KeyEvent.KEYCODE_DPAD_RIGHT: 818ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen if (handleKeyEvent) { 819ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen // Select the next icon 820ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen View newIcon = getIconInDirection(layout, parent, v, 1); 821ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen if (newIcon != null) { 822ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen newIcon.requestFocus(); 823ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen } else { 824ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen title.requestFocus(); 825ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen } 826b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal v.playSoundEffect(SoundEffectConstants.NAVIGATION_RIGHT); 827ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen } 828ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen wasHandled = true; 829ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen break; 830ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen case KeyEvent.KEYCODE_DPAD_UP: 831ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen if (handleKeyEvent) { 832ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen // Select the closest icon in the previous line 833ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen View newIcon = getClosestIconOnLine(layout, parent, v, -1); 834ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen if (newIcon != null) { 835ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen newIcon.requestFocus(); 836b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal v.playSoundEffect(SoundEffectConstants.NAVIGATION_UP); 837ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen } 838ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen } 839ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen wasHandled = true; 840ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen break; 841ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen case KeyEvent.KEYCODE_DPAD_DOWN: 842ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen if (handleKeyEvent) { 843ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen // Select the closest icon in the next line 844ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen View newIcon = getClosestIconOnLine(layout, parent, v, 1); 845ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen if (newIcon != null) { 846ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen newIcon.requestFocus(); 847ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen } else { 848ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen title.requestFocus(); 849ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen } 850b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal v.playSoundEffect(SoundEffectConstants.NAVIGATION_DOWN); 851ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen } 852ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen wasHandled = true; 853ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen break; 854ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen case KeyEvent.KEYCODE_MOVE_HOME: 855ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen if (handleKeyEvent) { 856ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen // Select the first icon on this page 857ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen View newIcon = getIconInDirection(layout, parent, -1, 1); 85897d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (newIcon != null) { 85997d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung newIcon.requestFocus(); 860b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal v.playSoundEffect(SoundEffectConstants.NAVIGATION_UP); 86197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 86297d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 86397d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung wasHandled = true; 86497d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung break; 86597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung case KeyEvent.KEYCODE_MOVE_END: 86697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (handleKeyEvent) { 86797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung // Select the last icon on this page 868ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen View newIcon = getIconInDirection(layout, parent, 86997d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung parent.getChildCount(), -1); 87097d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung if (newIcon != null) { 87197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung newIcon.requestFocus(); 872b3726d90a567e992e4d0f43e7c7acdd8739ae805Sunny Goyal v.playSoundEffect(SoundEffectConstants.NAVIGATION_DOWN); 87397d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 87497d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 87597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung wasHandled = true; 87697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung break; 87797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung default: break; 87897d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 87997d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung return wasHandled; 88097d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung } 88197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung} 882