diff options
author | Sunny Goyal <sunnygoyal@google.com> | 2018-03-26 15:33:41 -0700 |
---|---|---|
committer | Sunny Goyal <sunnygoyal@google.com> | 2018-03-26 17:24:12 -0700 |
commit | 00c9c9a6fc551fef89658a11abe544248247f3b6 (patch) | |
tree | e1f452f350129fe10fda2c589522f500ab12976d | |
parent | 3d58de67a87b589eacbf8b4d4e3872b7bb7576e7 (diff) | |
download | android_packages_apps_Trebuchet-00c9c9a6fc551fef89658a11abe544248247f3b6.tar.gz android_packages_apps_Trebuchet-00c9c9a6fc551fef89658a11abe544248247f3b6.tar.bz2 android_packages_apps_Trebuchet-00c9c9a6fc551fef89658a11abe544248247f3b6.zip |
Adding an empty message in RecentsView
Moving the content instead of translating the view. This ensures
that the empty message fades in place while the other content come-in
from the side.
Change-Id: I081d2e21206de24ad530814cb6a8ca7c3e293724
8 files changed, 176 insertions, 11 deletions
diff --git a/quickstep/res/drawable/ic_empty_recents.xml b/quickstep/res/drawable/ic_empty_recents.xml new file mode 100644 index 000000000..518373397 --- /dev/null +++ b/quickstep/res/drawable/ic_empty_recents.xml @@ -0,0 +1,30 @@ +<!-- +Copyright (C) 2018 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="92dp" + android:height="80dp" + android:viewportWidth="92.0" + android:viewportHeight="80.0" + android:tint="?android:attr/textColorPrimary"> + <path + android:fillColor="#AAFFFFFF" + android:pathData="M18,6H2C0.9,6,0,6.9,0,8v64c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8C20,6.9,19.1,6,18,6z M16,69.25 + c0,0.41-0.34,0.75-0.75,0.75H4.75C4.34,70,4,69.66,4,69.25v-58.5C4,10.34,4.34,10,4.75,10h10.5c0.41,0,0.75,0.34,0.75,0.75V69.25 + z M90,6H74c-1.1,0-2,0.9-2,2v64c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8C92,6.9,91.1,6,90,6z M88,69.25c0,0.41-0.34,0.75-0.75,0.75 + h-10.5C76.34,70,76,69.66,76,69.25v-58.5c0-0.41,0.34-0.75,0.75-0.75h10.5c0.41,0,0.75,0.34,0.75,0.75V69.25z M64,0H28 + c-2.21,0-4,1.79-4,4v72c0,2.21,1.79,4,4,4h36c2.21,0,4-1.79,4-4V4C68,1.79,66.21,0,64,0z M64,75c0,0.55-0.45,1-1,1H29 + c-0.55,0-1-0.45-1-1V5c0-0.55,0.45-1,1-1h34c0.55,0,1,0.45,1,1V75z"/> +</vector> diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml index b751e0d9c..e35419310 100644 --- a/quickstep/res/values/dimens.xml +++ b/quickstep/res/values/dimens.xml @@ -36,4 +36,8 @@ <dimen name="recents_adjacent_trans_x">140dp</dimen> <dimen name="recents_adjacent_trans_y">80dp</dimen> <fraction name="recents_adjacent_scale">150%</fraction> + + <dimen name="recents_empty_message_text_size">16sp</dimen> + <dimen name="recents_empty_message_text_padding">16dp</dimen> + </resources> diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml index c36e1ff18..bd37a06ae 100644 --- a/quickstep/res/values/strings.xml +++ b/quickstep/res/values/strings.xml @@ -32,4 +32,7 @@ <!-- Content description for the recent apps panel (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_desc_recent_apps">Overview</string> + + <!-- Recents: The empty recents string. [CHAR LIMIT=NONE] --> + <string name="recents_empty_message">No recent items</string> </resources>
\ No newline at end of file diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java index d8f206c5e..5f94bcaf1 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java @@ -56,6 +56,7 @@ public class RecentsViewStateController implements StateHandler { mRecentsView.setTranslationXFactor(translationFactor[0]); mRecentsView.setTranslationYFactor(translationFactor[1]); if (state.overviewUi) { + mRecentsView.updateEmptyMessage(); mRecentsView.resetTaskVisuals(); } } @@ -94,6 +95,7 @@ public class RecentsViewStateController implements StateHandler { }); updateAnim.setDuration(config.duration); builder.play(updateAnim); + mRecentsView.updateEmptyMessage(); } } } diff --git a/quickstep/src/com/android/quickstep/FallbackRecentsView.java b/quickstep/src/com/android/quickstep/FallbackRecentsView.java index 032d753a6..251e95806 100644 --- a/quickstep/src/com/android/quickstep/FallbackRecentsView.java +++ b/quickstep/src/com/android/quickstep/FallbackRecentsView.java @@ -16,8 +16,10 @@ package com.android.quickstep; import android.content.Context; +import android.graphics.Canvas; import android.graphics.Rect; import android.util.AttributeSet; +import android.view.View; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Insettable; @@ -32,6 +34,7 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity> implements public FallbackRecentsView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setOverviewStateEnabled(true); + updateEmptyMessage(); } @Override @@ -40,6 +43,18 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity> implements } @Override + public void onViewAdded(View child) { + super.onViewAdded(child); + updateEmptyMessage(); + } + + @Override + public void onViewRemoved(View child) { + super.onViewRemoved(child); + updateEmptyMessage(); + } + + @Override public void setInsets(Rect insets) { mInsets.set(insets); DeviceProfile dp = mActivity.getDeviceProfile(); @@ -65,4 +80,10 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity> implements grid.widthPx - targetPadding.right - insets.right, grid.heightPx - targetPadding.bottom - insets.bottom); } + + @Override + public void draw(Canvas canvas) { + maybeDrawEmptyMessage(canvas); + super.draw(canvas); + } } diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java index 861b5fa03..34c3e4f05 100644 --- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java +++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java @@ -19,10 +19,12 @@ import static com.android.launcher3.LauncherState.NORMAL; import android.annotation.TargetApi; import android.content.Context; +import android.graphics.Canvas; import android.graphics.Rect; import android.os.Build; import android.util.AttributeSet; import android.util.FloatProperty; +import android.view.View; import android.widget.FrameLayout; import com.android.launcher3.DeviceProfile; @@ -103,19 +105,12 @@ public class LauncherRecentsView extends RecentsView<Launcher> implements Insett @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); - - int width = right - left; - setTranslationX(mTranslationXFactor * (mIsRtl ? -width : width)); setTranslationYFactor(mTranslationYFactor); } public void setTranslationXFactor(float translationFactor) { mTranslationXFactor = translationFactor; - setTranslationX(translationFactor * (mIsRtl ? -getWidth() : getWidth())); - } - - public float getTranslationXFactor() { - return mTranslationXFactor; + invalidate(); } public void setTranslationYFactor(float translationFactor) { @@ -123,7 +118,24 @@ public class LauncherRecentsView extends RecentsView<Launcher> implements Insett setTranslationY(mTranslationYFactor * (mPagePadding.bottom - mPagePadding.top)); } - public float getTranslationYFactor() { - return mTranslationYFactor; + @Override + public void draw(Canvas canvas) { + maybeDrawEmptyMessage(canvas); + int count = canvas.save(); + canvas.translate(mTranslationXFactor * (mIsRtl ? -getWidth() : getWidth()), 0); + super.draw(canvas); + canvas.restoreToCount(count); + } + + @Override + public void onViewAdded(View child) { + super.onViewAdded(child); + updateEmptyMessage(); + } + + @Override + protected void onTaskStackUpdated() { + // Lazily update the empty message only when the task stack is reapplied + updateEmptyMessage(); } } diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index 8901e6d8c..f75d6bcf7 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -29,8 +29,14 @@ import android.annotation.TargetApi; import android.content.Context; import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; +import android.graphics.Canvas; +import android.graphics.Point; import android.graphics.Rect; +import android.graphics.drawable.Drawable; import android.os.Build; +import android.text.Layout; +import android.text.StaticLayout; +import android.text.TextPaint; import android.util.ArraySet; import android.util.AttributeSet; import android.util.FloatProperty; @@ -46,6 +52,7 @@ import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.config.FeatureFlags; +import com.android.launcher3.util.Themes; import com.android.quickstep.PendingAnimation; import com.android.quickstep.QuickScrubController; import com.android.quickstep.RecentsModel; @@ -130,6 +137,15 @@ public abstract class RecentsView<T extends BaseActivity> // Keeps track of task views whose visual state should not be reset private ArraySet<TaskView> mIgnoreResetTaskViews = new ArraySet<>(); + // Variables for empty state + private final Drawable mEmptyIcon; + private final CharSequence mEmptyMessage; + private final TextPaint mEmptyMessagePaint; + private final Point mLastMeasureSize = new Point(); + private final int mEmptyMessagePadding; + private boolean mShowEmptyMessage; + private Layout mEmptyTextLayout; + public RecentsView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setPageSpacing(getResources().getDimensionPixelSize(R.dimen.recents_page_spacing)); @@ -143,6 +159,17 @@ public abstract class RecentsView<T extends BaseActivity> mModel = RecentsModel.getInstance(context); onSharedPreferenceChanged(Utilities.getPrefs(context), PREF_FLIP_RECENTS); + + mEmptyIcon = context.getDrawable(R.drawable.ic_empty_recents); + mEmptyIcon.setCallback(this); + mEmptyMessage = context.getText(R.string.recents_empty_message); + mEmptyMessagePaint = new TextPaint(); + mEmptyMessagePaint.setColor(Themes.getAttrColor(context, android.R.attr.textColorPrimary)); + mEmptyMessagePaint.setTextSize(getResources() + .getDimension(R.dimen.recents_empty_message_text_size)); + mEmptyMessagePadding = getResources() + .getDimensionPixelSize(R.dimen.recents_empty_message_text_padding); + setWillNotDraw(false); } @Override @@ -247,6 +274,7 @@ public abstract class RecentsView<T extends BaseActivity> TaskStack stack = loadPlan != null ? loadPlan.getTaskStack() : null; if (stack == null) { removeAllViews(); + onTaskStackUpdated(); return; } @@ -283,8 +311,11 @@ public abstract class RecentsView<T extends BaseActivity> if (oldChildCount != getChildCount()) { mQuickScrubController.snapToNextTaskIfAvailable(); } + onTaskStackUpdated(); } + protected void onTaskStackUpdated() { } + public void resetTaskVisuals() { for (int i = getChildCount() - 1; i >= 0; i--) { TaskView taskView = (TaskView) getChildAt(i); @@ -700,6 +731,11 @@ public abstract class RecentsView<T extends BaseActivity> for (int i = getChildCount() - 1; i >= 0; i--) { getChildAt(i).setAlpha(alpha); } + + int alphaInt = Math.round(alpha * 255); + mEmptyMessagePaint.setAlpha(alphaInt); + mEmptyIcon.setAlpha(alphaInt); + setVisibility(alpha > 0 ? VISIBLE : GONE); } @@ -708,4 +744,62 @@ public abstract class RecentsView<T extends BaseActivity> super.onViewAdded(child); child.setAlpha(mContentAlpha); } + + public void updateEmptyMessage() { + boolean isEmpty = getChildCount() == 0; + boolean hasSizeChanged = mLastMeasureSize.x != getWidth() + || mLastMeasureSize.y != getHeight(); + if (isEmpty == mShowEmptyMessage && !hasSizeChanged) { + return; + } + setContentDescription(isEmpty ? mEmptyMessage : ""); + mShowEmptyMessage = isEmpty; + updateEmptyStateUi(hasSizeChanged); + invalidate(); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + updateEmptyStateUi(changed); + } + + private void updateEmptyStateUi(boolean sizeChanged) { + boolean hasValidSize = getWidth() > 0 && getHeight() > 0; + if (sizeChanged && hasValidSize) { + mEmptyTextLayout = null; + } + + if (mShowEmptyMessage && hasValidSize && mEmptyTextLayout == null) { + mLastMeasureSize.set(getWidth(), getHeight()); + int availableWidth = mLastMeasureSize.x - mEmptyMessagePadding - mEmptyMessagePadding; + mEmptyTextLayout = StaticLayout.Builder.obtain(mEmptyMessage, 0, mEmptyMessage.length(), + mEmptyMessagePaint, availableWidth) + .setAlignment(Layout.Alignment.ALIGN_CENTER) + .build(); + int totalHeight = mEmptyTextLayout.getHeight() + + mEmptyMessagePadding + mEmptyIcon.getIntrinsicHeight(); + + int top = (mLastMeasureSize.y - totalHeight) / 2; + int left = (mLastMeasureSize.x - mEmptyIcon.getIntrinsicWidth()) / 2; + mEmptyIcon.setBounds(left, top, left + mEmptyIcon.getIntrinsicWidth(), + top + mEmptyIcon.getIntrinsicHeight()); + } + } + + @Override + protected boolean verifyDrawable(Drawable who) { + return super.verifyDrawable(who) || (mShowEmptyMessage && who == mEmptyIcon); + } + + protected void maybeDrawEmptyMessage(Canvas canvas) { + if (mShowEmptyMessage && mEmptyTextLayout != null) { + mEmptyIcon.draw(canvas); + canvas.save(); + canvas.translate(mEmptyMessagePadding, + mEmptyIcon.getBounds().bottom + mEmptyMessagePadding); + mEmptyTextLayout.draw(canvas); + canvas.restore(); + } + } } diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java index a1ac122d8..1e761e41d 100644 --- a/src/com/android/launcher3/PagedView.java +++ b/src/com/android/launcher3/PagedView.java @@ -187,7 +187,6 @@ public abstract class PagedView<T extends View & PageIndicator> extends ViewGrou mFlingThresholdVelocity = (int) (FLING_THRESHOLD_VELOCITY * density); mMinFlingVelocity = (int) (MIN_FLING_VELOCITY * density); mMinSnapVelocity = (int) (MIN_SNAP_VELOCITY * density); - setWillNotDraw(false); if (Utilities.ATLEAST_OREO) { setDefaultFocusHighlightEnabled(false); |