Bladeren bron

Moved FolderSelectorDialog to commons and updated it a bit. Updated the sample for M storage access permissions.

Aidan Follestad 10 jaren geleden
bovenliggende
commit
46b3178feb

+ 40 - 10
README.md

@@ -2,7 +2,7 @@
 
 ![Screenshots](https://raw.githubusercontent.com/afollestad/material-dialogs/master/art/mdshowcase.png)
 
-# Table of Contents
+# Table of Contents (Core)
 
 1. [Sample Project](https://github.com/afollestad/material-dialogs#sample-project)
 2. [Gradle Dependency](https://github.com/afollestad/material-dialogs#gradle-dependency)
@@ -45,12 +45,20 @@
     4. [Coloring the Progress Bar](https://github.com/afollestad/material-dialogs#coloring-the-progress-bar)
     5. [Custom Number and Progress Formats](https://github.com/afollestad/material-dialogs#custom-number-and-progress-formats)
 22. [Color Chooser Dialog](https://github.com/afollestad/material-dialogs#color-chooser-dialog)
-23. [Preference Dialogs](https://github.com/afollestad/material-dialogs#preference-dialogs)
 24. [Tint Helper](https://github.com/afollestad/material-dialogs#tint-helper)
 25. [Misc](https://github.com/afollestad/material-dialogs#misc)
 
 ------
 
+# Table of Contents (Commons)
+
+1. [Color Chooser Dialogs](https://github.com/afollestad/material-dialogs#color-chooser-dialogs)
+2. [Folder Selector Dialogs](https://github.com/afollestad/material-dialogs#folder-selector-dialogs)
+3. [Preference Dialogs](https://github.com/afollestad/material-dialogs#preference-dialogs)
+4. [Simple List Dialogs](https://github.com/afollestad/material-dialogs#simple-list-dialogs) 
+
+------
+
 # Sample Project
 
 You can download the latest sample APK from this repo here: https://github.com/afollestad/material-dialogs/blob/master/sample/sample.apk
@@ -1023,14 +1031,6 @@ public void onColorSelection(@NonNull ColorChooserDialog dialog, @ColorInt int c
 
 See the sample project for more info.
 
----
-
-# Preference Dialogs
-
-Android's `EditTextPreference`, `ListPreference`, and `MultiSelectListPreference` allow you to associate a preference activity's settings
-with user input that's received through typing or selection. Material Dialogs includes `MaterialEditTextPreference`,
-`MaterialListPreference`, and `MaterialMultiSelectListPreference` classes that can be used in your preferences XML to automatically use Material-themed
-dialogs. See the sample project for details.
 
 ---
 
@@ -1053,3 +1053,33 @@ MaterialDialog dialog = new MaterialDialog.Builder(this)
         .autoDismiss(false)
         .show();
 ```
+
+---
+
+# Color Chooser Dialogs
+
+To be filled in.
+
+---
+
+# Preference Dialogs
+
+Android's `EditTextPreference`, `ListPreference`, and `MultiSelectListPreference` allow you to associate a preference activity's settings
+with user input that's received through typing or selection. Material Dialogs includes `MaterialEditTextPreference`,
+`MaterialListPreference`, and `MaterialMultiSelectListPreference` classes that can be used in your preferences XML to automatically use Material-themed
+dialogs. See the sample project for details.
+
+---
+
+# Folder Selector Dialogs
+
+To be filled in.
+
+---
+
+# Simple List Dialogs
+
+
+To be filled in.
+
+---

+ 11 - 2
commons/src/main/java/com/afollestad/materialdialogs/color/ColorChooserDialog.java

@@ -7,6 +7,7 @@ import android.support.annotation.ColorInt;
 import android.support.annotation.NonNull;
 import android.support.annotation.StringRes;
 import android.support.v4.app.DialogFragment;
+import android.support.v4.app.Fragment;
 import android.support.v4.content.res.ResourcesCompat;
 import android.support.v7.app.AppCompatActivity;
 import android.util.DisplayMetrics;
@@ -29,6 +30,8 @@ import java.io.Serializable;
 @SuppressWarnings({"FieldCanBeLocal", "ConstantConditions"})
 public class ColorChooserDialog extends DialogFragment implements View.OnClickListener {
 
+    private final static String TAG = "[MD_COLOR_CHOOSER]";
+
     private int[] mColorsTop;
     private int[][] mColorsSub;
 
@@ -139,7 +142,7 @@ public class ColorChooserDialog extends DialogFragment implements View.OnClickLi
     @NonNull
     @Override
     public Dialog onCreateDialog(Bundle savedInstanceState) {
-        if (getBuilder() == null)
+        if (getArguments() == null || !getArguments().containsKey("builder"))
             throw new IllegalStateException("ColorChooserDialog should be created using its Builder interface.");
         generateColors();
 
@@ -354,7 +357,13 @@ public class ColorChooserDialog extends DialogFragment implements View.OnClickLi
 
     @NonNull
     public ColorChooserDialog show(AppCompatActivity context) {
-        show(context.getSupportFragmentManager(), "[MD_COLOR_CHOOSER]");
+        Fragment frag = context.getSupportFragmentManager().findFragmentByTag(TAG);
+        if (frag != null) {
+            ((DialogFragment) frag).dismiss();
+            context.getSupportFragmentManager().beginTransaction()
+                    .remove(frag).commit();
+        }
+        show(context.getSupportFragmentManager(), TAG);
         return this;
     }
 }

+ 201 - 0
commons/src/main/java/com/afollestad/materialdialogs/folderselector/FolderSelectorDialog.java

@@ -0,0 +1,201 @@
+package com.afollestad.materialdialogs.folderselector;
+
+import android.Manifest;
+import android.app.Activity;
+import android.app.Dialog;
+import android.content.pm.PackageManager;
+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 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;
+
+/**
+ * @author Aidan Follestad (afollestad)
+ */
+public class FolderSelectorDialog extends DialogFragment implements MaterialDialog.ListCallback {
+
+    private final static String TAG = "[MD_FOLDER_SELECTOR]";
+
+    private File parentFolder;
+    private File[] parentContents;
+    private boolean canGoUp = true;
+    private FolderCallback mCallback;
+
+    private final MaterialDialog.ButtonCallback mButtonCallback = new MaterialDialog.ButtonCallback() {
+        @Override
+        public void onPositive(MaterialDialog materialDialog) {
+            materialDialog.dismiss();
+            mCallback.onFolderSelection(parentFolder);
+        }
+
+        @Override
+        public void onNegative(MaterialDialog materialDialog) {
+            materialDialog.dismiss();
+        }
+    };
+
+    public interface FolderCallback {
+        void onFolderSelection(File folder);
+    }
+
+    public FolderSelectorDialog() {
+    }
+
+    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() {
+        File[] contents = parentFolder.listFiles();
+        List<File> results = new ArrayList<>();
+        if (contents != null) {
+            for (File fi : contents) {
+                if (fi.isDirectory()) results.add(fi);
+            }
+            Collections.sort(results, new FolderSorter());
+            return results.toArray(new File[results.size()]);
+        }
+        return null;
+    }
+
+    @SuppressWarnings("ConstantConditions")
+    @NonNull
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        if (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 FolderSelectorDialog using the Builder.");
+        if (!getArguments().containsKey("current_path"))
+            getArguments().putString("current_path", getBuilder().mInitialPath);
+        parentFolder = new File(getArguments().getString("current_path"));
+        parentContents = listFiles();
+        return new MaterialDialog.Builder(getActivity())
+                .title(parentFolder.getAbsolutePath())
+                .items(getContentsArray())
+                .itemsCallback(this)
+                .callback(mButtonCallback)
+                .autoDismiss(false)
+                .positiveText(R.string.md_choose_label)
+                .negativeText(android.R.string.cancel)
+                .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;
+        }
+        parentContents = listFiles();
+        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 = (FolderCallback) 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 mChooseButton;
+        protected String mInitialPath;
+
+        public <ActivityType extends AppCompatActivity & FolderCallback> Builder(@NonNull ActivityType context) {
+            mContext = context;
+            mChooseButton = R.string.md_choose_label;
+            mInitialPath = Environment.getExternalStorageDirectory().getAbsolutePath();
+        }
+
+        @NonNull
+        public Builder chooseButton(@StringRes int text) {
+            mChooseButton = text;
+            return this;
+        }
+
+        @NonNull
+        public Builder initialPath(@Nullable String initialPath) {
+            if (initialPath == null)
+                initialPath = File.separator;
+            mInitialPath = initialPath;
+            return this;
+        }
+
+        @NonNull
+        public FolderSelectorDialog build() {
+            FolderSelectorDialog dialog = new FolderSelectorDialog();
+            Bundle args = new Bundle();
+            args.putSerializable("builder", this);
+            dialog.setArguments(args);
+            return dialog;
+        }
+
+        @NonNull
+        public FolderSelectorDialog show() {
+            FolderSelectorDialog dialog = build();
+            dialog.show(mContext);
+            return dialog;
+        }
+    }
+
+    @SuppressWarnings("ConstantConditions")
+    @NonNull
+    private Builder getBuilder() {
+        return (Builder) getArguments().getSerializable("builder");
+    }
+
+    private static class FolderSorter implements Comparator<File> {
+        @Override
+        public int compare(File lhs, File rhs) {
+            return lhs.getName().compareTo(rhs.getName());
+        }
+    }
+}

+ 9 - 0
commons/src/main/res/values/strings.xml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="md_back_label">Back</string>
+    <string name="md_done_label">Done</string>
+    <string name="md_cancel_label">Cancel</string>
+    <string name="md_choose_label">Choose</string>
+    <string name="md_error_label">Error</string>
+    <string name="md_storage_perm_error">Your app has not been granted the READ_EXTERNAL_STORAGE permission.</string>
+</resources>

+ 0 - 6
core/src/main/res/values/strings.xml

@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string name="md_back_label">Back</string>
-    <string name="md_done_label">Done</string>
-    <string name="md_cancel_label">Cancel</string>
-</resources>

+ 0 - 115
sample/src/main/java/com/afollestad/materialdialogssample/FolderSelectorDialog.java

@@ -1,115 +0,0 @@
-package com.afollestad.materialdialogssample;
-
-import android.app.Activity;
-import android.app.Dialog;
-import android.os.Bundle;
-import android.os.Environment;
-import android.support.annotation.NonNull;
-import android.support.v4.app.DialogFragment;
-import android.support.v7.app.AppCompatActivity;
-import android.view.View;
-
-import com.afollestad.materialdialogs.MaterialDialog;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-
-/**
- * @author Aidan Follestad (afollestad)
- */
-public class FolderSelectorDialog extends DialogFragment implements MaterialDialog.ListCallback {
-
-    private File parentFolder;
-    private File[] parentContents;
-    private boolean canGoUp = true;
-    private FolderSelectCallback mCallback;
-
-    private final MaterialDialog.ButtonCallback mButtonCallback = new MaterialDialog.ButtonCallback() {
-        @Override
-        public void onPositive(MaterialDialog materialDialog) {
-            materialDialog.dismiss();
-            mCallback.onFolderSelection(parentFolder);
-        }
-
-        @Override
-        public void onNegative(MaterialDialog materialDialog) {
-            materialDialog.dismiss();
-        }
-    };
-
-    public interface FolderSelectCallback {
-        void onFolderSelection(File folder);
-    }
-
-    public FolderSelectorDialog() {
-        parentFolder = Environment.getExternalStorageDirectory();
-        parentContents = listFiles();
-    }
-
-    String[] getContentsArray() {
-        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() {
-        File[] contents = parentFolder.listFiles();
-        List<File> results = new ArrayList<>();
-        for (File fi : contents) {
-            if (fi.isDirectory()) results.add(fi);
-        }
-        Collections.sort(results, new FolderSorter());
-        return results.toArray(new File[results.size()]);
-    }
-
-    @NonNull
-    @Override
-    public Dialog onCreateDialog(Bundle savedInstanceState) {
-        return new MaterialDialog.Builder(getActivity())
-                .title(parentFolder.getAbsolutePath())
-                .items(getContentsArray())
-                .itemsCallback(this)
-                .callback(mButtonCallback)
-                .autoDismiss(false)
-                .positiveText(R.string.choose)
-                .negativeText(android.R.string.cancel)
-                .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;
-        }
-        parentContents = listFiles();
-        MaterialDialog dialog = (MaterialDialog) getDialog();
-        dialog.setTitle(parentFolder.getAbsolutePath());
-        dialog.setItems(getContentsArray());
-    }
-
-    @Override
-    public void onAttach(Activity activity) {
-        super.onAttach(activity);
-        mCallback = (FolderSelectCallback) activity;
-    }
-
-    public void show(AppCompatActivity context) {
-        show(context.getSupportFragmentManager(), "FOLDER_SELECTOR");
-    }
-
-    private static class FolderSorter implements Comparator<File> {
-        @Override
-        public int compare(File lhs, File rhs) {
-            return lhs.getName().compareTo(rhs.getName());
-        }
-    }
-}

+ 32 - 4
sample/src/main/java/com/afollestad/materialdialogssample/MainActivity.java

@@ -1,14 +1,18 @@
 package com.afollestad.materialdialogssample;
 
+import android.Manifest;
 import android.content.DialogInterface;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.graphics.Color;
 import android.graphics.drawable.ColorDrawable;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.Handler;
 import android.support.annotation.ColorInt;
 import android.support.annotation.NonNull;
 import android.support.annotation.StringRes;
+import android.support.v4.app.ActivityCompat;
 import android.support.v4.content.ContextCompat;
 import android.support.v7.app.AppCompatActivity;
 import android.text.Editable;
@@ -30,6 +34,7 @@ import com.afollestad.materialdialogs.MaterialDialog;
 import com.afollestad.materialdialogs.Theme;
 import com.afollestad.materialdialogs.color.CircleView;
 import com.afollestad.materialdialogs.color.ColorChooserDialog;
+import com.afollestad.materialdialogs.folderselector.FolderSelectorDialog;
 import com.afollestad.materialdialogs.internal.MDTintHelper;
 import com.afollestad.materialdialogs.internal.ThemeSingleton;
 import com.afollestad.materialdialogs.simplelist.MaterialSimpleListAdapter;
@@ -42,10 +47,11 @@ import java.io.File;
  * @author Aidan Follestad (afollestad)
  */
 public class MainActivity extends AppCompatActivity implements
-        FolderSelectorDialog.FolderSelectCallback, ColorChooserDialog.ColorCallback {
+        FolderSelectorDialog.FolderCallback, ColorChooserDialog.ColorCallback {
 
     private Toast mToast;
     private Thread mThread;
+    private final static int STORAGE_PERMISSION_RC = 69;
 
     private void showToast(String message) {
         if (mToast != null) {
@@ -222,7 +228,12 @@ public class MainActivity extends AppCompatActivity implements
         findViewById(R.id.folder_chooser).setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
-                new FolderSelectorDialog().show(MainActivity.this);
+                if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) !=
+                        PackageManager.PERMISSION_GRANTED) {
+                    ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, STORAGE_PERMISSION_RC);
+                    return;
+                }
+                new FolderSelectorDialog.Builder(MainActivity.this).show();
             }
         });
 
@@ -413,7 +424,7 @@ public class MainActivity extends AppCompatActivity implements
                         return true; // allow selection
                     }
                 })
-                .positiveText(R.string.choose)
+                .positiveText(R.string.md_choose_label)
                 .show();
     }
 
@@ -442,7 +453,7 @@ public class MainActivity extends AppCompatActivity implements
                     }
                 })
                 .alwaysCallMultiChoiceCallback()
-                .positiveText(R.string.choose)
+                .positiveText(R.string.md_choose_label)
                 .autoDismiss(false)
                 .neutralText(R.string.clear_selection)
                 .show();
@@ -771,6 +782,23 @@ public class MainActivity extends AppCompatActivity implements
         return super.onOptionsItemSelected(item);
     }
 
+    @Override
+    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+        if (requestCode == STORAGE_PERMISSION_RC) {
+            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+                new Handler().postDelayed(new Runnable() {
+                    @Override
+                    public void run() {
+                        findViewById(R.id.folder_chooser).performClick();
+                    }
+                }, 1000);
+            } else {
+                Toast.makeText(this, "The folder chooser will not work without permission to read external storage.", Toast.LENGTH_LONG).show();
+            }
+        }
+    }
+
     @Override
     public void onFolderSelection(File folder) {
         showToast(folder.getAbsolutePath());