Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b41e6431 authored by Wenbo Jie's avatar Wenbo Jie
Browse files

[DocsUI M3] Add wrapper for file row icons

* For thumbnail icons, show a border around it.
* For non-thumbnail icons or icons which fail to load thumbnail, show a
  white background wrapper.

Check the attached bug for demo video.

Bug: 389552458
Test: m DocumentsUIGoogle && manual inspection
Flag: com.android.documentsui.flags.use_material3
Change-Id: I40ab403fb3166be7376d0c3c3605f792151ce14d
parent 68817fc3
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -42,11 +42,14 @@
            android:layout_height="@dimen/list_item_icon_size"
            android:layout_marginEnd="@dimen/list_item_icon_margin_end">

            <!-- stroke width will be controlled dynamically in the code. -->
            <com.google.android.material.card.MaterialCardView
                android:id="@+id/icon_wrapper"
                app:cardElevation="0dp"
                app:cardBackgroundColor="@android:color/transparent"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                app:cardBackgroundColor="@android:color/white"
                app:strokeColor="?attr/colorSecondaryContainer"
                app:strokeWidth="0dp">

                <ImageView
+4 −1
Original line number Diff line number Diff line
@@ -42,11 +42,14 @@
          android:layout_height="@dimen/list_item_icon_size"
          android:layout_marginEnd="@dimen/list_item_icon_margin_end">

        <!-- stroke width will be controlled dynamically in the code. -->
        <com.google.android.material.card.MaterialCardView
            android:id="@+id/icon_wrapper"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:cardBackgroundColor="@android:color/transparent"
            app:cardElevation="0dp"
            app:cardBackgroundColor="@android:color/white"
            app:strokeColor="?attr/colorSecondaryContainer"
            app:strokeWidth="0dp">

          <ImageView
+2 −1
Original line number Diff line number Diff line
@@ -202,7 +202,8 @@ final class GridDocumentHolder extends DocumentHolder {
        mIconThumb.animate().cancel();
        mIconThumb.setAlpha(0f);

        mIconHelper.load(mDoc, mIconThumb, mIconMimeLg, mIconMimeSm);
        mIconHelper.load(
                mDoc, mIconThumb, mIconMimeLg, mIconMimeSm, /* thumbnailLoadedCallback= */ null);

        mTitle.setText(mDoc.displayName, TextView.BufferType.SPANNABLE);
        mTitle.setVisibility(View.VISIBLE);
+6 −1
Original line number Diff line number Diff line
@@ -189,7 +189,12 @@ final class GridPhotoHolder extends DocumentHolder {
        mIconThumb.animate().cancel();
        mIconThumb.setAlpha(0f);

        mIconHelper.load(mDoc, mIconThumb, mIconMimeLg, null);
        mIconHelper.load(
                mDoc,
                mIconThumb,
                mIconMimeLg,
                /* subIconMime= */ null,
                /* thumbnailLoadedCallback= */ null);

        final String docSize =
                Formatter.formatFileSize(mContext, getCursorLong(cursor, Document.COLUMN_SIZE));
+30 −5
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ import com.android.documentsui.base.UserId;
import com.android.modules.utils.build.SdkLevel;

import java.util.function.BiConsumer;
import java.util.function.Consumer;

/**
 * A class to assist with loading and managing the Images (i.e. thumbnails and icons) associated
@@ -151,14 +152,18 @@ public class IconHelper {
     * @param iconThumb   The itemview's thumbnail icon.
     * @param iconMime    The itemview's mime icon. Hidden when iconThumb is shown.
     * @param subIconMime The second itemview's mime icon. Always visible.
     * @param thumbnailLoadedCallback The callback function which will be invoked after the
     *                                thumbnail is loaded, with a boolean parameter to indicate
     *                                if it's loaded or not.
     */
    public void load(
            DocumentInfo doc,
            ImageView iconThumb,
            ImageView iconMime,
            @Nullable ImageView subIconMime) {
            @Nullable ImageView subIconMime,
            @Nullable Consumer<Boolean> thumbnailLoadedCallback) {
        load(doc.derivedUri, doc.userId, doc.mimeType, doc.flags, doc.icon, doc.lastModified,
                iconThumb, iconMime, subIconMime);
                iconThumb, iconMime, subIconMime, thumbnailLoadedCallback);
    }

    /**
@@ -172,10 +177,13 @@ public class IconHelper {
     * @param iconThumb       The itemview's thumbnail icon.
     * @param iconMime        The itemview's mime icon. Hidden when iconThumb is shown.
     * @param subIconMime     The second itemview's mime icon. Always visible.
     * @param thumbnailLoadedCallback The callback function which will be invoked after the
     *                                thumbnail is loaded, with a boolean parameter to indicate
     *                                if it's loaded or not.
     */
    public void load(Uri uri, UserId userId, String mimeType, int docFlags, int docIcon,
            long docLastModified, ImageView iconThumb, ImageView iconMime,
            @Nullable ImageView subIconMime) {
            @Nullable ImageView subIconMime, @Nullable Consumer<Boolean> thumbnailLoadedCallback) {
        boolean loadedThumbnail = false;

        final String docAuthority = uri.getAuthority();
@@ -186,7 +194,14 @@ public class IconHelper {
        final boolean showThumbnail = supportsThumbnail && allowThumbnail && mThumbnailsEnabled;
        if (showThumbnail) {
            loadedThumbnail =
                    loadThumbnail(uri, userId, docAuthority, docLastModified, iconThumb, iconMime);
                    loadThumbnail(
                            uri,
                            userId,
                            docAuthority,
                            docLastModified,
                            iconThumb,
                            iconMime,
                            thumbnailLoadedCallback);
        }

        final Drawable mimeIcon = getDocumentIcon(mContext, userId, docAuthority,
@@ -202,15 +217,22 @@ public class IconHelper {
            setMimeIcon(iconMime, mimeIcon);
            hideImageView(iconThumb);
        }
        if (thumbnailLoadedCallback != null) {
            thumbnailLoadedCallback.accept(loadedThumbnail);
        }
    }

    private boolean loadThumbnail(Uri uri, UserId userId, String docAuthority, long docLastModified,
            ImageView iconThumb, ImageView iconMime) {
            ImageView iconThumb, ImageView iconMime,
            @Nullable Consumer<Boolean> thumbnailLoadedCallback) {
        final Result result = mThumbnailCache.getThumbnail(uri, userId, mCurrentSize);

        try {
            final Bitmap cachedThumbnail = result.getThumbnail();
            iconThumb.setImageBitmap(cachedThumbnail);
            if (thumbnailLoadedCallback != null) {
                thumbnailLoadedCallback.accept(cachedThumbnail != null);
            }

            boolean stale = (docLastModified > result.getLastModified());
            if (VERBOSE) {
@@ -230,6 +252,9 @@ public class IconHelper {
                                iconThumb.setImageBitmap(bitmap);
                                animator.accept(iconMime, iconThumb);
                            }
                            if (thumbnailLoadedCallback != null) {
                                thumbnailLoadedCallback.accept(bitmap != null);
                            }
                        }, true /* addToCache */);

                ProviderExecutor.forAuthority(docAuthority).execute(task);
Loading