diff options
Diffstat (limited to 'packages/DocumentsUI/src/com')
-rw-r--r-- | packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java | 101 | ||||
-rw-r--r-- | packages/DocumentsUI/src/com/android/documentsui/ThumbnailCache.java | 46 |
2 files changed, 141 insertions, 6 deletions
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java index ac5629e..fbdb3a7 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java +++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java @@ -16,17 +16,24 @@ package com.android.documentsui; +import static com.android.documentsui.DocumentsActivity.TAG; + import android.app.Fragment; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.app.LoaderManager.LoaderCallbacks; import android.content.Context; import android.content.Loader; +import android.graphics.Bitmap; +import android.graphics.Point; import android.net.Uri; +import android.os.AsyncTask; import android.os.Bundle; import android.provider.DocumentsContract; import android.text.format.DateUtils; import android.text.format.Formatter; +import android.text.format.Time; +import android.util.Log; import android.util.SparseBooleanArray; import android.view.ActionMode; import android.view.LayoutInflater; @@ -75,6 +82,8 @@ public class DirectoryFragment extends Fragment { private int mType = TYPE_NORMAL; + private Point mThumbSize; + private DocumentsAdapter mAdapter; private LoaderCallbacks<List<Document>> mCallbacks; @@ -217,7 +226,9 @@ public class DirectoryFragment extends Fragment { choiceMode = ListView.CHOICE_MODE_NONE; } + final int thumbSize; if (state.mode == DisplayState.MODE_GRID) { + thumbSize = getResources().getDimensionPixelSize(R.dimen.grid_width); mListView.setAdapter(null); mListView.setChoiceMode(ListView.CHOICE_MODE_NONE); mGridView.setAdapter(mAdapter); @@ -226,6 +237,7 @@ public class DirectoryFragment extends Fragment { mGridView.setChoiceMode(choiceMode); mCurrentView = mGridView; } else if (state.mode == DisplayState.MODE_LIST) { + thumbSize = getResources().getDimensionPixelSize(android.R.dimen.app_icon_size); mGridView.setAdapter(null); mGridView.setChoiceMode(ListView.CHOICE_MODE_NONE); mListView.setAdapter(mAdapter); @@ -234,6 +246,8 @@ public class DirectoryFragment extends Fragment { } else { throw new IllegalStateException(); } + + mThumbSize = new Point(thumbSize, thumbSize); } private OnItemClickListener mItemListener = new OnItemClickListener() { @@ -349,9 +363,21 @@ public class DirectoryFragment extends Fragment { final TextView date = (TextView) convertView.findViewById(R.id.date); final TextView size = (TextView) convertView.findViewById(R.id.size); + final ThumbnailAsyncTask oldTask = (ThumbnailAsyncTask) icon.getTag(); + if (oldTask != null) { + oldTask.cancel(false); + } + if (doc.isThumbnailSupported()) { - // TODO: load thumbnails async - icon.setImageURI(doc.uri); + final Bitmap cachedResult = ThumbnailCache.get(context).get(doc.uri); + if (cachedResult != null) { + icon.setImageBitmap(cachedResult); + } else { + final ThumbnailAsyncTask task = new ThumbnailAsyncTask(icon, mThumbSize); + icon.setImageBitmap(null); + icon.setTag(task); + task.execute(doc.uri); + } } else { icon.setImageDrawable(RootsCache.resolveDocumentIcon( context, doc.uri.getAuthority(), doc.mimeType)); @@ -380,10 +406,11 @@ public class DirectoryFragment extends Fragment { (summary.getVisibility() == View.VISIBLE) ? View.VISIBLE : View.GONE); } - // TODO: omit year from format - date.setText(DateUtils.formatSameDayTime( - doc.lastModified, System.currentTimeMillis(), DateFormat.SHORT, - DateFormat.SHORT)); + if (doc.lastModified == -1) { + date.setText(null); + } else { + date.setText(formatTime(context, doc.lastModified)); + } if (state.showSize) { size.setVisibility(View.VISIBLE); @@ -414,4 +441,66 @@ public class DirectoryFragment extends Fragment { return getItem(position).uri.hashCode(); } } + + private static class ThumbnailAsyncTask extends AsyncTask<Uri, Void, Bitmap> { + private final ImageView mTarget; + private final Point mSize; + + public ThumbnailAsyncTask(ImageView target, Point size) { + mTarget = target; + mSize = size; + } + + @Override + protected void onPreExecute() { + mTarget.setTag(this); + } + + @Override + protected Bitmap doInBackground(Uri... params) { + final Context context = mTarget.getContext(); + final Uri uri = params[0]; + + Bitmap result = null; + try { + result = DocumentsContract.getThumbnail( + context.getContentResolver(), uri, mSize); + if (result != null) { + ThumbnailCache.get(context).put(uri, result); + } + } catch (Exception e) { + Log.w(TAG, "Failed to load thumbnail: " + e); + } + return result; + } + + @Override + protected void onPostExecute(Bitmap result) { + if (mTarget.getTag() == this) { + mTarget.setImageBitmap(result); + mTarget.setTag(null); + } + } + } + + private static String formatTime(Context context, long when) { + // TODO: DateUtils should make this easier + Time then = new Time(); + then.set(when); + Time now = new Time(); + now.setToNow(); + + int flags = DateUtils.FORMAT_NO_NOON | DateUtils.FORMAT_NO_MIDNIGHT + | DateUtils.FORMAT_ABBREV_ALL; + + if (then.year != now.year) { + flags |= DateUtils.FORMAT_SHOW_YEAR | DateUtils.FORMAT_SHOW_DATE; + } else if (then.yearDay != now.yearDay) { + flags |= DateUtils.FORMAT_SHOW_DATE; + } else { + flags |= DateUtils.FORMAT_SHOW_TIME; + } + + return DateUtils.formatDateTime(context, when, flags); + } } diff --git a/packages/DocumentsUI/src/com/android/documentsui/ThumbnailCache.java b/packages/DocumentsUI/src/com/android/documentsui/ThumbnailCache.java new file mode 100644 index 0000000..bc7abeb --- /dev/null +++ b/packages/DocumentsUI/src/com/android/documentsui/ThumbnailCache.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2013 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 android.app.ActivityManager; +import android.content.Context; +import android.graphics.Bitmap; +import android.net.Uri; +import android.util.LruCache; + +public class ThumbnailCache extends LruCache<Uri, Bitmap> { + private static ThumbnailCache sCache; + + public static ThumbnailCache get(Context context) { + if (sCache == null) { + final ActivityManager am = (ActivityManager) context.getSystemService( + Context.ACTIVITY_SERVICE); + final int memoryClassBytes = am.getMemoryClass() * 1024 * 1024; + sCache = new ThumbnailCache(memoryClassBytes / 4); + } + return sCache; + } + + public ThumbnailCache(int maxSizeBytes) { + super(maxSizeBytes); + } + + @Override + protected int sizeOf(Uri key, Bitmap value) { + return value.getByteCount(); + } +} |