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 /quickstep/src/com/android | |
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
Diffstat (limited to 'quickstep/src/com/android')
4 files changed, 139 insertions, 10 deletions
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(); + } + } } |