Merge "Clean up bitmaps when necessary in the widget tray to prevent likelihood of OOM. (Bug: 5348390)"
diff --git a/fill_screens.py b/fill_screens.py
index 9607c80..5841b8e 100755
--- a/fill_screens.py
+++ b/fill_screens.py
@@ -15,13 +15,12 @@
AUTO_FILE = "launcher.db"
APPLICATION_COMPONENTS = [
- "com.google.android.apps.books/com.google.android.apps.books.app.BooksActivity",
"com.android.calculator2/com.android.calculator2.Calculator",
- "com.google.android.camera/com.android.camera.Camera",
- "com.google.android.carhome/com.google.android.carhome.CarHome",
"com.android.providers.downloads.ui/com.android.providers.downloads.ui.DownloadList",
- "com.google.android.gallery3d/com.android.gallery3d.app.Gallery",
- "com.google.android.apps.maps/com.google.android.maps.MapsActivity"
+ "com.android.settings/com.android.settings.Settings",
+ "com.android.mms/com.android.mms.ui.ConversationList",
+ "com.android.contacts/com.android.contacts.activities.PeopleActivity",
+ "com.android.contacts/com.android.contacts.activities.DialtactsActivity"
]
def usage():
diff --git a/res/layout-land/folder_icon.xml b/res/layout-land/folder_icon.xml
index 15867c7..4c92fca 100644
--- a/res/layout-land/folder_icon.xml
+++ b/res/layout-land/folder_icon.xml
@@ -19,7 +19,9 @@
xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:orientation="vertical">
+ android:orientation="vertical"
+ android:focusable="true"
+ android:background="@drawable/focusable_view_bg">
<ImageView
android:id="@+id/preview_background"
android:layout_gravity="center_horizontal"
diff --git a/res/layout-port/folder_icon.xml b/res/layout-port/folder_icon.xml
index 69e51e8..0df16b8 100644
--- a/res/layout-port/folder_icon.xml
+++ b/res/layout-port/folder_icon.xml
@@ -19,7 +19,9 @@
xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:orientation="vertical">
+ android:orientation="vertical"
+ android:focusable="true"
+ android:background="@drawable/focusable_view_bg">
<ImageView
android:id="@+id/preview_background"
android:layout_gravity="center_horizontal"
diff --git a/res/layout/apps_customize_progressbar.xml b/res/layout/apps_customize_progressbar.xml
index d790f21..6a8010f 100644
--- a/res/layout/apps_customize_progressbar.xml
+++ b/res/layout/apps_customize_progressbar.xml
@@ -20,5 +20,4 @@
android:id="@+id/apps_customize_progress_bar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:layout_marginRight="5dp" />
+ android:layout_gravity="center" />
diff --git a/res/layout/user_folder.xml b/res/layout/user_folder.xml
index 814c968..208390d 100644
--- a/res/layout/user_folder.xml
+++ b/res/layout/user_folder.xml
@@ -37,7 +37,7 @@
launcher:cellWidth="@dimen/folder_cell_width"
launcher:cellHeight="@dimen/folder_cell_height" />
- <EditText
+ <com.android.launcher2.FolderEditText
android:id="@+id/folder_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -50,5 +50,6 @@
android:textColor="#ff33b5e5"
android:textColorHighlight="#ff333333"
android:gravity="center_horizontal"
- android:singleLine="true"/>
+ android:singleLine="true"
+ android:imeOptions="flagNoExtractUi"/>
</com.android.launcher2.Folder>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index e5e1b3f..0ccd468 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -27,7 +27,7 @@
<dimen name="workspace_height_gap">-1dp</dimen>
<dimen name="workspace_max_gap">16dp</dimen>
<dimen name="folder_cell_width">74dp</dimen>
- <dimen name="folder_cell_height">80dp</dimen>
+ <dimen name="folder_cell_height">82dp</dimen>
<dimen name="workspace_divider_padding_left">12dp</dimen>
<dimen name="workspace_divider_padding_right">12dp</dimen>
<dimen name="workspace_divider_padding_top">0dp</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 5c806e2..63d7b3b 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -153,8 +153,8 @@
<!-- Noun, menu item used to show help. [CHAR_LIMIT=none] -->
<string name="menu_help">Help</string>
- <!-- URL pointing to help text. [DO NOT TRANSLATE] -->
- <string name="help_url" translatable="false">http://www.google.com/support/mobile/?p=help_home</string>
+ <!-- URL pointing to help text. If empty, no link to help will be created [DO NOT TRANSLATE] -->
+ <string name="help_url" translatable="false"></string>
<!-- Strings for the contextual action bar (CAB) in All Apps -->
<skip />
@@ -199,18 +199,9 @@
<!-- Widgets: -->
<skip />
- <!-- The Google Apps folder name -->
- <string name="google_apps_folder_name">Google</string>
-
<!-- Text to show user in place of a gadget when we can't display it properly -->
<string name="gadget_error_text">Problem loading widget</string>
- <!-- URL to use when detecting the current default browser.
- Attempts to mimic homepage_base in Browser; {CID} should be replaced
- by the client-id, e.g. "android-google". -->
- <string name="default_browser_url" translatable="false">
- http://www.google.com/m?client=ms-{CID}&source=android-home-hotseat</string>
-
<!-- Text to inform the user that they can't uninstall a system application -->
<string name="uninstall_system_app_text">This is a system application and cannot be uninstalled.</string>
diff --git a/res/xml/default_workspace.xml b/res/xml/default_workspace.xml
index ccc8022..f2f4240 100644
--- a/res/xml/default_workspace.xml
+++ b/res/xml/default_workspace.xml
@@ -29,7 +29,7 @@
<!-- Middle screen [2] -->
<appwidget
- launcher:packageName="com.google.android.deskclock"
+ launcher:packageName="com.android.deskclock"
launcher:className="com.android.alarmclock.AnalogAppWidgetProvider"
launcher:screen="2"
launcher:x="1"
@@ -37,59 +37,15 @@
launcher:spanX="2"
launcher:spanY="2" />
<favorite
- launcher:packageName="com.google.android.camera"
+ launcher:packageName="com.android.camera"
launcher:className="com.android.camera.Camera"
launcher:screen="2"
launcher:x="0"
launcher:y="3" />
- <folder
- launcher:screen="2"
- launcher:x="3"
- launcher:y="3"
- launcher:title="@string/google_apps_folder_name">
- <favorite
- launcher:packageName="com.google.android.apps.maps"
- launcher:className="com.google.android.maps.MapsActivity" />
- <favorite
- launcher:packageName="com.google.android.gm"
- launcher:className="com.google.android.gm.ConversationListActivityGmail" />
- <favorite
- launcher:packageName="com.google.android.calendar"
- launcher:className="com.android.calendar.AllInOneActivity" />
- <favorite
- launcher:packageName="com.google.android.apps.plus"
- launcher:className="com.google.android.apps.plus.phone.HomeActivity" />
- <favorite
- launcher:packageName="com.google.android.music"
- launcher:className="com.android.music.activitymanagement.TopLevelActivity" />
- <favorite
- launcher:packageName="com.google.android.apps.books"
- launcher:className="com.google.android.apps.books.app.BooksActivity" />
- <favorite
- launcher:packageName="com.google.android.videos"
- launcher:className="com.google.android.youtube.videos.honeycomb.VideosActivity" />
- <favorite
- launcher:packageName="com.android.vending"
- launcher:className="com.android.vending.AssetBrowserActivity" />
- <favorite
- launcher:packageName="com.google.android.talk"
- launcher:className="com.google.android.talk.SigningInActivity" />
- <favorite
- launcher:packageName="com.google.android.youtube"
- launcher:className="com.google.android.youtube.app.honeycomb.Shell$HomeActivity" />
- </folder>
<!-- Right screen [3] -->
- <appwidget
- launcher:packageName="com.android.vending"
- launcher:className="com.android.vending.MarketWidgetProvider"
- launcher:screen="3"
- launcher:x="1"
- launcher:y="1"
- launcher:spanX="2"
- launcher:spanY="2" />
<favorite
- launcher:packageName="com.google.android.gallery3d"
+ launcher:packageName="com.android.gallery3d"
launcher:className="com.android.gallery3d.app.Gallery"
launcher:screen="3"
launcher:x="1"
@@ -126,7 +82,7 @@
launcher:x="3"
launcher:y="0" />
<favorite
- launcher:packageName="com.google.android.browser"
+ launcher:packageName="com.android.browser"
launcher:className="com.android.browser.BrowserActivity"
launcher:container="-101"
launcher:screen="4"
diff --git a/src/com/android/launcher2/FocusHelper.java b/src/com/android/launcher2/FocusHelper.java
index f030739..967b02f 100644
--- a/src/com/android/launcher2/FocusHelper.java
+++ b/src/com/android/launcher2/FocusHelper.java
@@ -23,6 +23,7 @@
import android.view.ViewParent;
import android.widget.TabHost;
import android.widget.TabWidget;
+import android.widget.TextView;
import com.android.launcher.R;
@@ -33,18 +34,25 @@
/**
* A keyboard listener we set on all the workspace icons.
*/
-class BubbleTextViewKeyEventListener implements View.OnKeyListener {
- @Override
+class IconKeyEventListener implements View.OnKeyListener {
public boolean onKey(View v, int keyCode, KeyEvent event) {
- return FocusHelper.handleBubbleTextViewKeyEvent((BubbleTextView) v, keyCode, event);
+ return FocusHelper.handleIconKeyEvent(v, keyCode, event);
+ }
+}
+
+/**
+ * A keyboard listener we set on all the workspace icons.
+ */
+class FolderKeyEventListener implements View.OnKeyListener {
+ public boolean onKey(View v, int keyCode, KeyEvent event) {
+ return FocusHelper.handleFolderKeyEvent(v, keyCode, event);
}
}
/**
* A keyboard listener we set on all the hotseat buttons.
*/
-class HotseatBubbleTextViewKeyEventListener implements View.OnKeyListener {
- @Override
+class HotseatIconKeyEventListener implements View.OnKeyListener {
public boolean onKey(View v, int keyCode, KeyEvent event) {
final Configuration configuration = v.getResources().getConfiguration();
return FocusHelper.handleHotseatButtonKeyEvent(v, keyCode, event, configuration.orientation);
@@ -56,7 +64,6 @@
* market icon and vice versa.
*/
class AppsCustomizeTabKeyEventListener implements View.OnKeyListener {
- @Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
return FocusHelper.handleAppsCustomizeTabKeyEvent(v, keyCode, event);
}
@@ -480,7 +487,6 @@
final int buttonIndex = parent.indexOfChild(v);
final int buttonCount = parent.getChildCount();
final int pageIndex = workspace.getCurrentPage();
- final int pageCount = workspace.getChildCount();
// NOTE: currently we don't special case for the phone UI in different
// orientations, even though the hotseat is on the side in landscape mode. This
@@ -517,7 +523,7 @@
// 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);
+ final View newIcon = getIconInDirection(layout, children, -1, 1);
if (newIcon != null) {
newIcon.requestFocus();
} else {
@@ -569,38 +575,41 @@
return views;
}
/**
- * Private helper method to find the index of the next BubbleTextView in the delta direction.
+ * Private helper method to find the index of the next BubbleTextView or FolderIcon in the
+ * direction delta.
+ *
* @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) {
+ private static View findIndexOfIcon(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) {
+ if (newV instanceof BubbleTextView || newV instanceof FolderIcon) {
return newV;
}
newI += delta;
}
return null;
}
- private static View getBubbleTextViewInDirection(CellLayout layout, ViewGroup parent, int i,
+ private static View getIconInDirection(CellLayout layout, ViewGroup parent, int i,
int delta) {
final ArrayList<View> views = getCellLayoutChildrenSortedSpatially(layout, parent);
- return findIndexOfBubbleTextView(views, i, delta);
+ return findIndexOfIcon(views, i, delta);
}
- private static View getBubbleTextViewInDirection(CellLayout layout, ViewGroup parent, View v,
+ private static View getIconInDirection(CellLayout layout, ViewGroup parent, View v,
int delta) {
final ArrayList<View> views = getCellLayoutChildrenSortedSpatially(layout, parent);
- return findIndexOfBubbleTextView(views, views.indexOf(v), delta);
+ return findIndexOfIcon(views, views.indexOf(v), delta);
}
/**
- * Private helper method to find the next closest BubbleTextView in the delta direction on the
- * next line.
+ * Private helper method to find the next closest BubbleTextView or FolderIcon in the direction
+ * delta 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,
+ private static View getClosestIconOnLine(CellLayout layout, ViewGroup parent, View v,
int lineDelta) {
final ArrayList<View> views = getCellLayoutChildrenSortedSpatially(layout, parent);
final CellLayout.LayoutParams lp = (CellLayout.LayoutParams) v.getLayoutParams();
@@ -617,7 +626,8 @@
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) {
+ if (satisfiesRow &&
+ (newV instanceof BubbleTextView || newV instanceof FolderIcon)) {
float tmpDistance = (float) Math.sqrt(Math.pow(tmpLp.cellX - lp.cellX, 2) +
Math.pow(tmpLp.cellY - lp.cellY, 2));
if (tmpDistance < closestDistance) {
@@ -639,17 +649,15 @@
}
/**
- * Handles key events in a Workspace containing BubbleTextView.
+ * Handles key events in a Workspace containing.
*/
- static boolean handleBubbleTextViewKeyEvent(BubbleTextView v, int keyCode, KeyEvent e) {
+ static boolean handleIconKeyEvent(View v, int keyCode, KeyEvent e) {
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.qsb_bar);
final ViewGroup hotseat = (ViewGroup) launcher.findViewById(R.id.hotseat);
- int iconIndex = parent.indexOfChild(v);
- int iconCount = parent.getChildCount();
int pageIndex = workspace.indexOfChild(layout);
int pageCount = workspace.getChildCount();
@@ -660,13 +668,13 @@
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);
+ View newIcon = getIconInDirection(layout, parent, v, -1);
if (newIcon != null) {
newIcon.requestFocus();
} else {
if (pageIndex > 0) {
parent = getCellLayoutChildrenForIndex(workspace, pageIndex - 1);
- newIcon = getBubbleTextViewInDirection(layout, parent,
+ newIcon = getIconInDirection(layout, parent,
parent.getChildCount(), -1);
if (newIcon != null) {
newIcon.requestFocus();
@@ -682,13 +690,13 @@
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);
+ View newIcon = getIconInDirection(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);
+ newIcon = getIconInDirection(layout, parent, -1, 1);
if (newIcon != null) {
newIcon.requestFocus();
} else {
@@ -703,7 +711,7 @@
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);
+ View newIcon = getClosestIconOnLine(layout, parent, v, -1);
if (newIcon != null) {
newIcon.requestFocus();
wasHandled = true;
@@ -715,7 +723,7 @@
case KeyEvent.KEYCODE_DPAD_DOWN:
if (handleKeyEvent) {
// Select the closest icon in the next line, otherwise select the button bar
- View newIcon = getClosestBubbleTextViewOnLine(layout, parent, v, 1);
+ View newIcon = getClosestIconOnLine(layout, parent, v, 1);
if (newIcon != null) {
newIcon.requestFocus();
wasHandled = true;
@@ -730,7 +738,7 @@
// if there is no previous page
if (pageIndex > 0) {
parent = getCellLayoutChildrenForIndex(workspace, pageIndex - 1);
- View newIcon = getBubbleTextViewInDirection(layout, parent, -1, 1);
+ View newIcon = getIconInDirection(layout, parent, -1, 1);
if (newIcon != null) {
newIcon.requestFocus();
} else {
@@ -738,7 +746,7 @@
workspace.snapToPage(pageIndex - 1);
}
} else {
- View newIcon = getBubbleTextViewInDirection(layout, parent, -1, 1);
+ View newIcon = getIconInDirection(layout, parent, -1, 1);
if (newIcon != null) {
newIcon.requestFocus();
}
@@ -752,7 +760,7 @@
// if there is no previous page
if (pageIndex < (pageCount - 1)) {
parent = getCellLayoutChildrenForIndex(workspace, pageIndex + 1);
- View newIcon = getBubbleTextViewInDirection(layout, parent, -1, 1);
+ View newIcon = getIconInDirection(layout, parent, -1, 1);
if (newIcon != null) {
newIcon.requestFocus();
} else {
@@ -760,7 +768,7 @@
workspace.snapToPage(pageIndex + 1);
}
} else {
- View newIcon = getBubbleTextViewInDirection(layout, parent,
+ View newIcon = getIconInDirection(layout, parent,
parent.getChildCount(), -1);
if (newIcon != null) {
newIcon.requestFocus();
@@ -772,7 +780,7 @@
case KeyEvent.KEYCODE_MOVE_HOME:
if (handleKeyEvent) {
// Select the first icon on this page
- View newIcon = getBubbleTextViewInDirection(layout, parent, -1, 1);
+ View newIcon = getIconInDirection(layout, parent, -1, 1);
if (newIcon != null) {
newIcon.requestFocus();
}
@@ -782,7 +790,90 @@
case KeyEvent.KEYCODE_MOVE_END:
if (handleKeyEvent) {
// Select the last icon on this page
- View newIcon = getBubbleTextViewInDirection(layout, parent,
+ View newIcon = getIconInDirection(layout, parent,
+ parent.getChildCount(), -1);
+ if (newIcon != null) {
+ newIcon.requestFocus();
+ }
+ }
+ wasHandled = true;
+ break;
+ default: break;
+ }
+ return wasHandled;
+ }
+
+ /**
+ * Handles key events for items in a Folder.
+ */
+ static boolean handleFolderKeyEvent(View v, int keyCode, KeyEvent e) {
+ CellLayoutChildren parent = (CellLayoutChildren) v.getParent();
+ final CellLayout layout = (CellLayout) parent.getParent();
+ final Folder folder = (Folder) layout.getParent();
+ View title = folder.mFolderName;
+
+ 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
+ View newIcon = getIconInDirection(layout, parent, v, -1);
+ if (newIcon != null) {
+ newIcon.requestFocus();
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ if (handleKeyEvent) {
+ // Select the next icon
+ View newIcon = getIconInDirection(layout, parent, v, 1);
+ if (newIcon != null) {
+ newIcon.requestFocus();
+ } else {
+ title.requestFocus();
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_UP:
+ if (handleKeyEvent) {
+ // Select the closest icon in the previous line
+ View newIcon = getClosestIconOnLine(layout, parent, v, -1);
+ if (newIcon != null) {
+ newIcon.requestFocus();
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ if (handleKeyEvent) {
+ // Select the closest icon in the next line
+ View newIcon = getClosestIconOnLine(layout, parent, v, 1);
+ if (newIcon != null) {
+ newIcon.requestFocus();
+ } else {
+ title.requestFocus();
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_MOVE_HOME:
+ if (handleKeyEvent) {
+ // Select the first icon on this page
+ View newIcon = getIconInDirection(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 = getIconInDirection(layout, parent,
parent.getChildCount(), -1);
if (newIcon != null) {
newIcon.requestFocus();
diff --git a/src/com/android/launcher2/Folder.java b/src/com/android/launcher2/Folder.java
index 71b7081..1b863de 100644
--- a/src/com/android/launcher2/Folder.java
+++ b/src/com/android/launcher2/Folder.java
@@ -93,7 +93,6 @@
private int[] mEmptyCell = new int[2];
private Alarm mReorderAlarm = new Alarm();
private Alarm mOnExitAlarm = new Alarm();
- private TextView mFolderName;
private int mFolderNameHeight;
private Rect mHitRect = new Rect();
private Rect mTempRect = new Rect();
@@ -101,6 +100,7 @@
private boolean mDeleteFolderOnDropCompleted = false;
private boolean mSuppressFolderDeletion = false;
private boolean mItemAddedBackToSelfViaIcon = false;
+ FolderEditText mFolderName;
private boolean mIsEditingName = false;
private InputMethodManager mInputMethodManager;
@@ -134,8 +134,11 @@
if (sHintText == null) {
sHintText = res.getString(R.string.folder_hint_text);
}
-
mLauncher = (Launcher) context;
+ // We need this view to be focusable in touch mode so that when text editing of the folder
+ // name is complete, we have something to focus on, thus hiding the cursor and giving
+ // reliable behvior when clicking the text field (since it will always gain focus on click).
+ setFocusableInTouchMode(true);
}
@Override
@@ -143,7 +146,8 @@
super.onFinishInflate();
mContent = (CellLayout) findViewById(R.id.folder_content);
mContent.setGridSize(0, 0);
- mFolderName = (TextView) findViewById(R.id.folder_name);
+ mFolderName = (FolderEditText) findViewById(R.id.folder_name);
+ mFolderName.setFolder(this);
// We find out how tall the text view wants to be (it is set to wrap_content), so that
// we can allocate the appropriate amount of space for it.
@@ -153,7 +157,6 @@
// We disable action mode for now since it messes up the view on phones
mFolderName.setCustomSelectionActionModeCallback(mActionModeCallback);
- mFolderName.setCursorVisible(false);
mFolderName.setOnEditorActionListener(this);
mFolderName.setSelectAllOnFocus(true);
mFolderName.setInputType(mFolderName.getInputType() |
@@ -233,7 +236,6 @@
public void startEditingFolderName() {
mFolderName.setHint("");
- mFolderName.setCursorVisible(true);
mIsEditingName = true;
}
@@ -248,8 +250,11 @@
// gets saved.
mInfo.setTitle(mFolderName.getText().toString());
LauncherModel.updateItemInDatabase(mLauncher, mInfo);
- mFolderName.setCursorVisible(false);
- mFolderName.clearFocus();
+
+ // In order to clear the focus from the text field, we set the focus on ourself. This
+ // ensures that every time the field is clicked, focus is gained, giving reliable behavior.
+ requestFocus();
+
Selection.setSelection((Spannable) mFolderName.getText(), 0, 0);
mIsEditingName = false;
}
@@ -320,6 +325,7 @@
}
mItemsInvalidated = true;
+ updateTextViewFocus();
mInfo.addListener(this);
if (!sDefaultFolderName.contentEquals(mInfo.title)) {
@@ -410,12 +416,20 @@
if (cling != null) {
cling.bringToFront();
}
+ setFocusOnFirstChild();
}
});
oa.setDuration(mExpandDuration);
oa.start();
}
+ private void setFocusOnFirstChild() {
+ View firstChild = mContent.getChildAt(0, 0);
+ if (firstChild != null) {
+ firstChild.requestFocus();
+ }
+ }
+
public void animateClosed() {
if (!(getParent() instanceof DragLayer)) return;
@@ -512,6 +526,7 @@
CellLayout.LayoutParams lp =
new CellLayout.LayoutParams(item.cellX, item.cellY, item.spanX, item.spanY);
boolean insert = false;
+ textView.setOnKeyListener(new FolderKeyEventListener());
mContent.addViewToCellLayout(textView, insert ? 0 : -1, (int)item.id, lp, true);
return true;
}
@@ -842,6 +857,7 @@
parent.removeView(this);
mDragController.removeDropTarget((DropTarget) this);
clearFocus();
+ mFolderIcon.requestFocus();
if (mRearrangeOnClose) {
setupContentForNumItems(getItemCount());
@@ -888,6 +904,19 @@
}
}
+ // This method keeps track of the last item in the folder for the purposes
+ // of keyboard focus
+ private void updateTextViewFocus() {
+ View lastChild = getItemAt(getItemCount() - 1);
+ getItemAt(getItemCount() - 1);
+ if (lastChild != null) {
+ mFolderName.setNextFocusDownId(lastChild.getId());
+ mFolderName.setNextFocusRightId(lastChild.getId());
+ mFolderName.setNextFocusLeftId(lastChild.getId());
+ mFolderName.setNextFocusUpId(lastChild.getId());
+ }
+ }
+
public void onDrop(DragObject d) {
ShortcutInfo item;
if (d.dragInfo instanceof ApplicationInfo) {
@@ -963,7 +992,9 @@
}
public void onItemsChanged() {
+ updateTextViewFocus();
}
+
public void onTitleChanged(CharSequence title) {
}
diff --git a/src/com/android/launcher2/FolderEditText.java b/src/com/android/launcher2/FolderEditText.java
new file mode 100644
index 0000000..13169bd
--- /dev/null
+++ b/src/com/android/launcher2/FolderEditText.java
@@ -0,0 +1,36 @@
+package com.android.launcher2;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.KeyEvent;
+import android.widget.EditText;
+
+public class FolderEditText extends EditText {
+
+ private Folder mFolder;
+
+ public FolderEditText(Context context) {
+ super(context);
+ }
+
+ public FolderEditText(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public FolderEditText(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ public void setFolder(Folder folder) {
+ mFolder = folder;
+ }
+
+ @Override
+ public boolean onKeyPreIme(int keyCode, KeyEvent event) {
+ // Catch the back button on the soft keyboard so that we can just close the activity
+ if (event.getKeyCode() == android.view.KeyEvent.KEYCODE_BACK) {
+ mFolder.doneEditingFolderName(true);
+ }
+ return super.onKeyPreIme(keyCode, event);
+ }
+}
diff --git a/src/com/android/launcher2/FolderInfo.java b/src/com/android/launcher2/FolderInfo.java
index 3ae31d2..f597076 100644
--- a/src/com/android/launcher2/FolderInfo.java
+++ b/src/com/android/launcher2/FolderInfo.java
@@ -56,6 +56,7 @@
for (int i = 0; i < listeners.size(); i++) {
listeners.get(i).onAdd(item);
}
+ itemsChanged();
}
/**
@@ -68,6 +69,7 @@
for (int i = 0; i < listeners.size(); i++) {
listeners.get(i).onRemove(item);
}
+ itemsChanged();
}
public void setTitle(CharSequence title) {
diff --git a/src/com/android/launcher2/Hotseat.java b/src/com/android/launcher2/Hotseat.java
index b9be6dc..85412c6 100644
--- a/src/com/android/launcher2/Hotseat.java
+++ b/src/com/android/launcher2/Hotseat.java
@@ -58,7 +58,7 @@
public void setup(Launcher launcher) {
mLauncher = launcher;
- setOnKeyListener(new HotseatBubbleTextViewKeyEventListener());
+ setOnKeyListener(new HotseatIconKeyEventListener());
}
CellLayout getLayout() {
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index 59386ad..02fccc5 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -1147,16 +1147,18 @@
// also will cancel mWaitingForResult.
closeSystemDialogs();
- closeFolder();
-
boolean alreadyOnHome = ((intent.getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT)
!= Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
+ Folder openFolder = mWorkspace.getOpenFolder();
// In all these cases, only animate if we're already on home
mWorkspace.exitWidgetResizeMode();
- if (alreadyOnHome && mState == State.WORKSPACE && !mWorkspace.isTouchActive()) {
+ if (alreadyOnHome && mState == State.WORKSPACE && !mWorkspace.isTouchActive() &&
+ openFolder == null) {
mWorkspace.moveToDefaultScreen(true);
}
+
+ closeFolder();
exitSpringLoadedDragMode();
showWorkspace(alreadyOnHome);
@@ -1302,7 +1304,8 @@
Intent settings = new Intent(android.provider.Settings.ACTION_SETTINGS);
settings.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
- Intent help = new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.help_url)));
+ String helpUrl = getString(R.string.help_url);
+ Intent help = new Intent(Intent.ACTION_VIEW, Uri.parse(helpUrl));
help.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
@@ -1317,10 +1320,12 @@
.setIcon(android.R.drawable.ic_menu_preferences)
.setIntent(settings)
.setAlphabeticShortcut('P');
- menu.add(0, MENU_HELP, 0, R.string.menu_help)
- .setIcon(android.R.drawable.ic_menu_help)
- .setIntent(help)
- .setAlphabeticShortcut('H');
+ if (!helpUrl.isEmpty()) {
+ menu.add(0, MENU_HELP, 0, R.string.menu_help)
+ .setIcon(android.R.drawable.ic_menu_help)
+ .setIntent(help)
+ .setAlphabeticShortcut('H');
+ }
return true;
}
@@ -1873,6 +1878,9 @@
public void closeFolder() {
Folder folder = mWorkspace.getOpenFolder();
if (folder != null) {
+ if (folder.isEditingName()) {
+ folder.dismissEditingName();
+ }
closeFolder(folder);
// Dismiss the folder cling
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index bf18456..44c533b 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -469,7 +469,7 @@
}
layout = (CellLayout) getChildAt(screen);
- child.setOnKeyListener(new BubbleTextViewKeyEventListener());
+ child.setOnKeyListener(new IconKeyEventListener());
}
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();