diff options
author | jmartingit <jmartindev@gmail.com> | 2015-12-07 12:29:48 +0100 |
---|---|---|
committer | jmartingit <jmartindev@gmail.com> | 2015-12-07 12:29:48 +0100 |
commit | 0da98d0d7fb667b1562c36ab7f50517eff8871ec (patch) | |
tree | ac68b14326082d8e2bc94b73db729e3492a429b9 | |
parent | 36ee9b8e5a282a22bf7fa15012d9f62e29323985 (diff) | |
download | afollestad-0da98d0d7fb667b1562c36ab7f50517eff8871ec.tar.gz |
new File Chooser Dialog
-rw-r--r-- | commons/src/main/java/com/afollestad/materialdialogs/folderselector/FileChooserDialog.java | 254 |
1 files changed, 254 insertions, 0 deletions
diff --git a/commons/src/main/java/com/afollestad/materialdialogs/folderselector/FileChooserDialog.java b/commons/src/main/java/com/afollestad/materialdialogs/folderselector/FileChooserDialog.java new file mode 100644 index 0000000..4381dc9 --- /dev/null +++ b/commons/src/main/java/com/afollestad/materialdialogs/folderselector/FileChooserDialog.java @@ -0,0 +1,254 @@ +package com.afollestad.materialdialogs.folderselector; + +import android.Manifest; +import android.app.Activity; +import android.app.Dialog; +import android.content.pm.PackageManager; +import android.os.Build; +import android.os.Bundle; +import android.os.Environment; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.annotation.StringRes; +import android.support.v4.app.ActivityCompat; +import android.support.v4.app.DialogFragment; +import android.support.v4.app.Fragment; +import android.support.v7.app.AppCompatActivity; +import android.view.View; +import android.webkit.MimeTypeMap; + +import com.afollestad.materialdialogs.DialogAction; +import com.afollestad.materialdialogs.MaterialDialog; +import com.afollestad.materialdialogs.commons.R; + +import java.io.File; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +public class FileChooserDialog extends DialogFragment implements MaterialDialog.ListCallback { + + private final static String TAG = "[MD_FILE_SELECTOR]"; + + private File parentFolder; + private File[] parentContents; + private boolean canGoUp = true; + private FileCallback mCallback; + + public interface FileCallback { + void onFileSelection(File file); + } + + public FileChooserDialog() { + } + + String[] getContentsArray() { + if (parentContents == null) return new String[]{}; + String[] results = new String[parentContents.length + (canGoUp ? 1 : 0)]; + if (canGoUp) results[0] = "..."; + for (int i = 0; i < parentContents.length; i++) + results[canGoUp ? i + 1 : i] = parentContents[i].getName(); + return results; + } + + File[] listFiles(String mimeType) { + File[] contents = parentFolder.listFiles(); + List<File> results = new ArrayList<>(); + if (contents != null) { + MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton(); + for (File fi : contents) { + if (fi.isDirectory()) { + results.add(fi); + } else { + if (fileIsMimeType(fi, mimeType, mimeTypeMap)) { + results.add(fi); + } + } + } + Collections.sort(results, new FileSorter()); + return results.toArray(new File[results.size()]); + } + return null; + } + + boolean fileIsMimeType(File file, String mimeType, MimeTypeMap mimeTypeMap) { + if (mimeType == null || mimeType.equals("*/*")) { + return true; + } else { + // get the file mime type + String filename = file.toURI().toString(); + int dotPos = filename.lastIndexOf('.'); + if (dotPos == -1) { + return false; + } + String fileExtension = filename.substring(dotPos + 1); + String fileType = mimeTypeMap.getMimeTypeFromExtension(fileExtension); + if (fileType == null) { + return false; + } + // check the 'type/subtype' pattern + if (fileType.equals(mimeType)) { + return true; + } + // check the 'type/*' pattern + int mimeTypeDelimiter = mimeType.lastIndexOf('/'); + if (mimeTypeDelimiter == -1) { + return false; + } + String mimeTypeMainType = mimeType.substring(0, mimeTypeDelimiter); + String mimeTypeSubtype = mimeType.substring(mimeTypeDelimiter + 1); + if (!mimeTypeSubtype.equals("*")) { + return false; + } + int fileTypeDelimiter = fileType.lastIndexOf('/'); + if (fileTypeDelimiter == -1 ) { + return false; + } + String fileTypeMainType = fileType.substring(0, fileTypeDelimiter); + if (fileTypeMainType.equals(mimeTypeMainType)) { + return true; + } + } + return false; + } + + @SuppressWarnings("ConstantConditions") + @NonNull + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && + ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE) != + PackageManager.PERMISSION_GRANTED) { + return new MaterialDialog.Builder(getActivity()) + .title(R.string.md_error_label) + .content(R.string.md_storage_perm_error) + .positiveText(android.R.string.ok) + .build(); + } + + if (getArguments() == null || !getArguments().containsKey("builder")) + throw new IllegalStateException("You must create a FileChooserDialog using the Builder."); + if (!getArguments().containsKey("current_path")) + getArguments().putString("current_path", getBuilder().mInitialPath); + parentFolder = new File(getArguments().getString("current_path")); + parentContents = listFiles(getBuilder().mMimeType); + return new MaterialDialog.Builder(getActivity()) + .title(parentFolder.getAbsolutePath()) + .items(getContentsArray()) + .itemsCallback(this) + .onNegative(new MaterialDialog.SingleButtonCallback() { + @Override + public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) { + dialog.dismiss(); + } + }) + .autoDismiss(false) + .negativeText(getBuilder().mCancelButton) + .build(); + } + + @Override + public void onSelection(MaterialDialog materialDialog, View view, int i, CharSequence s) { + if (canGoUp && i == 0) { + parentFolder = parentFolder.getParentFile(); + canGoUp = parentFolder.getParent() != null; + } else { + parentFolder = parentContents[canGoUp ? i - 1 : i]; + canGoUp = true; + } + if (parentFolder.isFile()) { + mCallback.onFileSelection(parentFolder); + dismiss(); + } else { + parentContents = listFiles(getBuilder().mMimeType); + MaterialDialog dialog = (MaterialDialog) getDialog(); + dialog.setTitle(parentFolder.getAbsolutePath()); + getArguments().putString("current_path", parentFolder.getAbsolutePath()); + dialog.setItems(getContentsArray()); + } + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + mCallback = (FileCallback) activity; + } + + public void show(AppCompatActivity context) { + Fragment frag = context.getSupportFragmentManager().findFragmentByTag(TAG); + if (frag != null) { + ((DialogFragment) frag).dismiss(); + context.getSupportFragmentManager().beginTransaction() + .remove(frag).commit(); + } + show(context.getSupportFragmentManager(), TAG); + } + + public static class Builder implements Serializable { + + @NonNull + protected final transient AppCompatActivity mContext; + @StringRes + protected int mCancelButton; + protected String mInitialPath; + protected String mMimeType; + + public <ActivityType extends AppCompatActivity & FileCallback> Builder(@NonNull ActivityType context) { + mContext = context; + mCancelButton = android.R.string.cancel; + mInitialPath = Environment.getExternalStorageDirectory().getAbsolutePath(); + mMimeType = null; + } + + @NonNull + public Builder cancelButton(@StringRes int text) { + mCancelButton = text; + return this; + } + + @NonNull + public Builder initialPath(@Nullable String initialPath) { + if (initialPath == null) + initialPath = File.separator; + mInitialPath = initialPath; + return this; + } + + @NonNull + public Builder mimeType(@Nullable String type) { + mMimeType = type; + return this; + } + + @NonNull + public FileChooserDialog build() { + FileChooserDialog dialog = new FileChooserDialog(); + Bundle args = new Bundle(); + args.putSerializable("builder", this); + dialog.setArguments(args); + return dialog; + } + + @NonNull + public FileChooserDialog show() { + FileChooserDialog dialog = build(); + dialog.show(mContext); + return dialog; + } + } + + @SuppressWarnings("ConstantConditions") + @NonNull + private Builder getBuilder() { + return (Builder) getArguments().getSerializable("builder"); + } + + private static class FileSorter implements Comparator<File> { + @Override + public int compare(File lhs, File rhs) { + return lhs.getName().compareTo(rhs.getName()); + } + } +}
\ No newline at end of file |