Fixing focus issues in Launcher (keyboard support).
Change-Id: Ieafd713393daf5628f229a66441bd3ed293245da
This commit is contained in:
parent
721a06bb65
commit
97d85d23b0
Binary file not shown.
After Width: | Height: | Size: 2.8 KiB |
|
@ -15,6 +15,7 @@
|
|||
-->
|
||||
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_focused="true" android:drawable="@drawable/focused_bg" />
|
||||
<item android:state_pressed="true" android:drawable="@drawable/home_press" />
|
||||
<item android:drawable="@android:color/transparent" />
|
||||
</selector>
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2010 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_focused="true" android:drawable="@drawable/focused_bg" />
|
||||
</selector>
|
|
@ -15,4 +15,6 @@
|
|||
-->
|
||||
|
||||
<com.android.launcher2.BubbleTextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
style="@style/WorkspaceIcon.Landscape" />
|
||||
style="@style/WorkspaceIcon.Landscape"
|
||||
android:focusable="true"
|
||||
android:background="@drawable/focusable_view_bg" />
|
||||
|
|
|
@ -32,4 +32,5 @@
|
|||
android:drawablePadding="0dip"
|
||||
|
||||
android:maxLines="2"
|
||||
android:fadingEdge="horizontal" />
|
||||
android:fadingEdge="horizontal"
|
||||
android:focusable="false" />
|
||||
|
|
|
@ -21,9 +21,12 @@
|
|||
launcher:blurColor="#FF6B8CF0"
|
||||
launcher:outlineColor="#FF8CD2FF"
|
||||
|
||||
style="@style/WorkspaceIcon.AllApps"
|
||||
|
||||
android:id="@+id/application_icon"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_horizontal"
|
||||
|
||||
style="@style/WorkspaceIcon.AllApps" />
|
||||
android:focusable="true"
|
||||
android:background="@drawable/focusable_view_bg" />
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:background="@drawable/tab_unselected_holo">
|
||||
<TabWidget
|
||||
<com.android.launcher2.FocusOnlyTabWidget
|
||||
android:id="@android:id/tabs"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -50,7 +50,9 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:visibility="invisible"/>
|
||||
android:visibility="invisible"
|
||||
android:background="@drawable/focusable_view_bg"
|
||||
android:focusable="true" />
|
||||
<TextView
|
||||
android:id="@+id/market_button"
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -64,7 +66,9 @@
|
|||
android:shadowColor="@color/workspace_all_apps_and_delete_zone_text_shadow_color"
|
||||
android:shadowDx="0.0"
|
||||
android:shadowDy="0.0"
|
||||
android:shadowRadius="2.0" />
|
||||
android:shadowRadius="2.0"
|
||||
android:background="@drawable/focusable_view_bg"
|
||||
android:focusable="true" />
|
||||
</FrameLayout>
|
||||
<com.android.launcher2.DeleteZone
|
||||
android:id="@+id/all_apps_delete_zone"
|
||||
|
@ -84,7 +88,10 @@
|
|||
android:shadowColor="@color/workspace_all_apps_and_delete_zone_text_shadow_color"
|
||||
android:shadowDx="0.0"
|
||||
android:shadowDy="0.0"
|
||||
android:shadowRadius="2.0" />
|
||||
android:shadowRadius="2.0"
|
||||
|
||||
android:background="@drawable/focusable_view_bg"
|
||||
android:focusable="true" />
|
||||
</RelativeLayout>
|
||||
<FrameLayout
|
||||
android:id="@android:id/tabcontent"
|
||||
|
|
|
@ -15,31 +15,33 @@
|
|||
-->
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher">
|
||||
xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
|
||||
android:focusable="false">
|
||||
|
||||
<!-- Global search icon -->
|
||||
<ImageView
|
||||
android:id="@+id/search_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:paddingLeft="@dimen/toolbar_button_horizontal_padding"
|
||||
android:paddingRight="@dimen/toolbar_button_horizontal_padding"
|
||||
android:paddingTop="@dimen/toolbar_button_vertical_padding"
|
||||
android:paddingBottom="@dimen/toolbar_button_vertical_padding"
|
||||
android:src="@drawable/ic_generic_search"
|
||||
android:background="@drawable/button_bg"
|
||||
android:onClick="onClickSearchButton"
|
||||
android:focusable="true"
|
||||
android:clickable="true" />
|
||||
android:id="@+id/search_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:paddingLeft="@dimen/toolbar_button_horizontal_padding"
|
||||
android:paddingRight="@dimen/toolbar_button_horizontal_padding"
|
||||
android:paddingTop="@dimen/toolbar_button_vertical_padding"
|
||||
android:paddingBottom="@dimen/toolbar_button_vertical_padding"
|
||||
android:src="@drawable/ic_generic_search"
|
||||
android:background="@drawable/button_bg"
|
||||
android:onClick="onClickSearchButton"
|
||||
|
||||
android:focusable="true"
|
||||
android:clickable="true" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/search_divider"
|
||||
android:src="@drawable/divider_launcher_holo"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_toRightOf="@id/search_button"
|
||||
android:layout_toRightOf="@+id/search_button"
|
||||
android:paddingTop="@dimen/toolbar_button_vertical_padding"
|
||||
android:paddingBottom="@dimen/toolbar_button_vertical_padding"
|
||||
|
||||
|
@ -52,7 +54,7 @@
|
|||
android:id="@+id/voice_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toRightOf="@id/search_divider"
|
||||
android:layout_toRightOf="@+id/search_divider"
|
||||
android:paddingLeft="@dimen/toolbar_button_horizontal_padding"
|
||||
android:paddingRight="@dimen/toolbar_button_horizontal_padding"
|
||||
android:paddingTop="@dimen/toolbar_button_vertical_padding"
|
||||
|
@ -60,35 +62,11 @@
|
|||
android:src="@drawable/ic_voice_search"
|
||||
android:background="@drawable/button_bg"
|
||||
android:onClick="onClickVoiceButton"
|
||||
|
||||
android:focusable="true"
|
||||
android:clickable="true"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/configure_button"
|
||||
android:src="@drawable/ic_home_add_holo_dark"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:paddingLeft="@dimen/toolbar_button_horizontal_padding"
|
||||
android:paddingRight="@dimen/toolbar_button_horizontal_padding"
|
||||
android:paddingTop="@dimen/toolbar_button_vertical_padding"
|
||||
android:paddingBottom="@dimen/toolbar_button_vertical_padding"
|
||||
android:background="@drawable/button_bg"
|
||||
|
||||
android:focusable="true"
|
||||
android:clickable="true" />
|
||||
<ImageView
|
||||
android:id="@+id/divider"
|
||||
android:src="@drawable/divider_launcher_holo"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_toLeftOf="@id/configure_button"
|
||||
android:paddingTop="@dimen/toolbar_button_vertical_padding"
|
||||
android:paddingBottom="@dimen/toolbar_button_vertical_padding"
|
||||
|
||||
android:focusable="false"
|
||||
android:clickable="true" />
|
||||
<!-- AllApps icon -->
|
||||
<com.android.launcher2.StrokedTextView
|
||||
android:id="@+id/all_apps_button"
|
||||
android:text="@string/all_apps_button_label"
|
||||
|
@ -96,12 +74,12 @@
|
|||
android:drawableLeft="@drawable/ic_home_all_apps_holo_dark"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toLeftOf="@id/divider"
|
||||
android:layout_toLeftOf="@+id/all_apps_divider"
|
||||
android:paddingLeft="@dimen/toolbar_button_horizontal_padding"
|
||||
android:paddingRight="@dimen/toolbar_button_horizontal_padding"
|
||||
android:paddingTop="@dimen/all_apps_button_vertical_padding"
|
||||
android:paddingBottom="@dimen/all_apps_button_vertical_padding"
|
||||
android:background="@drawable/button_bg"
|
||||
android:background="@drawable/button_bg"
|
||||
|
||||
android:gravity="center_horizontal|center_vertical"
|
||||
android:textColor="#CCFFFFFF"
|
||||
|
@ -118,15 +96,36 @@
|
|||
|
||||
android:focusable="true"
|
||||
android:clickable="true" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/divider_during_drag"
|
||||
android:id="@+id/all_apps_divider"
|
||||
android:src="@drawable/divider_launcher_holo"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_toLeftOf="@id/configure_button"
|
||||
android:layout_toLeftOf="@+id/configure_button"
|
||||
android:paddingTop="@dimen/toolbar_button_vertical_padding"
|
||||
android:paddingBottom="@dimen/toolbar_button_vertical_padding"
|
||||
android:visibility="gone" />
|
||||
|
||||
android:focusable="false"
|
||||
android:clickable="true" />
|
||||
|
||||
<!-- Customize icon -->
|
||||
<ImageView
|
||||
android:id="@+id/configure_button"
|
||||
android:src="@drawable/ic_home_add_holo_dark"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:paddingLeft="@dimen/toolbar_button_horizontal_padding"
|
||||
android:paddingRight="@dimen/toolbar_button_horizontal_padding"
|
||||
android:paddingTop="@dimen/toolbar_button_vertical_padding"
|
||||
android:paddingBottom="@dimen/toolbar_button_vertical_padding"
|
||||
android:background="@drawable/button_bg"
|
||||
android:focusable="true"
|
||||
/>
|
||||
|
||||
<!-- Delete icon -->
|
||||
<com.android.launcher2.DeleteZone
|
||||
android:id="@+id/delete_zone"
|
||||
android:text="@string/delete_zone_label_workspace"
|
||||
|
@ -134,12 +133,12 @@
|
|||
android:drawableLeft="@drawable/delete_zone_selector"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignRight="@id/configure_button"
|
||||
android:layout_alignRight="@+id/configure_button"
|
||||
android:paddingLeft="@dimen/toolbar_button_horizontal_padding"
|
||||
android:paddingRight="@dimen/toolbar_button_horizontal_padding"
|
||||
android:paddingTop="@dimen/toolbar_button_vertical_padding"
|
||||
android:paddingBottom="@dimen/toolbar_button_vertical_padding"
|
||||
android:background="@drawable/button_bg"
|
||||
android:background="@drawable/button_bg"
|
||||
|
||||
android:gravity="center_horizontal|center_vertical"
|
||||
android:textColor="@color/workspace_all_apps_and_delete_zone_text_color"
|
||||
|
@ -150,5 +149,8 @@
|
|||
android:shadowRadius="2.0"
|
||||
|
||||
android:visibility="gone"
|
||||
launcher:direction="horizontal" />
|
||||
</RelativeLayout>
|
||||
launcher:direction="horizontal"
|
||||
|
||||
android:focusable="true"
|
||||
/>
|
||||
</RelativeLayout>
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
android:layout_height="match_parent">
|
||||
<!-- The layout_width of this RelativeLayout gets overwritten in
|
||||
CustomizeTrayTabHost.onFinishInflate -->
|
||||
<TabWidget
|
||||
<com.android.launcher2.FocusOnlyTabWidget
|
||||
android:id="@android:id/tabs"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
|
|
|
@ -25,4 +25,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
|
||||
style="@style/WorkspaceIcon.Landscape" />
|
||||
style="@style/WorkspaceIcon.Landscape"
|
||||
|
||||
android:background="@drawable/focusable_view_bg"
|
||||
android:focusable="true" />
|
||||
|
|
|
@ -25,7 +25,10 @@
|
|||
android:paddingBottom="50dp"
|
||||
|
||||
launcher:blurColor="#FF6B8CF0"
|
||||
launcher:outlineColor="#FF8CD2FF">
|
||||
launcher:outlineColor="#FF8CD2FF"
|
||||
|
||||
android:background="@drawable/focusable_view_bg"
|
||||
android:focusable="true">
|
||||
|
||||
<!-- The preview image for the wallpaper. -->
|
||||
<ImageView
|
||||
|
|
|
@ -25,7 +25,10 @@
|
|||
android:paddingBottom="50dp"
|
||||
|
||||
launcher:blurColor="#FF6B8CF0"
|
||||
launcher:outlineColor="#FF8CD2FF">
|
||||
launcher:outlineColor="#FF8CD2FF"
|
||||
|
||||
android:background="@drawable/focusable_view_bg"
|
||||
android:focusable="true">
|
||||
|
||||
<!-- The icon of the widget. -->
|
||||
<ImageView
|
||||
|
|
|
@ -20,7 +20,8 @@
|
|||
|
||||
android:id="@+id/drag_layer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="match_parent"
|
||||
android:focusable="false">
|
||||
|
||||
<!-- The workspace contains 5 screens of cells -->
|
||||
<com.android.launcher2.Workspace
|
||||
|
@ -41,6 +42,12 @@
|
|||
<include android:id="@+id/cell5" layout="@layout/workspace_screen" />
|
||||
</com.android.launcher2.Workspace>
|
||||
|
||||
<include layout="@layout/button_bar"
|
||||
android:id="@+id/all_apps_button_cluster"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="?android:attr/actionBarSize"
|
||||
android:layout_gravity="top" />
|
||||
|
||||
<include
|
||||
layout="@layout/all_apps_tabbed"
|
||||
android:id="@+id/all_apps_view"
|
||||
|
@ -48,12 +55,6 @@
|
|||
android:layout_height="match_parent"
|
||||
android:layout_gravity="top" />
|
||||
|
||||
<include layout="@layout/button_bar"
|
||||
android:id="@+id/all_apps_button_cluster"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="?android:attr/actionBarSize"
|
||||
android:layout_gravity="top" />
|
||||
|
||||
<include layout="@layout/customization_drawer"
|
||||
android:id="@+id/customization_drawer"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -14,6 +14,6 @@
|
|||
limitations under the License.
|
||||
-->
|
||||
|
||||
<TextView
|
||||
<com.android.launcher2.AccessibleTabView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
style="@style/TabIndicator" />
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.launcher2;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.KeyEvent;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class AccessibleTabView extends TextView {
|
||||
public AccessibleTabView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public AccessibleTabView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public AccessibleTabView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
return FocusHelper.handleTabKeyEvent(this, keyCode, event)
|
||||
|| super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||
return FocusHelper.handleTabKeyEvent(this, keyCode, event)
|
||||
|| super.onKeyUp(keyCode, event);
|
||||
}
|
||||
}
|
|
@ -29,11 +29,13 @@ import android.util.Log;
|
|||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TabHost;
|
||||
import android.widget.TabWidget;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Implements a tabbed version of AllApps2D.
|
||||
|
@ -80,6 +82,7 @@ public class AllAppsTabbed extends TabHost implements AllAppsView, LauncherTrans
|
|||
};
|
||||
|
||||
// Create the tabs and wire them up properly
|
||||
AllAppsTabKeyEventListener keyListener = new AllAppsTabKeyEventListener();
|
||||
TextView tabView;
|
||||
TabWidget tabWidget = (TabWidget) findViewById(com.android.internal.R.id.tabs);
|
||||
tabView = (TextView) mInflater.inflate(R.layout.tab_widget_indicator, tabWidget, false);
|
||||
|
@ -90,6 +93,12 @@ public class AllAppsTabbed extends TabHost implements AllAppsView, LauncherTrans
|
|||
tabView.setText(mContext.getString(R.string.all_apps_tab_downloaded));
|
||||
addTab(newTabSpec(TAG_DOWNLOADED).setIndicator(tabView).setContent(contentFactory));
|
||||
|
||||
// Setup the key listener to jump between the last tab view and the market icon
|
||||
View lastTab = tabWidget.getChildTabViewAt(tabWidget.getTabCount() - 1);
|
||||
lastTab.setOnKeyListener(keyListener);
|
||||
View shopButton = findViewById(R.id.market_button);
|
||||
shopButton.setOnKeyListener(keyListener);
|
||||
|
||||
setOnTabChangedListener(new OnTabChangeListener() {
|
||||
public void onTabChanged(String tabId) {
|
||||
// animate the changing of the tab content by fading pages in and out
|
||||
|
@ -259,4 +268,12 @@ public class AllAppsTabbed extends TabHost implements AllAppsView, LauncherTrans
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDescendantFocusability() {
|
||||
if (getVisibility() != View.VISIBLE) {
|
||||
return ViewGroup.FOCUS_BLOCK_DESCENDANTS;
|
||||
}
|
||||
return super.getDescendantFocusability();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import android.graphics.Region;
|
|||
import android.graphics.Region.Op;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
@ -87,8 +88,6 @@ public class BubbleTextView extends TextView implements VisibilityChangedBroadca
|
|||
|
||||
private void init() {
|
||||
mBackground = getBackground();
|
||||
setFocusable(true);
|
||||
setBackgroundDrawable(null);
|
||||
|
||||
final Resources res = getContext().getResources();
|
||||
int bubbleColor = res.getColor(R.color.bubble_dark_background);
|
||||
|
@ -330,4 +329,16 @@ public class BubbleTextView extends TextView implements VisibilityChangedBroadca
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
return FocusHelper.handleBubbleTextViewKeyEvent(this, keyCode, event)
|
||||
|| super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||
return FocusHelper.handleBubbleTextViewKeyEvent(this, keyCode, event)
|
||||
|| super.onKeyUp(keyCode, event);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,10 +18,11 @@ package com.android.launcher2;
|
|||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Bitmap.Config;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Bitmap.Config;
|
||||
import android.graphics.PorterDuff.Mode;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.text.Layout;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.TextView;
|
||||
|
@ -163,6 +164,16 @@ public class CachedTextView extends TextView {
|
|||
if (mPrevAlpha != alpha) {
|
||||
mPrevAlpha = alpha;
|
||||
mCachePaint.setAlpha(alpha);
|
||||
|
||||
// We manually update the drawables alpha since the default TextView implementation may
|
||||
// not do this if there is a background set (which we may due to the focus bg)
|
||||
final Drawable[] dr = getCompoundDrawables();
|
||||
for (int i = 0; i < dr.length; ++i) {
|
||||
if (dr[i] != null) {
|
||||
dr[i].mutate().setAlpha(alpha);
|
||||
}
|
||||
}
|
||||
|
||||
super.onSetAlpha(alpha);
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -488,8 +488,6 @@ public class CustomizePagedView extends PagedViewWithDraggableItems
|
|||
|
||||
@Override
|
||||
public void onClick(final View v) {
|
||||
// Return early if this is not initiated from a touch
|
||||
if (!v.isInTouchMode()) return;
|
||||
// Return early if we are still animating the pages
|
||||
if (mNextPage != INVALID_PAGE) return;
|
||||
|
||||
|
|
|
@ -16,8 +16,7 @@
|
|||
|
||||
package com.android.launcher2;
|
||||
|
||||
import com.android.launcher.R;
|
||||
import com.android.launcher2.CustomizePagedView.CustomizationType;
|
||||
import java.util.Random;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
|
@ -28,10 +27,14 @@ import android.content.res.Resources;
|
|||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TabHost;
|
||||
import android.widget.TabWidget;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.launcher.R;
|
||||
import com.android.launcher2.CustomizePagedView.CustomizationType;
|
||||
|
||||
public class CustomizeTrayTabHost extends TabHost implements LauncherTransitionable {
|
||||
// tags for the customization tabs
|
||||
private static final String WIDGETS_TAG = "widgets";
|
||||
|
@ -69,7 +72,8 @@ public class CustomizeTrayTabHost extends TabHost implements LauncherTransitiona
|
|||
|
||||
tabView = (TextView) mInflater.inflate(R.layout.tab_widget_indicator, tabWidget, false);
|
||||
tabView.setText(mContext.getString(R.string.widgets_tab_label));
|
||||
addTab(newTabSpec(WIDGETS_TAG).setIndicator(tabView).setContent(contentFactory));
|
||||
addTab(newTabSpec(WIDGETS_TAG)
|
||||
.setIndicator(tabView).setContent(contentFactory));
|
||||
tabView = (TextView) mInflater.inflate(R.layout.tab_widget_indicator, tabWidget, false);
|
||||
tabView.setText(mContext.getString(R.string.applications_tab_label));
|
||||
addTab(newTabSpec(APPLICATIONS_TAG)
|
||||
|
@ -82,6 +86,7 @@ public class CustomizeTrayTabHost extends TabHost implements LauncherTransitiona
|
|||
tabView.setText(mContext.getString(R.string.shortcuts_tab_label));
|
||||
addTab(newTabSpec(SHORTCUTS_TAG)
|
||||
.setIndicator(tabView).setContent(contentFactory));
|
||||
|
||||
setOnTabChangedListener(new OnTabChangeListener() {
|
||||
public void onTabChanged(String tabId) {
|
||||
final CustomizePagedView.CustomizationType newType =
|
||||
|
@ -149,6 +154,14 @@ public class CustomizeTrayTabHost extends TabHost implements LauncherTransitiona
|
|||
super.onLayout(changed, l, t, r, b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDescendantFocusability() {
|
||||
if (getVisibility() != View.VISIBLE) {
|
||||
return ViewGroup.FOCUS_BLOCK_DESCENDANTS;
|
||||
}
|
||||
return super.getDescendantFocusability();
|
||||
}
|
||||
|
||||
CustomizationType getCustomizeFilterForTabTag(String tag) {
|
||||
if (tag.equals(WIDGETS_TAG)) {
|
||||
return CustomizationType.WidgetCustomization;
|
||||
|
|
|
@ -0,0 +1,772 @@
|
|||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.launcher2;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewParent;
|
||||
import android.widget.TabHost;
|
||||
import android.widget.TabWidget;
|
||||
|
||||
import com.android.launcher.R;
|
||||
|
||||
/**
|
||||
* A keyboard listener we set on all the button bar buttons.
|
||||
*/
|
||||
class ButtonBarKeyEventListener implements View.OnKeyListener {
|
||||
@Override
|
||||
public boolean onKey(View v, int keyCode, KeyEvent event) {
|
||||
return FocusHelper.handleButtonBarButtonKeyEvent(v, keyCode, event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A keyboard listener we set on the last tab button in AllApps to jump to then
|
||||
* market icon and vice versa.
|
||||
*/
|
||||
class AllAppsTabKeyEventListener implements View.OnKeyListener {
|
||||
@Override
|
||||
public boolean onKey(View v, int keyCode, KeyEvent event) {
|
||||
return FocusHelper.handleAllAppsTabKeyEvent(v, keyCode, event);
|
||||
}
|
||||
}
|
||||
|
||||
public class FocusHelper {
|
||||
/**
|
||||
* Private helper to get the parent TabHost in the view hiearchy.
|
||||
*/
|
||||
private static TabHost findTabHostParent(View v) {
|
||||
ViewParent p = v.getParent();
|
||||
while (p != null && !(p instanceof TabHost)) {
|
||||
p = p.getParent();
|
||||
}
|
||||
return (TabHost) p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles key events in a AllApps tab between the last tab view and the shop button.
|
||||
*/
|
||||
static boolean handleAllAppsTabKeyEvent(View v, int keyCode, KeyEvent e) {
|
||||
final TabHost tabHost = findTabHostParent(v);
|
||||
final ViewGroup contents = (ViewGroup)
|
||||
tabHost.findViewById(com.android.internal.R.id.tabcontent);
|
||||
final View shop = tabHost.findViewById(R.id.market_button);
|
||||
|
||||
final int action = e.getAction();
|
||||
final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
|
||||
boolean wasHandled = false;
|
||||
switch (keyCode) {
|
||||
case KeyEvent.KEYCODE_DPAD_RIGHT:
|
||||
if (handleKeyEvent) {
|
||||
// Select the shop button if we aren't on it
|
||||
if (v != shop) {
|
||||
shop.requestFocus();
|
||||
}
|
||||
}
|
||||
wasHandled = true;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_DPAD_DOWN:
|
||||
if (handleKeyEvent) {
|
||||
// Select the content view (down is handled by the tab key handler otherwise)
|
||||
if (v == shop) {
|
||||
contents.requestFocus();
|
||||
wasHandled = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
return wasHandled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Private helper to determine whether a view is visible.
|
||||
*/
|
||||
private static boolean isVisible(View v) {
|
||||
return v.getVisibility() == View.VISIBLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles key events in a PageViewExtendedLayout containing PagedViewWidgets.
|
||||
*/
|
||||
static boolean handlePagedViewWidgetKeyEvent(PagedViewWidget w, int keyCode, KeyEvent e) {
|
||||
if (!LauncherApplication.isScreenXLarge()) return false;
|
||||
|
||||
final PagedViewExtendedLayout parent = (PagedViewExtendedLayout) w.getParent();
|
||||
final ViewGroup container = (ViewGroup) 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 pageCount = container.getChildCount();
|
||||
|
||||
final int action = e.getAction();
|
||||
final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
|
||||
PagedViewExtendedLayout newParent = null;
|
||||
boolean wasHandled = false;
|
||||
switch (keyCode) {
|
||||
case KeyEvent.KEYCODE_DPAD_LEFT:
|
||||
if (handleKeyEvent) {
|
||||
// Select the previous widget or the last widget on the previous page
|
||||
if (widgetIndex > 0) {
|
||||
parent.getChildAt(widgetIndex - 1).requestFocus();
|
||||
} else {
|
||||
if (pageIndex > 0) {
|
||||
newParent = (PagedViewExtendedLayout)
|
||||
container.getChildAt(pageIndex - 1);
|
||||
newParent.getChildAt(newParent.getChildCount() - 1).requestFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
wasHandled = true;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_DPAD_RIGHT:
|
||||
if (handleKeyEvent) {
|
||||
// Select the next widget or the first widget on the next page
|
||||
if (widgetIndex < (widgetCount - 1)) {
|
||||
parent.getChildAt(widgetIndex + 1).requestFocus();
|
||||
} else {
|
||||
if (pageIndex < (pageCount - 1)) {
|
||||
newParent = (PagedViewExtendedLayout)
|
||||
container.getChildAt(pageIndex + 1);
|
||||
newParent.getChildAt(0).requestFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
wasHandled = true;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_DPAD_UP:
|
||||
if (handleKeyEvent) {
|
||||
// Select widgets tab on the tab bar
|
||||
tabs.requestFocus();
|
||||
}
|
||||
wasHandled = true;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_DPAD_DOWN:
|
||||
if (handleKeyEvent) {
|
||||
// TODO: Should focus the global search bar
|
||||
}
|
||||
wasHandled = true;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_ENTER:
|
||||
case KeyEvent.KEYCODE_DPAD_CENTER:
|
||||
if (handleKeyEvent) {
|
||||
// Simulate a click on the widget
|
||||
View.OnClickListener clickListener = (View.OnClickListener) container;
|
||||
clickListener.onClick(w);
|
||||
}
|
||||
wasHandled = true;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_PAGE_UP:
|
||||
if (handleKeyEvent) {
|
||||
// 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 = (PagedViewExtendedLayout) container.getChildAt(pageIndex - 1);
|
||||
newParent.getChildAt(0).requestFocus();
|
||||
} else {
|
||||
parent.getChildAt(0).requestFocus();
|
||||
}
|
||||
}
|
||||
wasHandled = true;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_PAGE_DOWN:
|
||||
if (handleKeyEvent) {
|
||||
// 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 = (PagedViewExtendedLayout) container.getChildAt(pageIndex + 1);
|
||||
newParent.getChildAt(0).requestFocus();
|
||||
} else {
|
||||
parent.getChildAt(widgetCount - 1).requestFocus();
|
||||
}
|
||||
}
|
||||
wasHandled = true;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_MOVE_HOME:
|
||||
if (handleKeyEvent) {
|
||||
// Select the first item on this page
|
||||
parent.getChildAt(0).requestFocus();
|
||||
}
|
||||
wasHandled = true;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_MOVE_END:
|
||||
if (handleKeyEvent) {
|
||||
// Select the last item on this page
|
||||
parent.getChildAt(widgetCount - 1).requestFocus();
|
||||
}
|
||||
wasHandled = true;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
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) {
|
||||
if (!LauncherApplication.isScreenXLarge()) return false;
|
||||
|
||||
final PagedViewCellLayoutChildren parent = (PagedViewCellLayoutChildren) v.getParent();
|
||||
final PagedViewCellLayout parentLayout = (PagedViewCellLayout) parent.getParent();
|
||||
// Note we have an extra parent because of the
|
||||
// PagedViewCellLayout/PagedViewCellLayoutChildren relationship
|
||||
final ViewGroup container = (ViewGroup) parentLayout.getParent();
|
||||
final TabHost tabHost = findTabHostParent(container);
|
||||
final TabWidget tabs = (TabWidget) tabHost.findViewById(com.android.internal.R.id.tabs);
|
||||
final int widgetIndex = parent.indexOfChild(v);
|
||||
final int widgetCount = parent.getChildCount();
|
||||
final int pageIndex = container.indexOfChild(parentLayout);
|
||||
final int pageCount = container.getChildCount();
|
||||
final int cellCountX = parentLayout.getCellCountX();
|
||||
final int cellCountY = parentLayout.getCellCountY();
|
||||
final int x = widgetIndex % cellCountX;
|
||||
final int y = widgetIndex / cellCountX;
|
||||
|
||||
final int action = e.getAction();
|
||||
final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
|
||||
PagedViewCellLayoutChildren newParent = null;
|
||||
boolean wasHandled = false;
|
||||
switch (keyCode) {
|
||||
case KeyEvent.KEYCODE_DPAD_LEFT:
|
||||
if (handleKeyEvent) {
|
||||
// Select the previous icon or the last icon on the previous page
|
||||
if (widgetIndex > 0) {
|
||||
parent.getChildAt(widgetIndex - 1).requestFocus();
|
||||
} else {
|
||||
if (pageIndex > 0) {
|
||||
newParent = getPagedViewCellLayoutChildrenForIndex(container,
|
||||
pageIndex - 1);
|
||||
newParent.getChildAt(newParent.getChildCount() - 1).requestFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
wasHandled = true;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_DPAD_RIGHT:
|
||||
if (handleKeyEvent) {
|
||||
// Select the next icon or the first icon on the next page
|
||||
if (widgetIndex < (widgetCount - 1)) {
|
||||
parent.getChildAt(widgetIndex + 1).requestFocus();
|
||||
} else {
|
||||
if (pageIndex < (pageCount - 1)) {
|
||||
newParent = getPagedViewCellLayoutChildrenForIndex(container,
|
||||
pageIndex + 1);
|
||||
newParent.getChildAt(0).requestFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
wasHandled = true;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_DPAD_UP:
|
||||
if (handleKeyEvent) {
|
||||
// Select the closest icon in the previous row, otherwise select the tab bar
|
||||
if (y > 0) {
|
||||
int newWidgetIndex = ((y - 1) * cellCountX) + x;
|
||||
parent.getChildAt(newWidgetIndex).requestFocus();
|
||||
} else {
|
||||
tabs.requestFocus();
|
||||
}
|
||||
}
|
||||
wasHandled = true;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_DPAD_DOWN:
|
||||
if (handleKeyEvent) {
|
||||
// Select the closest icon in the previous row, otherwise do nothing
|
||||
if (y < (cellCountY - 1)) {
|
||||
int newWidgetIndex = Math.min(widgetCount - 1, ((y + 1) * cellCountX) + x);
|
||||
parent.getChildAt(newWidgetIndex).requestFocus();
|
||||
}
|
||||
}
|
||||
wasHandled = true;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_ENTER:
|
||||
case KeyEvent.KEYCODE_DPAD_CENTER:
|
||||
if (handleKeyEvent) {
|
||||
// Simulate a click on the icon
|
||||
View.OnClickListener clickListener = (View.OnClickListener) container;
|
||||
clickListener.onClick(v);
|
||||
}
|
||||
wasHandled = true;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_PAGE_UP:
|
||||
if (handleKeyEvent) {
|
||||
// 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.getChildAt(0).requestFocus();
|
||||
} else {
|
||||
parent.getChildAt(0).requestFocus();
|
||||
}
|
||||
}
|
||||
wasHandled = true;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_PAGE_DOWN:
|
||||
if (handleKeyEvent) {
|
||||
// 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.getChildAt(0).requestFocus();
|
||||
} else {
|
||||
parent.getChildAt(widgetCount - 1).requestFocus();
|
||||
}
|
||||
}
|
||||
wasHandled = true;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_MOVE_HOME:
|
||||
if (handleKeyEvent) {
|
||||
// Select the first icon on this page
|
||||
parent.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();
|
||||
}
|
||||
wasHandled = true;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
return wasHandled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles key events in the tab widget.
|
||||
*/
|
||||
static boolean handleTabKeyEvent(AccessibleTabView v, int keyCode, KeyEvent e) {
|
||||
if (!LauncherApplication.isScreenXLarge()) return false;
|
||||
|
||||
final FocusOnlyTabWidget parent = (FocusOnlyTabWidget) v.getParent();
|
||||
final TabHost tabHost = findTabHostParent(parent);
|
||||
final ViewGroup contents = (ViewGroup)
|
||||
tabHost.findViewById(com.android.internal.R.id.tabcontent);
|
||||
final int tabCount = parent.getTabCount();
|
||||
final int tabIndex = parent.getChildTabIndex(v);
|
||||
|
||||
final int action = e.getAction();
|
||||
final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
|
||||
boolean wasHandled = false;
|
||||
switch (keyCode) {
|
||||
case KeyEvent.KEYCODE_DPAD_LEFT:
|
||||
if (handleKeyEvent) {
|
||||
// Select the previous tab
|
||||
if (tabIndex > 0) {
|
||||
parent.getChildTabViewAt(tabIndex - 1).requestFocus();
|
||||
}
|
||||
}
|
||||
wasHandled = true;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_DPAD_RIGHT:
|
||||
if (handleKeyEvent) {
|
||||
// Select the next tab, or if the last tab has a focus right id, select that
|
||||
if (tabIndex < (tabCount - 1)) {
|
||||
parent.getChildTabViewAt(tabIndex + 1).requestFocus();
|
||||
} else {
|
||||
if (v.getNextFocusRightId() != View.NO_ID) {
|
||||
tabHost.findViewById(v.getNextFocusRightId()).requestFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
wasHandled = true;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_DPAD_UP:
|
||||
// Do nothing
|
||||
wasHandled = true;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_DPAD_DOWN:
|
||||
if (handleKeyEvent) {
|
||||
// Select the content view
|
||||
contents.requestFocus();
|
||||
}
|
||||
wasHandled = true;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
return wasHandled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles key events in a the workspace button bar.
|
||||
*/
|
||||
static boolean handleButtonBarButtonKeyEvent(View v, int keyCode, KeyEvent e) {
|
||||
if (!LauncherApplication.isScreenXLarge()) return false;
|
||||
|
||||
final ViewGroup parent = (ViewGroup) v.getParent();
|
||||
final ViewGroup launcher = (ViewGroup) parent.getParent();
|
||||
final Workspace workspace = (Workspace) launcher.findViewById(R.id.workspace);
|
||||
final int buttonIndex = parent.indexOfChild(v);
|
||||
final int buttonCount = parent.getChildCount();
|
||||
final int pageIndex = workspace.getCurrentPage();
|
||||
final int pageCount = workspace.getChildCount();
|
||||
final int firstButtonIndex = parent.indexOfChild(parent.findViewById(R.id.search_button));
|
||||
final int lastButtonIndex = parent.indexOfChild(parent.findViewById(R.id.configure_button));
|
||||
|
||||
final int action = e.getAction();
|
||||
final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
|
||||
boolean wasHandled = false;
|
||||
switch (keyCode) {
|
||||
case KeyEvent.KEYCODE_DPAD_LEFT:
|
||||
if (handleKeyEvent) {
|
||||
// Select the previous button, otherwise do nothing (since the button bar is
|
||||
// static)
|
||||
if (buttonIndex > firstButtonIndex) {
|
||||
int newButtonIndex = buttonIndex - 1;
|
||||
while (newButtonIndex >= firstButtonIndex) {
|
||||
View prev = parent.getChildAt(newButtonIndex);
|
||||
if (isVisible(prev) && prev.isFocusable()) {
|
||||
prev.requestFocus();
|
||||
break;
|
||||
}
|
||||
--newButtonIndex;
|
||||
}
|
||||
} else {
|
||||
if (pageIndex > 0) {
|
||||
// Snap to previous page and clear focus
|
||||
workspace.snapToPage(pageIndex - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
wasHandled = true;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_DPAD_RIGHT:
|
||||
if (handleKeyEvent) {
|
||||
// Select the next button, otherwise do nothing (since the button bar is
|
||||
// static)
|
||||
if (buttonIndex < lastButtonIndex) {
|
||||
int newButtonIndex = buttonIndex + 1;
|
||||
while (newButtonIndex <= lastButtonIndex) {
|
||||
View next = parent.getChildAt(newButtonIndex);
|
||||
if (isVisible(next) && next.isFocusable()) {
|
||||
next.requestFocus();
|
||||
break;
|
||||
}
|
||||
++newButtonIndex;
|
||||
}
|
||||
} else {
|
||||
if (pageIndex < (pageCount - 1)) {
|
||||
// Snap to next page and clear focus
|
||||
workspace.snapToPage(pageIndex + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
wasHandled = true;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_DPAD_UP:
|
||||
// Do nothing
|
||||
wasHandled = true;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_DPAD_DOWN:
|
||||
if (handleKeyEvent) {
|
||||
// Select the first bubble text view in the current page of the workspace
|
||||
final CellLayout layout = (CellLayout) workspace.getChildAt(pageIndex);
|
||||
final CellLayoutChildren children = layout.getChildrenLayout();
|
||||
final View newIcon = getBubbleTextViewInDirection(layout, children, -1, 1);
|
||||
if (newIcon != null) {
|
||||
newIcon.requestFocus();
|
||||
} else {
|
||||
workspace.requestFocus();
|
||||
}
|
||||
}
|
||||
wasHandled = true;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
return wasHandled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Private helper method to get the CellLayoutChildren given a CellLayout index.
|
||||
*/
|
||||
private static CellLayoutChildren getCellLayoutChildrenForIndex(ViewGroup container, int i) {
|
||||
ViewGroup parent = (ViewGroup) container.getChildAt(i);
|
||||
return (CellLayoutChildren) parent.getChildAt(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Private helper method to sort all the CellLayout children in order of their (x,y) spatially
|
||||
* from top left to bottom right.
|
||||
*/
|
||||
private static ArrayList<View> getCellLayoutChildrenSortedSpatially(CellLayout layout,
|
||||
ViewGroup parent) {
|
||||
// First we order each the CellLayout children by their x,y coordinates
|
||||
final int cellCountX = layout.getCountX();
|
||||
final int count = parent.getChildCount();
|
||||
ArrayList<View> views = new ArrayList<View>();
|
||||
for (int j = 0; j < count; ++j) {
|
||||
views.add(parent.getChildAt(j));
|
||||
}
|
||||
Collections.sort(views, new Comparator<View>() {
|
||||
@Override
|
||||
public int compare(View lhs, View rhs) {
|
||||
CellLayout.LayoutParams llp = (CellLayout.LayoutParams) lhs.getLayoutParams();
|
||||
CellLayout.LayoutParams rlp = (CellLayout.LayoutParams) rhs.getLayoutParams();
|
||||
int lvIndex = (llp.cellY * cellCountX) + llp.cellX;
|
||||
int rvIndex = (rlp.cellY * cellCountX) + rlp.cellX;
|
||||
return lvIndex - rvIndex;
|
||||
}
|
||||
});
|
||||
return views;
|
||||
}
|
||||
/**
|
||||
* Private helper method to find the index of the next BubbleTextView in the delta direction.
|
||||
* @param delta either -1 or 1 depending on the direction we want to search
|
||||
*/
|
||||
private static View findIndexOfBubbleTextView(ArrayList<View> views, int i, int delta) {
|
||||
// Then we find the next BubbleTextView offset by delta from i
|
||||
final int count = views.size();
|
||||
int newI = i + delta;
|
||||
while (0 <= newI && newI < count) {
|
||||
View newV = views.get(newI);
|
||||
if (newV instanceof BubbleTextView) {
|
||||
return newV;
|
||||
}
|
||||
newI += delta;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private static View getBubbleTextViewInDirection(CellLayout layout, ViewGroup parent, int i,
|
||||
int delta) {
|
||||
final ArrayList<View> views = getCellLayoutChildrenSortedSpatially(layout, parent);
|
||||
return findIndexOfBubbleTextView(views, i, delta);
|
||||
}
|
||||
private static View getBubbleTextViewInDirection(CellLayout layout, ViewGroup parent, View v,
|
||||
int delta) {
|
||||
final ArrayList<View> views = getCellLayoutChildrenSortedSpatially(layout, parent);
|
||||
return findIndexOfBubbleTextView(views, views.indexOf(v), delta);
|
||||
}
|
||||
/**
|
||||
* Private helper method to find the next closest BubbleTextView in the delta direction on the
|
||||
* next line.
|
||||
* @param delta either -1 or 1 depending on the line and direction we want to search
|
||||
*/
|
||||
private static View getClosestBubbleTextViewOnLine(CellLayout layout, ViewGroup parent, View v,
|
||||
int lineDelta) {
|
||||
final ArrayList<View> views = getCellLayoutChildrenSortedSpatially(layout, parent);
|
||||
final CellLayout.LayoutParams lp = (CellLayout.LayoutParams) v.getLayoutParams();
|
||||
final int cellCountX = layout.getCountX();
|
||||
final int cellCountY = layout.getCountY();
|
||||
final int row = lp.cellY;
|
||||
final int newRow = row + lineDelta;
|
||||
if (0 <= newRow && newRow < cellCountY) {
|
||||
float closestDistance = Float.MAX_VALUE;
|
||||
int closestIndex = -1;
|
||||
int index = views.indexOf(v);
|
||||
int endIndex = (lineDelta < 0) ? -1 : views.size();
|
||||
while (index != endIndex) {
|
||||
View newV = views.get(index);
|
||||
CellLayout.LayoutParams tmpLp = (CellLayout.LayoutParams) newV.getLayoutParams();
|
||||
boolean satisfiesRow = (lineDelta < 0) ? (tmpLp.cellY < row) : (tmpLp.cellY > row);
|
||||
if (satisfiesRow && newV instanceof BubbleTextView) {
|
||||
float tmpDistance = (float) Math.sqrt(Math.pow(tmpLp.cellX - lp.cellX, 2) +
|
||||
Math.pow(tmpLp.cellY - lp.cellY, 2));
|
||||
if (tmpDistance < closestDistance) {
|
||||
closestIndex = index;
|
||||
closestDistance = tmpDistance;
|
||||
}
|
||||
}
|
||||
if (index <= endIndex) {
|
||||
++index;
|
||||
} else {
|
||||
--index;
|
||||
}
|
||||
}
|
||||
if (closestIndex > -1) {
|
||||
return views.get(closestIndex);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles key events in a Workspace containing BubbleTextView.
|
||||
*/
|
||||
static boolean handleBubbleTextViewKeyEvent(BubbleTextView v, int keyCode, KeyEvent e) {
|
||||
if (!LauncherApplication.isScreenXLarge()) return false;
|
||||
|
||||
CellLayoutChildren parent = (CellLayoutChildren) v.getParent();
|
||||
final CellLayout layout = (CellLayout) parent.getParent();
|
||||
final Workspace workspace = (Workspace) layout.getParent();
|
||||
final ViewGroup launcher = (ViewGroup) workspace.getParent();
|
||||
final ViewGroup tabs = (ViewGroup) launcher.findViewById(R.id.all_apps_button_cluster);
|
||||
int iconIndex = parent.indexOfChild(v);
|
||||
int iconCount = parent.getChildCount();
|
||||
int pageIndex = workspace.indexOfChild(layout);
|
||||
int pageCount = workspace.getChildCount();
|
||||
|
||||
final int action = e.getAction();
|
||||
final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
|
||||
boolean wasHandled = false;
|
||||
switch (keyCode) {
|
||||
case KeyEvent.KEYCODE_DPAD_LEFT:
|
||||
if (handleKeyEvent) {
|
||||
// Select the previous icon or the last icon on the previous page if possible
|
||||
View newIcon = getBubbleTextViewInDirection(layout, parent, v, -1);
|
||||
if (newIcon != null) {
|
||||
newIcon.requestFocus();
|
||||
} else {
|
||||
if (pageIndex > 0) {
|
||||
parent = getCellLayoutChildrenForIndex(workspace, pageIndex - 1);
|
||||
newIcon = getBubbleTextViewInDirection(layout, parent,
|
||||
parent.getChildCount(), -1);
|
||||
if (newIcon != null) {
|
||||
newIcon.requestFocus();
|
||||
} else {
|
||||
// Snap to the previous page
|
||||
workspace.snapToPage(pageIndex - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
wasHandled = true;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_DPAD_RIGHT:
|
||||
if (handleKeyEvent) {
|
||||
// Select the next icon or the first icon on the next page if possible
|
||||
View newIcon = getBubbleTextViewInDirection(layout, parent, v, 1);
|
||||
if (newIcon != null) {
|
||||
newIcon.requestFocus();
|
||||
} else {
|
||||
if (pageIndex < (pageCount - 1)) {
|
||||
parent = getCellLayoutChildrenForIndex(workspace, pageIndex + 1);
|
||||
newIcon = getBubbleTextViewInDirection(layout, parent, -1, 1);
|
||||
if (newIcon != null) {
|
||||
newIcon.requestFocus();
|
||||
} else {
|
||||
// Snap to the next page
|
||||
workspace.snapToPage(pageIndex + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
wasHandled = true;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_DPAD_UP:
|
||||
if (handleKeyEvent) {
|
||||
// Select the closest icon in the previous line, otherwise select the tab bar
|
||||
View newIcon = getClosestBubbleTextViewOnLine(layout, parent, v, -1);
|
||||
if (newIcon != null) {
|
||||
newIcon.requestFocus();
|
||||
wasHandled = true;
|
||||
} else {
|
||||
tabs.requestFocus();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case KeyEvent.KEYCODE_DPAD_DOWN:
|
||||
if (handleKeyEvent) {
|
||||
// Select the closest icon in the next line, otherwise select the tab bar
|
||||
View newIcon = getClosestBubbleTextViewOnLine(layout, parent, v, 1);
|
||||
if (newIcon != null) {
|
||||
newIcon.requestFocus();
|
||||
wasHandled = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case KeyEvent.KEYCODE_PAGE_UP:
|
||||
if (handleKeyEvent) {
|
||||
// Select the first icon on the previous page or the first icon on this page
|
||||
// if there is no previous page
|
||||
if (pageIndex > 0) {
|
||||
parent = getCellLayoutChildrenForIndex(workspace, pageIndex - 1);
|
||||
View newIcon = getBubbleTextViewInDirection(layout, parent, -1, 1);
|
||||
if (newIcon != null) {
|
||||
newIcon.requestFocus();
|
||||
} else {
|
||||
// Snap to the previous page
|
||||
workspace.snapToPage(pageIndex - 1);
|
||||
}
|
||||
} else {
|
||||
View newIcon = getBubbleTextViewInDirection(layout, parent, -1, 1);
|
||||
if (newIcon != null) {
|
||||
newIcon.requestFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
wasHandled = true;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_PAGE_DOWN:
|
||||
if (handleKeyEvent) {
|
||||
// Select the first icon on the next page or the last icon on this page
|
||||
// if there is no previous page
|
||||
if (pageIndex < (pageCount - 1)) {
|
||||
parent = getCellLayoutChildrenForIndex(workspace, pageIndex + 1);
|
||||
View newIcon = getBubbleTextViewInDirection(layout, parent, -1, 1);
|
||||
if (newIcon != null) {
|
||||
newIcon.requestFocus();
|
||||
} else {
|
||||
// Snap to the next page
|
||||
workspace.snapToPage(pageIndex + 1);
|
||||
}
|
||||
} else {
|
||||
View newIcon = getBubbleTextViewInDirection(layout, parent,
|
||||
parent.getChildCount(), -1);
|
||||
if (newIcon != null) {
|
||||
newIcon.requestFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
wasHandled = true;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_MOVE_HOME:
|
||||
if (handleKeyEvent) {
|
||||
// Select the first icon on this page
|
||||
View newIcon = getBubbleTextViewInDirection(layout, parent, -1, 1);
|
||||
if (newIcon != null) {
|
||||
newIcon.requestFocus();
|
||||
}
|
||||
}
|
||||
wasHandled = true;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_MOVE_END:
|
||||
if (handleKeyEvent) {
|
||||
// Select the last icon on this page
|
||||
View newIcon = getBubbleTextViewInDirection(layout, parent,
|
||||
parent.getChildCount(), -1);
|
||||
if (newIcon != null) {
|
||||
newIcon.requestFocus();
|
||||
}
|
||||
}
|
||||
wasHandled = true;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
return wasHandled;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.launcher2;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.TabWidget;
|
||||
|
||||
public class FocusOnlyTabWidget extends TabWidget {
|
||||
public FocusOnlyTabWidget(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public FocusOnlyTabWidget(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public FocusOnlyTabWidget(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
public View getSelectedTab() {
|
||||
final int count = getTabCount();
|
||||
for (int i = 0; i < count; ++i) {
|
||||
View v = getChildTabViewAt(i);
|
||||
if (v.isSelected()) {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getChildTabIndex(View v) {
|
||||
final int tabCount = getTabCount();
|
||||
for (int i = 0; i < tabCount; ++i) {
|
||||
if (getChildTabViewAt(i) == v) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public void setCurrentTabToFocusedTab() {
|
||||
View tab = null;
|
||||
int index = -1;
|
||||
final int count = getTabCount();
|
||||
for (int i = 0; i < count; ++i) {
|
||||
View v = getChildTabViewAt(i);
|
||||
if (v.hasFocus()) {
|
||||
tab = v;
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (index > -1) {
|
||||
super.setCurrentTab(index);
|
||||
super.onFocusChange(tab, true);
|
||||
}
|
||||
}
|
||||
public void superOnFocusChange(View v, boolean hasFocus) {
|
||||
super.onFocusChange(v, hasFocus);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFocusChange(android.view.View v, boolean hasFocus) {
|
||||
if (v == this && hasFocus && getTabCount() > 0) {
|
||||
getSelectedTab().requestFocus();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -206,7 +206,7 @@ public final class Launcher extends Activity
|
|||
private CustomizeTrayTabHost mHomeCustomizationDrawer;
|
||||
private boolean mAutoAdvanceRunning = false;
|
||||
|
||||
private View mButtonCluster;
|
||||
private ViewGroup mButtonCluster;
|
||||
private View mAllAppsButton;
|
||||
private View mDivider;
|
||||
private View mConfigureButton;
|
||||
|
@ -771,8 +771,10 @@ public final class Launcher extends Activity
|
|||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
boolean handled = super.onKeyDown(keyCode, event);
|
||||
if (!handled && acceptFilter() && keyCode != KeyEvent.KEYCODE_ENTER) {
|
||||
final int uniChar = event.getUnicodeChar();
|
||||
final boolean handled = super.onKeyDown(keyCode, event);
|
||||
final boolean isKeyNotWhitespace = uniChar > 0 && !Character.isWhitespace(uniChar);
|
||||
if (!handled && acceptFilter() && isKeyNotWhitespace) {
|
||||
boolean gotKey = TextKeyListener.getInstance().onKeyDown(mWorkspace, mDefaultKeySsb,
|
||||
keyCode, event);
|
||||
if (gotKey && mDefaultKeySsb != null && mDefaultKeySsb.length() > 0) {
|
||||
|
@ -960,7 +962,7 @@ public final class Launcher extends Activity
|
|||
deleteZone.setDragController(dragController);
|
||||
|
||||
final View allAppsButton = findViewById(R.id.all_apps_button);
|
||||
final View divider = findViewById(R.id.divider);
|
||||
final View divider = findViewById(R.id.all_apps_divider);
|
||||
final View configureButton = findViewById(R.id.configure_button);
|
||||
|
||||
if (LauncherApplication.isScreenXLarge()) {
|
||||
|
@ -1009,10 +1011,15 @@ public final class Launcher extends Activity
|
|||
if (allAppsDeleteZone != null) {
|
||||
dragController.addDropTarget(allAppsDeleteZone);
|
||||
}
|
||||
mButtonCluster = findViewById(R.id.all_apps_button_cluster);
|
||||
mButtonCluster = (ViewGroup) findViewById(R.id.all_apps_button_cluster);
|
||||
View.OnKeyListener listener = new ButtonBarKeyEventListener();
|
||||
int buttonCount = mButtonCluster.getChildCount();
|
||||
for (int i = 0; i < buttonCount; ++i) {
|
||||
mButtonCluster.getChildAt(i).setOnKeyListener(listener);
|
||||
}
|
||||
|
||||
mAllAppsButton = findViewById(R.id.all_apps_button);
|
||||
mDivider = findViewById(R.id.divider);
|
||||
mDivider = findViewById(R.id.all_apps_divider);
|
||||
mConfigureButton = findViewById(R.id.configure_button);
|
||||
|
||||
// We had previously set these click handlers in XML, but the first time we launched
|
||||
|
@ -2576,7 +2583,6 @@ public final class Launcher extends Activity
|
|||
|
||||
private void showAndEnableToolbarButton(View button) {
|
||||
button.setVisibility(View.VISIBLE);
|
||||
button.setFocusable(true);
|
||||
button.setClickable(true);
|
||||
}
|
||||
|
||||
|
@ -2587,7 +2593,6 @@ public final class Launcher extends Activity
|
|||
}
|
||||
|
||||
private void disableToolbarButton(View button) {
|
||||
button.setFocusable(false);
|
||||
button.setClickable(false);
|
||||
}
|
||||
|
||||
|
@ -3146,14 +3151,20 @@ public final class Launcher extends Activity
|
|||
|
||||
private void updateGlobalSearchIcon() {
|
||||
if (LauncherApplication.isScreenXLarge()) {
|
||||
final View searchButton = findViewById(R.id.search_button);
|
||||
final View searchDivider = findViewById(R.id.search_divider);
|
||||
|
||||
final SearchManager searchManager =
|
||||
(SearchManager) getSystemService(Context.SEARCH_SERVICE);
|
||||
ComponentName activityName = searchManager.getGlobalSearchActivity();
|
||||
if (activityName != null) {
|
||||
sGlobalSearchIcon = updateButtonWithIconFromExternalActivity(
|
||||
R.id.search_button, activityName, R.drawable.ic_generic_search);
|
||||
searchButton.setVisibility(View.VISIBLE);
|
||||
searchDivider.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
findViewById(R.id.search_button).setVisibility(View.GONE);
|
||||
searchButton.setVisibility(View.GONE);
|
||||
searchDivider.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3164,13 +3175,19 @@ public final class Launcher extends Activity
|
|||
|
||||
private void updateVoiceSearchIcon() {
|
||||
if (LauncherApplication.isScreenXLarge()) {
|
||||
final View searchDivider = findViewById(R.id.search_divider);
|
||||
final View voiceButton = findViewById(R.id.voice_button);
|
||||
|
||||
Intent intent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
|
||||
ComponentName activityName = intent.resolveActivity(getPackageManager());
|
||||
if (activityName != null) {
|
||||
sVoiceSearchIcon = updateButtonWithIconFromExternalActivity(
|
||||
R.id.voice_button, activityName, R.drawable.ic_voice_search);
|
||||
searchDivider.setVisibility(View.VISIBLE);
|
||||
voiceButton.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
findViewById(R.id.voice_button).setVisibility(View.GONE);
|
||||
searchDivider.setVisibility(View.GONE);
|
||||
voiceButton.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import android.view.LayoutInflater;
|
|||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.android.launcher.R;
|
||||
|
||||
|
@ -122,4 +123,9 @@ public class LauncherAppWidgetHostView extends AppWidgetHostView
|
|||
}
|
||||
super.onVisibilityChanged(changedView, visibility);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDescendantFocusability() {
|
||||
return ViewGroup.FOCUS_BLOCK_DESCENDANTS;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1166,7 +1166,7 @@ public abstract class PagedView extends ViewGroup {
|
|||
public void requestChildFocus(View child, View focused) {
|
||||
super.requestChildFocus(child, focused);
|
||||
int page = indexOfChild(child);
|
||||
if (page >= 0 && !isInTouchMode()) {
|
||||
if (page >= 0 && page != getCurrentPage() && !isInTouchMode()) {
|
||||
snapToPage(page);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -180,6 +180,14 @@ public class PagedViewCellLayout extends ViewGroup implements Page {
|
|||
return mChildren.indexOfChild(v);
|
||||
}
|
||||
|
||||
public int getCellCountX() {
|
||||
return mCellCountX;
|
||||
}
|
||||
|
||||
public int getCellCountY() {
|
||||
return mCellCountY;
|
||||
}
|
||||
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
// TODO: currently ignoring padding
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ import android.widget.LinearLayout;
|
|||
* The linear layout used strictly for the widget/wallpaper tab of the customization tray
|
||||
*/
|
||||
public class PagedViewExtendedLayout extends LinearLayout implements Page {
|
||||
static final String TAG = "PagedViewWidgetLayout";
|
||||
static final String TAG = "PagedViewExtendedLayout";
|
||||
|
||||
public PagedViewExtendedLayout(Context context) {
|
||||
this(context, null);
|
||||
|
|
|
@ -31,6 +31,7 @@ import android.os.Handler;
|
|||
import android.os.HandlerThread;
|
||||
import android.os.Message;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.KeyEvent;
|
||||
import android.widget.Checkable;
|
||||
import android.widget.TextView;
|
||||
|
||||
|
@ -128,8 +129,6 @@ public class PagedViewIcon extends CachedTextView implements Checkable {
|
|||
mCheckedFadeOutDuration = r.getInteger(R.integer.icon_allAppsCustomizeFadeOutTime);
|
||||
}
|
||||
|
||||
setFocusable(true);
|
||||
setBackgroundDrawable(null);
|
||||
mHolographicOutlineView = new HolographicPagedViewIcon(context, this);
|
||||
}
|
||||
|
||||
|
@ -244,6 +243,18 @@ public class PagedViewIcon extends CachedTextView implements Checkable {
|
|||
sWorker.removeMessages(MESSAGE_CREATE_HOLOGRAPHIC_OUTLINE, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
return FocusHelper.handlePagedViewIconKeyEvent(this, keyCode, event)
|
||||
|| super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||
return FocusHelper.handlePagedViewIconKeyEvent(this, keyCode, event)
|
||||
|| super.onKeyUp(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChecked() {
|
||||
return mIsChecked;
|
||||
|
|
|
@ -36,6 +36,7 @@ import android.os.Handler;
|
|||
import android.os.HandlerThread;
|
||||
import android.os.Message;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.widget.Checkable;
|
||||
|
@ -227,6 +228,18 @@ public class PagedViewWidget extends LinearLayout implements Checkable {
|
|||
return super.onTouchEvent(event) || true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
return FocusHelper.handlePagedViewWidgetKeyEvent(this, keyCode, event)
|
||||
|| super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||
return FocusHelper.handlePagedViewWidgetKeyEvent(this, keyCode, event)
|
||||
|| super.onKeyUp(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
if (mAlpha > 0) {
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
package com.android.launcher2;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
|
@ -389,4 +391,8 @@ final class Utilities {
|
|||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
static int generateRandomId() {
|
||||
return new Random(System.currentTimeMillis()).nextInt(1 << 24);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1252,6 +1252,14 @@ public class Workspace extends SmoothPagedView
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDescendantFocusability() {
|
||||
if (mIsSmall) {
|
||||
return ViewGroup.FOCUS_BLOCK_DESCENDANTS;
|
||||
}
|
||||
return super.getDescendantFocusability();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
|
||||
if (!mLauncher.isAllAppsVisible()) {
|
||||
|
|
Loading…
Reference in New Issue