mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-02-27 15:26:58 +00:00
Merge "[Predictive Back] Support WidgetsTwoPaneSheet" into main
This commit is contained in:
@@ -40,6 +40,7 @@
|
||||
<item type="id" name="cache_entry_tag_id" />
|
||||
|
||||
<item type="id" name="saved_clip_children_tag_id" />
|
||||
<item type="id" name="saved_clip_to_padding_tag_id" />
|
||||
|
||||
<item type="id" name="saved_floating_widget_foreground" />
|
||||
<item type="id" name="saved_floating_widget_background" />
|
||||
|
||||
@@ -68,6 +68,8 @@ import android.util.TypedValue;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewParent;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import androidx.annotation.ChecksSdkIntAtLeast;
|
||||
@@ -772,6 +774,136 @@ public final class Utilities {
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively call {@link ViewGroup#setClipChildren(boolean)} from {@link View} to ts parent
|
||||
* (direct or indirect) inclusive. This method will also save the old clipChildren value on each
|
||||
* view with {@link View#setTag(int, Object)}, which can be restored in
|
||||
* {@link #restoreClipChildrenOnViewTree(View, ViewParent)}.
|
||||
*
|
||||
* Note that if parent is null or not a parent of the view, this method will be applied all the
|
||||
* way to root view.
|
||||
*
|
||||
* @param v child view
|
||||
* @param parent direct or indirect parent of child view
|
||||
* @param clipChildren whether we should clip children
|
||||
*/
|
||||
public static void setClipChildrenOnViewTree(
|
||||
@Nullable View v,
|
||||
@Nullable ViewParent parent,
|
||||
boolean clipChildren) {
|
||||
if (v == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (v instanceof ViewGroup) {
|
||||
ViewGroup viewGroup = (ViewGroup) v;
|
||||
boolean oldClipChildren = viewGroup.getClipChildren();
|
||||
if (oldClipChildren != clipChildren) {
|
||||
v.setTag(R.id.saved_clip_children_tag_id, oldClipChildren);
|
||||
viewGroup.setClipChildren(clipChildren);
|
||||
}
|
||||
}
|
||||
|
||||
if (v == parent) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (v.getParent() instanceof View) {
|
||||
setClipChildrenOnViewTree((View) v.getParent(), parent, clipChildren);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively call {@link ViewGroup#setClipChildren(boolean)} to restore clip children value
|
||||
* set in {@link #setClipChildrenOnViewTree(View, ViewParent, boolean)} on view to its parent
|
||||
* (direct or indirect) inclusive.
|
||||
*
|
||||
* Note that if parent is null or not a parent of the view, this method will be applied all the
|
||||
* way to root view.
|
||||
*
|
||||
* @param v child view
|
||||
* @param parent direct or indirect parent of child view
|
||||
*/
|
||||
public static void restoreClipChildrenOnViewTree(
|
||||
@Nullable View v, @Nullable ViewParent parent) {
|
||||
if (v == null) {
|
||||
return;
|
||||
}
|
||||
if (v instanceof ViewGroup) {
|
||||
ViewGroup viewGroup = (ViewGroup) v;
|
||||
Object viewTag = viewGroup.getTag(R.id.saved_clip_children_tag_id);
|
||||
if (viewTag instanceof Boolean) {
|
||||
viewGroup.setClipChildren((boolean) viewTag);
|
||||
viewGroup.setTag(R.id.saved_clip_children_tag_id, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (v == parent) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (v.getParent() instanceof View) {
|
||||
restoreClipChildrenOnViewTree((View) v.getParent(), parent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to {@link #setClipChildrenOnViewTree(View, ViewParent, boolean)} but is calling
|
||||
* {@link ViewGroup#setClipToPadding}.
|
||||
*/
|
||||
public static void setClipToPaddingOnViewTree(
|
||||
@Nullable View v,
|
||||
@Nullable ViewParent parent,
|
||||
boolean clipToPadding) {
|
||||
if (v == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (v instanceof ViewGroup) {
|
||||
ViewGroup viewGroup = (ViewGroup) v;
|
||||
boolean oldClipToPadding = viewGroup.getClipToPadding();
|
||||
if (oldClipToPadding != clipToPadding) {
|
||||
v.setTag(R.id.saved_clip_to_padding_tag_id, oldClipToPadding);
|
||||
viewGroup.setClipToPadding(clipToPadding);
|
||||
}
|
||||
}
|
||||
|
||||
if (v == parent) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (v.getParent() instanceof View) {
|
||||
setClipToPaddingOnViewTree((View) v.getParent(), parent, clipToPadding);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to {@link #restoreClipChildrenOnViewTree(View, ViewParent)} but is calling
|
||||
* {@link ViewGroup#setClipToPadding}.
|
||||
*/
|
||||
public static void restoreClipToPaddingOnViewTree(
|
||||
@Nullable View v, @Nullable ViewParent parent) {
|
||||
if (v == null) {
|
||||
return;
|
||||
}
|
||||
if (v instanceof ViewGroup) {
|
||||
ViewGroup viewGroup = (ViewGroup) v;
|
||||
Object viewTag = viewGroup.getTag(R.id.saved_clip_to_padding_tag_id);
|
||||
if (viewTag instanceof Boolean) {
|
||||
viewGroup.setClipToPadding((boolean) viewTag);
|
||||
viewGroup.setTag(R.id.saved_clip_to_padding_tag_id, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (v == parent) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (v.getParent() instanceof View) {
|
||||
restoreClipToPaddingOnViewTree((View) v.getParent(), parent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates the {@code targetView} so that it overlaps with {@code exclusionBounds} as little
|
||||
* as possible, while remaining within {@code inclusionBounds}.
|
||||
|
||||
@@ -24,6 +24,8 @@ import static com.android.launcher3.LauncherState.ALL_APPS;
|
||||
import static com.android.launcher3.LauncherState.ALL_APPS_CONTENT;
|
||||
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.Utilities.restoreClipChildrenOnViewTree;
|
||||
import static com.android.launcher3.Utilities.setClipChildrenOnViewTree;
|
||||
import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_BOTTOM_SHEET_FADE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
|
||||
@@ -38,12 +40,9 @@ import android.animation.ValueAnimator;
|
||||
import android.util.FloatProperty;
|
||||
import android.view.HapticFeedbackConstants;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewParent;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import androidx.annotation.FloatRange;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.app.animation.Interpolators;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
@@ -422,79 +421,6 @@ public class AllAppsTransitionController
|
||||
mAppsView, VIEW_TRANSLATE_Y, APPS_VIEW_INDEX_COUNT, Float::sum);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively call {@link ViewGroup#setClipChildren(boolean)} from {@link View} to ts parent
|
||||
* (direct or indirect) inclusive. This method will also save the old clipChildren value on each
|
||||
* view with {@link View#setTag(int, Object)}, which can be restored in
|
||||
* {@link #restoreClipChildrenOnViewTree(View, ViewParent)}.
|
||||
*
|
||||
* Note that if parent is null or not a parent of the view, this method will be applied all the
|
||||
* way to root view.
|
||||
*
|
||||
* @param v child view
|
||||
* @param parent direct or indirect parent of child view
|
||||
* @param clipChildren whether we should clip children
|
||||
*/
|
||||
private static void setClipChildrenOnViewTree(
|
||||
@Nullable View v,
|
||||
@Nullable ViewParent parent,
|
||||
boolean clipChildren) {
|
||||
if (v == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (v instanceof ViewGroup) {
|
||||
ViewGroup viewGroup = (ViewGroup) v;
|
||||
boolean oldClipChildren = viewGroup.getClipChildren();
|
||||
if (oldClipChildren != clipChildren) {
|
||||
v.setTag(R.id.saved_clip_children_tag_id, oldClipChildren);
|
||||
viewGroup.setClipChildren(clipChildren);
|
||||
}
|
||||
}
|
||||
|
||||
if (v == parent) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (v.getParent() instanceof View) {
|
||||
setClipChildrenOnViewTree((View) v.getParent(), parent, clipChildren);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively call {@link ViewGroup#setClipChildren(boolean)} to restore clip children value
|
||||
* set in {@link #setClipChildrenOnViewTree(View, ViewParent, boolean)} on view to its parent
|
||||
* (direct or indirect) inclusive.
|
||||
*
|
||||
* Note that if parent is null or not a parent of the view, this method will be applied all the
|
||||
* way to root view.
|
||||
*
|
||||
* @param v child view
|
||||
* @param parent direct or indirect parent of child view
|
||||
*/
|
||||
private static void restoreClipChildrenOnViewTree(
|
||||
@Nullable View v, @Nullable ViewParent parent) {
|
||||
if (v == null) {
|
||||
return;
|
||||
}
|
||||
if (v instanceof ViewGroup) {
|
||||
ViewGroup viewGroup = (ViewGroup) v;
|
||||
Object viewTag = viewGroup.getTag(R.id.saved_clip_children_tag_id);
|
||||
if (viewTag instanceof Boolean) {
|
||||
viewGroup.setClipChildren((boolean) viewTag);
|
||||
viewGroup.setTag(R.id.saved_clip_children_tag_id, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (v == parent) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (v.getParent() instanceof View) {
|
||||
restoreClipChildrenOnViewTree((View) v.getParent(), parent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the total scroll range but does not update the UI.
|
||||
*/
|
||||
|
||||
@@ -347,8 +347,7 @@ public abstract class AbstractSlideInView<T extends Context & ActivityContext>
|
||||
/** Return extra space revealed during predictive back animation. */
|
||||
@Px
|
||||
protected int getBottomOffsetPx() {
|
||||
final int height = getMeasuredHeight();
|
||||
return (int) ((height / PREDICTIVE_BACK_MIN_SCALE - height) / 2);
|
||||
return (int) (getMeasuredHeight() * (1 - PREDICTIVE_BACK_MIN_SCALE));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,6 +17,10 @@ package com.android.launcher3.widget.picker;
|
||||
|
||||
import static com.android.launcher3.Flags.enableCategorizedWidgetSuggestions;
|
||||
import static com.android.launcher3.Flags.enableUnfoldedTwoPanePicker;
|
||||
import static com.android.launcher3.Utilities.restoreClipChildrenOnViewTree;
|
||||
import static com.android.launcher3.Utilities.restoreClipToPaddingOnViewTree;
|
||||
import static com.android.launcher3.Utilities.setClipChildrenOnViewTree;
|
||||
import static com.android.launcher3.Utilities.setClipToPaddingOnViewTree;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Outline;
|
||||
@@ -27,6 +31,7 @@ import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewOutlineProvider;
|
||||
import android.view.ViewParent;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ScrollView;
|
||||
@@ -60,10 +65,13 @@ public class WidgetsTwoPaneSheet extends WidgetsFullSheet {
|
||||
private FrameLayout mSuggestedWidgetsContainer;
|
||||
private WidgetsListHeader mSuggestedWidgetsHeader;
|
||||
private PackageUserKey mSuggestedWidgetsPackageUserKey;
|
||||
private View mPrimaryWidgetListView;
|
||||
private LinearLayout mRightPane;
|
||||
|
||||
private ScrollView mRightPaneScrollView;
|
||||
private WidgetsListTableViewHolderBinder mWidgetsListTableViewHolderBinder;
|
||||
|
||||
private boolean mOldIsBackSwipeProgressing;
|
||||
private int mActivePage = -1;
|
||||
private PackageUserKey mSelectedHeader;
|
||||
|
||||
@@ -124,6 +132,12 @@ public class WidgetsTwoPaneSheet extends WidgetsFullSheet {
|
||||
mRightPane.setOutlineProvider(mViewOutlineProviderRightPane);
|
||||
mRightPaneScrollView = mContent.findViewById(R.id.right_pane_scroll_view);
|
||||
mRightPaneScrollView.setOverScrollMode(View.OVER_SCROLL_NEVER);
|
||||
mRightPaneScrollView.setOutlineProvider(mViewOutlineProvider);
|
||||
mRightPaneScrollView.setClipToOutline(true);
|
||||
|
||||
mPrimaryWidgetListView = findViewById(R.id.primary_widgets_list_view);
|
||||
mPrimaryWidgetListView.setOutlineProvider(mViewOutlineProvider);
|
||||
mPrimaryWidgetListView.setClipToOutline(true);
|
||||
|
||||
onRecommendedWidgetsBound();
|
||||
onWidgetsBound();
|
||||
@@ -133,6 +147,25 @@ public class WidgetsTwoPaneSheet extends WidgetsFullSheet {
|
||||
mFastScroller.setVisibility(GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onScaleProgressChanged() {
|
||||
super.onScaleProgressChanged();
|
||||
boolean isBackSwipeProgressing = mSlideInViewScale.value > 0;
|
||||
if (isBackSwipeProgressing == mOldIsBackSwipeProgressing) {
|
||||
return;
|
||||
}
|
||||
mOldIsBackSwipeProgressing = isBackSwipeProgressing;
|
||||
if (isBackSwipeProgressing) {
|
||||
setClipChildrenOnViewTree(mPrimaryWidgetListView, (ViewParent) mContent, false);
|
||||
setClipChildrenOnViewTree(mRightPaneScrollView, (ViewParent) mContent, false);
|
||||
setClipToPaddingOnViewTree(mRightPaneScrollView, (ViewParent) mContent, false);
|
||||
} else {
|
||||
restoreClipChildrenOnViewTree(mPrimaryWidgetListView, mContent);
|
||||
restoreClipChildrenOnViewTree(mRightPaneScrollView, mContent);
|
||||
restoreClipToPaddingOnViewTree(mRightPaneScrollView, mContent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||
super.onLayout(changed, l, t, r, b);
|
||||
|
||||
Reference in New Issue
Block a user