Moving widget padding to drawable instead of using itemDecorator

ItemDecorator uses item position which is not stable during animations.
Moving it to the background allows the padding to be stable

Bug: 236961658
Test: Verified that the app doesn't crash.
Change-Id: Ied12077de4097e827c5c4157f5196346a301f185
This commit is contained in:
Sunny Goyal 2022-06-23 12:00:57 -07:00
parent 80179921f3
commit ed681548fc
3 changed files with 12 additions and 41 deletions

View File

@ -19,7 +19,6 @@
android:id="@+id/widgets_list_header" android:id="@+id/widgets_list_header"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingVertical="@dimen/widget_list_header_view_vertical_padding"
android:orientation="horizontal" android:orientation="horizontal"
android:importantForAccessibility="yes" android:importantForAccessibility="yes"
android:focusable="true" android:focusable="true"

View File

@ -27,6 +27,7 @@ import android.content.res.ColorStateList;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable; import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.InsetDrawable;
import android.graphics.drawable.RippleDrawable; import android.graphics.drawable.RippleDrawable;
import android.graphics.drawable.StateListDrawable; import android.graphics.drawable.StateListDrawable;
@ -40,6 +41,8 @@ final class WidgetsListDrawableFactory {
private final float mMiddleCornerRadius; private final float mMiddleCornerRadius;
private final ColorStateList mSurfaceColor; private final ColorStateList mSurfaceColor;
private final ColorStateList mRippleColor; private final ColorStateList mRippleColor;
private final int mVerticalPadding;
private final int mHeaderMargin;
WidgetsListDrawableFactory(Context context) { WidgetsListDrawableFactory(Context context) {
Resources res = context.getResources(); Resources res = context.getResources();
@ -48,6 +51,9 @@ final class WidgetsListDrawableFactory {
mSurfaceColor = context.getColorStateList(R.color.surface); mSurfaceColor = context.getColorStateList(R.color.surface);
mRippleColor = ColorStateList.valueOf( mRippleColor = ColorStateList.valueOf(
Themes.getAttrColor(context, android.R.attr.colorControlHighlight)); Themes.getAttrColor(context, android.R.attr.colorControlHighlight));
mVerticalPadding =
res.getDimensionPixelSize(R.dimen.widget_list_header_view_vertical_padding);
mHeaderMargin = res.getDimensionPixelSize(R.dimen.widget_list_entry_spacing);
} }
/** /**
@ -74,7 +80,10 @@ final class WidgetsListDrawableFactory {
stateList.addState( stateList.addState(
LAST.mStateSet, LAST.mStateSet,
createRoundedRectDrawable(mMiddleCornerRadius, mTopBottomCornerRadius)); createRoundedRectDrawable(mMiddleCornerRadius, mTopBottomCornerRadius));
return new RippleDrawable(mRippleColor, /* content= */ stateList, /* mask= */ stateList); RippleDrawable ripple =
new RippleDrawable(mRippleColor, /* content= */ stateList, /* mask= */ stateList);
ripple.setPadding(0, mVerticalPadding, 0, mVerticalPadding);
return new InsetDrawable(ripple, 0, mHeaderMargin, 0, 0);
} }
/** /**

View File

@ -16,18 +16,12 @@
package com.android.launcher3.widget.picker; package com.android.launcher3.widget.picker;
import static com.android.launcher3.widget.picker.WidgetsListAdapter.VIEW_TYPE_WIDGETS_HEADER;
import static com.android.launcher3.widget.picker.WidgetsListAdapter.VIEW_TYPE_WIDGETS_SEARCH_HEADER;
import android.content.Context; import android.content.Context;
import android.graphics.Point; import android.graphics.Point;
import android.graphics.Rect;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.SparseIntArray; import android.util.SparseIntArray;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.RecyclerView.OnItemTouchListener; import androidx.recyclerview.widget.RecyclerView.OnItemTouchListener;
@ -55,7 +49,6 @@ public class WidgetsRecyclerView extends FastScrollRecyclerView implements OnIte
* VIEW_TYPE_WIDGETS_LIST is not visible on the screen. * VIEW_TYPE_WIDGETS_LIST is not visible on the screen.
*/ */
private final SparseIntArray mCachedSizes = new SparseIntArray(); private final SparseIntArray mCachedSizes = new SparseIntArray();
private final SpacingDecoration mSpacingDecoration;
public WidgetsRecyclerView(Context context) { public WidgetsRecyclerView(Context context) {
this(context, null); this(context, null);
@ -70,9 +63,6 @@ public class WidgetsRecyclerView extends FastScrollRecyclerView implements OnIte
super(context, attrs, defStyleAttr); super(context, attrs, defStyleAttr);
mScrollbarTop = getResources().getDimensionPixelSize(R.dimen.dynamic_grid_edge_margin); mScrollbarTop = getResources().getDimensionPixelSize(R.dimen.dynamic_grid_edge_margin);
addOnItemTouchListener(this); addOnItemTouchListener(this);
mSpacingDecoration = new SpacingDecoration(context);
addItemDecoration(mSpacingDecoration);
} }
@Override @Override
@ -183,7 +173,7 @@ public class WidgetsRecyclerView extends FastScrollRecyclerView implements OnIte
@Override @Override
protected int getItemsHeight(int untilIndex) { protected int getItemsHeight(int untilIndex) {
// Initialize cache // Initialize cache
int childCount = getChildCount(); int childCount = Math.min(getChildCount(), getAdapter().getItemCount());
int startPosition; int startPosition;
if (childCount > 0 if (childCount > 0
&& ((startPosition = getChildAdapterPosition(getChildAt(0))) != NO_POSITION)) { && ((startPosition = getChildAdapterPosition(getChildAt(0))) != NO_POSITION)) {
@ -200,7 +190,7 @@ public class WidgetsRecyclerView extends FastScrollRecyclerView implements OnIte
int totalItemsHeight = 0; int totalItemsHeight = 0;
for (int i = 0; i < untilIndex; i++) { for (int i = 0; i < untilIndex; i++) {
int type = mAdapter.getItemViewType(i); int type = mAdapter.getItemViewType(i);
totalItemsHeight += mCachedSizes.get(type) + mSpacingDecoration.getSpacing(i, type); totalItemsHeight += mCachedSizes.get(type);
} }
return totalItemsHeight; return totalItemsHeight;
} }
@ -216,31 +206,4 @@ public class WidgetsRecyclerView extends FastScrollRecyclerView implements OnIte
*/ */
int getHeaderViewHeight(); int getHeaderViewHeight();
} }
private static class SpacingDecoration extends RecyclerView.ItemDecoration {
private final int mSpacingBetweenEntries;
SpacingDecoration(@NonNull Context context) {
mSpacingBetweenEntries =
context.getResources().getDimensionPixelSize(R.dimen.widget_list_entry_spacing);
}
@Override
public void getItemOffsets(
@NonNull Rect outRect,
@NonNull View view,
@NonNull RecyclerView parent,
@NonNull RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
int position = parent.getChildAdapterPosition(view);
outRect.top += getSpacing(position, parent.getAdapter().getItemViewType(position));
}
public int getSpacing(int position, int type) {
boolean isHeader = type == VIEW_TYPE_WIDGETS_SEARCH_HEADER
|| type == VIEW_TYPE_WIDGETS_HEADER;
return position > 0 && isHeader ? mSpacingBetweenEntries : 0;
}
}
} }