Support for animating A-Z <-> Search.

Demo videos (1/5 speed) and APK: https://drive.google.com/drive/folders/1qQNzcoibiFMzxYhvXc7UEHCaBhJg6SjN?resourcekey=0-OWD06iLXg3wf_eWce4rUPA&usp=sharing

Bug: 234882587
Bug: 243688989
Test: Manually tested a bunch of cases at 1/10 animation speed.
Such as work profile or not, suggested apps enabled/disabled,
typing during the animation, going back during the animation,
web results injected above apps, etc.

Change-Id: Id4f1a858d387bf3a7f9cf2d23564a276544abef1
This commit is contained in:
Andy Wickham
2022-08-28 21:54:04 -07:00
parent 3426372ff8
commit 94d5d3cb6c
11 changed files with 417 additions and 58 deletions

View File

@@ -42,6 +42,7 @@ import com.android.systemui.plugins.AllAppsRow.OnHeightUpdatedListener;
import com.android.systemui.plugins.PluginListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Map;
public class FloatingHeaderView extends LinearLayout implements
@@ -82,8 +83,8 @@ public class FloatingHeaderView extends LinearLayout implements
protected final Map<AllAppsRow, PluginHeaderRow> mPluginRows = new ArrayMap<>();
// These two values are necessary to ensure that the header protection is drawn correctly.
private final int mHeaderTopAdjustment;
private final int mHeaderBottomAdjustment;
private final int mTabsAdditionalPaddingTop;
private final int mTabsAdditionalPaddingBottom;
private boolean mHeaderProtectionSupported;
protected ViewGroup mTabLayout;
@@ -91,7 +92,6 @@ public class FloatingHeaderView extends LinearLayout implements
private AllAppsRecyclerView mWorkRV;
private SearchRecyclerView mSearchRV;
private AllAppsRecyclerView mCurrentRV;
public boolean mHeaderCollapsed;
protected int mSnappedScrolledY;
private int mTranslationY;
@@ -100,7 +100,12 @@ public class FloatingHeaderView extends LinearLayout implements
protected boolean mTabsHidden;
protected int mMaxTranslation;
private boolean mCollapsed = false;
// Whether the header has been scrolled off-screen.
private boolean mHeaderCollapsed;
// Whether floating rows like predicted apps are hidden.
private boolean mFloatingRowsCollapsed;
// Total height of all current floating rows. Collapsed rows == 0 height.
private int mFloatingRowsHeight;
// This is initialized once during inflation and stays constant after that. Fixed views
// cannot be added or removed dynamically.
@@ -117,9 +122,9 @@ public class FloatingHeaderView extends LinearLayout implements
public FloatingHeaderView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mHeaderTopAdjustment = context.getResources()
mTabsAdditionalPaddingTop = context.getResources()
.getDimensionPixelSize(R.dimen.all_apps_header_top_adjustment);
mHeaderBottomAdjustment = context.getResources()
mTabsAdditionalPaddingBottom = context.getResources()
.getDimensionPixelSize(R.dimen.all_apps_header_bottom_adjustment);
mHeaderProtectionSupported = context.getResources().getBoolean(
R.bool.config_header_protection_supported);
@@ -148,6 +153,7 @@ public class FloatingHeaderView extends LinearLayout implements
}
mFixedRows = rows.toArray(new FloatingHeaderRow[rows.size()]);
mAllRows = mFixedRows;
updateFloatingRowsHeight();
}
@Override
@@ -179,6 +185,7 @@ public class FloatingHeaderView extends LinearLayout implements
count++;
}
}
updateFloatingRowsHeight();
}
@Override
@@ -195,7 +202,7 @@ public class FloatingHeaderView extends LinearLayout implements
int oldMaxHeight = mMaxTranslation;
updateExpectedHeight();
if (mMaxTranslation != oldMaxHeight || mCollapsed) {
if (mMaxTranslation != oldMaxHeight || mFloatingRowsCollapsed) {
BaseAllAppsContainerView<?> parent = (BaseAllAppsContainerView<?>) getParent();
if (parent != null) {
parent.setupHeader();
@@ -258,20 +265,19 @@ public class FloatingHeaderView extends LinearLayout implements
}
private void updateExpectedHeight() {
updateFloatingRowsHeight();
mMaxTranslation = 0;
if (mCollapsed) {
if (mFloatingRowsCollapsed) {
return;
}
for (FloatingHeaderRow row : mAllRows) {
mMaxTranslation += row.getExpectedHeight();
}
mMaxTranslation += mFloatingRowsHeight;
if (!mTabsHidden) {
mMaxTranslation += mHeaderBottomAdjustment;
mMaxTranslation += mTabsAdditionalPaddingBottom;
}
}
public int getMaxTranslation() {
if (mMaxTranslation == 0 && mTabsHidden) {
if (mMaxTranslation == 0 && (mTabsHidden || mFloatingRowsCollapsed)) {
return getResources().getDimensionPixelSize(R.dimen.all_apps_search_bar_bottom_padding);
} else if (mMaxTranslation > 0 && mTabsHidden) {
return mMaxTranslation + getPaddingTop();
@@ -312,7 +318,7 @@ public class FloatingHeaderView extends LinearLayout implements
int uncappedTranslationY = mTranslationY;
mTranslationY = Math.max(mTranslationY, -mMaxTranslation);
if (mCollapsed || uncappedTranslationY < mTranslationY - getPaddingTop()) {
if (mFloatingRowsCollapsed || uncappedTranslationY < mTranslationY - getPaddingTop()) {
// we hide it completely if already capped (for opening search anim)
for (FloatingHeaderRow row : mAllRows) {
row.setVerticalScroll(0, true /* isScrolledOut */);
@@ -325,11 +331,11 @@ public class FloatingHeaderView extends LinearLayout implements
mTabLayout.setTranslationY(mTranslationY);
int clipTop = getPaddingTop() - mHeaderTopAdjustment;
int clipTop = getPaddingTop() - mTabsAdditionalPaddingTop;
if (mTabsHidden) {
clipTop += getPaddingBottom() - mHeaderBottomAdjustment;
clipTop += getPaddingBottom() - mTabsAdditionalPaddingBottom;
}
mRVClip.top = mTabsHidden ? clipTop : 0;
mRVClip.top = mTabsHidden || mFloatingRowsCollapsed ? clipTop : 0;
mHeaderClip.top = clipTop;
// clipping on a draw might cause additional redraw
setClipBounds(mHeaderClip);
@@ -347,10 +353,12 @@ public class FloatingHeaderView extends LinearLayout implements
/**
* Hides all the floating rows
*/
public void setCollapsed(boolean collapse) {
if (mCollapsed == collapse) return;
public void setFloatingRowsCollapsed(boolean collapsed) {
if (mFloatingRowsCollapsed == collapsed) {
return;
}
mCollapsed = collapse;
mFloatingRowsCollapsed = collapsed;
onHeightUpdated();
}
@@ -376,6 +384,30 @@ public class FloatingHeaderView extends LinearLayout implements
return !mHeaderCollapsed;
}
/** Returns true if personal/work tabs are currently in use. */
public boolean usingTabs() {
return !mTabsHidden;
}
ViewGroup getTabLayout() {
return mTabLayout;
}
/** Calculates the combined height of any floating rows (e.g. predicted apps, app divider). */
private void updateFloatingRowsHeight() {
mFloatingRowsHeight =
Arrays.stream(mAllRows).mapToInt(FloatingHeaderRow::getExpectedHeight).sum();
}
/** Gets the combined height of any floating rows (e.g. predicted apps, app divider). */
int getFloatingRowsHeight() {
return mFloatingRowsHeight;
}
int getTabsAdditionalPaddingBottom() {
return mTabsAdditionalPaddingBottom;
}
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mTranslationY = (Integer) animation.getAnimatedValue();
@@ -447,9 +479,10 @@ public class FloatingHeaderView extends LinearLayout implements
// 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) {
if (mTabsHidden || mFloatingRowsCollapsed || !mHeaderCollapsed) {
return 0;
}
return Math.max(getHeight() - getPaddingTop() + mTranslationY, 0);
return Math.max(0,
getTabLayout().getBottom() - getPaddingTop() + getPaddingBottom() + mTranslationY);
}
}