summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--res/layout/inspector_header.xml11
-rw-r--r--src/com/android/documentsui/ThumbnailLoader.java134
-rw-r--r--src/com/android/documentsui/dirlist/IconHelper.java103
-rw-r--r--src/com/android/documentsui/inspector/HeaderView.java43
4 files changed, 193 insertions, 98 deletions
diff --git a/res/layout/inspector_header.xml b/res/layout/inspector_header.xml
index cfbc29f98..bb6acb4da 100644
--- a/res/layout/inspector_header.xml
+++ b/res/layout/inspector_header.xml
@@ -17,11 +17,22 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
+
+ <ImageView
+ android:id="@+id/inspector_mime"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:scaleType="fitCenter"
+ android:background="@android:color/black" />
+
<ImageView
android:id="@+id/inspector_thumbnail"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:alpha="0.0"
+ android:scaleType="centerCrop"
android:background="@android:color/black" />
+
<TextView
android:id="@+id/inspector_file_title"
android:layout_width="wrap_content"
diff --git a/src/com/android/documentsui/ThumbnailLoader.java b/src/com/android/documentsui/ThumbnailLoader.java
new file mode 100644
index 000000000..bb1e5d5a4
--- /dev/null
+++ b/src/com/android/documentsui/ThumbnailLoader.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2017 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.documentsui;
+
+import static com.android.documentsui.base.Shared.VERBOSE;
+
+import android.content.ContentProviderClient;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Point;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.CancellationSignal;
+import android.os.OperationCanceledException;
+import android.provider.DocumentsContract;
+import android.util.Log;
+import android.view.View;
+import android.widget.ImageView;
+import com.android.documentsui.ProviderExecutor.Preemptable;
+import java.util.function.BiConsumer;
+
+/**
+ * Loads a Thumbnails asynchronously then animates from the mime icon to the thumbnail
+ */
+public final class ThumbnailLoader extends AsyncTask<Uri, Void, Bitmap> implements Preemptable {
+
+ private static final String TAG = ThumbnailLoader.class.getCanonicalName();
+
+ /**
+ * Two animations applied to image views. The first is used to switch mime icon and thumbnail.
+ * The second is used when we need to update thumbnail.
+ */
+ public static final BiConsumer<View, View> ANIM_FADE_IN = (mime, thumb) -> {
+ float alpha = mime.getAlpha();
+ mime.animate().alpha(0f).start();
+ thumb.setAlpha(0f);
+ thumb.animate().alpha(alpha).start();
+ };
+ public static final BiConsumer<View, View> ANIM_NO_OP = (mime, thumb) -> {};
+
+ private final ImageView mIconThumb;
+ private final Point mThumbSize;
+ // A callback to apply animation to image views after the thumbnail is loaded.
+ private final BiConsumer<View, View> mImageAnimator;
+ private final Uri mUri;
+ private final ImageView mIconMime;
+ private final long mLastModified;
+ private final boolean mAddToCache;
+ private final CancellationSignal mSignal;
+
+ /**
+ * @param uri - to a thumbnail.
+ * @param iconMime - ImageView for displaying a mime type.
+ * @param iconThumb - ImageView to display the thumbnail.
+ * @param thumbSize - size of the thumbnail.
+ * @param lastModified - used for updating thumbnail caches.
+ * @param animator - used to animate from the mime icon to the thumbnail.
+ * @param addToCache - flag that determines if the loader saves the thumbnail to the cache.
+ */
+ public ThumbnailLoader(Uri uri, ImageView iconMime, ImageView iconThumb,
+ Point thumbSize, long lastModified, BiConsumer<View, View> animator, boolean addToCache) {
+ mUri = uri;
+ mIconMime = iconMime;
+ mIconThumb = iconThumb;
+ mThumbSize = thumbSize;
+ mImageAnimator = animator;
+ mLastModified = lastModified;
+ mAddToCache = addToCache;
+ mSignal = new CancellationSignal();
+ mIconThumb.setTag(this);
+ if (VERBOSE) Log.v(TAG, "Starting icon loader task for " + mUri);
+ }
+
+ @Override
+ public void preempt() {
+ if (VERBOSE) Log.v(TAG, "Icon loader task for " + mUri + " was cancelled.");
+ cancel(false);
+ mSignal.cancel();
+ }
+
+ @Override
+ protected Bitmap doInBackground(Uri... params) {
+ if (isCancelled()) {
+ return null;
+ }
+
+ final Context context = mIconThumb.getContext();
+ final ContentResolver resolver = context.getContentResolver();
+
+ ContentProviderClient client = null;
+ Bitmap result = null;
+ try {
+ client = DocumentsApplication.acquireUnstableProviderOrThrow(
+ resolver, mUri.getAuthority());
+ result = DocumentsContract.getDocumentThumbnail(client, mUri, mThumbSize, mSignal);
+ if (result != null && mAddToCache) {
+ final ThumbnailCache cache = DocumentsApplication.getThumbnailCache(context);
+ cache.putThumbnail(mUri, mThumbSize, result, mLastModified);
+ }
+ } catch (Exception e) {
+ if (!(e instanceof OperationCanceledException)) {
+ Log.w(TAG, "Failed to load thumbnail for " + mUri + ": " + e);
+ }
+ } finally {
+ ContentProviderClient.releaseQuietly(client);
+ }
+ return result;
+ }
+
+ @Override
+ protected void onPostExecute(Bitmap result) {
+ if (VERBOSE) Log.v(TAG, "Loader task for " + mUri + " completed");
+
+ if (mIconThumb.getTag() == this && result != null) {
+ mIconThumb.setTag(null);
+ mIconThumb.setImageBitmap(result);
+ mImageAnimator.accept(mIconMime, mIconThumb);
+ }
+ }
+}
diff --git a/src/com/android/documentsui/dirlist/IconHelper.java b/src/com/android/documentsui/dirlist/IconHelper.java
index 77a646695..d9eabae25 100644
--- a/src/com/android/documentsui/dirlist/IconHelper.java
+++ b/src/com/android/documentsui/dirlist/IconHelper.java
@@ -20,16 +20,11 @@ import static com.android.documentsui.base.Shared.VERBOSE;
import static com.android.documentsui.base.State.MODE_GRID;
import static com.android.documentsui.base.State.MODE_LIST;
-import android.content.ContentProviderClient;
-import android.content.ContentResolver;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.net.Uri;
-import android.os.AsyncTask;
-import android.os.CancellationSignal;
-import android.os.OperationCanceledException;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
import android.support.annotation.Nullable;
@@ -40,10 +35,10 @@ import android.widget.ImageView;
import com.android.documentsui.DocumentsApplication;
import com.android.documentsui.IconUtils;
import com.android.documentsui.ProviderExecutor;
-import com.android.documentsui.ProviderExecutor.Preemptable;
import com.android.documentsui.R;
import com.android.documentsui.ThumbnailCache;
import com.android.documentsui.ThumbnailCache.Result;
+import com.android.documentsui.ThumbnailLoader;
import com.android.documentsui.base.DocumentInfo;
import com.android.documentsui.base.MimeTypes;
import com.android.documentsui.base.State;
@@ -58,16 +53,6 @@ import java.util.function.BiConsumer;
public class IconHelper {
private static final String TAG = "IconHelper";
- // Two animations applied to image views. The first is used to switch mime icon and thumbnail.
- // The second is used when we need to update thumbnail.
- private static final BiConsumer<View, View> ANIM_FADE_IN = (mime, thumb) -> {
- float alpha = mime.getAlpha();
- mime.animate().alpha(0f).start();
- thumb.setAlpha(0f);
- thumb.animate().alpha(alpha).start();
- };
- private static final BiConsumer<View, View> ANIM_NO_OP = (mime, thumb) -> {};
-
private final Context mContext;
private final ThumbnailCache mThumbnailCache;
@@ -129,89 +114,13 @@ public class IconHelper {
* @param icon
*/
public void stopLoading(ImageView icon) {
- final LoaderTask oldTask = (LoaderTask) icon.getTag();
+ final ThumbnailLoader oldTask = (ThumbnailLoader) icon.getTag();
if (oldTask != null) {
oldTask.preempt();
icon.setTag(null);
}
}
- /** Internal task for loading thumbnails asynchronously. */
- private static class LoaderTask
- extends AsyncTask<Uri, Void, Bitmap>
- implements Preemptable {
- private final Uri mUri;
- private final ImageView mIconMime;
- private final ImageView mIconThumb;
- private final Point mThumbSize;
- private final long mLastModified;
-
- // A callback to apply animation to image views after the thumbnail is loaded.
- private final BiConsumer<View, View> mImageAnimator;
-
- private final CancellationSignal mSignal;
-
- public LoaderTask(Uri uri, ImageView iconMime, ImageView iconThumb,
- Point thumbSize, long lastModified, BiConsumer<View, View> animator) {
- mUri = uri;
- mIconMime = iconMime;
- mIconThumb = iconThumb;
- mThumbSize = thumbSize;
- mImageAnimator = animator;
- mLastModified = lastModified;
- mSignal = new CancellationSignal();
- if (VERBOSE) Log.v(TAG, "Starting icon loader task for " + mUri);
- }
-
- @Override
- public void preempt() {
- if (VERBOSE) Log.v(TAG, "Icon loader task for " + mUri + " was cancelled.");
- cancel(false);
- mSignal.cancel();
- }
-
- @Override
- protected Bitmap doInBackground(Uri... params) {
- if (isCancelled()) {
- return null;
- }
-
- final Context context = mIconThumb.getContext();
- final ContentResolver resolver = context.getContentResolver();
-
- ContentProviderClient client = null;
- Bitmap result = null;
- try {
- client = DocumentsApplication.acquireUnstableProviderOrThrow(
- resolver, mUri.getAuthority());
- result = DocumentsContract.getDocumentThumbnail(client, mUri, mThumbSize, mSignal);
- if (result != null) {
- final ThumbnailCache cache = DocumentsApplication.getThumbnailCache(context);
- cache.putThumbnail(mUri, mThumbSize, result, mLastModified);
- }
- } catch (Exception e) {
- if (!(e instanceof OperationCanceledException)) {
- Log.w(TAG, "Failed to load thumbnail for " + mUri + ": " + e);
- }
- } finally {
- ContentProviderClient.releaseQuietly(client);
- }
- return result;
- }
-
- @Override
- protected void onPostExecute(Bitmap result) {
- if (VERBOSE) Log.v(TAG, "Loader task for " + mUri + " completed");
-
- if (mIconThumb.getTag() == this && result != null) {
- mIconThumb.setTag(null);
- mIconThumb.setImageBitmap(result);
-
- mImageAnimator.accept(mIconMime, mIconThumb);
- }
- }
- }
-
/**
* Load thumbnails for a directory list item.
*
@@ -287,11 +196,11 @@ public class IconHelper {
uri.toString(), result.getStatus(), stale));
if (!result.isExactHit() || stale) {
final BiConsumer<View, View> animator =
- (cachedThumbnail == null ? ANIM_FADE_IN : ANIM_NO_OP);
- final LoaderTask task = new LoaderTask(uri, iconMime, iconThumb, mCurrentSize,
- docLastModified, animator);
+ (cachedThumbnail == null ? ThumbnailLoader.ANIM_FADE_IN :
+ ThumbnailLoader.ANIM_NO_OP);
- iconThumb.setTag(task);
+ final ThumbnailLoader task = new ThumbnailLoader(uri, iconMime, iconThumb,
+ mCurrentSize, docLastModified, animator, true);
ProviderExecutor.forAuthority(docAuthority).execute(task);
}
diff --git a/src/com/android/documentsui/inspector/HeaderView.java b/src/com/android/documentsui/inspector/HeaderView.java
index a9f36f285..c9c6b3ec3 100644
--- a/src/com/android/documentsui/inspector/HeaderView.java
+++ b/src/com/android/documentsui/inspector/HeaderView.java
@@ -15,13 +15,20 @@
*/
package com.android.documentsui.inspector;
+import android.app.Activity;
import android.content.Context;
+import android.graphics.Point;
+import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
+import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
+import com.android.documentsui.ProviderExecutor;
+import com.android.documentsui.ThumbnailLoader;
+import com.android.documentsui.base.Display;
import com.android.documentsui.base.DocumentInfo;
import com.android.documentsui.R;
import java.util.function.Consumer;
@@ -31,8 +38,14 @@ import java.util.function.Consumer;
*/
public final class HeaderView extends RelativeLayout implements Consumer<DocumentInfo> {
+ private static final String TAG = HeaderView.class.getCanonicalName();
+
+ private final Context mContext;
private final View mHeader;
+ private ImageView mMime;
+ private ImageView mThumbnail;
private final TextView mTitle;
+ private Point mImageDimensions;
public HeaderView(Context context) {
this(context, null);
@@ -46,8 +59,15 @@ public final class HeaderView extends RelativeLayout implements Consumer<Documen
super(context, attrs, defStyleAttr);
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
+ mContext = context;
mHeader = inflater.inflate(R.layout.inspector_header, null);
+ mMime = (ImageView) mHeader.findViewById(R.id.inspector_mime);
+ mThumbnail = (ImageView) mHeader.findViewById(R.id.inspector_thumbnail);
mTitle = (TextView) mHeader.findViewById(R.id.inspector_file_title);
+
+ int width = (int) Display.screenWidth((Activity)context);
+ int height = mContext.getResources().getDimensionPixelSize(R.dimen.inspector_header_height);
+ mImageDimensions = new Point(width, height);
}
@Override
@@ -55,6 +75,10 @@ public final class HeaderView extends RelativeLayout implements Consumer<Documen
if (!hasHeader()) {
addView(mHeader);
}
+
+ if(!hasHeaderImage()) {
+ loadHeaderImage(info);
+ }
mTitle.setText(info.displayName);
}
@@ -66,4 +90,21 @@ public final class HeaderView extends RelativeLayout implements Consumer<Documen
}
return false;
}
-}
+
+ private void loadHeaderImage(DocumentInfo info) {
+
+ // load the mime icon.
+ Drawable d = mContext.getContentResolver().getTypeDrawable(info.mimeType);
+ mMime.setImageDrawable(d);
+
+ // load the thumbnail async.
+ final ThumbnailLoader task = new ThumbnailLoader(info.derivedUri, mMime, mThumbnail,
+ mImageDimensions, info.lastModified, ThumbnailLoader.ANIM_FADE_IN, false);
+ task.executeOnExecutor(ProviderExecutor.forAuthority(info.derivedUri.getAuthority()),
+ info.derivedUri);
+ }
+
+ private boolean hasHeaderImage() {
+ return mThumbnail.getAlpha() == 1.0f;
+ }
+} \ No newline at end of file