diff --git a/res/values/config.xml b/res/values/config.xml index 04c359ede3..72959b2d5c 100644 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -34,6 +34,9 @@ popup_container_iterate_children + + false + diff --git a/src/com/android/launcher3/ExtendedEditText.java b/src/com/android/launcher3/ExtendedEditText.java index a4e1af6fb3..21bc479c22 100644 --- a/src/com/android/launcher3/ExtendedEditText.java +++ b/src/com/android/launcher3/ExtendedEditText.java @@ -99,8 +99,18 @@ public class ExtendedEditText extends EditText { } } - // inherited class can override to change the appearance of the edit text. - public void show() {} + /** + * Sets whether EditText background should be visible + * @param maxAlpha defines the maximum alpha the background should animates to + */ + public void setBackgroundVisibility(boolean visible, float maxAlpha) {} + + /** + * Returns whether a visible background is set on EditText + */ + public boolean getBackgroundVisibility() { + return getBackground() != null; + } public void showKeyboard() { mShowImeAfterFirstLayout = !showSoftInput(); diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java index 9c61c1b69f..57a3e1c7bb 100644 --- a/src/com/android/launcher3/allapps/AllAppsContainerView.java +++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java @@ -59,6 +59,7 @@ import com.android.launcher3.DeviceProfile; import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener; import com.android.launcher3.DragSource; import com.android.launcher3.DropTarget.DragObject; +import com.android.launcher3.ExtendedEditText; import com.android.launcher3.Insettable; import com.android.launcher3.InsettableFrameLayout; import com.android.launcher3.R; @@ -118,7 +119,7 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo private SpannableStringBuilder mSearchQueryBuilder = null; protected boolean mUsingTabs; - private boolean mSearchModeWhileUsingTabs = false; + private boolean mIsSearching; protected RecyclerViewFastScroller mTouchHandler; protected final Point mFastScrollerOffset = new Point(); @@ -132,6 +133,7 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo private final float mHeaderThreshold; private ScrimView mScrimView; private int mHeaderColor; + private int mTabsProtectionAlpha; public AllAppsContainerView(Context context) { this(context, null); @@ -625,18 +627,19 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo for (int i = 0; i < mAH.length; i++) { mAH[i].adapter.setLastSearchQuery(query); } + mIsSearching = true; if (mUsingTabs) { - mSearchModeWhileUsingTabs = true; rebindAdapters(false); // hide tabs } mHeader.setCollapsed(true); } public void onClearSearchResult() { - if (mSearchModeWhileUsingTabs) { + if (mUsingTabs) { rebindAdapters(true); // show tabs - mSearchModeWhileUsingTabs = false; } + mIsSearching = false; + getActiveRecyclerView().scrollToTop(); } public void onSearchResultsChanged() { @@ -710,13 +713,12 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo mHeaderPaint.setColor(mHeaderColor); mHeaderPaint.setAlpha((int) (getAlpha() * Color.alpha(mHeaderColor))); if (mHeaderPaint.getColor() != mScrimColor && mHeaderPaint.getColor() != 0) { - int bottom = mUsingTabs && mHeader.mHeaderCollapsed ? mHeader.getVisibleBottomBound() - : mSearchContainer.getBottom(); - canvas.drawRect(0, 0, canvas.getWidth(), bottom + getTranslationY(), - mHeaderPaint); - - if (FeatureFlags.ENABLE_DEVICE_SEARCH.get() && getTranslationY() == 0) { - mSearchUiManager.getEditText().setBackground(null); + int bottom = (int) (mSearchContainer.getBottom() + getTranslationY()); + canvas.drawRect(0, 0, canvas.getWidth(), bottom, mHeaderPaint); + int tabsHeight = getFloatingHeaderView().getPeripheralProtectionHeight(); + if (mTabsProtectionAlpha > 0 && tabsHeight != 0) { + mHeaderPaint.setAlpha((int) (getAlpha() * mTabsProtectionAlpha)); + canvas.drawRect(0, bottom, canvas.getWidth(), bottom + tabsHeight, mHeaderPaint); } } } @@ -796,18 +798,29 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo protected void updateHeaderScroll(int scrolledOffset) { - float prog = Math.max(0, Math.min(1, (float) scrolledOffset / mHeaderThreshold)); + + float prog = Utilities.boundToRange((float) scrolledOffset / mHeaderThreshold, 0f, 1f); int viewBG = ColorUtils.blendARGB(mScrimColor, mHeaderProtectionColor, prog); int headerColor = ColorUtils.setAlphaComponent(viewBG, (int) (getSearchView().getAlpha() * 255)); - if (headerColor != mHeaderColor) { + int tabsAlpha = mHeader.getPeripheralProtectionHeight() == 0 ? 0 + : (int) (Utilities.boundToRange( + (scrolledOffset + mHeader.mSnappedScrolledY) / mHeaderThreshold, 0f, 1f) + * 255); + if (headerColor != mHeaderColor || mTabsProtectionAlpha != tabsAlpha) { mHeaderColor = headerColor; - getSearchView().setBackgroundColor(viewBG); - getFloatingHeaderView().setHeaderColor(viewBG); + mTabsProtectionAlpha = tabsAlpha; invalidateHeader(); - if (scrolledOffset == 0 && mSearchUiManager.getEditText() != null) { - mSearchUiManager.getEditText().show(); + } + if (mSearchUiManager.getEditText() != null) { + ExtendedEditText editText = mSearchUiManager.getEditText(); + boolean bgVisible = editText.getBackgroundVisibility(); + if (scrolledOffset == 0 && !mIsSearching) { + bgVisible = true; + } else if (scrolledOffset > mHeaderThreshold) { + bgVisible = false; } + editText.setBackgroundVisibility(bgVisible, 1 - prog); } } @@ -815,7 +828,7 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo * redraws header protection */ public void invalidateHeader() { - if (mScrimView != null && FeatureFlags.ENABLE_DEVICE_SEARCH.get()) { + if (mScrimView != null && mHeader.isHeaderProtectionSupported()) { mScrimView.invalidate(); } } diff --git a/src/com/android/launcher3/allapps/FloatingHeaderView.java b/src/com/android/launcher3/allapps/FloatingHeaderView.java index 8ea83d56ac..debb5b20c1 100644 --- a/src/com/android/launcher3/allapps/FloatingHeaderView.java +++ b/src/com/android/launcher3/allapps/FloatingHeaderView.java @@ -17,9 +17,6 @@ package com.android.launcher3.allapps; import android.animation.ValueAnimator; import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; import android.graphics.Point; import android.graphics.Rect; import android.util.ArrayMap; @@ -50,11 +47,10 @@ public class FloatingHeaderView extends LinearLayout implements ValueAnimator.AnimatorUpdateListener, PluginListener, Insettable, OnHeightUpdatedListener { - private final Rect mClip = new Rect(0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE); + private final Rect mRVClip = new Rect(0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE); + private final Rect mHeaderClip = new Rect(0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE); private final ValueAnimator mAnimator = ValueAnimator.ofInt(0, 0); - private final ValueAnimator mHeaderAnimator = ValueAnimator.ofInt(0, 1).setDuration(100); private final Point mTempOffset = new Point(); - private final Paint mBGPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private final RecyclerView.OnScrollListener mOnScrollListener = new RecyclerView.OnScrollListener() { @Override @@ -82,19 +78,19 @@ public class FloatingHeaderView extends LinearLayout implements } }; - private final int mHeaderTopPadding; - protected final Map mPluginRows = new ArrayMap<>(); + private final int mHeaderTopPadding; + private final boolean mHeaderProtectionSupported; + protected ViewGroup mTabLayout; private AllAppsRecyclerView mMainRV; private AllAppsRecyclerView mWorkRV; private AllAppsRecyclerView mCurrentRV; private ViewGroup mParent; public boolean mHeaderCollapsed; - private int mSnappedScrolledY; + protected int mSnappedScrolledY; private int mTranslationY; - private int mHeaderColor; private boolean mForwardToRecyclerView; @@ -120,6 +116,8 @@ public class FloatingHeaderView extends LinearLayout implements super(context, attrs); mHeaderTopPadding = context.getResources() .getDimensionPixelSize(R.dimen.all_apps_header_top_padding); + mHeaderProtectionSupported = context.getResources().getBoolean( + R.bool.config_header_protection_supported); } @Override @@ -138,7 +136,6 @@ public class FloatingHeaderView extends LinearLayout implements } mFixedRows = rows.toArray(new FloatingHeaderRow[rows.size()]); mAllRows = mFixedRows; - mHeaderAnimator.addUpdateListener(valueAnimator -> invalidate()); } @Override @@ -285,7 +282,7 @@ public class FloatingHeaderView extends LinearLayout implements mHeaderCollapsed = false; } mTranslationY = currentScrollY; - } else if (!mHeaderCollapsed) { + } else { mTranslationY = currentScrollY - mSnappedScrolledY - mMaxTranslation; // update state vars @@ -295,31 +292,10 @@ public class FloatingHeaderView extends LinearLayout implements } else if (mTranslationY <= -mMaxTranslation) { // hide or stay hidden mHeaderCollapsed = true; mSnappedScrolledY = -mMaxTranslation; - mHeaderAnimator.setCurrentFraction(0); - mHeaderAnimator.start(); } } } - /** - * Set current header protection background color - */ - public void setHeaderColor(int color) { - mHeaderColor = color; - invalidate(); - } - - @Override - protected void dispatchDraw(Canvas canvas) { - if (mHeaderCollapsed && !mCollapsed && mTabLayout.getVisibility() == VISIBLE - && mHeaderColor != Color.TRANSPARENT && FeatureFlags.ENABLE_DEVICE_SEARCH.get()) { - mBGPaint.setColor(mHeaderColor); - mBGPaint.setAlpha((int) (255 * mHeaderAnimator.getAnimatedFraction())); - canvas.drawRect(0, 0, getWidth(), getHeight() + mTranslationY, mBGPaint); - } - super.dispatchDraw(canvas); - } - protected void applyVerticalMove() { int uncappedTranslationY = mTranslationY; mTranslationY = Math.max(mTranslationY, -mMaxTranslation); @@ -336,11 +312,15 @@ public class FloatingHeaderView extends LinearLayout implements } mTabLayout.setTranslationY(mTranslationY); - mClip.top = mMaxTranslation + mTranslationY; + + int clipHeight = mHeaderTopPadding - getPaddingBottom(); + mRVClip.top = mTabsHidden ? clipHeight : 0; + mHeaderClip.top = clipHeight; // clipping on a draw might cause additional redraw - mMainRV.setClipBounds(mClip); + setClipBounds(mHeaderClip); + mMainRV.setClipBounds(mRVClip); if (mWorkRV != null) { - mWorkRV.setClipBounds(mClip); + mWorkRV.setClipBounds(mRVClip); } } @@ -421,6 +401,10 @@ public class FloatingHeaderView extends LinearLayout implements return false; } + public boolean isHeaderProtectionSupported() { + return mHeaderProtectionSupported; + } + @Override public boolean hasOverlappingRendering() { return false; @@ -444,10 +428,19 @@ public class FloatingHeaderView extends LinearLayout implements } /** - * Returns visible height of FloatingHeaderView contents + * Returns visible height of FloatingHeaderView contents requiring header protection */ - public int getVisibleBottomBound() { - return getBottom() + mTranslationY; + public int getPeripheralProtectionHeight() { + if (!mHeaderProtectionSupported) { + return 0; + } + + // we only want to show protection when work tab is available and header is either + // collapsed or animating to/from collapsed state + if (mTabsHidden || !mHeaderCollapsed) { + return 0; + } + return Math.max(getHeight() - getPaddingTop() + mTranslationY, 0); } }