Optimize the UI of the PermissionDialog
- If there is no thumbnails or images, load the mime icon to
instead
- Sort the thumbnails by the order (Images, Videos, Audios, Others)
Test: add the screenshots
Fix: 162564974
Bug: 161758014
Merged-In: Ifb5796488b1071ef1b389f4ffd6e87255580c0d0
Change-Id: Ifb5796488b1071ef1b389f4ffd6e87255580c0d0
(cherry picked from commit f923930f0e908f164a0d28319fe5d600ee20b1ca)
diff --git a/res/drawable/thumb_clip_gradient.xml b/res/drawable/thumb_clip_gradient.xml
new file mode 100644
index 0000000..d94b0c2
--- /dev/null
+++ b/res/drawable/thumb_clip_gradient.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <solid android:color="@color/thumb_more_tint"/>
+ <corners android:radius="4dp" />
+</shape>
diff --git a/res/layout/permission_body.xml b/res/layout/permission_body.xml
index 6282c7c..0fb4ece 100644
--- a/res/layout/permission_body.xml
+++ b/res/layout/permission_body.xml
@@ -61,8 +61,13 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/thumb_clip"
- android:scaleType="centerCrop"
- android:tint="@color/thumb_more_tint" />
+ android:scaleType="centerCrop"/>
+ <View
+ android:id="@+id/thumb_more_gradient"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@drawable/thumb_clip_gradient"
+ android:visibility="gone"/>
<TextView
android:id="@+id/thumb_more_text"
android:layout_width="match_parent"
diff --git a/src/com/android/providers/media/PermissionActivity.java b/src/com/android/providers/media/PermissionActivity.java
index 944353f..0d721f9 100644
--- a/src/com/android/providers/media/PermissionActivity.java
+++ b/src/com/android/providers/media/PermissionActivity.java
@@ -41,6 +41,8 @@
import android.graphics.ImageDecoder;
import android.graphics.ImageDecoder.ImageInfo;
import android.graphics.ImageDecoder.Source;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
@@ -68,9 +70,11 @@
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.function.Predicate;
+import java.util.function.ToIntFunction;
import java.util.stream.Collectors;
/**
@@ -114,6 +118,12 @@
private static final String DATA_IMAGE = "image";
private static final String DATA_GENERIC = "generic";
+ // Use to sort the thumbnails.
+ private static final int ORDER_IMAGE = 1;
+ private static final int ORDER_VIDEO = 2;
+ private static final int ORDER_AUDIO = 3;
+ private static final int ORDER_GENERIC = 4;
+
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -485,6 +495,25 @@
}
}
+ // Sort the uris in DATA_GENERIC case (Image, Video, Audio, Others)
+ if (TextUtils.equals(data, DATA_GENERIC) && uris.size() > 1) {
+ final ToIntFunction<Uri> score = (uri) -> {
+ final LocalUriMatcher matcher = new LocalUriMatcher(MediaStore.AUTHORITY);
+ final int match = matcher.matchUri(uri, false);
+
+ switch (match) {
+ case AUDIO_MEDIA_ID: return ORDER_AUDIO;
+ case VIDEO_MEDIA_ID: return ORDER_VIDEO;
+ case IMAGES_MEDIA_ID: return ORDER_IMAGE;
+ default: return ORDER_GENERIC;
+ }
+ };
+ final Comparator<Uri> bestScore = (a, b) ->
+ score.applyAsInt(a) - score.applyAsInt(b);
+
+ uris.sort(bestScore);
+ }
+
for (Uri uri : uris) {
try {
final Description desc = new Description(bodyView.getContext(), uri, loadFlags);
@@ -527,15 +556,23 @@
}
/**
- * Bind dialog as a single full-bleed image.
+ * Bind dialog as a single full-bleed image. If there is no image, use
+ * the icon of Mime type instead.
*/
private void bindAsFull(@NonNull Description result) {
final ImageView thumbFull = bodyView.requireViewById(R.id.thumb_full);
- result.bindFull(thumbFull);
+ if (result.full != null) {
+ result.bindFull(thumbFull);
+ } else {
+ thumbFull.setScaleType(ImageView.ScaleType.FIT_CENTER);
+ thumbFull.setBackground(new ColorDrawable(getColor(R.color.thumb_gray_color)));
+ result.bindMimeIcon(thumbFull);
+ }
}
/**
- * Bind dialog as a list of multiple thumbnails.
+ * Bind dialog as a list of multiple thumbnails. If there is no thumbnail for some
+ * items, use the icons of the MIME type instead.
*/
private void bindAsThumbs(@NonNull List<Description> results,
@NonNull List<Description> visualResults) {
@@ -552,6 +589,7 @@
final View thumbMoreContainer = bodyView.requireViewById(R.id.thumb_more_container);
final ImageView thumbMore = bodyView.requireViewById(R.id.thumb_more);
final TextView thumbMoreText = bodyView.requireViewById(R.id.thumb_more_text);
+ final View gradientView = bodyView.requireViewById(R.id.thumb_more_gradient);
// Since we only want three tiles displayed maximum, swap out
// the first tile for our "more" tile
@@ -565,6 +603,7 @@
thumbMoreText.setText(moreText);
thumbMoreContainer.setVisibility(View.VISIBLE);
+ gradientView.setVisibility(View.VISIBLE);
}
// Trim off extra thumbnails from the front of our list, so that we
@@ -577,7 +616,11 @@
for (int i = 0; i < thumbs.size(); i++) {
final Description desc = visualResults.get(i);
final ImageView imageView = thumbs.get(i);
- desc.bindThumbnail(imageView);
+ if (desc.thumbnail != null) {
+ desc.bindThumbnail(imageView);
+ } else {
+ desc.bindMimeIcon(imageView);
+ }
}
}
@@ -612,6 +655,7 @@
public @Nullable CharSequence contentDescription;
public @Nullable Bitmap thumbnail;
public @Nullable Bitmap full;
+ public @Nullable Icon mimeIcon;
public static final int LOAD_CONTENT_DESCRIPTION = 1 << 0;
public static final int LOAD_THUMBNAIL = 1 << 1;
@@ -650,11 +694,15 @@
}
} catch (IOException e) {
Log.w(TAG, e);
+ if (thumbnail == null && full == null) {
+ final String mimeType = resolver.getType(uri);
+ mimeIcon = resolver.getTypeInfo(mimeType).getIcon();
+ }
}
}
public boolean isVisual() {
- return thumbnail != null || full != null;
+ return thumbnail != null || full != null || mimeIcon != null;
}
public void bindThumbnail(ImageView imageView) {
@@ -671,6 +719,14 @@
imageView.setContentDescription(contentDescription);
imageView.setVisibility(View.VISIBLE);
}
+
+ public void bindMimeIcon(ImageView imageView) {
+ Objects.requireNonNull(mimeIcon);
+ imageView.setImageIcon(mimeIcon);
+ imageView.setContentDescription(contentDescription);
+ imageView.setVisibility(View.VISIBLE);
+ imageView.setClipToOutline(true);
+ }
}
/**