From 928bc9858768b3697c64a2fd30b48e206768e7d3 Mon Sep 17 00:00:00 2001 From: Andrey Epin Date: Wed, 26 Jul 2023 15:07:53 -0700 Subject: Add headline view argument to content preview UI "Sticky" headline is one of the requirements of the scrollable preview feature. Currently headling row is included in every preview type we have and to be "sticky" it should be moved out of all of them. This change is a preparation work that makes all of the preview UI controllers aware of a possible external headline row (but no actual external headline view is used). Bug: 287102904 Test: manual testing of all preivew types checking that there are no regressions Test: atest com.android.intentresolver.contentpreview Change-Id: Ib6110aaa82246e3354fdce18f431ab1c116e7b73 --- .../android/intentresolver/ChooserActivity.java | 5 ++- .../contentpreview/ChooserContentPreviewUi.java | 8 +++- .../contentpreview/ContentPreviewUi.java | 39 +++++++++++++------- .../contentpreview/FileContentPreviewUi.java | 22 ++++++++--- .../FilesPlusTextContentPreviewUi.java | 43 ++++++++++++++-------- .../contentpreview/NoContextPreviewUi.kt | 6 ++- .../contentpreview/TextContentPreviewUi.java | 20 +++++++--- .../contentpreview/UnifiedContentPreviewUi.java | 31 +++++++++++----- 8 files changed, 121 insertions(+), 53 deletions(-) (limited to 'java/src') diff --git a/java/src/com/android/intentresolver/ChooserActivity.java b/java/src/com/android/intentresolver/ChooserActivity.java index 63ba7ef6..26dbd224 100644 --- a/java/src/com/android/intentresolver/ChooserActivity.java +++ b/java/src/com/android/intentresolver/ChooserActivity.java @@ -23,7 +23,9 @@ import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CANT import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CROSS_PROFILE_BLOCKED_TITLE; import static android.stats.devicepolicy.nano.DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_PERSONAL; import static android.stats.devicepolicy.nano.DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_WORK; + import static androidx.lifecycle.LifecycleKt.getCoroutineScope; + import static com.android.internal.util.LatencyTracker.ACTION_LOAD_SHARE_SHEET; import android.annotation.IntDef; @@ -664,7 +666,8 @@ public class ChooserActivity extends Hilt_ChooserActivity implements ViewGroup layout = mChooserContentPreviewUi.displayContentPreview( getResources(), getLayoutInflater(), - parent); + parent, + /*headlineViewParent=*/null); if (layout != null) { adjustPreviewWidth(getResources().getConfiguration().orientation, layout); diff --git a/java/src/com/android/intentresolver/contentpreview/ChooserContentPreviewUi.java b/java/src/com/android/intentresolver/contentpreview/ChooserContentPreviewUi.java index b7650b9d..7226ae4a 100644 --- a/java/src/com/android/intentresolver/contentpreview/ChooserContentPreviewUi.java +++ b/java/src/com/android/intentresolver/contentpreview/ChooserContentPreviewUi.java @@ -28,6 +28,7 @@ import android.content.res.Resources; import android.net.Uri; import android.text.TextUtils; import android.view.LayoutInflater; +import android.view.View; import android.view.ViewGroup; import androidx.annotation.Nullable; @@ -188,9 +189,12 @@ public final class ChooserContentPreviewUi { * specified {@code intent}. */ public ViewGroup displayContentPreview( - Resources resources, LayoutInflater layoutInflater, ViewGroup parent) { + Resources resources, + LayoutInflater layoutInflater, + ViewGroup parent, + @Nullable View headlineViewParent) { - return mContentPreviewUi.display(resources, layoutInflater, parent); + return mContentPreviewUi.display(resources, layoutInflater, parent, headlineViewParent); } private static TextContentPreviewUi createTextPreview( diff --git a/java/src/com/android/intentresolver/contentpreview/ContentPreviewUi.java b/java/src/com/android/intentresolver/contentpreview/ContentPreviewUi.java index 2d81794e..dce146b0 100644 --- a/java/src/com/android/intentresolver/contentpreview/ContentPreviewUi.java +++ b/java/src/com/android/intentresolver/contentpreview/ContentPreviewUi.java @@ -24,10 +24,13 @@ import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.view.ViewStub; import android.view.animation.DecelerateInterpolator; import android.widget.ImageView; import android.widget.TextView; +import androidx.annotation.Nullable; + import com.android.intentresolver.R; import com.android.intentresolver.widget.ActionRow; import com.android.intentresolver.widget.ScrollableImagePreviewView; @@ -40,7 +43,10 @@ abstract class ContentPreviewUi { public abstract int getType(); public abstract ViewGroup display( - Resources resources, LayoutInflater layoutInflater, ViewGroup parent); + Resources resources, + LayoutInflater layoutInflater, + ViewGroup parent, + @Nullable View headlineViewParent); protected static void updateViewWithImage(ImageView imageView, Bitmap image) { if (image == null) { @@ -57,23 +63,28 @@ abstract class ContentPreviewUi { fadeAnim.start(); } - protected static void displayHeadline(ViewGroup layout, String headline) { - if (layout != null) { - TextView titleView = layout.findViewById(R.id.headline); - if (titleView != null) { - if (!TextUtils.isEmpty(headline)) { - titleView.setText(headline); - titleView.setVisibility(View.VISIBLE); - } else { - titleView.setVisibility(View.GONE); - } - } + protected static void inflateHeadline(View layout) { + ViewStub stub = layout.findViewById(R.id.chooser_headline_row_stub); + if (stub != null) { + stub.inflate(); + } + } + + protected static void displayHeadline(View layout, String headline) { + TextView titleView = layout == null ? null : layout.findViewById(R.id.headline); + if (titleView == null) { + return; + } + if (!TextUtils.isEmpty(headline)) { + titleView.setText(headline); + titleView.setVisibility(View.VISIBLE); + } else { + titleView.setVisibility(View.GONE); } } protected static void displayModifyShareAction( - ViewGroup layout, - ChooserContentPreviewUi.ActionFactory actionFactory) { + View layout, ChooserContentPreviewUi.ActionFactory actionFactory) { ActionRow.Action modifyShareAction = actionFactory.getModifyShareAction(); if (modifyShareAction != null && layout != null) { TextView modifyShareView = layout.findViewById(R.id.reselection_action); diff --git a/java/src/com/android/intentresolver/contentpreview/FileContentPreviewUi.java b/java/src/com/android/intentresolver/contentpreview/FileContentPreviewUi.java index 20758189..89e7e528 100644 --- a/java/src/com/android/intentresolver/contentpreview/FileContentPreviewUi.java +++ b/java/src/com/android/intentresolver/contentpreview/FileContentPreviewUi.java @@ -67,18 +67,30 @@ class FileContentPreviewUi extends ContentPreviewUi { } @Override - public ViewGroup display(Resources resources, LayoutInflater layoutInflater, ViewGroup parent) { - ViewGroup layout = displayInternal(resources, layoutInflater, parent); - displayModifyShareAction(layout, mActionFactory); + public ViewGroup display( + Resources resources, + LayoutInflater layoutInflater, + ViewGroup parent, + @Nullable View headlineViewParent) { + ViewGroup layout = displayInternal(resources, layoutInflater, parent, headlineViewParent); + displayModifyShareAction( + headlineViewParent == null ? layout : headlineViewParent, mActionFactory); return layout; } private ViewGroup displayInternal( - Resources resources, LayoutInflater layoutInflater, ViewGroup parent) { + Resources resources, + LayoutInflater layoutInflater, + ViewGroup parent, + @Nullable View headlineViewParent) { mContentPreview = (ViewGroup) layoutInflater.inflate( R.layout.chooser_grid_preview_file, parent, false); + if (headlineViewParent == null) { + headlineViewParent = mContentPreview; + } + inflateHeadline(headlineViewParent); - displayHeadline(mContentPreview, mHeadlineGenerator.getFilesHeadline(mFileCount)); + displayHeadline(headlineViewParent, mHeadlineGenerator.getFilesHeadline(mFileCount)); if (mFileCount == 0) { mContentPreview.setVisibility(View.GONE); diff --git a/java/src/com/android/intentresolver/contentpreview/FilesPlusTextContentPreviewUi.java b/java/src/com/android/intentresolver/contentpreview/FilesPlusTextContentPreviewUi.java index 6e1212e9..1f84b348 100644 --- a/java/src/com/android/intentresolver/contentpreview/FilesPlusTextContentPreviewUi.java +++ b/java/src/com/android/intentresolver/contentpreview/FilesPlusTextContentPreviewUi.java @@ -59,6 +59,7 @@ class FilesPlusTextContentPreviewUi extends ContentPreviewUi { private final boolean mIsSingleImage; private final int mFileCount; private ViewGroup mContentPreviewView; + private View mHeadliveView; private boolean mIsMetadataUpdated = false; @Nullable private Uri mFirstFilePreviewUri; @@ -98,9 +99,14 @@ class FilesPlusTextContentPreviewUi extends ContentPreviewUi { } @Override - public ViewGroup display(Resources resources, LayoutInflater layoutInflater, ViewGroup parent) { - ViewGroup layout = displayInternal(layoutInflater, parent); - displayModifyShareAction(layout, mActionFactory); + public ViewGroup display( + Resources resources, + LayoutInflater layoutInflater, + ViewGroup parent, + @Nullable View headlineViewParent) { + ViewGroup layout = displayInternal(layoutInflater, parent, headlineViewParent); + displayModifyShareAction( + headlineViewParent == null ? layout : headlineViewParent, mActionFactory); return layout; } @@ -118,13 +124,18 @@ class FilesPlusTextContentPreviewUi extends ContentPreviewUi { mFirstFilePreviewUri = files.isEmpty() ? null : files.get(0).getPreviewUri(); mIsMetadataUpdated = true; if (mContentPreviewView != null) { - updateUiWithMetadata(mContentPreviewView); + updateUiWithMetadata(mContentPreviewView, mHeadliveView); } } - private ViewGroup displayInternal(LayoutInflater layoutInflater, ViewGroup parent) { + private ViewGroup displayInternal( + LayoutInflater layoutInflater, + ViewGroup parent, + @Nullable View headlineViewParent) { mContentPreviewView = (ViewGroup) layoutInflater.inflate( R.layout.chooser_grid_preview_files_text, parent, false); + mHeadliveView = headlineViewParent == null ? mContentPreviewView : headlineViewParent; + inflateHeadline(mHeadliveView); final ActionRow actionRow = mContentPreviewView.findViewById(com.android.internal.R.id.chooser_action_row); @@ -134,12 +145,12 @@ class FilesPlusTextContentPreviewUi extends ContentPreviewUi { if (!mIsSingleImage) { mContentPreviewView.requireViewById(R.id.image_view).setVisibility(View.GONE); } - prepareTextPreview(mContentPreviewView, mActionFactory); + prepareTextPreview(mContentPreviewView, mHeadliveView, mActionFactory); if (mIsMetadataUpdated) { - updateUiWithMetadata(mContentPreviewView); + updateUiWithMetadata(mContentPreviewView, mHeadliveView); } else { updateHeadline( - mContentPreviewView, + mHeadliveView, mFileCount, mTypeClassifier.isImageType(mIntentMimeType), mTypeClassifier.isVideoType(mIntentMimeType)); @@ -148,8 +159,9 @@ class FilesPlusTextContentPreviewUi extends ContentPreviewUi { return mContentPreviewView; } - private void updateUiWithMetadata(ViewGroup contentPreviewView) { - updateHeadline(contentPreviewView, mFileCount, mAllImages, mAllVideos); + private void updateUiWithMetadata(ViewGroup contentPreviewView, View headlineView) { + prepareTextPreview(contentPreviewView, headlineView, mActionFactory); + updateHeadline(headlineView, mFileCount, mAllImages, mAllVideos); ImageView imagePreview = mContentPreviewView.requireViewById(R.id.image_view); if (mIsSingleImage && mFirstFilePreviewUri != null) { @@ -169,8 +181,8 @@ class FilesPlusTextContentPreviewUi extends ContentPreviewUi { } private void updateHeadline( - ViewGroup contentPreview, int fileCount, boolean allImages, boolean allVideos) { - CheckBox includeText = contentPreview.requireViewById(R.id.include_text_action); + View headlineView, int fileCount, boolean allImages, boolean allVideos) { + CheckBox includeText = headlineView.requireViewById(R.id.include_text_action); String headline; if (includeText.getVisibility() == View.VISIBLE && includeText.isChecked()) { if (allImages) { @@ -190,14 +202,15 @@ class FilesPlusTextContentPreviewUi extends ContentPreviewUi { } } - displayHeadline(contentPreview, headline); + displayHeadline(headlineView, headline); } private void prepareTextPreview( ViewGroup contentPreview, + View headlineView, ChooserContentPreviewUi.ActionFactory actionFactory) { final TextView textView = contentPreview.requireViewById(R.id.content_preview_text); - CheckBox includeText = contentPreview.requireViewById(R.id.include_text_action); + CheckBox includeText = headlineView.requireViewById(R.id.include_text_action); boolean isLink = HttpUriMatcher.isHttpUri(mText.toString()); textView.setAutoLinkMask(isLink ? Linkify.WEB_URLS : 0); textView.setText(mText); @@ -213,7 +226,7 @@ class FilesPlusTextContentPreviewUi extends ContentPreviewUi { textView.setText(getNoTextString(contentPreview.getResources())); } shareTextAction.accept(!isChecked); - updateHeadline(contentPreview, mFileCount, mAllImages, mAllVideos); + updateHeadline(headlineView, mFileCount, mAllImages, mAllVideos); }); if (SHOW_TOGGLE_CHECKMARK) { includeText.setVisibility(View.VISIBLE); diff --git a/java/src/com/android/intentresolver/contentpreview/NoContextPreviewUi.kt b/java/src/com/android/intentresolver/contentpreview/NoContextPreviewUi.kt index 90016932..31a7006c 100644 --- a/java/src/com/android/intentresolver/contentpreview/NoContextPreviewUi.kt +++ b/java/src/com/android/intentresolver/contentpreview/NoContextPreviewUi.kt @@ -19,13 +19,17 @@ package com.android.intentresolver.contentpreview import android.content.res.Resources import android.util.Log import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup internal class NoContextPreviewUi(private val type: Int) : ContentPreviewUi() { override fun getType(): Int = type override fun display( - resources: Resources?, layoutInflater: LayoutInflater?, parent: ViewGroup? + resources: Resources?, + layoutInflater: LayoutInflater?, + parent: ViewGroup?, + headlineViewParent: View?, ): ViewGroup? { Log.e(TAG, "Unexpected content preview type: $type") return null diff --git a/java/src/com/android/intentresolver/contentpreview/TextContentPreviewUi.java b/java/src/com/android/intentresolver/contentpreview/TextContentPreviewUi.java index b383fbcf..db7b261e 100644 --- a/java/src/com/android/intentresolver/contentpreview/TextContentPreviewUi.java +++ b/java/src/com/android/intentresolver/contentpreview/TextContentPreviewUi.java @@ -69,17 +69,27 @@ class TextContentPreviewUi extends ContentPreviewUi { } @Override - public ViewGroup display(Resources resources, LayoutInflater layoutInflater, ViewGroup parent) { - ViewGroup layout = displayInternal(layoutInflater, parent); - displayModifyShareAction(layout, mActionFactory); + public ViewGroup display( + Resources resources, + LayoutInflater layoutInflater, + ViewGroup parent, + @Nullable View headlineViewParent) { + ViewGroup layout = displayInternal(layoutInflater, parent, headlineViewParent); + displayModifyShareAction( + headlineViewParent == null ? layout : headlineViewParent, mActionFactory); return layout; } private ViewGroup displayInternal( LayoutInflater layoutInflater, - ViewGroup parent) { + ViewGroup parent, + @Nullable View headlineViewParent) { ViewGroup contentPreviewLayout = (ViewGroup) layoutInflater.inflate( R.layout.chooser_grid_preview_text, parent, false); + if (headlineViewParent == null) { + headlineViewParent = contentPreviewLayout; + } + inflateHeadline(headlineViewParent); final ActionRow actionRow = contentPreviewLayout.findViewById(com.android.internal.R.id.chooser_action_row); @@ -128,7 +138,7 @@ class TextContentPreviewUi extends ContentPreviewUi { copyButton.setVisibility(View.GONE); } - displayHeadline(contentPreviewLayout, mHeadlineGenerator.getTextHeadline(mSharingText)); + displayHeadline(headlineViewParent, mHeadlineGenerator.getTextHeadline(mSharingText)); return contentPreviewLayout; } diff --git a/java/src/com/android/intentresolver/contentpreview/UnifiedContentPreviewUi.java b/java/src/com/android/intentresolver/contentpreview/UnifiedContentPreviewUi.java index 8e635aba..8ddd5273 100644 --- a/java/src/com/android/intentresolver/contentpreview/UnifiedContentPreviewUi.java +++ b/java/src/com/android/intentresolver/contentpreview/UnifiedContentPreviewUi.java @@ -52,6 +52,8 @@ class UnifiedContentPreviewUi extends ContentPreviewUi { private List mFiles; @Nullable private ViewGroup mContentPreviewView; + @Nullable + private View mHeadlineView; UnifiedContentPreviewUi( CoroutineScope scope, @@ -83,9 +85,14 @@ class UnifiedContentPreviewUi extends ContentPreviewUi { } @Override - public ViewGroup display(Resources resources, LayoutInflater layoutInflater, ViewGroup parent) { - ViewGroup layout = displayInternal(layoutInflater, parent); - displayModifyShareAction(layout, mActionFactory); + public ViewGroup display( + Resources resources, + LayoutInflater layoutInflater, + ViewGroup parent, + @Nullable View headlineViewParent) { + ViewGroup layout = displayInternal(layoutInflater, parent, headlineViewParent); + displayModifyShareAction( + headlineViewParent == null ? layout : headlineViewParent, mActionFactory); return layout; } @@ -96,13 +103,16 @@ class UnifiedContentPreviewUi extends ContentPreviewUi { .toList()); mFiles = files; if (mContentPreviewView != null) { - updatePreviewWithFiles(mContentPreviewView, files); + updatePreviewWithFiles(mContentPreviewView, mHeadlineView, files); } } - private ViewGroup displayInternal(LayoutInflater layoutInflater, ViewGroup parent) { + private ViewGroup displayInternal( + LayoutInflater layoutInflater, ViewGroup parent, @Nullable View headlineViewParent) { mContentPreviewView = (ViewGroup) layoutInflater.inflate( R.layout.chooser_grid_preview_image, parent, false); + mHeadlineView = headlineViewParent == null ? mContentPreviewView : headlineViewParent; + inflateHeadline(mHeadlineView); final ActionRow actionRow = mContentPreviewView.findViewById(com.android.internal.R.id.chooser_action_row); @@ -122,10 +132,10 @@ class UnifiedContentPreviewUi extends ContentPreviewUi { mItemCount); if (mFiles != null) { - updatePreviewWithFiles(mContentPreviewView, mFiles); + updatePreviewWithFiles(mContentPreviewView, mHeadlineView, mFiles); } else { displayHeadline( - mContentPreviewView, + mHeadlineView, mItemCount, mTypeClassifier.isImageType(mIntentMimeType), mTypeClassifier.isVideoType(mIntentMimeType)); @@ -135,7 +145,8 @@ class UnifiedContentPreviewUi extends ContentPreviewUi { return mContentPreviewView; } - private void updatePreviewWithFiles(ViewGroup contentPreviewView, List files) { + private void updatePreviewWithFiles( + ViewGroup contentPreviewView, View headlineView, List files) { final int count = files.size(); ScrollableImagePreviewView imagePreview = contentPreviewView.requireViewById(R.id.scrollable_image_preview); @@ -158,11 +169,11 @@ class UnifiedContentPreviewUi extends ContentPreviewUi { allVideos = allVideos && previewType == ScrollableImagePreviewView.PreviewType.Video; } - displayHeadline(contentPreviewView, count, allImages, allVideos); + displayHeadline(headlineView, count, allImages, allVideos); } private void displayHeadline( - ViewGroup layout, int count, boolean allImages, boolean allVideos) { + View layout, int count, boolean allImages, boolean allVideos) { if (allImages) { displayHeadline(layout, mHeadlineGenerator.getImagesHeadline(count)); } else if (allVideos) { -- cgit v1.2.3-59-g8ed1b