Merge "Use drawable states for list positions instead of swapping drawables" into sc-dev
This commit is contained in:
commit
358411a96a
|
@ -13,7 +13,7 @@
|
||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
<TableLayout
|
<com.android.launcher3.widget.picker.WidgetsListTableView
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:id="@+id/widgets_table"
|
android:id="@+id/widgets_table"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -140,7 +140,6 @@
|
||||||
|
|
||||||
<dimen name="widget_list_top_bottom_corner_radius">28dp</dimen>
|
<dimen name="widget_list_top_bottom_corner_radius">28dp</dimen>
|
||||||
<dimen name="widget_list_content_corner_radius">4dp</dimen>
|
<dimen name="widget_list_content_corner_radius">4dp</dimen>
|
||||||
<dimen name="widget_list_content_joined_corner_radius">0dp</dimen>
|
|
||||||
|
|
||||||
<dimen name="widget_list_header_view_vertical_padding">20dp</dimen>
|
<dimen name="widget_list_header_view_vertical_padding">20dp</dimen>
|
||||||
<dimen name="widget_list_entry_bottom_margin">2dp</dimen>
|
<dimen name="widget_list_entry_bottom_margin">2dp</dimen>
|
||||||
|
|
|
@ -107,7 +107,10 @@ public final class WidgetsListHeaderViewHolderBinderTest {
|
||||||
/* iconClickListener= */ view -> {},
|
/* iconClickListener= */ view -> {},
|
||||||
/* iconLongClickListener= */ view -> false);
|
/* iconLongClickListener= */ view -> false);
|
||||||
mViewHolderBinder = new WidgetsListHeaderViewHolderBinder(
|
mViewHolderBinder = new WidgetsListHeaderViewHolderBinder(
|
||||||
LayoutInflater.from(mTestActivity), mOnHeaderClickListener, widgetsListAdapter);
|
LayoutInflater.from(mTestActivity),
|
||||||
|
mOnHeaderClickListener,
|
||||||
|
new WidgetsListDrawableFactory(mTestActivity),
|
||||||
|
widgetsListAdapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
|
|
|
@ -107,7 +107,10 @@ public final class WidgetsListSearchHeaderViewHolderBinderTest {
|
||||||
/* iconClickListener= */ view -> {},
|
/* iconClickListener= */ view -> {},
|
||||||
/* iconLongClickListener= */ view -> false);
|
/* iconLongClickListener= */ view -> false);
|
||||||
mViewHolderBinder = new WidgetsListSearchHeaderViewHolderBinder(
|
mViewHolderBinder = new WidgetsListSearchHeaderViewHolderBinder(
|
||||||
LayoutInflater.from(mTestActivity), mOnHeaderClickListener, widgetsListAdapter);
|
LayoutInflater.from(mTestActivity),
|
||||||
|
mOnHeaderClickListener,
|
||||||
|
new WidgetsListDrawableFactory(mTestActivity),
|
||||||
|
widgetsListAdapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
|
|
|
@ -118,6 +118,7 @@ public final class WidgetsListTableViewHolderBinderTest {
|
||||||
mOnIconClickListener,
|
mOnIconClickListener,
|
||||||
mOnLongClickListener,
|
mOnLongClickListener,
|
||||||
mWidgetPreviewLoader,
|
mWidgetPreviewLoader,
|
||||||
|
new WidgetsListDrawableFactory(mTestActivity),
|
||||||
widgetsListAdapter);
|
widgetsListAdapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -103,18 +103,25 @@ public class WidgetsListAdapter extends Adapter<ViewHolder> implements OnHeaderC
|
||||||
OnClickListener iconClickListener, OnLongClickListener iconLongClickListener) {
|
OnClickListener iconClickListener, OnLongClickListener iconLongClickListener) {
|
||||||
mLauncher = Launcher.getLauncher(context);
|
mLauncher = Launcher.getLauncher(context);
|
||||||
mDiffReporter = new WidgetsDiffReporter(iconCache, this);
|
mDiffReporter = new WidgetsDiffReporter(iconCache, this);
|
||||||
|
WidgetsListDrawableFactory listDrawableFactory = new WidgetsListDrawableFactory(context);
|
||||||
mWidgetsListTableViewHolderBinder = new WidgetsListTableViewHolderBinder(context,
|
mWidgetsListTableViewHolderBinder = new WidgetsListTableViewHolderBinder(context,
|
||||||
layoutInflater, iconClickListener, iconLongClickListener,
|
layoutInflater, iconClickListener, iconLongClickListener,
|
||||||
widgetPreviewLoader, /* listAdapter= */ this);
|
widgetPreviewLoader, listDrawableFactory, /* listAdapter= */ this);
|
||||||
mViewHolderBinders.put(VIEW_TYPE_WIDGETS_LIST, mWidgetsListTableViewHolderBinder);
|
mViewHolderBinders.put(VIEW_TYPE_WIDGETS_LIST, mWidgetsListTableViewHolderBinder);
|
||||||
mViewHolderBinders.put(
|
mViewHolderBinders.put(
|
||||||
VIEW_TYPE_WIDGETS_HEADER,
|
VIEW_TYPE_WIDGETS_HEADER,
|
||||||
new WidgetsListHeaderViewHolderBinder(
|
new WidgetsListHeaderViewHolderBinder(
|
||||||
layoutInflater, /* onHeaderClickListener= */this, /* listAdapter= */ this));
|
layoutInflater,
|
||||||
|
/* onHeaderClickListener= */ this,
|
||||||
|
listDrawableFactory,
|
||||||
|
/* listAdapter= */ this));
|
||||||
mViewHolderBinders.put(
|
mViewHolderBinders.put(
|
||||||
VIEW_TYPE_WIDGETS_SEARCH_HEADER,
|
VIEW_TYPE_WIDGETS_SEARCH_HEADER,
|
||||||
new WidgetsListSearchHeaderViewHolderBinder(
|
new WidgetsListSearchHeaderViewHolderBinder(
|
||||||
layoutInflater, /*onHeaderClickListener=*/ this, /* listAdapter= */ this));
|
layoutInflater,
|
||||||
|
/* onHeaderClickListener= */ this,
|
||||||
|
listDrawableFactory,
|
||||||
|
/* listAdapter= */ this));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,113 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.android.launcher3.widget.picker;
|
||||||
|
|
||||||
|
import static com.android.launcher3.widget.picker.WidgetsListDrawableState.FIRST;
|
||||||
|
import static com.android.launcher3.widget.picker.WidgetsListDrawableState.FIRST_EXPANDED;
|
||||||
|
import static com.android.launcher3.widget.picker.WidgetsListDrawableState.LAST;
|
||||||
|
import static com.android.launcher3.widget.picker.WidgetsListDrawableState.MIDDLE;
|
||||||
|
import static com.android.launcher3.widget.picker.WidgetsListDrawableState.MIDDLE_EXPANDED;
|
||||||
|
import static com.android.launcher3.widget.picker.WidgetsListDrawableState.SINGLE;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.ColorStateList;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.graphics.drawable.GradientDrawable;
|
||||||
|
import android.graphics.drawable.RippleDrawable;
|
||||||
|
import android.graphics.drawable.StateListDrawable;
|
||||||
|
|
||||||
|
import com.android.launcher3.R;
|
||||||
|
import com.android.launcher3.util.Themes;
|
||||||
|
|
||||||
|
/** Factory for creating drawables to use as background for list elements. */
|
||||||
|
final class WidgetsListDrawableFactory {
|
||||||
|
|
||||||
|
private final float mTopBottomCornerRadius;
|
||||||
|
private final float mMiddleCornerRadius;
|
||||||
|
private final ColorStateList mSurfaceColor;
|
||||||
|
private final ColorStateList mRippleColor;
|
||||||
|
|
||||||
|
WidgetsListDrawableFactory(Context context) {
|
||||||
|
Resources res = context.getResources();
|
||||||
|
mTopBottomCornerRadius = res.getDimension(R.dimen.widget_list_top_bottom_corner_radius);
|
||||||
|
mMiddleCornerRadius = res.getDimension(R.dimen.widget_list_content_corner_radius);
|
||||||
|
mSurfaceColor = context.getColorStateList(R.color.surface);
|
||||||
|
mRippleColor = ColorStateList.valueOf(
|
||||||
|
Themes.getAttrColor(context, android.R.attr.colorControlHighlight));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a drawable for widget header list items. This drawable supports all positions
|
||||||
|
* in {@link WidgetsListDrawableState}.
|
||||||
|
*/
|
||||||
|
Drawable createHeaderBackgroundDrawable() {
|
||||||
|
StateListDrawable stateList = new StateListDrawable();
|
||||||
|
stateList.addState(
|
||||||
|
SINGLE.mStateSet,
|
||||||
|
createRoundedRectDrawable(mTopBottomCornerRadius, mTopBottomCornerRadius));
|
||||||
|
stateList.addState(
|
||||||
|
FIRST_EXPANDED.mStateSet,
|
||||||
|
createRoundedRectDrawable(mTopBottomCornerRadius, 0));
|
||||||
|
stateList.addState(
|
||||||
|
FIRST.mStateSet,
|
||||||
|
createRoundedRectDrawable(mTopBottomCornerRadius, mMiddleCornerRadius));
|
||||||
|
stateList.addState(
|
||||||
|
MIDDLE_EXPANDED.mStateSet,
|
||||||
|
createRoundedRectDrawable(mMiddleCornerRadius, 0));
|
||||||
|
stateList.addState(
|
||||||
|
MIDDLE.mStateSet,
|
||||||
|
createRoundedRectDrawable(mMiddleCornerRadius, mMiddleCornerRadius));
|
||||||
|
stateList.addState(
|
||||||
|
LAST.mStateSet,
|
||||||
|
createRoundedRectDrawable(mMiddleCornerRadius, mTopBottomCornerRadius));
|
||||||
|
return new RippleDrawable(mRippleColor, /* content= */ stateList, /* mask= */ stateList);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a drawable for widget content list items. This state list supports the middle and
|
||||||
|
* last states.
|
||||||
|
*/
|
||||||
|
Drawable createContentBackgroundDrawable() {
|
||||||
|
StateListDrawable stateList = new StateListDrawable();
|
||||||
|
stateList.addState(
|
||||||
|
MIDDLE.mStateSet,
|
||||||
|
createRoundedRectDrawable(0, mMiddleCornerRadius));
|
||||||
|
stateList.addState(
|
||||||
|
LAST.mStateSet,
|
||||||
|
createRoundedRectDrawable(0, mTopBottomCornerRadius));
|
||||||
|
return new RippleDrawable(mRippleColor, /* content= */ stateList, /* mask= */ stateList);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Creates a rounded-rect drawable with the specified radii. */
|
||||||
|
private Drawable createRoundedRectDrawable(float topRadius, float bottomRadius) {
|
||||||
|
GradientDrawable backgroundMask = new GradientDrawable();
|
||||||
|
backgroundMask.setColor(mSurfaceColor);
|
||||||
|
backgroundMask.setShape(GradientDrawable.RECTANGLE);
|
||||||
|
backgroundMask.setCornerRadii(
|
||||||
|
new float[]{
|
||||||
|
topRadius,
|
||||||
|
topRadius,
|
||||||
|
topRadius,
|
||||||
|
topRadius,
|
||||||
|
bottomRadius,
|
||||||
|
bottomRadius,
|
||||||
|
bottomRadius,
|
||||||
|
bottomRadius
|
||||||
|
});
|
||||||
|
return backgroundMask;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.android.launcher3.widget.picker;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Different possible list position states for an item in the widgets list to have. Note that only
|
||||||
|
* headers use the expanded state.
|
||||||
|
*/
|
||||||
|
enum WidgetsListDrawableState {
|
||||||
|
FIRST(new int[]{android.R.attr.state_first}),
|
||||||
|
FIRST_EXPANDED(new int[]{android.R.attr.state_first, android.R.attr.state_expanded}),
|
||||||
|
MIDDLE(new int[]{android.R.attr.state_middle}),
|
||||||
|
MIDDLE_EXPANDED(new int[]{android.R.attr.state_middle, android.R.attr.state_expanded}),
|
||||||
|
LAST(new int[]{android.R.attr.state_last}),
|
||||||
|
SINGLE(new int[]{android.R.attr.state_single});
|
||||||
|
|
||||||
|
final int[] mStateSet;
|
||||||
|
|
||||||
|
WidgetsListDrawableState(int[] stateSet) {
|
||||||
|
mStateSet = stateSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
static WidgetsListDrawableState obtain(boolean isFirst, boolean isLast, boolean isExpanded) {
|
||||||
|
if (isFirst && isLast) return SINGLE;
|
||||||
|
if (isFirst && isExpanded) return FIRST_EXPANDED;
|
||||||
|
if (isFirst) return FIRST;
|
||||||
|
if (isLast) return LAST;
|
||||||
|
if (isExpanded) return MIDDLE_EXPANDED;
|
||||||
|
return MIDDLE;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,60 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2021 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package com.android.launcher3.widget.picker;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.res.ColorStateList;
|
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.graphics.drawable.GradientDrawable;
|
|
||||||
import android.graphics.drawable.RippleDrawable;
|
|
||||||
|
|
||||||
import com.android.launcher3.R;
|
|
||||||
import com.android.launcher3.util.Themes;
|
|
||||||
|
|
||||||
/** Helper class for creating drawables to use as background for list elements. */
|
|
||||||
final class WidgetsListDrawables {
|
|
||||||
|
|
||||||
private WidgetsListDrawables() {}
|
|
||||||
|
|
||||||
/** Creates a list background drawable with the specified radii. */
|
|
||||||
static Drawable createListBackgroundDrawable(
|
|
||||||
Context context,
|
|
||||||
float topRadius,
|
|
||||||
float bottomRadius) {
|
|
||||||
GradientDrawable backgroundMask = new GradientDrawable();
|
|
||||||
backgroundMask.setColor(context.getColorStateList(R.color.surface));
|
|
||||||
backgroundMask.setShape(GradientDrawable.RECTANGLE);
|
|
||||||
|
|
||||||
backgroundMask.setCornerRadii(
|
|
||||||
new float[]{
|
|
||||||
topRadius,
|
|
||||||
topRadius,
|
|
||||||
topRadius,
|
|
||||||
topRadius,
|
|
||||||
bottomRadius,
|
|
||||||
bottomRadius,
|
|
||||||
bottomRadius,
|
|
||||||
bottomRadius
|
|
||||||
});
|
|
||||||
|
|
||||||
return new RippleDrawable(
|
|
||||||
/* color= */ ColorStateList.valueOf(
|
|
||||||
Themes.getAttrColor(context, android.R.attr.colorControlHighlight)),
|
|
||||||
/* content= */ backgroundMask,
|
|
||||||
/* mask= */ backgroundMask);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -60,9 +60,6 @@ public final class WidgetsListHeader extends LinearLayout implements ItemInfoUpd
|
||||||
@Nullable private Drawable mIconDrawable;
|
@Nullable private Drawable mIconDrawable;
|
||||||
private final int mIconSize;
|
private final int mIconSize;
|
||||||
private final int mBottomMarginSize;
|
private final int mBottomMarginSize;
|
||||||
private final float mTopBottomCornerRadius;
|
|
||||||
private final float mMiddleCornerRadius;
|
|
||||||
private final float mJoinedCornerRadius;
|
|
||||||
|
|
||||||
private ImageView mAppIcon;
|
private ImageView mAppIcon;
|
||||||
private TextView mTitle;
|
private TextView mTitle;
|
||||||
|
@ -70,6 +67,7 @@ public final class WidgetsListHeader extends LinearLayout implements ItemInfoUpd
|
||||||
|
|
||||||
private CheckBox mExpandToggle;
|
private CheckBox mExpandToggle;
|
||||||
private boolean mIsExpanded = false;
|
private boolean mIsExpanded = false;
|
||||||
|
@Nullable private WidgetsListDrawableState mListDrawableState;
|
||||||
|
|
||||||
public WidgetsListHeader(Context context) {
|
public WidgetsListHeader(Context context) {
|
||||||
this(context, /* attrs= */ null);
|
this(context, /* attrs= */ null);
|
||||||
|
@ -90,12 +88,6 @@ public final class WidgetsListHeader extends LinearLayout implements ItemInfoUpd
|
||||||
grid.iconSizePx);
|
grid.iconSizePx);
|
||||||
mBottomMarginSize =
|
mBottomMarginSize =
|
||||||
getResources().getDimensionPixelSize(R.dimen.widget_list_entry_bottom_margin);
|
getResources().getDimensionPixelSize(R.dimen.widget_list_entry_bottom_margin);
|
||||||
mTopBottomCornerRadius =
|
|
||||||
getResources().getDimension(R.dimen.widget_list_top_bottom_corner_radius);
|
|
||||||
mMiddleCornerRadius =
|
|
||||||
getResources().getDimension(R.dimen.widget_list_content_corner_radius);
|
|
||||||
mJoinedCornerRadius =
|
|
||||||
getResources().getDimension(R.dimen.widget_list_content_joined_corner_radius);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -163,6 +155,14 @@ public final class WidgetsListHeader extends LinearLayout implements ItemInfoUpd
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Sets the {@link WidgetsListDrawableState} and refreshes the background drawable. */
|
||||||
|
@UiThread
|
||||||
|
public void setListDrawableState(WidgetsListDrawableState state) {
|
||||||
|
if (state == mListDrawableState) return;
|
||||||
|
this.mListDrawableState = state;
|
||||||
|
refreshDrawableState();
|
||||||
|
}
|
||||||
|
|
||||||
/** Apply app icon, labels and tag using a generic {@link WidgetsListHeaderEntry}. */
|
/** Apply app icon, labels and tag using a generic {@link WidgetsListHeaderEntry}. */
|
||||||
@UiThread
|
@UiThread
|
||||||
public void applyFromItemInfoWithIcon(WidgetsListHeaderEntry entry) {
|
public void applyFromItemInfoWithIcon(WidgetsListHeaderEntry entry) {
|
||||||
|
@ -263,20 +263,6 @@ public final class WidgetsListHeader extends LinearLayout implements ItemInfoUpd
|
||||||
verifyHighRes();
|
verifyHighRes();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Updates the list to have a background drawable with the appropriate corner radii. */
|
|
||||||
@UiThread
|
|
||||||
public void updateListBackground(boolean isFirst, boolean isLast, boolean isExpanded) {
|
|
||||||
float topRadius = isFirst ? mTopBottomCornerRadius : mMiddleCornerRadius;
|
|
||||||
float bottomRadius = isLast
|
|
||||||
? mTopBottomCornerRadius
|
|
||||||
: isExpanded
|
|
||||||
? mJoinedCornerRadius
|
|
||||||
: mMiddleCornerRadius;
|
|
||||||
setBackground(
|
|
||||||
WidgetsListDrawables.createListBackgroundDrawable(
|
|
||||||
getContext(), topRadius, bottomRadius));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setTitles(WidgetsListSearchHeaderEntry entry) {
|
private void setTitles(WidgetsListSearchHeaderEntry entry) {
|
||||||
mTitle.setText(entry.mPkgItem.title);
|
mTitle.setText(entry.mPkgItem.title);
|
||||||
|
|
||||||
|
@ -300,6 +286,17 @@ public final class WidgetsListHeader extends LinearLayout implements ItemInfoUpd
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int[] onCreateDrawableState(int extraSpace) {
|
||||||
|
if (mListDrawableState == null) return super.onCreateDrawableState(extraSpace);
|
||||||
|
// Augment the state set from the super implementation with the custom states from
|
||||||
|
// mListDrawableState.
|
||||||
|
int[] drawableState =
|
||||||
|
super.onCreateDrawableState(extraSpace + mListDrawableState.mStateSet.length);
|
||||||
|
mergeDrawableStates(drawableState, mListDrawableState.mStateSet);
|
||||||
|
return drawableState;
|
||||||
|
}
|
||||||
|
|
||||||
/** Verifies that the current icon is high-res otherwise posts a request to load the icon. */
|
/** Verifies that the current icon is high-res otherwise posts a request to load the icon. */
|
||||||
public void verifyHighRes() {
|
public void verifyHighRes() {
|
||||||
if (mIconLoadRequest != null) {
|
if (mIconLoadRequest != null) {
|
||||||
|
|
|
@ -30,13 +30,16 @@ public final class WidgetsListHeaderViewHolderBinder implements
|
||||||
ViewHolderBinder<WidgetsListHeaderEntry, WidgetsListHeaderHolder> {
|
ViewHolderBinder<WidgetsListHeaderEntry, WidgetsListHeaderHolder> {
|
||||||
private final LayoutInflater mLayoutInflater;
|
private final LayoutInflater mLayoutInflater;
|
||||||
private final OnHeaderClickListener mOnHeaderClickListener;
|
private final OnHeaderClickListener mOnHeaderClickListener;
|
||||||
|
private final WidgetsListDrawableFactory mListDrawableFactory;
|
||||||
private final WidgetsListAdapter mWidgetsListAdapter;
|
private final WidgetsListAdapter mWidgetsListAdapter;
|
||||||
|
|
||||||
public WidgetsListHeaderViewHolderBinder(LayoutInflater layoutInflater,
|
public WidgetsListHeaderViewHolderBinder(LayoutInflater layoutInflater,
|
||||||
OnHeaderClickListener onHeaderClickListener,
|
OnHeaderClickListener onHeaderClickListener,
|
||||||
|
WidgetsListDrawableFactory listDrawableFactory,
|
||||||
WidgetsListAdapter listAdapter) {
|
WidgetsListAdapter listAdapter) {
|
||||||
mLayoutInflater = layoutInflater;
|
mLayoutInflater = layoutInflater;
|
||||||
mOnHeaderClickListener = onHeaderClickListener;
|
mOnHeaderClickListener = onHeaderClickListener;
|
||||||
|
mListDrawableFactory = listDrawableFactory;
|
||||||
mWidgetsListAdapter = listAdapter;
|
mWidgetsListAdapter = listAdapter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +47,7 @@ public final class WidgetsListHeaderViewHolderBinder implements
|
||||||
public WidgetsListHeaderHolder newViewHolder(ViewGroup parent) {
|
public WidgetsListHeaderHolder newViewHolder(ViewGroup parent) {
|
||||||
WidgetsListHeader header = (WidgetsListHeader) mLayoutInflater.inflate(
|
WidgetsListHeader header = (WidgetsListHeader) mLayoutInflater.inflate(
|
||||||
R.layout.widgets_list_row_header, parent, false);
|
R.layout.widgets_list_row_header, parent, false);
|
||||||
|
header.setBackground(mListDrawableFactory.createHeaderBackgroundDrawable());
|
||||||
return new WidgetsListHeaderHolder(header);
|
return new WidgetsListHeaderHolder(header);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,12 +55,13 @@ public final class WidgetsListHeaderViewHolderBinder implements
|
||||||
public void bindViewHolder(WidgetsListHeaderHolder viewHolder, WidgetsListHeaderEntry data,
|
public void bindViewHolder(WidgetsListHeaderHolder viewHolder, WidgetsListHeaderEntry data,
|
||||||
int position) {
|
int position) {
|
||||||
WidgetsListHeader widgetsListHeader = viewHolder.mWidgetsListHeader;
|
WidgetsListHeader widgetsListHeader = viewHolder.mWidgetsListHeader;
|
||||||
widgetsListHeader.updateListBackground(
|
|
||||||
/* isFirst= */ position == 0,
|
|
||||||
/* isLast= */ position == mWidgetsListAdapter.getItemCount() - 1,
|
|
||||||
/* isExpanded= */ data.isWidgetListShown());
|
|
||||||
widgetsListHeader.applyFromItemInfoWithIcon(data);
|
widgetsListHeader.applyFromItemInfoWithIcon(data);
|
||||||
widgetsListHeader.setExpanded(data.isWidgetListShown());
|
widgetsListHeader.setExpanded(data.isWidgetListShown());
|
||||||
|
widgetsListHeader.setListDrawableState(
|
||||||
|
WidgetsListDrawableState.obtain(
|
||||||
|
/* isFirst= */ position == 0,
|
||||||
|
/* isLast= */ position == mWidgetsListAdapter.getItemCount() - 1,
|
||||||
|
/* isExpanded= */ data.isWidgetListShown()));
|
||||||
widgetsListHeader.setOnExpandChangeListener(isExpanded ->
|
widgetsListHeader.setOnExpandChangeListener(isExpanded ->
|
||||||
mOnHeaderClickListener.onHeaderClicked(
|
mOnHeaderClickListener.onHeaderClicked(
|
||||||
isExpanded,
|
isExpanded,
|
||||||
|
|
|
@ -31,13 +31,16 @@ public final class WidgetsListSearchHeaderViewHolderBinder implements
|
||||||
ViewHolderBinder<WidgetsListSearchHeaderEntry, WidgetsListSearchHeaderHolder> {
|
ViewHolderBinder<WidgetsListSearchHeaderEntry, WidgetsListSearchHeaderHolder> {
|
||||||
private final LayoutInflater mLayoutInflater;
|
private final LayoutInflater mLayoutInflater;
|
||||||
private final OnHeaderClickListener mOnHeaderClickListener;
|
private final OnHeaderClickListener mOnHeaderClickListener;
|
||||||
|
private final WidgetsListDrawableFactory mListDrawableFactory;
|
||||||
private final WidgetsListAdapter mWidgetsListAdapter;
|
private final WidgetsListAdapter mWidgetsListAdapter;
|
||||||
|
|
||||||
public WidgetsListSearchHeaderViewHolderBinder(LayoutInflater layoutInflater,
|
public WidgetsListSearchHeaderViewHolderBinder(LayoutInflater layoutInflater,
|
||||||
OnHeaderClickListener onHeaderClickListener,
|
OnHeaderClickListener onHeaderClickListener,
|
||||||
|
WidgetsListDrawableFactory listDrawableFactory,
|
||||||
WidgetsListAdapter listAdapter) {
|
WidgetsListAdapter listAdapter) {
|
||||||
mLayoutInflater = layoutInflater;
|
mLayoutInflater = layoutInflater;
|
||||||
mOnHeaderClickListener = onHeaderClickListener;
|
mOnHeaderClickListener = onHeaderClickListener;
|
||||||
|
mListDrawableFactory = listDrawableFactory;
|
||||||
mWidgetsListAdapter = listAdapter;
|
mWidgetsListAdapter = listAdapter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +48,7 @@ public final class WidgetsListSearchHeaderViewHolderBinder implements
|
||||||
public WidgetsListSearchHeaderHolder newViewHolder(ViewGroup parent) {
|
public WidgetsListSearchHeaderHolder newViewHolder(ViewGroup parent) {
|
||||||
WidgetsListHeader header = (WidgetsListHeader) mLayoutInflater.inflate(
|
WidgetsListHeader header = (WidgetsListHeader) mLayoutInflater.inflate(
|
||||||
R.layout.widgets_list_row_header, parent, false);
|
R.layout.widgets_list_row_header, parent, false);
|
||||||
|
header.setBackground(mListDrawableFactory.createHeaderBackgroundDrawable());
|
||||||
return new WidgetsListSearchHeaderHolder(header);
|
return new WidgetsListSearchHeaderHolder(header);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,12 +56,13 @@ public final class WidgetsListSearchHeaderViewHolderBinder implements
|
||||||
public void bindViewHolder(WidgetsListSearchHeaderHolder viewHolder,
|
public void bindViewHolder(WidgetsListSearchHeaderHolder viewHolder,
|
||||||
WidgetsListSearchHeaderEntry data, int position) {
|
WidgetsListSearchHeaderEntry data, int position) {
|
||||||
WidgetsListHeader widgetsListHeader = viewHolder.mWidgetsListHeader;
|
WidgetsListHeader widgetsListHeader = viewHolder.mWidgetsListHeader;
|
||||||
widgetsListHeader.updateListBackground(
|
|
||||||
/* isFirst= */ position == 0,
|
|
||||||
/* isLast= */ position == mWidgetsListAdapter.getItemCount() - 1,
|
|
||||||
/* isExpanded= */ data.isWidgetListShown());
|
|
||||||
widgetsListHeader.applyFromItemInfoWithIcon(data);
|
widgetsListHeader.applyFromItemInfoWithIcon(data);
|
||||||
widgetsListHeader.setExpanded(data.isWidgetListShown());
|
widgetsListHeader.setExpanded(data.isWidgetListShown());
|
||||||
|
widgetsListHeader.setListDrawableState(
|
||||||
|
WidgetsListDrawableState.obtain(
|
||||||
|
/* isFirst= */ position == 0,
|
||||||
|
/* isLast= */ position == mWidgetsListAdapter.getItemCount() - 1,
|
||||||
|
/* isExpanded= */ data.isWidgetListShown()));
|
||||||
widgetsListHeader.setOnExpandChangeListener(isExpanded ->
|
widgetsListHeader.setOnExpandChangeListener(isExpanded ->
|
||||||
mOnHeaderClickListener.onHeaderClicked(isExpanded,
|
mOnHeaderClickListener.onHeaderClicked(isExpanded,
|
||||||
new PackageUserKey(data.mPkgItem.packageName, data.mPkgItem.user)));
|
new PackageUserKey(data.mPkgItem.packageName, data.mPkgItem.user)));
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.android.launcher3.widget.picker;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.widget.TableLayout;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.annotation.UiThread;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extension of {@link TableLayout} to support the drawable states used by
|
||||||
|
* {@link WidgetsListDrawableState}.
|
||||||
|
*/
|
||||||
|
public class WidgetsListTableView extends TableLayout {
|
||||||
|
|
||||||
|
@Nullable private WidgetsListDrawableState mListDrawableState;
|
||||||
|
|
||||||
|
public WidgetsListTableView(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WidgetsListTableView(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Sets the {@link WidgetsListDrawableState} and refreshes the background drawable. */
|
||||||
|
@UiThread
|
||||||
|
public void setListDrawableState(WidgetsListDrawableState state) {
|
||||||
|
if (state == mListDrawableState) return;
|
||||||
|
mListDrawableState = state;
|
||||||
|
refreshDrawableState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int[] onCreateDrawableState(int extraSpace) {
|
||||||
|
if (mListDrawableState == null) return super.onCreateDrawableState(extraSpace);
|
||||||
|
// Augment the state set from the super implementation with the custom states from
|
||||||
|
// mListDrawableState.
|
||||||
|
int[] drawableState =
|
||||||
|
super.onCreateDrawableState(extraSpace + mListDrawableState.mStateSet.length);
|
||||||
|
mergeDrawableStates(drawableState, mListDrawableState.mStateSet);
|
||||||
|
return drawableState;
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,8 +15,10 @@
|
||||||
*/
|
*/
|
||||||
package com.android.launcher3.widget.picker;
|
package com.android.launcher3.widget.picker;
|
||||||
|
|
||||||
|
import static com.android.launcher3.widget.picker.WidgetsListDrawableState.LAST;
|
||||||
|
import static com.android.launcher3.widget.picker.WidgetsListDrawableState.MIDDLE;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
@ -51,10 +53,8 @@ public final class WidgetsListTableViewHolderBinder
|
||||||
private final OnClickListener mIconClickListener;
|
private final OnClickListener mIconClickListener;
|
||||||
private final OnLongClickListener mIconLongClickListener;
|
private final OnLongClickListener mIconLongClickListener;
|
||||||
private final WidgetPreviewLoader mWidgetPreviewLoader;
|
private final WidgetPreviewLoader mWidgetPreviewLoader;
|
||||||
|
private final WidgetsListDrawableFactory mListDrawableFactory;
|
||||||
private final WidgetsListAdapter mWidgetsListAdapter;
|
private final WidgetsListAdapter mWidgetsListAdapter;
|
||||||
private final float mTopBottomCornerRadius;
|
|
||||||
private final float mMiddleCornerRadius;
|
|
||||||
private final float mJoinedCornerRadius;
|
|
||||||
private boolean mApplyBitmapDeferred = false;
|
private boolean mApplyBitmapDeferred = false;
|
||||||
|
|
||||||
public WidgetsListTableViewHolderBinder(
|
public WidgetsListTableViewHolderBinder(
|
||||||
|
@ -63,19 +63,14 @@ public final class WidgetsListTableViewHolderBinder
|
||||||
OnClickListener iconClickListener,
|
OnClickListener iconClickListener,
|
||||||
OnLongClickListener iconLongClickListener,
|
OnLongClickListener iconLongClickListener,
|
||||||
WidgetPreviewLoader widgetPreviewLoader,
|
WidgetPreviewLoader widgetPreviewLoader,
|
||||||
|
WidgetsListDrawableFactory listDrawableFactory,
|
||||||
WidgetsListAdapter listAdapter) {
|
WidgetsListAdapter listAdapter) {
|
||||||
mLayoutInflater = layoutInflater;
|
mLayoutInflater = layoutInflater;
|
||||||
mIconClickListener = iconClickListener;
|
mIconClickListener = iconClickListener;
|
||||||
mIconLongClickListener = iconLongClickListener;
|
mIconLongClickListener = iconLongClickListener;
|
||||||
mWidgetPreviewLoader = widgetPreviewLoader;
|
mWidgetPreviewLoader = widgetPreviewLoader;
|
||||||
|
mListDrawableFactory = listDrawableFactory;
|
||||||
mWidgetsListAdapter = listAdapter;
|
mWidgetsListAdapter = listAdapter;
|
||||||
Resources resources = context.getResources();
|
|
||||||
mTopBottomCornerRadius =
|
|
||||||
resources.getDimension(R.dimen.widget_list_top_bottom_corner_radius);
|
|
||||||
mMiddleCornerRadius =
|
|
||||||
resources.getDimension(R.dimen.widget_list_content_corner_radius);
|
|
||||||
mJoinedCornerRadius =
|
|
||||||
resources.getDimension(R.dimen.widget_list_content_joined_corner_radius);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -97,28 +92,25 @@ public final class WidgetsListTableViewHolderBinder
|
||||||
Log.v(TAG, "\nonCreateViewHolder");
|
Log.v(TAG, "\nonCreateViewHolder");
|
||||||
}
|
}
|
||||||
|
|
||||||
ViewGroup container = (ViewGroup) mLayoutInflater.inflate(
|
WidgetsRowViewHolder viewHolder =
|
||||||
R.layout.widgets_table_container, parent, false);
|
new WidgetsRowViewHolder(mLayoutInflater.inflate(
|
||||||
return new WidgetsRowViewHolder(container);
|
R.layout.widgets_table_container, parent, false));
|
||||||
|
viewHolder.mTableContainer.setBackgroundDrawable(
|
||||||
|
mListDrawableFactory.createContentBackgroundDrawable());
|
||||||
|
return viewHolder;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void bindViewHolder(WidgetsRowViewHolder holder, WidgetsListContentEntry entry,
|
public void bindViewHolder(WidgetsRowViewHolder holder, WidgetsListContentEntry entry,
|
||||||
int position) {
|
int position) {
|
||||||
TableLayout table = holder.mTableContainer;
|
WidgetsListTableView table = holder.mTableContainer;
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.d(TAG, String.format("onBindViewHolder [widget#=%d, table.getChildCount=%d]",
|
Log.d(TAG, String.format("onBindViewHolder [widget#=%d, table.getChildCount=%d]",
|
||||||
entry.mWidgets.size(), table.getChildCount()));
|
entry.mWidgets.size(), table.getChildCount()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// The content is always joined to an expanded header above.
|
table.setListDrawableState(
|
||||||
float topRadius = mJoinedCornerRadius;
|
position == mWidgetsListAdapter.getItemCount() - 1 ? LAST : MIDDLE);
|
||||||
float bottomRadius = position == mWidgetsListAdapter.getItemCount() - 1
|
|
||||||
? mTopBottomCornerRadius
|
|
||||||
: mMiddleCornerRadius;
|
|
||||||
table.setBackgroundDrawable(
|
|
||||||
WidgetsListDrawables.createListBackgroundDrawable(
|
|
||||||
holder.itemView.getContext(), topRadius, bottomRadius));
|
|
||||||
|
|
||||||
List<ArrayList<WidgetItem>> widgetItemsTable =
|
List<ArrayList<WidgetItem>> widgetItemsTable =
|
||||||
WidgetsTableUtils.groupWidgetItemsIntoTable(entry.mWidgets, mMaxSpansPerRow);
|
WidgetsTableUtils.groupWidgetItemsIntoTable(entry.mWidgets, mMaxSpansPerRow);
|
||||||
|
|
|
@ -15,8 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package com.android.launcher3.widget.picker;
|
package com.android.launcher3.widget.picker;
|
||||||
|
|
||||||
import android.view.ViewGroup;
|
import android.view.View;
|
||||||
import android.widget.TableLayout;
|
|
||||||
|
|
||||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
|
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
|
||||||
|
|
||||||
|
@ -25,9 +24,9 @@ import com.android.launcher3.R;
|
||||||
/** A {@link ViewHolder} for showing widgets of an app in the full widget picker. */
|
/** A {@link ViewHolder} for showing widgets of an app in the full widget picker. */
|
||||||
public final class WidgetsRowViewHolder extends ViewHolder {
|
public final class WidgetsRowViewHolder extends ViewHolder {
|
||||||
|
|
||||||
public final TableLayout mTableContainer;
|
public final WidgetsListTableView mTableContainer;
|
||||||
|
|
||||||
public WidgetsRowViewHolder(ViewGroup v) {
|
public WidgetsRowViewHolder(View v) {
|
||||||
super(v);
|
super(v);
|
||||||
|
|
||||||
mTableContainer = v.findViewById(R.id.widgets_table);
|
mTableContainer = v.findViewById(R.id.widgets_table);
|
||||||
|
|
Loading…
Reference in New Issue