DirectoryFragmentpublic class DirectoryFragment extends android.app.Fragment Display the documents inside a single directory. |
Fields Summary |
---|
private android.view.View | mEmptyView | private android.widget.ListView | mListView | private android.widget.GridView | mGridView | private android.widget.AbsListView | mCurrentView | public static final int | TYPE_NORMAL | public static final int | TYPE_SEARCH | public static final int | TYPE_RECENT_OPEN | public static final int | ANIM_NONE | public static final int | ANIM_SIDE | public static final int | ANIM_DOWN | public static final int | ANIM_UP | private int | mType | private String | mStateKey | private int | mLastMode | private int | mLastSortOrder | private boolean | mLastShowSize | private boolean | mHideGridTitles | private boolean | mSvelteRecents | private android.graphics.Point | mThumbSize | private DocumentsAdapter | mAdapter | private android.app.LoaderManager.LoaderCallbacks | mCallbacks | private static final String | EXTRA_TYPE | private static final String | EXTRA_ROOT | private static final String | EXTRA_DOC | private static final String | EXTRA_QUERY | private static final String | EXTRA_IGNORE_STATE | private final int | mLoaderId | private android.widget.AdapterView.OnItemClickListener | mItemListener | private android.widget.AbsListView.MultiChoiceModeListener | mMultiListener | private android.widget.AbsListView.RecyclerListener | mRecycleListener |
Methods Summary |
---|
private static java.lang.String | buildStateKey(com.android.documentsui.model.RootInfo root, com.android.documentsui.model.DocumentInfo doc)
final StringBuilder builder = new StringBuilder();
builder.append(root != null ? root.authority : "null").append(';");
builder.append(root != null ? root.rootId : "null").append(';");
builder.append(doc != null ? doc.documentId : "null");
return builder.toString();
| private java.lang.String | findCommonMimeType(java.util.List mimeTypes)
String[] commonType = mimeTypes.get(0).split("/");
if (commonType.length != 2) {
return "*/*";
}
for (int i = 1; i < mimeTypes.size(); i++) {
String[] type = mimeTypes.get(i).split("/");
if (type.length != 2) continue;
if (!commonType[1].equals(type[1])) {
commonType[1] = "*";
}
if (!commonType[0].equals(type[0])) {
commonType[0] = "*";
commonType[1] = "*";
break;
}
}
return commonType[0] + "/" + commonType[1];
| private static java.lang.String | formatTime(android.content.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);
| public static com.android.documentsui.DirectoryFragment | get(android.app.FragmentManager fm)
// TODO: deal with multiple directories shown at once
return (DirectoryFragment) fm.findFragmentById(R.id.container_directory);
| private static com.android.documentsui.DocumentsActivity.State | getDisplayState(android.app.Fragment fragment)
return ((DocumentsActivity) fragment.getActivity()).getDisplayState();
| private boolean | isDocumentEnabled(java.lang.String docMimeType, int docFlags)
final State state = getDisplayState(DirectoryFragment.this);
// Directories are always enabled
if (Document.MIME_TYPE_DIR.equals(docMimeType)) {
return true;
}
// Read-only files are disabled when creating
if (state.action == ACTION_CREATE && (docFlags & Document.FLAG_SUPPORTS_WRITE) == 0) {
return false;
}
return MimePredicate.mimeMatches(state.acceptMimes, docMimeType);
| public void | onActivityCreated(android.os.Bundle savedInstanceState)
super.onActivityCreated(savedInstanceState);
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);
mStateKey = buildStateKey(root, doc);
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();
}
final ActivityManager am = (ActivityManager) context.getSystemService(
Context.ACTIVITY_SERVICE);
mSvelteRecents = am.isLowRamDevice() && (mType == TYPE_RECENT_OPEN);
mCallbacks = new LoaderCallbacks<DirectoryResult>() {
@Override
public Loader<DirectoryResult> onCreateLoader(int id, Bundle args) {
final String query = getArguments().getString(EXTRA_QUERY);
Uri contentsUri;
switch (mType) {
case TYPE_NORMAL:
contentsUri = DocumentsContract.buildChildDocumentsUri(
doc.authority, doc.documentId);
if (state.action == ACTION_MANAGE) {
contentsUri = DocumentsContract.setManageMode(contentsUri);
}
return new DirectoryLoader(
context, mType, root, doc, contentsUri, state.userSortOrder);
case TYPE_SEARCH:
contentsUri = DocumentsContract.buildSearchDocumentsUri(
root.authority, root.rootId, query);
if (state.action == ACTION_MANAGE) {
contentsUri = DocumentsContract.setManageMode(contentsUri);
}
return new DirectoryLoader(
context, mType, root, doc, contentsUri, state.userSortOrder);
case TYPE_RECENT_OPEN:
final RootsCache roots = DocumentsApplication.getRootsCache(context);
return new RecentLoader(context, roots, state);
default:
throw new IllegalStateException("Unknown type " + mType);
}
}
@Override
public void onLoadFinished(Loader<DirectoryResult> loader, DirectoryResult result) {
if (!isAdded()) return;
mAdapter.swapResult(result);
// Push latest state up to UI
// TODO: if mode change was racing with us, don't overwrite it
if (result.mode != MODE_UNKNOWN) {
state.derivedMode = result.mode;
}
state.derivedSortOrder = result.sortOrder;
((DocumentsActivity) context).onStateChanged();
updateDisplayState();
// When launched into empty recents, show drawer
if (mType == TYPE_RECENT_OPEN && mAdapter.isEmpty() && !state.stackTouched) {
((DocumentsActivity) context).setRootsDrawerOpen(true);
}
// Restore any previous instance state
final SparseArray<Parcelable> container = state.dirState.remove(mStateKey);
if (container != null && !getArguments().getBoolean(EXTRA_IGNORE_STATE, false)) {
getView().restoreHierarchyState(container);
} else if (mLastSortOrder != state.derivedSortOrder) {
mListView.smoothScrollToPosition(0);
mGridView.smoothScrollToPosition(0);
}
mLastSortOrder = state.derivedSortOrder;
}
@Override
public void onLoaderReset(Loader<DirectoryResult> loader) {
mAdapter.swapResult(null);
}
};
// Kick off loader at least once
getLoaderManager().restartLoader(mLoaderId, null, mCallbacks);
updateDisplayState();
| public android.view.View | onCreateView(android.view.LayoutInflater inflater, android.view.ViewGroup container, android.os.Bundle savedInstanceState)
final Context context = inflater.getContext();
final Resources res = context.getResources();
final View view = inflater.inflate(R.layout.fragment_directory, container, false);
mEmptyView = view.findViewById(android.R.id.empty);
mListView = (ListView) view.findViewById(R.id.list);
mListView.setOnItemClickListener(mItemListener);
mListView.setMultiChoiceModeListener(mMultiListener);
mListView.setRecyclerListener(mRecycleListener);
// Indent our list divider to align with text
final Drawable divider = mListView.getDivider();
final boolean insetLeft = res.getBoolean(R.bool.list_divider_inset_left);
final int insetSize = res.getDimensionPixelSize(R.dimen.list_divider_inset);
if (insetLeft) {
mListView.setDivider(new InsetDrawable(divider, insetSize, 0, 0, 0));
} else {
mListView.setDivider(new InsetDrawable(divider, 0, 0, insetSize, 0));
}
mGridView = (GridView) view.findViewById(R.id.grid);
mGridView.setOnItemClickListener(mItemListener);
mGridView.setMultiChoiceModeListener(mMultiListener);
mGridView.setRecyclerListener(mRecycleListener);
return view;
| private void | onDeleteDocuments(java.util.List docs)
final Context context = getActivity();
final ContentResolver resolver = context.getContentResolver();
boolean hadTrouble = false;
for (DocumentInfo doc : docs) {
if (!doc.isDeleteSupported()) {
Log.w(TAG, "Skipping " + doc);
hadTrouble = true;
continue;
}
ContentProviderClient client = null;
try {
client = DocumentsApplication.acquireUnstableProviderOrThrow(
resolver, doc.derivedUri.getAuthority());
DocumentsContract.deleteDocument(client, doc.derivedUri);
} catch (Exception e) {
Log.w(TAG, "Failed to delete " + doc);
hadTrouble = true;
} finally {
ContentProviderClient.releaseQuietly(client);
}
}
if (hadTrouble) {
Toast.makeText(context, R.string.toast_failed_delete, Toast.LENGTH_SHORT).show();
}
| public void | onDestroyView()
super.onDestroyView();
// Cancel any outstanding thumbnail requests
final ViewGroup target = (mListView.getAdapter() != null) ? mListView : mGridView;
final int count = target.getChildCount();
for (int i = 0; i < count; i++) {
final View view = target.getChildAt(i);
mRecycleListener.onMovedToScrapHeap(view);
}
// Tear down any selection in progress
mListView.setChoiceMode(AbsListView.CHOICE_MODE_NONE);
mGridView.setChoiceMode(AbsListView.CHOICE_MODE_NONE);
| public void | onDisplayStateChanged()
updateDisplayState();
| public void | onResume()
super.onResume();
updateDisplayState();
| private void | onShareDocuments(java.util.List docs)
Intent intent;
if (docs.size() == 1) {
final DocumentInfo doc = docs.get(0);
intent = new Intent(Intent.ACTION_SEND);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setType(doc.mimeType);
intent.putExtra(Intent.EXTRA_STREAM, doc.derivedUri);
} else if (docs.size() > 1) {
intent = new Intent(Intent.ACTION_SEND_MULTIPLE);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addCategory(Intent.CATEGORY_DEFAULT);
final ArrayList<String> mimeTypes = Lists.newArrayList();
final ArrayList<Uri> uris = Lists.newArrayList();
for (DocumentInfo doc : docs) {
mimeTypes.add(doc.mimeType);
uris.add(doc.derivedUri);
}
intent.setType(findCommonMimeType(mimeTypes));
intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);
} else {
return;
}
intent = Intent.createChooser(intent, getActivity().getText(R.string.share_via));
startActivity(intent);
| public void | onStop()
super.onStop();
// Remember last scroll location
final SparseArray<Parcelable> container = new SparseArray<Parcelable>();
getView().saveHierarchyState(container);
final State state = getDisplayState(this);
state.dirState.put(mStateKey, container);
| public void | onUserModeChanged()
final ContentResolver resolver = getActivity().getContentResolver();
final State state = getDisplayState(this);
final RootInfo root = getArguments().getParcelable(EXTRA_ROOT);
final DocumentInfo doc = getArguments().getParcelable(EXTRA_DOC);
if (root != null && doc != null) {
final Uri stateUri = RecentsProvider.buildState(
root.authority, root.rootId, doc.documentId);
final ContentValues values = new ContentValues();
values.put(StateColumns.MODE, state.userMode);
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
resolver.insert(stateUri, values);
return null;
}
}.execute();
}
// Mode change is just visual change; no need to kick loader, and
// deliver change event immediately.
state.derivedMode = state.userMode;
((DocumentsActivity) getActivity()).onStateChanged();
updateDisplayState();
| public void | onUserSortOrderChanged()
// Sort order change always triggers reload; we'll trigger state change
// on the flip side.
getLoaderManager().restartLoader(mLoaderId, null, mCallbacks);
| private void | setEnabledRecursive(android.view.View v, boolean enabled)
if (v == null) return;
if (v.isEnabled() == enabled) return;
v.setEnabled(enabled);
if (v instanceof ViewGroup) {
final ViewGroup vg = (ViewGroup) v;
for (int i = vg.getChildCount() - 1; i >= 0; i--) {
setEnabledRecursive(vg.getChildAt(i), enabled);
}
}
| private static void | show(android.app.FragmentManager fm, int type, com.android.documentsui.model.RootInfo root, com.android.documentsui.model.DocumentInfo doc, java.lang.String query, int anim)
final Bundle args = new Bundle();
args.putInt(EXTRA_TYPE, type);
args.putParcelable(EXTRA_ROOT, root);
args.putParcelable(EXTRA_DOC, doc);
args.putString(EXTRA_QUERY, query);
final FragmentTransaction ft = fm.beginTransaction();
switch (anim) {
case ANIM_SIDE:
args.putBoolean(EXTRA_IGNORE_STATE, true);
break;
case ANIM_DOWN:
args.putBoolean(EXTRA_IGNORE_STATE, true);
ft.setCustomAnimations(R.animator.dir_down, R.animator.dir_frozen);
break;
case ANIM_UP:
ft.setCustomAnimations(R.animator.dir_frozen, R.animator.dir_up);
break;
}
final DirectoryFragment fragment = new DirectoryFragment();
fragment.setArguments(args);
ft.replace(R.id.container_directory, fragment);
ft.commitAllowingStateLoss();
| public static void | showNormal(android.app.FragmentManager fm, com.android.documentsui.model.RootInfo root, com.android.documentsui.model.DocumentInfo doc, int anim)
show(fm, TYPE_NORMAL, root, doc, null, anim);
| public static void | showRecentsOpen(android.app.FragmentManager fm, int anim)
show(fm, TYPE_RECENT_OPEN, null, null, null, anim);
| public static void | showSearch(android.app.FragmentManager fm, com.android.documentsui.model.RootInfo root, java.lang.String query, int anim)
show(fm, TYPE_SEARCH, root, null, query, anim);
| private void | updateDisplayState()
final State state = getDisplayState(this);
if (mLastMode == state.derivedMode && mLastShowSize == state.showSize) return;
mLastMode = state.derivedMode;
mLastShowSize = state.showSize;
mListView.setVisibility(state.derivedMode == MODE_LIST ? View.VISIBLE : View.GONE);
mGridView.setVisibility(state.derivedMode == MODE_GRID ? View.VISIBLE : View.GONE);
final int choiceMode;
if (state.allowMultiple) {
choiceMode = ListView.CHOICE_MODE_MULTIPLE_MODAL;
} else {
choiceMode = ListView.CHOICE_MODE_NONE;
}
final int thumbSize;
if (state.derivedMode == MODE_GRID) {
thumbSize = getResources().getDimensionPixelSize(R.dimen.grid_width);
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 if (state.derivedMode == MODE_LIST) {
thumbSize = getResources().getDimensionPixelSize(R.dimen.icon_size);
mGridView.setAdapter(null);
mGridView.setChoiceMode(ListView.CHOICE_MODE_NONE);
mListView.setAdapter(mAdapter);
mListView.setChoiceMode(choiceMode);
mCurrentView = mListView;
} else {
throw new IllegalStateException("Unknown state " + state.derivedMode);
}
mThumbSize = new Point(thumbSize, thumbSize);
|
|