diff options
| author | 2022-11-28 22:33:51 +0000 | |
|---|---|---|
| committer | 2022-11-28 22:33:51 +0000 | |
| commit | 7d10435590e2230d283758871ae6aae15a22da6e (patch) | |
| tree | dd26bf4d9c4acdc341d977cdde5145fcde997f1b /java/src/com | |
| parent | 0919a83ee94b469eba0a72ee6e79fddb1e7dc7f7 (diff) | |
| parent | 83128998e50f5bce173638b4b25c5722f8267932 (diff) | |
Merge "Extract ChooserActivity inner ViewHolder classes" into tm-qpr-dev
Diffstat (limited to 'java/src/com')
7 files changed, 514 insertions, 314 deletions
diff --git a/java/src/com/android/intentresolver/ChooserActivity.java b/java/src/com/android/intentresolver/ChooserActivity.java index 776d34a9..11044a1d 100644 --- a/java/src/com/android/intentresolver/ChooserActivity.java +++ b/java/src/com/android/intentresolver/ChooserActivity.java @@ -26,8 +26,6 @@ import static android.stats.devicepolicy.nano.DevicePolicyEnums.RESOLVER_EMPTY_S import static com.android.internal.util.LatencyTracker.ACTION_LOAD_SHARE_SHEET; -import android.animation.Animator; -import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; @@ -93,7 +91,6 @@ import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.view.ViewTreeObserver; import android.view.WindowInsets; -import android.view.animation.AccelerateInterpolator; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.view.animation.DecelerateInterpolator; @@ -114,6 +111,12 @@ import com.android.intentresolver.ResolverListAdapter.ViewHolder; import com.android.intentresolver.chooser.DisplayResolveInfo; import com.android.intentresolver.chooser.MultiDisplayResolveInfo; import com.android.intentresolver.chooser.TargetInfo; +import com.android.intentresolver.grid.DirectShareViewHolder; +import com.android.intentresolver.grid.FooterViewHolder; +import com.android.intentresolver.grid.ItemGroupViewHolder; +import com.android.intentresolver.grid.ItemViewHolder; +import com.android.intentresolver.grid.SingleRowViewHolder; +import com.android.intentresolver.grid.ViewHolderBase; import com.android.intentresolver.model.AbstractResolverComparator; import com.android.intentresolver.model.AppPredictionServiceResolverComparator; import com.android.intentresolver.model.ResolverRankerServiceResolverComparator; @@ -136,7 +139,6 @@ import java.lang.annotation.RetentionPolicy; import java.net.URISyntaxException; import java.text.Collator; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; @@ -232,9 +234,9 @@ public class ChooserActivity extends ResolverActivity implements * The transition time between placeholders for direct share to a message * indicating that non are available. */ - private static final int NO_DIRECT_SHARE_ANIM_IN_MILLIS = 200; + public static final int NO_DIRECT_SHARE_ANIM_IN_MILLIS = 200; - private static final float DIRECT_SHARE_EXPANSION_RATE = 0.78f; + public static final float DIRECT_SHARE_EXPANSION_RATE = 0.78f; private static final int DEFAULT_SALT_EXPIRATION_DAYS = 7; private final int mMaxHashSaltDays = DeviceConfig.getInt(DeviceConfig.NAMESPACE_SYSTEMUI, @@ -2210,60 +2212,6 @@ public class ChooserActivity extends ResolverActivity implements return mContentView; } - abstract static class ViewHolderBase extends RecyclerView.ViewHolder { - private int mViewType; - - ViewHolderBase(View itemView, int viewType) { - super(itemView); - this.mViewType = viewType; - } - - int getViewType() { - return mViewType; - } - } - - /** - * Used to bind types of individual item including - * {@link ChooserGridAdapter#VIEW_TYPE_NORMAL}, - * {@link ChooserGridAdapter#VIEW_TYPE_CONTENT_PREVIEW}, - * {@link ChooserGridAdapter#VIEW_TYPE_PROFILE}, - * and {@link ChooserGridAdapter#VIEW_TYPE_AZ_LABEL}. - */ - final class ItemViewHolder extends ViewHolderBase { - ResolverListAdapter.ViewHolder mWrappedViewHolder; - int mListPosition = ChooserListAdapter.NO_POSITION; - - ItemViewHolder(View itemView, boolean isClickable, int viewType) { - super(itemView, viewType); - mWrappedViewHolder = new ResolverListAdapter.ViewHolder(itemView); - if (isClickable) { - itemView.setOnClickListener(v -> startSelected(mListPosition, - false/* always */, true/* filterd */)); - - itemView.setOnLongClickListener(v -> { - final TargetInfo ti = mChooserMultiProfilePagerAdapter.getActiveListAdapter() - .targetInfoForPosition(mListPosition, /* filtered */ true); - - // This should always be the case for ItemViewHolder, check for validity - if (ti.isDisplayResolveInfo()) { - showTargetDetails(ti); - } - return true; - }); - } - } - } - - /** - * Add a footer to the list, to support scrolling behavior below the navbar. - */ - static final class FooterViewHolder extends ViewHolderBase { - FooterViewHolder(View itemView, int viewType) { - super(itemView, viewType); - } - } - /** * Intentionally override the {@link ResolverActivity} implementation as we only need that * implementation for the intent resolver case. @@ -2503,15 +2451,41 @@ public class ChooserActivity extends ResolverActivity implements case VIEW_TYPE_CONTENT_PREVIEW: return new ItemViewHolder( createContentPreviewView(parent, mPreviewCoordinator), - false, - viewType); + viewType, + null, + null); case VIEW_TYPE_PROFILE: - return new ItemViewHolder(createProfileView(parent), false, viewType); + return new ItemViewHolder( + createProfileView(parent), + viewType, + null, + null); case VIEW_TYPE_AZ_LABEL: - return new ItemViewHolder(createAzLabelView(parent), false, viewType); + return new ItemViewHolder( + createAzLabelView(parent), + viewType, + null, + null); case VIEW_TYPE_NORMAL: return new ItemViewHolder( - mChooserListAdapter.createView(parent), true, viewType); + mChooserListAdapter.createView(parent), + viewType, + selectedPosition -> startSelected( + selectedPosition, + /* always= */ false, + /* filtered= */ true), + selectedPosition -> { + final TargetInfo longPressedTargetInfo = + mChooserMultiProfilePagerAdapter + .getActiveListAdapter() + .targetInfoForPosition( + selectedPosition, /* filtered= */ true); + // ItemViewHolder contents should always be "display resolve info" + // targets, but check just to make sure. + if (longPressedTargetInfo.isDisplayResolveInfo()) { + showTargetDetails(longPressedTargetInfo); + } + }); case VIEW_TYPE_DIRECT_SHARE: case VIEW_TYPE_CALLER_AND_RANK: return createItemGroupViewHolder(viewType, parent); @@ -2704,7 +2678,7 @@ public class ChooserActivity extends ResolverActivity implements void bindItemViewHolder(int position, ItemViewHolder holder) { View v = holder.itemView; int listPosition = getListPosition(position); - holder.mListPosition = listPosition; + holder.setListPosition(listPosition); mChooserListAdapter.bindView(listPosition, v); } @@ -2821,254 +2795,6 @@ public class ChooserActivity extends ResolverActivity implements } } - /** - * Used to bind types for group of items including: - * {@link ChooserGridAdapter#VIEW_TYPE_DIRECT_SHARE}, - * and {@link ChooserGridAdapter#VIEW_TYPE_CALLER_AND_RANK}. - */ - abstract static class ItemGroupViewHolder extends ViewHolderBase { - protected int mMeasuredRowHeight; - private int[] mItemIndices; - protected final View[] mCells; - private final int mColumnCount; - - ItemGroupViewHolder(int cellCount, View itemView, int viewType) { - super(itemView, viewType); - this.mCells = new View[cellCount]; - this.mItemIndices = new int[cellCount]; - this.mColumnCount = cellCount; - } - - abstract ViewGroup addView(int index, View v); - - abstract ViewGroup getViewGroup(); - - abstract ViewGroup getRowByIndex(int index); - - abstract ViewGroup getRow(int rowNumber); - - abstract void setViewVisibility(int i, int visibility); - - public int getColumnCount() { - return mColumnCount; - } - - public void measure() { - final int spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); - getViewGroup().measure(spec, spec); - mMeasuredRowHeight = getViewGroup().getMeasuredHeight(); - } - - public int getMeasuredRowHeight() { - return mMeasuredRowHeight; - } - - public void setItemIndex(int itemIndex, int listIndex) { - mItemIndices[itemIndex] = listIndex; - } - - public int getItemIndex(int itemIndex) { - return mItemIndices[itemIndex]; - } - - public View getView(int index) { - return mCells[index]; - } - } - - static class SingleRowViewHolder extends ItemGroupViewHolder { - private final ViewGroup mRow; - - SingleRowViewHolder(ViewGroup row, int cellCount, int viewType) { - super(cellCount, row, viewType); - - this.mRow = row; - } - - public ViewGroup getViewGroup() { - return mRow; - } - - public ViewGroup getRowByIndex(int index) { - return mRow; - } - - public ViewGroup getRow(int rowNumber) { - if (rowNumber == 0) return mRow; - return null; - } - - public ViewGroup addView(int index, View v) { - mRow.addView(v); - mCells[index] = v; - - return mRow; - } - - public void setViewVisibility(int i, int visibility) { - getView(i).setVisibility(visibility); - } - } - - static class DirectShareViewHolder extends ItemGroupViewHolder { - private final ViewGroup mParent; - private final List<ViewGroup> mRows; - private int mCellCountPerRow; - - private boolean mHideDirectShareExpansion = false; - private int mDirectShareMinHeight = 0; - private int mDirectShareCurrHeight = 0; - private int mDirectShareMaxHeight = 0; - - private final boolean[] mCellVisibility; - - private final Supplier<ChooserListAdapter> mListAdapterSupplier; - - DirectShareViewHolder(ViewGroup parent, List<ViewGroup> rows, int cellCountPerRow, - int viewType, Supplier<ChooserListAdapter> listAdapterSupplier) { - super(rows.size() * cellCountPerRow, parent, viewType); - - this.mParent = parent; - this.mRows = rows; - this.mCellCountPerRow = cellCountPerRow; - this.mCellVisibility = new boolean[rows.size() * cellCountPerRow]; - Arrays.fill(mCellVisibility, true); - this.mListAdapterSupplier = listAdapterSupplier; - } - - public ViewGroup addView(int index, View v) { - ViewGroup row = getRowByIndex(index); - row.addView(v); - mCells[index] = v; - - return row; - } - - public ViewGroup getViewGroup() { - return mParent; - } - - public ViewGroup getRowByIndex(int index) { - return mRows.get(index / mCellCountPerRow); - } - - public ViewGroup getRow(int rowNumber) { - return mRows.get(rowNumber); - } - - public void measure() { - final int spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); - getRow(0).measure(spec, spec); - getRow(1).measure(spec, spec); - - mDirectShareMinHeight = getRow(0).getMeasuredHeight(); - mDirectShareCurrHeight = mDirectShareCurrHeight > 0 - ? mDirectShareCurrHeight : mDirectShareMinHeight; - mDirectShareMaxHeight = 2 * mDirectShareMinHeight; - } - - public int getMeasuredRowHeight() { - return mDirectShareCurrHeight; - } - - public int getMinRowHeight() { - return mDirectShareMinHeight; - } - - public void setViewVisibility(int i, int visibility) { - final View v = getView(i); - if (visibility == View.VISIBLE) { - mCellVisibility[i] = true; - v.setVisibility(visibility); - v.setAlpha(1.0f); - } else if (visibility == View.INVISIBLE && mCellVisibility[i]) { - mCellVisibility[i] = false; - - ValueAnimator fadeAnim = ObjectAnimator.ofFloat(v, "alpha", 1.0f, 0f); - fadeAnim.setDuration(NO_DIRECT_SHARE_ANIM_IN_MILLIS); - fadeAnim.setInterpolator(new AccelerateInterpolator(1.0f)); - fadeAnim.addListener(new AnimatorListenerAdapter() { - public void onAnimationEnd(Animator animation) { - v.setVisibility(View.INVISIBLE); - } - }); - fadeAnim.start(); - } - } - - public void handleScroll(RecyclerView view, int y, int oldy, int maxTargetsPerRow) { - // only exit early if fully collapsed, otherwise onListRebuilt() with shifting - // targets can lock us into an expanded mode - boolean notExpanded = mDirectShareCurrHeight == mDirectShareMinHeight; - if (notExpanded) { - if (mHideDirectShareExpansion) { - return; - } - - // only expand if we have more than maxTargetsPerRow, and delay that decision - // until they start to scroll - ChooserListAdapter adapter = mListAdapterSupplier.get(); - int validTargets = adapter.getSelectableServiceTargetCount(); - if (validTargets <= maxTargetsPerRow) { - mHideDirectShareExpansion = true; - return; - } - } - - int yDiff = (int) ((oldy - y) * DIRECT_SHARE_EXPANSION_RATE); - - int prevHeight = mDirectShareCurrHeight; - int newHeight = Math.min(prevHeight + yDiff, mDirectShareMaxHeight); - newHeight = Math.max(newHeight, mDirectShareMinHeight); - yDiff = newHeight - prevHeight; - - updateDirectShareRowHeight(view, yDiff, newHeight); - } - - void expand(RecyclerView view) { - updateDirectShareRowHeight(view, mDirectShareMaxHeight - mDirectShareCurrHeight, - mDirectShareMaxHeight); - } - - void collapse(RecyclerView view) { - updateDirectShareRowHeight(view, mDirectShareMinHeight - mDirectShareCurrHeight, - mDirectShareMinHeight); - } - - private void updateDirectShareRowHeight(RecyclerView view, int yDiff, int newHeight) { - if (view == null || view.getChildCount() == 0 || yDiff == 0) { - return; - } - - // locate the item to expand, and offset the rows below that one - boolean foundExpansion = false; - for (int i = 0; i < view.getChildCount(); i++) { - View child = view.getChildAt(i); - - if (foundExpansion) { - child.offsetTopAndBottom(yDiff); - } else { - if (child.getTag() != null && child.getTag() instanceof DirectShareViewHolder) { - int widthSpec = MeasureSpec.makeMeasureSpec(child.getWidth(), - MeasureSpec.EXACTLY); - int heightSpec = MeasureSpec.makeMeasureSpec(newHeight, - MeasureSpec.EXACTLY); - child.measure(widthSpec, heightSpec); - child.getLayoutParams().height = child.getMeasuredHeight(); - child.layout(child.getLeft(), child.getTop(), child.getRight(), - child.getTop() + child.getMeasuredHeight()); - - foundExpansion = true; - } - } - } - - if (foundExpansion) { - mDirectShareCurrHeight = newHeight; - } - } - } - static class ChooserTargetRankingInfo { public final List<AppTarget> scores; public final UserHandle userHandle; diff --git a/java/src/com/android/intentresolver/grid/DirectShareViewHolder.java b/java/src/com/android/intentresolver/grid/DirectShareViewHolder.java new file mode 100644 index 00000000..95c61e3a --- /dev/null +++ b/java/src/com/android/intentresolver/grid/DirectShareViewHolder.java @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2022 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.intentresolver.grid; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; +import android.view.View; +import android.view.View.MeasureSpec; +import android.view.ViewGroup; +import android.view.animation.AccelerateInterpolator; + +import androidx.recyclerview.widget.RecyclerView; + +import com.android.intentresolver.ChooserActivity; +import com.android.intentresolver.ChooserListAdapter; + +import java.util.Arrays; +import java.util.List; +import java.util.function.Supplier; + +/** Holder for direct share targets in the {@link ChooserGridAdapter}. */ +public class DirectShareViewHolder extends ItemGroupViewHolder { + private final ViewGroup mParent; + private final List<ViewGroup> mRows; + private int mCellCountPerRow; + + private boolean mHideDirectShareExpansion = false; + private int mDirectShareMinHeight = 0; + private int mDirectShareCurrHeight = 0; + private int mDirectShareMaxHeight = 0; + + private final boolean[] mCellVisibility; + + private final Supplier<ChooserListAdapter> mListAdapterSupplier; + + public DirectShareViewHolder( + ViewGroup parent, + List<ViewGroup> rows, + int cellCountPerRow, + int viewType, + Supplier<ChooserListAdapter> listAdapterSupplier) { + super(rows.size() * cellCountPerRow, parent, viewType); + + this.mParent = parent; + this.mRows = rows; + this.mCellCountPerRow = cellCountPerRow; + this.mCellVisibility = new boolean[rows.size() * cellCountPerRow]; + Arrays.fill(mCellVisibility, true); + this.mListAdapterSupplier = listAdapterSupplier; + } + + public ViewGroup addView(int index, View v) { + ViewGroup row = getRowByIndex(index); + row.addView(v); + mCells[index] = v; + + return row; + } + + public ViewGroup getViewGroup() { + return mParent; + } + + public ViewGroup getRowByIndex(int index) { + return mRows.get(index / mCellCountPerRow); + } + + public ViewGroup getRow(int rowNumber) { + return mRows.get(rowNumber); + } + + public void measure() { + final int spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); + getRow(0).measure(spec, spec); + getRow(1).measure(spec, spec); + + mDirectShareMinHeight = getRow(0).getMeasuredHeight(); + mDirectShareCurrHeight = (mDirectShareCurrHeight > 0) + ? mDirectShareCurrHeight : mDirectShareMinHeight; + mDirectShareMaxHeight = 2 * mDirectShareMinHeight; + } + + public int getMeasuredRowHeight() { + return mDirectShareCurrHeight; + } + + public int getMinRowHeight() { + return mDirectShareMinHeight; + } + + public void setViewVisibility(int i, int visibility) { + final View v = getView(i); + if (visibility == View.VISIBLE) { + mCellVisibility[i] = true; + v.setVisibility(visibility); + v.setAlpha(1.0f); + } else if (visibility == View.INVISIBLE && mCellVisibility[i]) { + mCellVisibility[i] = false; + + ValueAnimator fadeAnim = ObjectAnimator.ofFloat(v, "alpha", 1.0f, 0f); + fadeAnim.setDuration(ChooserActivity.NO_DIRECT_SHARE_ANIM_IN_MILLIS); + fadeAnim.setInterpolator(new AccelerateInterpolator(1.0f)); + fadeAnim.addListener(new AnimatorListenerAdapter() { + public void onAnimationEnd(Animator animation) { + v.setVisibility(View.INVISIBLE); + } + }); + fadeAnim.start(); + } + } + + public void handleScroll(RecyclerView view, int y, int oldy, int maxTargetsPerRow) { + // only exit early if fully collapsed, otherwise onListRebuilt() with shifting + // targets can lock us into an expanded mode + boolean notExpanded = mDirectShareCurrHeight == mDirectShareMinHeight; + if (notExpanded) { + if (mHideDirectShareExpansion) { + return; + } + + // only expand if we have more than maxTargetsPerRow, and delay that decision + // until they start to scroll + ChooserListAdapter adapter = mListAdapterSupplier.get(); + int validTargets = adapter.getSelectableServiceTargetCount(); + if (validTargets <= maxTargetsPerRow) { + mHideDirectShareExpansion = true; + return; + } + } + + int yDiff = (int) ((oldy - y) * ChooserActivity.DIRECT_SHARE_EXPANSION_RATE); + + int prevHeight = mDirectShareCurrHeight; + int newHeight = Math.min(prevHeight + yDiff, mDirectShareMaxHeight); + newHeight = Math.max(newHeight, mDirectShareMinHeight); + yDiff = newHeight - prevHeight; + + updateDirectShareRowHeight(view, yDiff, newHeight); + } + + public void expand(RecyclerView view) { + updateDirectShareRowHeight( + view, mDirectShareMaxHeight - mDirectShareCurrHeight, mDirectShareMaxHeight); + } + + public void collapse(RecyclerView view) { + updateDirectShareRowHeight( + view, mDirectShareMinHeight - mDirectShareCurrHeight, mDirectShareMinHeight); + } + + private void updateDirectShareRowHeight(RecyclerView view, int yDiff, int newHeight) { + if (view == null || view.getChildCount() == 0 || yDiff == 0) { + return; + } + + // locate the item to expand, and offset the rows below that one + boolean foundExpansion = false; + for (int i = 0; i < view.getChildCount(); i++) { + View child = view.getChildAt(i); + + if (foundExpansion) { + child.offsetTopAndBottom(yDiff); + } else { + if (child.getTag() != null && child.getTag() instanceof DirectShareViewHolder) { + int widthSpec = MeasureSpec.makeMeasureSpec(child.getWidth(), + MeasureSpec.EXACTLY); + int heightSpec = MeasureSpec.makeMeasureSpec(newHeight, + MeasureSpec.EXACTLY); + child.measure(widthSpec, heightSpec); + child.getLayoutParams().height = child.getMeasuredHeight(); + child.layout(child.getLeft(), child.getTop(), child.getRight(), + child.getTop() + child.getMeasuredHeight()); + + foundExpansion = true; + } + } + } + + if (foundExpansion) { + mDirectShareCurrHeight = newHeight; + } + } +} diff --git a/java/src/com/android/intentresolver/grid/FooterViewHolder.java b/java/src/com/android/intentresolver/grid/FooterViewHolder.java new file mode 100644 index 00000000..0c94e3ed --- /dev/null +++ b/java/src/com/android/intentresolver/grid/FooterViewHolder.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2022 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.intentresolver.grid; + +import android.view.View; + +/** + * A footer on the list, to support scrolling behavior below the navbar. + */ +public final class FooterViewHolder extends ViewHolderBase { + public FooterViewHolder(View itemView, int viewType) { + super(itemView, viewType); + } +} diff --git a/java/src/com/android/intentresolver/grid/ItemGroupViewHolder.java b/java/src/com/android/intentresolver/grid/ItemGroupViewHolder.java new file mode 100644 index 00000000..5470506b --- /dev/null +++ b/java/src/com/android/intentresolver/grid/ItemGroupViewHolder.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2022 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.intentresolver.grid; + +import android.view.View; +import android.view.View.MeasureSpec; +import android.view.ViewGroup; + +/** + * Used to bind types for group of items including: + * {@link ChooserGridAdapter#VIEW_TYPE_DIRECT_SHARE}, + * and {@link ChooserGridAdapter#VIEW_TYPE_CALLER_AND_RANK}. + */ +public abstract class ItemGroupViewHolder extends ViewHolderBase { + protected int mMeasuredRowHeight; + private int[] mItemIndices; + protected final View[] mCells; + private final int mColumnCount; + + public ItemGroupViewHolder(int cellCount, View itemView, int viewType) { + super(itemView, viewType); + this.mCells = new View[cellCount]; + this.mItemIndices = new int[cellCount]; + this.mColumnCount = cellCount; + } + + public abstract ViewGroup addView(int index, View v); + + public abstract ViewGroup getViewGroup(); + + public abstract ViewGroup getRowByIndex(int index); + + public abstract ViewGroup getRow(int rowNumber); + + public abstract void setViewVisibility(int i, int visibility); + + public int getColumnCount() { + return mColumnCount; + } + + public void measure() { + final int spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); + getViewGroup().measure(spec, spec); + mMeasuredRowHeight = getViewGroup().getMeasuredHeight(); + } + + public int getMeasuredRowHeight() { + return mMeasuredRowHeight; + } + + public void setItemIndex(int itemIndex, int listIndex) { + mItemIndices[itemIndex] = listIndex; + } + + public int getItemIndex(int itemIndex) { + return mItemIndices[itemIndex]; + } + + public View getView(int index) { + return mCells[index]; + } +} diff --git a/java/src/com/android/intentresolver/grid/ItemViewHolder.java b/java/src/com/android/intentresolver/grid/ItemViewHolder.java new file mode 100644 index 00000000..2ec56b1b --- /dev/null +++ b/java/src/com/android/intentresolver/grid/ItemViewHolder.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2022 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.intentresolver.grid; + +import android.view.View; + +import androidx.annotation.Nullable; + +import com.android.intentresolver.ChooserListAdapter; +import com.android.intentresolver.ResolverListAdapter; + +import java.util.function.Consumer; + +/** + * Used to bind types of individual item including + * {@link ChooserGridAdapter#VIEW_TYPE_NORMAL}, + * {@link ChooserGridAdapter#VIEW_TYPE_CONTENT_PREVIEW}, + * {@link ChooserGridAdapter#VIEW_TYPE_PROFILE}, + * and {@link ChooserGridAdapter#VIEW_TYPE_AZ_LABEL}. + */ +public final class ItemViewHolder extends ViewHolderBase { + private final ResolverListAdapter.ViewHolder mWrappedViewHolder; + + private int mListPosition = ChooserListAdapter.NO_POSITION; + + public ItemViewHolder( + View itemView, + int viewType, + @Nullable Consumer<Integer> onClick, + @Nullable Consumer<Integer> onLongClick) { + super(itemView, viewType); + mWrappedViewHolder = new ResolverListAdapter.ViewHolder(itemView); + + if (onClick != null) { + itemView.setOnClickListener(v -> onClick.accept(mListPosition)); + } + + if (onLongClick != null) { + itemView.setOnLongClickListener(v -> { + onLongClick.accept(mListPosition); + return true; + }); + } + } + + public void setListPosition(int listPosition) { + mListPosition = listPosition; + } +} diff --git a/java/src/com/android/intentresolver/grid/SingleRowViewHolder.java b/java/src/com/android/intentresolver/grid/SingleRowViewHolder.java new file mode 100644 index 00000000..a72da7aa --- /dev/null +++ b/java/src/com/android/intentresolver/grid/SingleRowViewHolder.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2022 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.intentresolver.grid; + +import android.view.View; +import android.view.ViewGroup; + +/** Holder for a group of items displayed in a single row of the {@link ChooserGridAdapter}. */ +public final class SingleRowViewHolder extends ItemGroupViewHolder { + private final ViewGroup mRow; + + public SingleRowViewHolder(ViewGroup row, int cellCount, int viewType) { + super(cellCount, row, viewType); + + this.mRow = row; + } + + /** Get the group of all views in this holder. */ + public ViewGroup getViewGroup() { + return mRow; + } + + /** + * Get the group of views for the row containing the specified cell index. + * TODO: unclear if that's what this `index` meant. It doesn't matter for our "single row" + * holders, and it doesn't look like this is an override from some other interface; maybe we can + * just remove? + */ + public ViewGroup getRowByIndex(int index) { + return mRow; + } + + /** Get the group of views for the specified {@code rowNumber}, if any. */ + public ViewGroup getRow(int rowNumber) { + if (rowNumber == 0) { + return mRow; + } + return null; + } + + /** + * @param index the index of the cell to add the view into. + * @param v the view to add into the cell. + */ + public ViewGroup addView(int index, View v) { + mRow.addView(v); + mCells[index] = v; + + return mRow; + } + + /** + * @param i the index of the cell containing the view to modify. + * @param visibility the new visibility to set on the view with the specified index. + */ + public void setViewVisibility(int i, int visibility) { + getView(i).setVisibility(visibility); + } +} diff --git a/java/src/com/android/intentresolver/grid/ViewHolderBase.java b/java/src/com/android/intentresolver/grid/ViewHolderBase.java new file mode 100644 index 00000000..78e9104a --- /dev/null +++ b/java/src/com/android/intentresolver/grid/ViewHolderBase.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2022 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.intentresolver.grid; + +import android.view.View; + +import androidx.recyclerview.widget.RecyclerView; + +/** Base class for all {@link RecyclerView.ViewHolder} types in the {@link ChooserGridAdapter}. */ +public abstract class ViewHolderBase extends RecyclerView.ViewHolder { + private int mViewType; + + ViewHolderBase(View itemView, int viewType) { + super(itemView); + this.mViewType = viewType; + } + + public int getViewType() { + return mViewType; + } +} |