From dcbcc86353e9ed52daac87f292aece667cd0ac71 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Tue, 12 Aug 2014 15:58:36 -0700 Subject: [PATCH] Updating the UI for focused state of an icon/folder. issue: 16352129 Change-Id: If2e154dba06a0648f933f9aea38898642db9fd85 --- res/drawable-hdpi/focused_bg.9.png | Bin 188 -> 0 bytes res/drawable-mdpi/focused_bg.9.png | Bin 180 -> 0 bytes res/drawable-xhdpi/focused_bg.9.png | Bin 194 -> 0 bytes res/drawable-xxhdpi/focused_bg.9.png | Bin 2884 -> 0 bytes res/drawable/focusable_view_bg.xml | 13 +- res/layout-land/launcher.xml | 5 + res/layout-port/launcher.xml | 5 + res/layout-sw720dp/launcher.xml | 5 + res/layout/all_apps_button.xml | 3 +- res/layout/application.xml | 3 +- res/layout/apps_customize_application.xml | 3 +- res/layout/folder_application.xml | 3 +- res/layout/folder_icon.xml | 3 +- res/values/colors.xml | 1 + .../launcher3/AppsCustomizeCellLayout.java | 8 + .../launcher3/AppsCustomizePagedView.java | 1 + src/com/android/launcher3/CellLayout.java | 5 +- .../android/launcher3/FocusIndicatorView.java | 146 ++++++++++++++++++ src/com/android/launcher3/Folder.java | 8 + src/com/android/launcher3/FolderIcon.java | 1 + src/com/android/launcher3/Hotseat.java | 1 + src/com/android/launcher3/Launcher.java | 4 + 22 files changed, 201 insertions(+), 17 deletions(-) delete mode 100644 res/drawable-hdpi/focused_bg.9.png delete mode 100644 res/drawable-mdpi/focused_bg.9.png delete mode 100644 res/drawable-xhdpi/focused_bg.9.png delete mode 100644 res/drawable-xxhdpi/focused_bg.9.png create mode 100644 src/com/android/launcher3/FocusIndicatorView.java diff --git a/res/drawable-hdpi/focused_bg.9.png b/res/drawable-hdpi/focused_bg.9.png deleted file mode 100644 index 2925ae85864ee77ac73b5d1a245189b67c871831..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 188 zcmeAS@N?(olHy`uVBq!ia0vp^JRr=$1|-8uW1a&kmSQK*5Dp-y;YjHK@;M7UB8wRq zxI00Z(fs7;wLrl*PZ!4!jfra~T;yyp;Bk51C0)YqUaTHoJo9$K@Wn;1M@{an^LB{Ts5m1jR7 diff --git a/res/drawable-mdpi/focused_bg.9.png b/res/drawable-mdpi/focused_bg.9.png deleted file mode 100644 index 89c29ac5166e4d854503b4308e8163018a68c246..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 180 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PFqEX7WqAsj$Z!;#Vf4nJ zaCd?*qxs3xYk`7co-U3d5>s>g4+=Io@Gwo6wiiou{g&vztt|idfp$yxi#0+LY#iG< zcXHld(PtaVFln3Sj<{+zv4(G3bR60H98Gp4wPhz5C7qRfyZ+AV6}c+4b*vlK3NK+5 Vd(Ek=&;+!B!PC{xWt~$(695*NHl+Xn diff --git a/res/drawable-xhdpi/focused_bg.9.png b/res/drawable-xhdpi/focused_bg.9.png deleted file mode 100644 index 197a26988f5e9b8bcc6165e693b848957836f5b0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 194 zcmeAS@N?(olHy`uVBq!ia0vp^{24nJ zaCd?*qxs3xYk`6(o-U3d8WYz}JjmN%z~TC{ck_;(>K&6;?>zJQQZxGsfj^#;=O1cz z;@#kI<}v$0le40#u9Hgow7!IK-&yJ?Z{PlQ l@#UN_Zn1<(r|NlMFk0S|NSemcst&Y|!PC{xWt~$(698`MLX!Xh diff --git a/res/drawable-xxhdpi/focused_bg.9.png b/res/drawable-xxhdpi/focused_bg.9.png deleted file mode 100644 index 84d3062f1d45fab5de219b96e266eef9a29cf8f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2884 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 imiG^60{{U3{{sMltRHy0Kn`920000 - - - + + + + + + + + \ No newline at end of file diff --git a/res/layout-land/launcher.xml b/res/layout-land/launcher.xml index 7791609252..0af9e59aaa 100644 --- a/res/layout-land/launcher.xml +++ b/res/layout-land/launcher.xml @@ -30,6 +30,11 @@ android:layout_height="match_parent" android:fitsSystemWindows="true"> + + + + + + + android:focusable="true" /> diff --git a/res/layout/application.xml b/res/layout/application.xml index e4909ddadd..c21dea070f 100644 --- a/res/layout/application.xml +++ b/res/layout/application.xml @@ -16,5 +16,4 @@ + android:focusable="true" /> diff --git a/res/layout/apps_customize_application.xml b/res/layout/apps_customize_application.xml index b48b9b7ac3..17f4a8e15e 100644 --- a/res/layout/apps_customize_application.xml +++ b/res/layout/apps_customize_application.xml @@ -20,5 +20,4 @@ style="@style/WorkspaceIcon.AppsCustomize" android:id="@+id/application_icon" - android:focusable="true" - android:background="@drawable/focusable_view_bg" /> + android:focusable="true" /> diff --git a/res/layout/folder_application.xml b/res/layout/folder_application.xml index 37dd79d370..b48b61331d 100644 --- a/res/layout/folder_application.xml +++ b/res/layout/folder_application.xml @@ -16,5 +16,4 @@ + android:focusable="true" /> diff --git a/res/layout/folder_icon.xml b/res/layout/folder_icon.xml index 5147f99601..fd45d76859 100644 --- a/res/layout/folder_icon.xml +++ b/res/layout/folder_icon.xml @@ -19,8 +19,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" - android:focusable="true" - android:background="@drawable/focusable_view_bg"> + android:focusable="true" > #DA0099CC #20000000 + #80c6c5c5 #FCCC diff --git a/src/com/android/launcher3/AppsCustomizeCellLayout.java b/src/com/android/launcher3/AppsCustomizeCellLayout.java index 3c8bda9dba..76b81d2d18 100644 --- a/src/com/android/launcher3/AppsCustomizeCellLayout.java +++ b/src/com/android/launcher3/AppsCustomizeCellLayout.java @@ -20,8 +20,16 @@ import android.content.Context; import android.view.View; public class AppsCustomizeCellLayout extends CellLayout implements Page { + + final FocusIndicatorView mFocusHandlerView; + public AppsCustomizeCellLayout(Context context) { super(context); + + mFocusHandlerView = new FocusIndicatorView(context); + addView(mFocusHandlerView, 0); + mFocusHandlerView.getLayoutParams().width = FocusIndicatorView.DEFAULT_LAYOUT_SIZE; + mFocusHandlerView.getLayoutParams().height = FocusIndicatorView.DEFAULT_LAYOUT_SIZE; } @Override diff --git a/src/com/android/launcher3/AppsCustomizePagedView.java b/src/com/android/launcher3/AppsCustomizePagedView.java index e0543ceb66..f78cff09df 100644 --- a/src/com/android/launcher3/AppsCustomizePagedView.java +++ b/src/com/android/launcher3/AppsCustomizePagedView.java @@ -1041,6 +1041,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen icon.setOnLongClickListener(this); icon.setOnTouchListener(this); icon.setOnKeyListener(this); + icon.setOnFocusChangeListener(layout.mFocusHandlerView); int index = i - startIndex; int x = index % mCellCountX; diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java index 1073764826..07120c5e49 100644 --- a/src/com/android/launcher3/CellLayout.java +++ b/src/com/android/launcher3/CellLayout.java @@ -989,10 +989,7 @@ public class CellLayout extends ViewGroup { } public ShortcutAndWidgetContainer getShortcutsAndWidgets() { - if (getChildCount() > 0) { - return (ShortcutAndWidgetContainer) getChildAt(0); - } - return null; + return mShortcutsAndWidgets; } public View getChildAt(int x, int y) { diff --git a/src/com/android/launcher3/FocusIndicatorView.java b/src/com/android/launcher3/FocusIndicatorView.java new file mode 100644 index 0000000000..12b7a40767 --- /dev/null +++ b/src/com/android/launcher3/FocusIndicatorView.java @@ -0,0 +1,146 @@ +/* + * 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.launcher3; + +import android.content.Context; +import android.graphics.Canvas; +import android.util.AttributeSet; +import android.util.Pair; +import android.view.View; +import android.view.ViewParent; + +public class FocusIndicatorView extends View implements View.OnFocusChangeListener { + + // It can be any number >0. The view is resized using scaleX and scaleY. + static final int DEFAULT_LAYOUT_SIZE = 100; + private static final float MIN_VISIBLE_ALPHA = 0.2f; + + private static final int[] sTempPos = new int[2]; + private static final int[] sTempShift = new int[2]; + + private final int[] mIndicatorPos = new int[2]; + private final int[] mTargetViewPos = new int[2]; + + private View mLastFocusedView; + private boolean mInitiated; + + private Pair mPendingCall; + + public FocusIndicatorView(Context context) { + this(context, null); + } + + public FocusIndicatorView(Context context, AttributeSet attrs) { + super(context, attrs); + setAlpha(0); + setBackgroundColor(getResources().getColor(R.color.focused_background)); + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + + // Redraw if it is already showing. This avoids a bug where the height changes by a small + // amount on connecting/disconnecting a bluetooth keyboard. + if (mLastFocusedView != null) { + mPendingCall = Pair.create(mLastFocusedView, Boolean.TRUE); + invalidate(); + } + } + + @Override + public void onFocusChange(View v, boolean hasFocus) { + mPendingCall = null; + if (!mInitiated && (getWidth() == 0)) { + // View not yet laid out. Wait until the view is ready to be drawn, so that be can + // get the location on screen. + mPendingCall = Pair.create(v, hasFocus); + invalidate(); + return; + } + + if (!mInitiated) { + getLocationRelativeToParentPagedView(this, mIndicatorPos); + mInitiated = true; + } + + if (hasFocus) { + int indicatorWidth = getWidth(); + int indicatorHeight = getHeight(); + + float scaleX = v.getScaleX() * v.getWidth() / indicatorWidth; + float scaleY = v.getScaleY() * v.getHeight() / indicatorHeight; + + getLocationRelativeToParentPagedView(v, mTargetViewPos); + float x = mTargetViewPos[0] - mIndicatorPos[0] - (1 - scaleX) * indicatorWidth / 2; + float y = mTargetViewPos[1] - mIndicatorPos[1] - (1 - scaleY) * indicatorHeight / 2; + + if (getAlpha() > MIN_VISIBLE_ALPHA) { + animate() + .translationX(x) + .translationY(y) + .scaleX(scaleX) + .scaleY(scaleY) + .alpha(1); + } else { + setTranslationX(x); + setTranslationY(y); + setScaleX(scaleX); + setScaleY(scaleY); + animate().alpha(1); + } + mLastFocusedView = v; + } else { + if (mLastFocusedView == v) { + mLastFocusedView = null; + animate().alpha(0); + } + } + } + + @Override + protected void onDraw(Canvas canvas) { + if (mPendingCall != null) { + onFocusChange(mPendingCall.first, mPendingCall.second); + } + } + + /** + * Gets the location of a view relative in the window, off-setting any shift due to + * page view scroll + */ + private static void getLocationRelativeToParentPagedView(View v, int[] pos) { + getPagedViewScrollShift(v, sTempShift); + v.getLocationInWindow(sTempPos); + pos[0] = sTempPos[0] + sTempShift[0]; + pos[1] = sTempPos[1] + sTempShift[1]; + } + + private static void getPagedViewScrollShift(View child, int[] shift) { + ViewParent parent = child.getParent(); + if (parent instanceof PagedView) { + View parentView = (View) parent; + child.getLocationInWindow(sTempPos); + shift[0] = parentView.getPaddingLeft() - sTempPos[0]; + shift[1] = -(int) child.getTranslationY(); + } else if (parent instanceof View) { + getPagedViewScrollShift((View) parent, shift); + } else { + shift[0] = shift[1] = 0; + } + } +} diff --git a/src/com/android/launcher3/Folder.java b/src/com/android/launcher3/Folder.java index fcedaead37..4a707711d0 100644 --- a/src/com/android/launcher3/Folder.java +++ b/src/com/android/launcher3/Folder.java @@ -112,6 +112,8 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList private static String sDefaultFolderName; private static String sHintText; + private FocusIndicatorView mFocusIndicatorHandler; + private int DRAG_MODE_NONE = 0; private int DRAG_MODE_REORDER = 1; private int mDragMode = DRAG_MODE_NONE; @@ -178,6 +180,11 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList mScrollView = (ScrollView) findViewById(R.id.scroll_view); mContent = (CellLayout) findViewById(R.id.folder_content); + mFocusIndicatorHandler = new FocusIndicatorView(getContext()); + mContent.addView(mFocusIndicatorHandler, 0); + mFocusIndicatorHandler.getLayoutParams().height = FocusIndicatorView.DEFAULT_LAYOUT_SIZE; + mFocusIndicatorHandler.getLayoutParams().width = FocusIndicatorView.DEFAULT_LAYOUT_SIZE; + LauncherAppState app = LauncherAppState.getInstance(); DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); @@ -572,6 +579,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList textView.setOnClickListener(this); textView.setOnLongClickListener(this); + textView.setOnFocusChangeListener(mFocusIndicatorHandler); // We need to check here to verify that the given item's location isn't already occupied // by another item. diff --git a/src/com/android/launcher3/FolderIcon.java b/src/com/android/launcher3/FolderIcon.java index c0b9da7d48..21efd7113d 100644 --- a/src/com/android/launcher3/FolderIcon.java +++ b/src/com/android/launcher3/FolderIcon.java @@ -178,6 +178,7 @@ public class FolderIcon extends FrameLayout implements FolderListener { icon.mFolderRingAnimator = new FolderRingAnimator(launcher, icon); folderInfo.addListener(icon); + icon.setOnFocusChangeListener(launcher.mFocusHandler); return icon; } diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java index 79cac8f643..3d6befae5d 100644 --- a/src/com/android/launcher3/Hotseat.java +++ b/src/com/android/launcher3/Hotseat.java @@ -159,6 +159,7 @@ public class Hotseat extends FrameLayout { allAppsButton.setOnTouchListener(mLauncher.getHapticFeedbackTouchListener()); mLauncher.setAllAppsButton(allAppsButton); allAppsButton.setOnClickListener(mLauncher); + allAppsButton.setOnFocusChangeListener(mLauncher.mFocusHandler); } // Note: We do this to ensure that the hotseat is always laid out in the orientation of diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 062e848385..c9d423c34e 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -384,6 +384,8 @@ public class Launcher extends Activity private Stats mStats; + FocusIndicatorView mFocusHandler; + static boolean isPropertyEnabled(String propertyName) { return Log.isLoggable(propertyName, Log.VERBOSE); } @@ -1289,6 +1291,7 @@ public class Launcher extends Activity final DragController dragController = mDragController; mLauncherView = findViewById(R.id.launcher); + mFocusHandler = (FocusIndicatorView) findViewById(R.id.focus_indicator); mDragLayer = (DragLayer) findViewById(R.id.drag_layer); mWorkspace = (Workspace) mDragLayer.findViewById(R.id.workspace); mWorkspace.setPageSwitchListener(this); @@ -1428,6 +1431,7 @@ public class Launcher extends Activity BubbleTextView favorite = (BubbleTextView) mInflater.inflate(layoutResId, parent, false); favorite.applyFromShortcutInfo(info, mIconCache, true); favorite.setOnClickListener(this); + favorite.setOnFocusChangeListener(mFocusHandler); return favorite; }