diff options
author | Jeff Sharkey <jsharkey@android.com> | 2013-09-13 13:42:19 -0700 |
---|---|---|
committer | Jeff Sharkey <jsharkey@android.com> | 2013-09-13 16:02:14 -0700 |
commit | f6db154975ef575479ba4ab59d80bcf592288252 (patch) | |
tree | e2dab1b025abe925dd70a368a8bd4919f9fae6f4 /packages/DocumentsUI/src/com/android/documentsui | |
parent | 3e1189b3590aefb65a2af720ae2ba959bbd4188d (diff) | |
download | frameworks_base-f6db154975ef575479ba4ab59d80bcf592288252.zip frameworks_base-f6db154975ef575479ba4ab59d80bcf592288252.tar.gz frameworks_base-f6db154975ef575479ba4ab59d80bcf592288252.tar.bz2 |
More UX updates around picking images.
When picking images or videos, hide the titles in recents, since the
thumbnails should speak for themselves. Also respect new flag that
allows a directory to request their titles be hidden.
Show directory icon hint in grid mode when showing a thumbnail, to
remind user it's a directory.
Filter directories out of recents. Hide most action bar icons on
phones, even when room. Only show drawer on first launch. Hide most
drawer headers to match spec.
Bug: 10710331
Change-Id: I0ef1973ddd62750f57345336388366eda1449720
Diffstat (limited to 'packages/DocumentsUI/src/com/android/documentsui')
7 files changed, 90 insertions, 38 deletions
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java index aee865b..198927c 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java +++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java @@ -102,6 +102,8 @@ public class DirectoryFragment extends Fragment { private int mLastSortOrder = SORT_ORDER_UNKNOWN; private boolean mLastShowSize = false; + private boolean mHideGridTitles = false; + private Point mThumbSize; private DocumentsAdapter mAdapter; @@ -112,11 +114,6 @@ public class DirectoryFragment extends Fragment { private static final String EXTRA_DOC = "doc"; private static final String EXTRA_QUERY = "query"; - /** - * MIME types that should always show thumbnails in list mode. - */ - private static final String[] LIST_THUMBNAIL_MIMES = new String[] { "image/*", "video/*" }; - private static AtomicInteger sLoaderId = new AtomicInteger(4000); private final int mLoaderId = sLoaderId.incrementAndGet(); @@ -182,14 +179,23 @@ public class DirectoryFragment extends Fragment { final Context context = getActivity(); final State state = getDisplayState(DirectoryFragment.this); + final RootInfo root = getArguments().getParcelable(EXTRA_ROOT); + final DocumentInfo doc = getArguments().getParcelable(EXTRA_DOC); + mAdapter = new DocumentsAdapter(); mType = getArguments().getInt(EXTRA_TYPE); + if (mType == TYPE_RECENT_OPEN) { + // Hide titles when showing recents for picking images/videos + mHideGridTitles = MimePredicate.mimeMatches( + MimePredicate.VISUAL_MIMES, state.acceptMimes); + } else { + mHideGridTitles = (doc != null) && doc.isGridTitlesHidden(); + } + mCallbacks = new LoaderCallbacks<DirectoryResult>() { @Override public Loader<DirectoryResult> onCreateLoader(int id, Bundle args) { - final RootInfo root = getArguments().getParcelable(EXTRA_ROOT); - final DocumentInfo doc = getArguments().getParcelable(EXTRA_DOC); final String query = getArguments().getString(EXTRA_QUERY); Uri contentsUri; @@ -643,6 +649,8 @@ public class DirectoryFragment extends Fragment { final Context context = parent.getContext(); final State state = getDisplayState(DirectoryFragment.this); + final DocumentInfo doc = getArguments().getParcelable(EXTRA_DOC); + final RootsCache roots = DocumentsApplication.getRootsCache(context); final ThumbnailCache thumbs = DocumentsApplication.getThumbnailsCache( context, mThumbSize); @@ -671,12 +679,15 @@ public class DirectoryFragment extends Fragment { final String docSummary = getCursorString(cursor, Document.COLUMN_SUMMARY); final long docSize = getCursorLong(cursor, Document.COLUMN_SIZE); + final View line1 = convertView.findViewById(R.id.line1); + final View line2 = convertView.findViewById(R.id.line2); + final View icon = convertView.findViewById(android.R.id.icon); final ImageView iconMime = (ImageView) convertView.findViewById(R.id.icon_mime); final ImageView iconThumb = (ImageView) convertView.findViewById(R.id.icon_thumb); final TextView title = (TextView) convertView.findViewById(android.R.id.title); - final View line2 = convertView.findViewById(R.id.line2); final ImageView icon1 = (ImageView) convertView.findViewById(android.R.id.icon1); + final ImageView icon2 = (ImageView) convertView.findViewById(android.R.id.icon2); final TextView summary = (TextView) convertView.findViewById(android.R.id.summary); final TextView date = (TextView) convertView.findViewById(R.id.date); final TextView size = (TextView) convertView.findViewById(R.id.size); @@ -692,10 +703,11 @@ public class DirectoryFragment extends Fragment { final boolean supportsThumbnail = (docFlags & Document.FLAG_SUPPORTS_THUMBNAIL) != 0; final boolean allowThumbnail = (state.derivedMode == MODE_GRID) - || MimePredicate.mimeMatches(LIST_THUMBNAIL_MIMES, docMimeType); + || MimePredicate.mimeMatches(MimePredicate.VISUAL_MIMES, docMimeType); + final boolean showThumbnail = supportsThumbnail && allowThumbnail; boolean cacheHit = false; - if (supportsThumbnail && allowThumbnail) { + if (showThumbnail) { final Uri uri = DocumentsContract.buildDocumentUri(docAuthority, docId); final Bitmap cachedResult = thumbs.get(uri); if (cachedResult != null) { @@ -726,15 +738,19 @@ public class DirectoryFragment extends Fragment { } } - title.setText(docDisplayName); - + boolean hasLine1 = false; boolean hasLine2 = false; + final boolean hideTitle = (state.derivedMode == MODE_GRID) && mHideGridTitles; + if (!hideTitle) { + title.setText(docDisplayName); + hasLine1 = true; + } + + Drawable iconDrawable = null; if (mType == TYPE_RECENT_OPEN) { final RootInfo root = roots.getRoot(docAuthority, docRootId); - final Drawable iconDrawable = root.loadIcon(context); - icon1.setVisibility(View.VISIBLE); - icon1.setImageDrawable(iconDrawable); + iconDrawable = root.loadIcon(context); if (summary != null) { final boolean alwaysShowSummary = getResources() @@ -756,7 +772,13 @@ public class DirectoryFragment extends Fragment { } } } else { - icon1.setVisibility(View.GONE); + // Directories showing thumbnails in grid mode get a little icon + // hint to remind user they're a directory. + if (Document.MIME_TYPE_DIR.equals(docMimeType) && state.derivedMode == MODE_GRID + && showThumbnail) { + iconDrawable = context.getResources().getDrawable(R.drawable.ic_root_folder); + } + if (summary != null) { if (docSummary != null) { summary.setText(docSummary); @@ -768,6 +790,19 @@ public class DirectoryFragment extends Fragment { } } + if (icon1 != null) icon1.setVisibility(View.GONE); + if (icon2 != null) icon2.setVisibility(View.GONE); + + if (iconDrawable != null) { + if (hasLine1) { + icon1.setVisibility(View.VISIBLE); + icon1.setImageDrawable(iconDrawable); + } else { + icon2.setVisibility(View.VISIBLE); + icon2.setImageDrawable(iconDrawable); + } + } + if (docLastModified == -1) { date.setText(null); } else { @@ -787,6 +822,9 @@ public class DirectoryFragment extends Fragment { size.setVisibility(View.GONE); } + if (line1 != null) { + line1.setVisibility(hasLine1 ? View.VISIBLE : View.GONE); + } if (line2 != null) { line2.setVisibility(hasLine2 ? View.VISIBLE : View.GONE); } @@ -796,11 +834,13 @@ public class DirectoryFragment extends Fragment { if (enabled) { setEnabledRecursive(convertView, true); icon.setAlpha(1f); - icon1.setAlpha(1f); + if (icon1 != null) icon1.setAlpha(1f); + if (icon2 != null) icon2.setAlpha(1f); } else { setEnabledRecursive(convertView, false); icon.setAlpha(0.5f); - icon1.setAlpha(0.5f); + if (icon1 != null) icon1.setAlpha(0.5f); + if (icon2 != null) icon2.setAlpha(0.5f); } return convertView; @@ -943,6 +983,7 @@ public class DirectoryFragment extends Fragment { } private void setEnabledRecursive(View v, boolean enabled) { + if (v == null) return; if (v.isEnabled() == enabled) return; v.setEnabled(enabled); diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java index b1e51a0..f6cb481 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java +++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java @@ -244,6 +244,7 @@ public class DocumentsActivity extends Activity { } else { // Restore last stack for calling package // TODO: move into async loader + boolean restoredStack = false; final String packageName = getCallingPackage(); final Cursor cursor = getContentResolver() .query(RecentsProvider.buildResume(packageName), null, null, null, null); @@ -252,6 +253,7 @@ public class DocumentsActivity extends Activity { final byte[] rawStack = cursor.getBlob( cursor.getColumnIndex(ResumeColumns.STACK)); DurableUtils.readFromArray(rawStack, mState.stack); + restoredStack = true; } } catch (IOException e) { Log.w(TAG, "Failed to resume", e); @@ -264,10 +266,13 @@ public class DocumentsActivity extends Activity { final List<RootInfo> matchingRoots = mRoots.getMatchingRoots(mState); if (!matchingRoots.contains(root)) { mState.stack.reset(); + restoredStack = false; } - // Only open drawer when showing recents - if (mState.stack.isRecents()) { + // Only open drawer when not restoring stack, and when not showing + // visual content. + if (!restoredStack + && !MimePredicate.mimeMatches(MimePredicate.VISUAL_MIMES, mState.acceptMimes)) { setRootsDrawerOpen(true); } } diff --git a/packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java b/packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java index b55ce82..2d96876 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java +++ b/packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java @@ -22,6 +22,12 @@ import com.android.internal.util.Predicate; public class MimePredicate implements Predicate<DocumentInfo> { private final String[] mFilters; + /** + * MIME types that are visual in nature. For example, they should always be + * shown as thumbnails in list mode. + */ + public static final String[] VISUAL_MIMES = new String[] { "image/*", "video/*" }; + public MimePredicate(String[] filters) { mFilters = filters; } diff --git a/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java b/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java index a7173b6..1912010 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java +++ b/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java @@ -27,6 +27,7 @@ import android.database.Cursor; import android.database.MergeCursor; import android.net.Uri; import android.provider.DocumentsContract; +import android.provider.DocumentsContract.Document; import android.provider.DocumentsContract.Root; import android.util.Log; @@ -176,7 +177,7 @@ public class RecentLoader extends AsyncTaskLoader<DirectoryResult> { try { final Cursor cursor = task.get(); final FilteringCursorWrapper filtered = new FilteringCursorWrapper( - cursor, mAcceptMimes) { + cursor, mAcceptMimes, new String[] { Document.MIME_TYPE_DIR }) { @Override public void close() { // Ignored, since we manage cursor lifecycle internally diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java index 4d313e8..9b54948 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java +++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java @@ -137,12 +137,14 @@ public class RootsCache { @GuardedBy("ActivityThread") public boolean isIconUnique(RootInfo root) { + final int rootIcon = root.derivedIcon != 0 ? root.derivedIcon : root.icon; for (RootInfo test : mRoots) { if (Objects.equal(test.authority, root.authority)) { if (Objects.equal(test.rootId, root.rootId)) { continue; } - if (test.icon == root.icon) { + final int testIcon = test.derivedIcon != 0 ? test.derivedIcon : test.icon; + if (testIcon == rootIcon) { return false; } } diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java index 54dcf1c..908729c 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java +++ b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java @@ -35,6 +35,7 @@ import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.ListView; +import android.widget.Space; import android.widget.TextView; import com.android.documentsui.DocumentsActivity.State; @@ -136,11 +137,8 @@ public class RootsFragment extends Fragment { }; private static class RootsAdapter extends ArrayAdapter<RootInfo> implements SectionAdapter { - private int mHeaderId; - - public RootsAdapter(Context context, int headerId) { + public RootsAdapter(Context context) { super(context, 0); - mHeaderId = headerId; } @Override @@ -177,13 +175,8 @@ public class RootsFragment extends Fragment { @Override public View getHeaderView(View convertView, ViewGroup parent) { if (convertView == null) { - convertView = LayoutInflater.from(parent.getContext()) - .inflate(R.layout.item_root_header, parent, false); + convertView = new Space(parent.getContext()); } - - final TextView title = (TextView) convertView.findViewById(android.R.id.title); - title.setText(mHeaderId); - return convertView; } } @@ -237,9 +230,9 @@ public class RootsFragment extends Fragment { private final AppsAdapter mApps; public SectionedRootsAdapter(Context context, List<RootInfo> roots, Intent includeApps) { - mServices = new RootsAdapter(context, R.string.root_type_service); - mShortcuts = new RootsAdapter(context, R.string.root_type_shortcut); - mDevices = new RootsAdapter(context, R.string.root_type_device); + mServices = new RootsAdapter(context); + mShortcuts = new RootsAdapter(context); + mDevices = new RootsAdapter(context); mApps = new AppsAdapter(context); for (RootInfo root : roots) { @@ -274,15 +267,15 @@ public class RootsFragment extends Fragment { mShortcuts.sort(comp); mDevices.sort(comp); - if (mServices.getCount() > 0) { - addSection(mServices); - } if (mShortcuts.getCount() > 0) { addSection(mShortcuts); } if (mDevices.getCount() > 0) { addSection(mDevices); } + if (mServices.getCount() > 0) { + addSection(mServices); + } if (mApps.getCount() > 0) { addSection(mApps); } diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java b/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java index ab55d94..681cc9b 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java +++ b/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java @@ -204,6 +204,10 @@ public class DocumentInfo implements Durable, Parcelable { return (flags & Document.FLAG_SUPPORTS_DELETE) != 0; } + public boolean isGridTitlesHidden() { + return (flags & Document.FLAG_DIR_HIDE_GRID_TITLES) != 0; + } + public static String getCursorString(Cursor cursor, String columnName) { final int index = cursor.getColumnIndex(columnName); return (index != -1) ? cursor.getString(index) : null; |