Merge "[Search][Motion] Introduce header protection in AllApps" into sc-dev
This commit is contained in:
@@ -92,7 +92,8 @@
|
||||
<dimen name="all_apps_background_canvas_width">700dp</dimen>
|
||||
<dimen name="all_apps_background_canvas_height">475dp</dimen>
|
||||
<dimen name="all_apps_header_pill_height">50dp</dimen>
|
||||
<dimen name="all_apps_header_pill_corner_radius">50dp</dimen>
|
||||
<dimen name="all_apps_header_pill_corner_radius">48dp</dimen>
|
||||
<dimen name="all_apps_header_tab_height">48dp</dimen>
|
||||
<dimen name="all_apps_tabs_indicator_height">2dp</dimen>
|
||||
<dimen name="all_apps_header_top_padding">36dp</dimen>
|
||||
<dimen name="all_apps_work_profile_tab_footer_top_padding">16dp</dimen>
|
||||
|
||||
@@ -1192,7 +1192,7 @@ public class Launcher extends StatefulActivity<LauncherState> implements Launche
|
||||
|
||||
// Setup the drag controller (drop targets have to be added in reverse order in priority)
|
||||
mDropTargetBar.setup(mDragController);
|
||||
mAllAppsController.setupViews(mAppsView);
|
||||
mAllAppsController.setupViews(mScrimView, mAppsView);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -26,6 +26,7 @@ import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
@@ -44,6 +45,7 @@ import android.view.WindowInsets;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
import androidx.core.os.BuildCompat;
|
||||
import androidx.recyclerview.widget.DefaultItemAnimator;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
@@ -66,6 +68,7 @@ import com.android.launcher3.testing.TestProtocol;
|
||||
import com.android.launcher3.util.ItemInfoMatcher;
|
||||
import com.android.launcher3.util.Themes;
|
||||
import com.android.launcher3.views.RecyclerViewFastScroller;
|
||||
import com.android.launcher3.views.ScrimView;
|
||||
import com.android.launcher3.views.SpringRelativeLayout;
|
||||
import com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip.OnActivePageChangedListener;
|
||||
|
||||
@@ -73,13 +76,16 @@ import com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip.OnActivePag
|
||||
* The all apps view container.
|
||||
*/
|
||||
public class AllAppsContainerView extends SpringRelativeLayout implements DragSource,
|
||||
Insettable, OnDeviceProfileChangeListener, OnActivePageChangedListener {
|
||||
Insettable, OnDeviceProfileChangeListener, OnActivePageChangedListener,
|
||||
ScrimView.ScrimDrawingController {
|
||||
|
||||
private static final float FLING_VELOCITY_MULTIPLIER = 1000f;
|
||||
|
||||
// Starts the springs after at least 25% of the animation has passed.
|
||||
private static final float FLING_ANIMATION_THRESHOLD = 0.25f;
|
||||
|
||||
private final Paint mHeaderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
|
||||
protected final BaseDraggingActivity mLauncher;
|
||||
protected final AdapterHolder[] mAH;
|
||||
private final ItemInfoMatcher mPersonalMatcher = ItemInfoMatcher.ofUser(Process.myUserHandle());
|
||||
@@ -93,7 +99,7 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
|
||||
private View mSearchContainer;
|
||||
private AllAppsPagedView mViewPager;
|
||||
|
||||
private FloatingHeaderView mHeader;
|
||||
protected FloatingHeaderView mHeader;
|
||||
private WorkModeSwitch mWorkModeSwitch;
|
||||
|
||||
|
||||
@@ -107,7 +113,14 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
|
||||
|
||||
private Rect mInsets = new Rect();
|
||||
|
||||
SearchAdapterProvider mSearchAdapterProvider;
|
||||
private SearchAdapterProvider mSearchAdapterProvider;
|
||||
private final int mHeaderTopPadding;
|
||||
private final int mScrimColor;
|
||||
private final int mHeaderProtectionColor;
|
||||
private final float mHeaderThreshold;
|
||||
private ScrimView mScrimView;
|
||||
private int mHeaderColor;
|
||||
|
||||
|
||||
public AllAppsContainerView(Context context) {
|
||||
this(context, null);
|
||||
@@ -121,8 +134,19 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
|
||||
super(context, attrs, defStyleAttr);
|
||||
|
||||
mLauncher = BaseDraggingActivity.fromContext(context);
|
||||
|
||||
mScrimColor = Themes.getAttrColor(context, R.attr.allAppsScrimColor);
|
||||
mHeaderThreshold = getResources().getDimensionPixelSize(
|
||||
R.dimen.dynamic_grid_cell_border_spacing);
|
||||
mHeaderTopPadding = context.getResources()
|
||||
.getDimensionPixelSize(R.dimen.all_apps_header_top_padding);
|
||||
int accentColor = Themes.getColorAccent(getContext());
|
||||
mHeaderProtectionColor = ColorUtils.blendARGB(mScrimColor, accentColor, .3f);
|
||||
|
||||
mLauncher.addOnDeviceProfileChangeListener(this);
|
||||
|
||||
|
||||
|
||||
mSearchAdapterProvider = mLauncher.createSearchAdapterProvider(this);
|
||||
mSearchQueryBuilder = new SpannableStringBuilder();
|
||||
Selection.setSelection(mSearchQueryBuilder, 0);
|
||||
@@ -300,6 +324,7 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
|
||||
}
|
||||
// Reset the search bar and base recycler view after transitioning home
|
||||
mSearchUiManager.resetSearch();
|
||||
updateHeaderScroll(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -625,6 +650,26 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
|
||||
outRect.offset(0, (int) getTranslationY());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTranslationY(float translationY) {
|
||||
super.setTranslationY(translationY);
|
||||
invalidateHeader();
|
||||
}
|
||||
|
||||
public void setScrimView(ScrimView scrimView) {
|
||||
mScrimView = scrimView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawOnScrim(Canvas canvas) {
|
||||
mHeaderPaint.setColor(mHeaderColor);
|
||||
mHeaderPaint.setAlpha((int) (getAlpha() * Color.alpha(mHeaderColor)));
|
||||
if (mHeaderPaint.getColor() != mScrimColor && mHeaderPaint.getColor() != 0) {
|
||||
canvas.drawRect(0, 0, getWidth(), mHeaderTopPadding + getTranslationY(),
|
||||
mHeaderPaint);
|
||||
}
|
||||
}
|
||||
|
||||
public class AdapterHolder {
|
||||
public static final int MAIN = 0;
|
||||
public static final int WORK = 1;
|
||||
@@ -725,4 +770,24 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
|
||||
return mOverlay;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void updateHeaderScroll(int scrolledOffset) {
|
||||
float prog = Math.max(0, Math.min(1, (float) scrolledOffset / mHeaderThreshold));
|
||||
int headerColor = ColorUtils.setAlphaComponent(mHeaderProtectionColor, (int) (prog * 255));
|
||||
if (headerColor != mHeaderColor) {
|
||||
mHeaderColor = headerColor;
|
||||
getSearchView().setBackgroundColor(mHeaderColor);
|
||||
invalidateHeader();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* redraws header protection
|
||||
*/
|
||||
public void invalidateHeader() {
|
||||
if (mScrimView != null) {
|
||||
mScrimView.invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ import androidx.recyclerview.widget.RecyclerView;
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.BaseRecyclerView;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.logging.StatsLogManager;
|
||||
@@ -52,6 +53,7 @@ import java.util.List;
|
||||
public class AllAppsRecyclerView extends BaseRecyclerView {
|
||||
private static final String TAG = "AllAppsContainerView";
|
||||
private static final boolean DEBUG = false;
|
||||
private final Launcher mLauncher;
|
||||
|
||||
private AlphabeticalAppsList mApps;
|
||||
private final int mNumAppsPerRow;
|
||||
@@ -87,6 +89,7 @@ public class AllAppsRecyclerView extends BaseRecyclerView {
|
||||
R.dimen.all_apps_empty_search_bg_top_offset);
|
||||
mNumAppsPerRow = LauncherAppState.getIDP(context).numColumns;
|
||||
mFastScrollHelper = new AllAppsFastScrollHelper(this);
|
||||
mLauncher = Launcher.getLauncher(context);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -199,6 +202,12 @@ public class AllAppsRecyclerView extends BaseRecyclerView {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScrolled(int dx, int dy) {
|
||||
super.onScrolled(dx, dy);
|
||||
mLauncher.getAppsView().updateHeaderScroll(getCurrentScrollY());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(MotionEvent e) {
|
||||
boolean result = super.onInterceptTouchEvent(e);
|
||||
@@ -410,7 +419,7 @@ public class AllAppsRecyclerView extends BaseRecyclerView {
|
||||
|
||||
/**
|
||||
* Returns the available scroll height:
|
||||
* AvailableScrollHeight = Total height of the all items - last page height
|
||||
* AvailableScrollHeight = Total height of the all items - last page height
|
||||
*/
|
||||
@Override
|
||||
protected int getAvailableScrollHeight() {
|
||||
|
||||
@@ -45,6 +45,7 @@ import com.android.launcher3.anim.PropertySetter;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.statemanager.StateManager.StateHandler;
|
||||
import com.android.launcher3.states.StateAnimationConfig;
|
||||
import com.android.launcher3.views.ScrimView;
|
||||
|
||||
/**
|
||||
* Handles AllApps view transition.
|
||||
@@ -88,6 +89,7 @@ public class AllAppsTransitionController
|
||||
private float mProgress; // [0, 1], mShiftRange * mProgress = shiftCurrent
|
||||
|
||||
private float mScrollRangeDelta = 0;
|
||||
private ScrimView mScrimView;
|
||||
|
||||
public AllAppsTransitionController(Launcher l) {
|
||||
mLauncher = l;
|
||||
@@ -158,7 +160,7 @@ public class AllAppsTransitionController
|
||||
|
||||
Interpolator interpolator = toState.equals(ALL_APPS)
|
||||
? (config.userControlled ? ACCEL_2 : ACCEL_0_75) :
|
||||
(config.userControlled ? DEACCEL_2 : DEACCEL);
|
||||
(config.userControlled ? DEACCEL_2 : DEACCEL);
|
||||
|
||||
Animator anim = createSpringAnimation(mProgress, targetProgress);
|
||||
anim.setInterpolator(config.getInterpolator(ANIM_VERTICAL_PROGRESS, interpolator));
|
||||
@@ -181,19 +183,28 @@ public class AllAppsTransitionController
|
||||
|
||||
Interpolator allAppsFade = config.getInterpolator(ANIM_ALL_APPS_FADE, LINEAR);
|
||||
setter.setViewAlpha(mAppsView, hasAllAppsContent ? 1 : 0, allAppsFade);
|
||||
|
||||
boolean shouldProtectHeader =
|
||||
ALL_APPS == state || mLauncher.getStateManager().getState() == ALL_APPS;
|
||||
mScrimView.setDrawingController(shouldProtectHeader ? mAppsView : null);
|
||||
}
|
||||
|
||||
public AnimatorListenerAdapter getProgressAnimatorListener() {
|
||||
return AnimationSuccessListener.forRunnable(this::onProgressAnimationEnd);
|
||||
}
|
||||
|
||||
public void setupViews(AllAppsContainerView appsView) {
|
||||
/**
|
||||
* see Launcher#setupViews
|
||||
*/
|
||||
public void setupViews(ScrimView scrimView, AllAppsContainerView appsView) {
|
||||
mScrimView = scrimView;
|
||||
mAppsView = appsView;
|
||||
if (FeatureFlags.ENABLE_DEVICE_SEARCH.get() && Utilities.ATLEAST_R) {
|
||||
mLauncher.getSystemUiController().updateUiState(UI_STATE_ALLAPPS,
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
|
||||
}
|
||||
mAppsView.setScrimView(scrimView);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.launcher3.views;
|
||||
import static com.android.launcher3.util.SystemUiController.UI_STATE_SCRIM_VIEW;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.util.AttributeSet;
|
||||
@@ -37,13 +38,16 @@ public class ScrimView extends View implements Insettable {
|
||||
|
||||
private SystemUiController mSystemUiController;
|
||||
|
||||
private ScrimDrawingController mDrawingController;
|
||||
|
||||
public ScrimView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
setFocusable(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInsets(Rect insets) { }
|
||||
public void setInsets(Rect insets) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasOverlappingRendering() {
|
||||
@@ -62,6 +66,14 @@ public class ScrimView extends View implements Insettable {
|
||||
super.setBackgroundColor(color);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
if (mDrawingController != null) {
|
||||
mDrawingController.drawOnScrim(canvas);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onVisibilityChanged(View changedView, int visibility) {
|
||||
super.onVisibilityChanged(changedView, visibility);
|
||||
@@ -96,4 +108,24 @@ public class ScrimView extends View implements Insettable {
|
||||
return ColorUtils.calculateLuminance(
|
||||
((ColorDrawable) getBackground()).getColor()) < 0.5f;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets drawing controller. Invalidates ScrimView if drawerController has changed.
|
||||
*/
|
||||
public void setDrawingController(ScrimDrawingController drawingController) {
|
||||
if (mDrawingController != drawingController) {
|
||||
mDrawingController = drawingController;
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A Utility interface allowing for other surfaces to draw on ScrimView
|
||||
*/
|
||||
public interface ScrimDrawingController {
|
||||
/**
|
||||
* Called inside ScrimView#OnDraw
|
||||
*/
|
||||
void drawOnScrim(Canvas canvas);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user