diff options
author | Jeff Sharkey <jsharkey@android.com> | 2013-07-01 16:56:54 -0700 |
---|---|---|
committer | Jeff Sharkey <jsharkey@android.com> | 2013-07-01 17:00:14 -0700 |
commit | be8b12e687bd10a526b1f54c2d8a52abdad15d85 (patch) | |
tree | 1ef49eac10010b487799de3cdc625d0783bfe3d5 /packages/DocumentsUI/src | |
parent | 54e55b740fef1be654c3959aee41ef5ddfa61293 (diff) | |
download | frameworks_base-be8b12e687bd10a526b1f54c2d8a52abdad15d85.zip frameworks_base-be8b12e687bd10a526b1f54c2d8a52abdad15d85.tar.gz frameworks_base-be8b12e687bd10a526b1f54c2d8a52abdad15d85.tar.bz2 |
Support multi-select in storage UI.
When caller has specified that multiple documents are okay, enable
multi-select action mode. Currently only allows document selection,
not directories. Returns multiple documents through ClipData.
Fix bug where GridView was stuck with 2 columns on tablets.
Change-Id: Id49b29a86330639b56fa116d37e7f0d874980c5b
Diffstat (limited to 'packages/DocumentsUI/src')
-rw-r--r-- | packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java | 89 | ||||
-rw-r--r-- | packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java | 50 |
2 files changed, 129 insertions, 10 deletions
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java index 5ba1930..bae42d5 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java +++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java @@ -29,12 +29,16 @@ import android.os.Bundle; import android.provider.DocumentsContract; import android.provider.DocumentsContract.DocumentColumns; import android.text.format.DateUtils; +import android.util.SparseBooleanArray; +import android.view.ActionMode; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; +import android.widget.AbsListView; +import android.widget.AbsListView.MultiChoiceModeListener; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.CursorAdapter; @@ -44,6 +48,9 @@ import android.widget.ListView; import android.widget.TextView; import com.android.documentsui.DocumentsActivity.Document; +import com.google.android.collect.Lists; + +import java.util.ArrayList; /** * Display the documents inside a single directory. @@ -52,11 +59,12 @@ public class DirectoryFragment extends Fragment { // TODO: show storage backend in item views when requested // TODO: implement sorting dialog - // TODO: support multiple selection with actionmode private ListView mListView; private GridView mGridView; + private AbsListView mCurrentView; + private DocumentsAdapter mAdapter; private LoaderCallbacks<Cursor> mCallbacks; @@ -64,16 +72,19 @@ public class DirectoryFragment extends Fragment { private static final String EXTRA_URI = "uri"; private static final String EXTRA_MODE = "display_mode"; + private static final String EXTRA_ALLOW_MULTIPLE = "allow_multiple"; private static final int MODE_LIST = 1; private static final int MODE_GRID = 2; private static final int LOADER_DOCUMENTS = 2; - public static void show(FragmentManager fm, Uri uri, String displayName) { + public static void show( + FragmentManager fm, Uri uri, String displayName, boolean allowMultiple) { final Bundle args = new Bundle(); args.putParcelable(EXTRA_URI, uri); args.putInt(EXTRA_MODE, MODE_LIST); + args.putBoolean(EXTRA_ALLOW_MULTIPLE, allowMultiple); final DirectoryFragment fragment = new DirectoryFragment(); fragment.setArguments(args); @@ -100,9 +111,11 @@ public class DirectoryFragment extends Fragment { mListView = (ListView) view.findViewById(R.id.list); mListView.setOnItemClickListener(mItemListener); + mListView.setMultiChoiceModeListener(mMultiListener); mGridView = (GridView) view.findViewById(R.id.grid); mGridView.setOnItemClickListener(mItemListener); + mGridView.setMultiChoiceModeListener(mMultiListener); mAdapter = new DocumentsAdapter(context); updateMode(); @@ -184,13 +197,27 @@ public class DirectoryFragment extends Fragment { mListView.setVisibility(mode == MODE_LIST ? View.VISIBLE : View.GONE); mGridView.setVisibility(mode == MODE_GRID ? View.VISIBLE : View.GONE); + final int choiceMode; + if (getArguments().getBoolean(EXTRA_ALLOW_MULTIPLE)) { + choiceMode = ListView.CHOICE_MODE_MULTIPLE_MODAL; + } else { + choiceMode = ListView.CHOICE_MODE_NONE; + } + if (mode == MODE_GRID) { mListView.setAdapter(null); + mListView.setChoiceMode(ListView.CHOICE_MODE_NONE); mGridView.setAdapter(mAdapter); + mGridView.setColumnWidth(getResources().getDimensionPixelSize(R.dimen.grid_width)); mGridView.setNumColumns(GridView.AUTO_FIT); + mGridView.setChoiceMode(choiceMode); + mCurrentView = mGridView; } else { mGridView.setAdapter(null); + mGridView.setChoiceMode(ListView.CHOICE_MODE_NONE); mListView.setAdapter(mAdapter); + mListView.setChoiceMode(choiceMode); + mCurrentView = mListView; } } @@ -198,13 +225,69 @@ public class DirectoryFragment extends Fragment { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { final Cursor cursor = (Cursor) mAdapter.getItem(position); - final Uri uri = getArguments().getParcelable(EXTRA_URI); final Document doc = Document.fromCursor(uri.getAuthority(), cursor); ((DocumentsActivity) getActivity()).onDocumentPicked(doc); } }; + private MultiChoiceModeListener mMultiListener = new MultiChoiceModeListener() { + @Override + public boolean onCreateActionMode(ActionMode mode, Menu menu) { + mode.getMenuInflater().inflate(R.menu.mode_directory, menu); + return true; + } + + @Override + public boolean onPrepareActionMode(ActionMode mode, Menu menu) { + return true; + } + + @Override + public boolean onActionItemClicked(ActionMode mode, MenuItem item) { + if (item.getItemId() == R.id.menu_open) { + final Uri uri = getArguments().getParcelable(EXTRA_URI); + final SparseBooleanArray checked = mCurrentView.getCheckedItemPositions(); + final ArrayList<Document> docs = Lists.newArrayList(); + + final int size = checked.size(); + for (int i = 0; i < size; i++) { + if (checked.valueAt(i)) { + final Cursor cursor = (Cursor) mAdapter.getItem(checked.keyAt(i)); + docs.add(Document.fromCursor(uri.getAuthority(), cursor)); + } + } + + ((DocumentsActivity) getActivity()).onDocumentsPicked(docs); + return true; + } else { + return false; + } + } + + @Override + public void onDestroyActionMode(ActionMode mode) { + // ignored + } + + @Override + public void onItemCheckedStateChanged( + ActionMode mode, int position, long id, boolean checked) { + if (checked) { + final Cursor cursor = (Cursor) mAdapter.getItem(position); + final String mimeType = getCursorString(cursor, DocumentColumns.MIME_TYPE); + + // Directories cannot be checked + if (DocumentsContract.MIME_TYPE_DIRECTORY.equals(mimeType)) { + mCurrentView.setItemChecked(position, false); + } + } + + mode.setTitle(getResources() + .getString(R.string.mode_selected_count, mCurrentView.getCheckedItemCount())); + } + }; + private boolean getSupportsCreate() { return (mFlags & DocumentsContract.FLAG_SUPPORTS_CREATE) != 0; } diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java index c83edc4..ca4ea82 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java +++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java @@ -24,6 +24,8 @@ import android.app.Activity; import android.app.FragmentManager; import android.app.FragmentManager.BackStackEntry; import android.app.FragmentManager.OnBackStackChangedListener; +import android.content.ClipData; +import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; @@ -44,6 +46,9 @@ import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; +import java.util.Arrays; +import java.util.List; + public class DocumentsActivity extends Activity { private static final String TAG = "Documents"; @@ -54,6 +59,9 @@ public class DocumentsActivity extends Activity { private static final int MODE_CREATE = 2; private int mMode; + private boolean mAllowMultiple; + private String[] mAcceptMimes; + private boolean mIgnoreNextNavigation; private Uri mCurrentDir; @@ -63,11 +71,20 @@ public class DocumentsActivity extends Activity { public void onCreate(Bundle icicle) { super.onCreate(icicle); - final String action = getIntent().getAction(); + final Intent intent = getIntent(); + final String action = intent.getAction(); if (Intent.ACTION_OPEN_DOCUMENT.equals(action)) { mMode = MODE_OPEN; + mAllowMultiple = intent.getBooleanExtra(Intent.EXTRA_ALLOW_MULTIPLE, false); } else if (Intent.ACTION_CREATE_DOCUMENT.equals(action)) { mMode = MODE_CREATE; + mAllowMultiple = false; + } + + if (intent.hasExtra(Intent.EXTRA_MIME_TYPES)) { + mAcceptMimes = intent.getStringArrayExtra(Intent.EXTRA_MIME_TYPES); + } else { + mAcceptMimes = new String[] { intent.getType() }; } setResult(Activity.RESULT_CANCELED); @@ -208,14 +225,14 @@ public class DocumentsActivity extends Activity { final Uri uri = DocumentsContract.buildDocumentUri( info.authority, DocumentsContract.ROOT_GUID); final CharSequence displayName = info.loadLabel(getPackageManager()); - DirectoryFragment.show(getFragmentManager(), uri, displayName.toString()); + DirectoryFragment.show(getFragmentManager(), uri, displayName.toString(), mAllowMultiple); } public void onDocumentPicked(Document doc) { final FragmentManager fm = getFragmentManager(); if (DocumentsContract.MIME_TYPE_DIRECTORY.equals(doc.mimeType)) { // Nested directory picked, recurse using new fragment - DirectoryFragment.show(fm, doc.uri, doc.displayName); + DirectoryFragment.show(fm, doc.uri, doc.displayName, mAllowMultiple); } else if (mMode == MODE_OPEN) { // Explicit file picked, return onFinished(doc.uri); @@ -225,16 +242,35 @@ public class DocumentsActivity extends Activity { } } + public void onDocumentsPicked(List<Document> docs) { + final int size = docs.size(); + final Uri[] uris = new Uri[size]; + for (int i = 0; i < size; i++) { + uris[i] = docs.get(i).uri; + } + onFinished(uris); + } + public void onSaveRequested(String mimeType, String displayName) { // TODO: create file, confirming before overwriting - onFinished(null); + final Uri uri = null; + onFinished(uri); } - private void onFinished(Uri uri) { - Log.d(TAG, "onFinished() " + uri); + private void onFinished(Uri... uris) { + Log.d(TAG, "onFinished() " + Arrays.toString(uris)); final Intent intent = new Intent(); - intent.setData(uri); + if (uris.length == 1) { + intent.setData(uris[0]); + } else if (uris.length > 1) { + final ContentResolver resolver = getContentResolver(); + final ClipData clipData = new ClipData(null, mAcceptMimes, new ClipData.Item(uris[0])); + for (int i = 1; i < uris.length; i++) { + clipData.addItem(new ClipData.Item(uris[i])); + } + intent.setClipData(clipData); + } intent.addFlags( Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_PERSIST_GRANT_URI_PERMISSION); |