1
0
Эх сурвалжийг харах

Merge pull request #149 from hzsweers/master

Miscellaneous updates
Aidan Follestad 10 жил өмнө
parent
commit
e760ee7dff

+ 79 - 0
CHANGELOG.md

@@ -0,0 +1,79 @@
+Changelog
+=========
+
+###### Version 0.5.0
+
+> 1. The ability to choose whether or not custom views are placed inside of a `ScrollView` (the second parameter of `customView()` in the `Builder`). This is heavily based off a pull request by [Kevin Barry](https://github.com/teslacoil), thanks for your help! See the [Custom Views](https://github.com/afollestad/material-dialogs#custom-views) section for more details, see the sample project for an example in action.
+> 2. An enormous amount of fixes for padding and spacing throughout the different types of dialogs. A top divider is also used when there's scrollable content.
+> 3. Other bug fixes and improvements throughout.
+
+###### Version 0.4.8 – 0.4.9
+
+> 1. Improvements for padding in list dialogs.
+> 2. Fixed the `forceStacking` option.
+> 3. Single choice dialogs will wait to send selection callbacks until positive action button is pressed, if the positive action button is set.
+> 4. Pull request from [hzsweers](https://github.com/hzsweers): https://github.com/afollestad/material-dialogs/pull/146
+> 5. List items use pure black or white text depending on theme by default, rather than the former gray-ish color.
+
+###### Version 0.4.6 – 0.4.7
+
+> 1. Yet more fixes thanks to a pull request from [hzsweers](https://github.com/hzsweers).
+> 2. Note that the 3 variations of the action callbacks are deprecated and replaced with the single `ButtonCallback` interface.
+> 3. A fix for action button text styling on Lollipop, thanks [plusCubed](https://github.com/plusCubed)!
+> 4. Other fixes and improvements.
+> 5. The ability to force the action buttons to be stacked (see the [Misc.](#misc) section).
+
+###### Version 0.4.4 – 0.4.5
+
+> 1. Crash fix for Huawei devices
+> 2. Removed some unnecessary logging.
+> 3. New methods in `MaterialDialogCompat.Builder`
+> 4. Other crash fixes and improvements.
+> 5. Memory management improvements for Typefaces (thanks [Kevin Barry](https://github.com/teslacoil) of Nova Launcher!)
+> 6. Added `dismiss`, `cancel`, and `show` listener methods to the `Builder`.
+
+###### Version 0.4.1 – 0.4.3
+
+> 1. Added `md_item_color` attribute to global theming.
+> 2. Added `md_icon` attribute to global theming.
+> 3. Fixed a crash bug on pre-Lollipop devices related to list dialogs.
+> 4. Fixed list item default color on dark dialogs for pre-Lollipop.
+> 5. Fixes to action button insets, and the stacking algorithm. Thanks [plusCubed](https://github.com/plusCubed)!
+> 6. Major padding/margin fixes for using an icon with list dialogs.
+
+###### Version 0.4.0
+
+> 1. Bug fixes and improvements throughout
+> 2. Action button selectors have rounded corners
+> 3. Global theming capabilities. Override the accent color used for action buttons, titles, and content from your Activity theme. See the [Global Theming](#global-theming) section below.
+
+###### Version 0.3.5 – 0.3.6
+
+> 1. Bug fixes.
+> 2. Button stacking algorithm fixes.
+
+###### Version 0.3.3 – 0.3.4
+
+> 1. Crash fix when updating list items after they had previously been set.
+> 2. The ability to set the content color when constructing a dialog builder.
+
+###### Version 0.3.2
+
+> 1. Large performance improvements for list dialogs, thanks [hzsweers](https://github.com/hzsweers)! The item processor API was switched with custom list adapters, see the sample for an example.
+> 2. Other padding and logic fixes.
+
+###### Version 0.3.1
+
+> 1. Global theming! A single attribute can be added to your Activity theme to make all dialogs dark. See the [Global Theming](#global-theming) section below.
+
+###### Version 0.3.0
+
+> 1. `MaterialDialogCompat` allows easy migration from use of `AlertDialog` (see below).
+> 2. Convenience `show()` method in Builder, to skip call to `build()`.
+> 3. Various important fixes from pull requests and the maintainer.
+
+###### Version 0.2.0
+
+> 1. Action buttons must be explicitly shown by setting text to them. The buttons will be hidden in any dialog type if no text is passed for them. This also allows you to display neutral or negative action buttons individually without relying on positive text.
+> 2. List dialogs now use CharSequence arrays rather than String arrays.
+> 3. Other bug fixes are included.

+ 3 - 1
README.md

@@ -6,6 +6,8 @@ The code you see below is also found in the sample project. You can download a A
 
 ### What's New
 
+For the full history, see the [Changelog](https://github.com/afollestad/material-dialogs/blob/master/CHANGELOG.md)
+
 ###### Version 0.5.0
 
 > 1. The ability to choose whether or not custom views are placed inside of a `ScrollView` (the second parameter of `customView()` in the `Builder`). This is heavily based off a pull request by [Kevin Barry](https://github.com/teslacoil), thanks for your help! See the [Custom Views](https://github.com/afollestad/material-dialogs#custom-views) section for more details, see the sample project for an example in action.
@@ -362,7 +364,7 @@ new MaterialDialog.Builder(this)
         .positiveColor(materialRed500)
         .negativeColor(materialRed500)
         .neutralColor(materialRed500)
-        .titleAlignment(Alignment.CENTER)
+        .titleGravity(Gravity.CENTER_HORIZONTAL)
         .titleColor(materialRed500)
         .contentColor(Color.WHITE)
         .theme(Theme.DARK)

+ 0 - 16
library/src/main/java/com/afollestad/materialdialogs/Alignment.java

@@ -1,16 +0,0 @@
-package com.afollestad.materialdialogs;
-
-/**
- * @author Aidan Follestad (afollestad)
- */
-public enum Alignment {
-    /**
-     * Same as left for left-to-right layouts.
-     */
-    START,
-    CENTER,
-    /**
-     * Same as right for left-to-right layouts.
-     */
-    END
-}

+ 65 - 16
library/src/main/java/com/afollestad/materialdialogs/MaterialDialog.java

@@ -1,6 +1,7 @@
 package com.afollestad.materialdialogs;
 
 import android.annotation.SuppressLint;
+import android.annotation.TargetApi;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.res.ColorStateList;
@@ -11,8 +12,10 @@ import android.graphics.Typeface;
 import android.graphics.drawable.Drawable;
 import android.os.Build;
 import android.support.annotation.ArrayRes;
+import android.support.annotation.AttrRes;
 import android.support.annotation.ColorRes;
 import android.support.annotation.DrawableRes;
+import android.support.annotation.IntDef;
 import android.support.annotation.LayoutRes;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
@@ -50,6 +53,9 @@ import java.util.List;
  */
 public class MaterialDialog extends DialogBase implements View.OnClickListener {
 
+    @IntDef({Gravity.START, Gravity.CENTER_HORIZONTAL, Gravity.END})
+    public @interface GravityInt {}
+
     protected View view;
     protected ListView listView;
     protected ImageView icon;
@@ -62,6 +68,7 @@ public class MaterialDialog extends DialogBase implements View.OnClickListener {
     protected Button neutralButton;
     protected Button negativeButton;
     protected boolean isStacked;
+    protected boolean alwaysCallMultiChoiceCallback;
     protected final int defaultItemColor;
     protected ListType listType;
     protected List<Integer> selectedIndicesList;
@@ -113,10 +120,12 @@ public class MaterialDialog extends DialogBase implements View.OnClickListener {
         } else {
             content.setLinkTextColor(mBuilder.positiveColor);
         }
-        if (builder.contentAlignment == Alignment.CENTER) {
-            content.setGravity(Gravity.CENTER_HORIZONTAL);
-        } else if (builder.contentAlignment == Alignment.END) {
-            content.setGravity(Gravity.START);
+
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+            //noinspection ResourceType
+            title.setTextAlignment(gravityToAlignment(builder.titleGravity));
+        } else {
+            title.setGravity(builder.titleGravity);
         }
 
         if (builder.contentColor != -1) {
@@ -190,6 +199,7 @@ public class MaterialDialog extends DialogBase implements View.OnClickListener {
                     } else {
                         selectedIndicesList = new ArrayList<>();
                     }
+                    alwaysCallMultiChoiceCallback = builder.alwaysCallMultiChoiceCallback;
                 } else {
                     listType = ListType.REGULAR;
                 }
@@ -222,10 +232,12 @@ public class MaterialDialog extends DialogBase implements View.OnClickListener {
                 final int fallback = DialogUtils.resolveColor(getContext(), android.R.attr.textColorPrimary);
                 title.setTextColor(DialogUtils.resolveColor(getContext(), R.attr.md_title_color, fallback));
             }
-            if (builder.titleAlignment == Alignment.CENTER) {
-                title.setGravity(Gravity.CENTER_HORIZONTAL);
-            } else if (builder.titleAlignment == Alignment.END) {
-                title.setGravity(Gravity.END);
+
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+                //noinspection ResourceType
+                content.setTextAlignment(gravityToAlignment(builder.contentGravity));
+            } else {
+                content.setGravity(builder.contentGravity);
             }
         }
 
@@ -238,6 +250,9 @@ public class MaterialDialog extends DialogBase implements View.OnClickListener {
         if (builder.dismissListener != null) {
             setOnDismissListener(builder.dismissListener);
         }
+        if (builder.keyListener != null) {
+            setOnKeyListener(builder.keyListener);
+        }
 
         updateFramePadding();
         invalidateActions();
@@ -261,6 +276,20 @@ public class MaterialDialog extends DialogBase implements View.OnClickListener {
         }
     }
 
+    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
+    private static int gravityToAlignment(@GravityInt int gravity) {
+        switch (gravity) {
+            case Gravity.START:
+                return View.TEXT_ALIGNMENT_VIEW_START;
+            case Gravity.CENTER_HORIZONTAL:
+                return View.TEXT_ALIGNMENT_CENTER;
+            case Gravity.END:
+                return View.TEXT_ALIGNMENT_VIEW_END;
+            default:
+                return View.TEXT_ALIGNMENT_VIEW_START;
+        }
+    }
+
     @Override
     public void onShow(DialogInterface dialog) {
         super.onShow(dialog); // calls any external show listeners
@@ -701,6 +730,9 @@ public class MaterialDialog extends DialogBase implements View.OnClickListener {
                 } else if (mBuilder.listCallbackMulti != null) {
                     CheckBox cb = (CheckBox) ((LinearLayout) v).getChildAt(0);
                     cb.setChecked(!cb.isChecked());
+                    if (alwaysCallMultiChoiceCallback) {
+                        sendMultichoiceCallback();
+                    }
                 } else if (mBuilder.autoDismiss) dismiss();
                 break;
             }
@@ -714,8 +746,8 @@ public class MaterialDialog extends DialogBase implements View.OnClickListener {
 
         protected Context context;
         protected CharSequence title;
-        protected Alignment titleAlignment = Alignment.START;
-        protected Alignment contentAlignment = Alignment.START;
+        protected @GravityInt int titleGravity = Gravity.START;
+        protected @GravityInt int contentGravity = Gravity.START;
         protected int titleColor = -1;
         protected int contentColor = -1;
         protected CharSequence content;
@@ -731,6 +763,7 @@ public class MaterialDialog extends DialogBase implements View.OnClickListener {
         protected ListCallback listCallback;
         protected ListCallback listCallbackSingle;
         protected ListCallbackMulti listCallbackMulti;
+        protected boolean alwaysCallMultiChoiceCallback = false;
         protected Theme theme = Theme.LIGHT;
         protected boolean cancelable = true;
         protected float contentLineSpacingMultiplier = 1.3f;
@@ -743,6 +776,7 @@ public class MaterialDialog extends DialogBase implements View.OnClickListener {
         protected ListAdapter adapter;
         protected OnDismissListener dismissListener;
         protected OnCancelListener cancelListener;
+        protected OnKeyListener keyListener;
         protected OnShowListener showListener;
         protected boolean forceStacking;
         protected boolean wrapCustomViewInScroll;
@@ -789,8 +823,8 @@ public class MaterialDialog extends DialogBase implements View.OnClickListener {
             return this;
         }
 
-        public Builder titleAlignment(Alignment align) {
-            this.titleAlignment = align;
+        public Builder titleGravity(@GravityInt int gravity) {
+            this.titleGravity = gravity;
             return this;
         }
 
@@ -827,7 +861,7 @@ public class MaterialDialog extends DialogBase implements View.OnClickListener {
             return this;
         }
 
-        public Builder iconAttr(int iconAttr) {
+        public Builder iconAttr(@AttrRes int iconAttr) {
             this.icon = DialogUtils.resolveDrawable(context, iconAttr);
             return this;
         }
@@ -857,8 +891,8 @@ public class MaterialDialog extends DialogBase implements View.OnClickListener {
             return this;
         }
 
-        public Builder contentAlignment(Alignment align) {
-            this.contentAlignment = align;
+        public Builder contentGravity(@GravityInt int gravity) {
+            this.contentGravity = gravity;
             return this;
         }
 
@@ -868,7 +902,7 @@ public class MaterialDialog extends DialogBase implements View.OnClickListener {
         }
 
         public Builder items(@ArrayRes int itemsRes) {
-            items(this.context.getResources().getStringArray(itemsRes));
+            items(this.context.getResources().getTextArray(itemsRes));
             return this;
         }
 
@@ -916,6 +950,16 @@ public class MaterialDialog extends DialogBase implements View.OnClickListener {
             return this;
         }
 
+        /**
+         * By default, the multi choice callback is only called when the user clicks the positive button
+         * or if there are no buttons. Call this to force it to always call on item clicks even if the
+         * positive button exists.
+         */
+        public Builder alwaysCallMultiChoiceCallback() {
+            this.alwaysCallMultiChoiceCallback = true;
+            return this;
+        }
+
         public Builder positiveText(@StringRes int postiveRes) {
             positiveText(this.context.getString(postiveRes));
             return this;
@@ -1056,6 +1100,11 @@ public class MaterialDialog extends DialogBase implements View.OnClickListener {
             return this;
         }
 
+        public Builder keyListener(OnKeyListener listener) {
+            this.keyListener = listener;
+            return this;
+        }
+
         public Builder forceStacking(boolean stacked) {
             this.forceStacking = stacked;
             return this;

+ 88 - 30
library/src/main/java/com/afollestad/materialdialogs/MaterialDialogCompat.java

@@ -4,11 +4,17 @@ import android.app.AlertDialog;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.graphics.drawable.Drawable;
+import android.support.annotation.ArrayRes;
+import android.support.annotation.AttrRes;
 import android.support.annotation.DrawableRes;
 import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
 import android.support.annotation.StringRes;
 import android.view.View;
+import android.webkit.WebView;
+import android.widget.AdapterView;
 import android.widget.ListAdapter;
+import android.widget.ScrollView;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -98,6 +104,16 @@ public class MaterialDialogCompat {
             return this;
         }
 
+        /**
+         * Set the attribute ID of the {@link android.graphics.drawable.Drawable} to be used in the title (e.g. android.R.attr.dialogicon)
+         *
+         * @return This Builder object to allow for chaining of calls to set methods
+         */
+        public Builder setIconAttribute(@AttrRes int attrId) {
+            builder.iconAttr(attrId);
+            return this;
+        }
+
         /**
          * Set a listener to be invoked when the negative button of the dialog is pressed.
          *
@@ -293,10 +309,25 @@ public class MaterialDialogCompat {
 		 * @return This
 		 */
 		public Builder setView(View view) {
-			builder.customView(view);
+            boolean wrapInScrollView = !(view instanceof ScrollView || view instanceof AdapterView || view instanceof WebView);
+            builder.customView(view, wrapInScrollView);
 			return this;
 		}
 
+        /**
+         * Set a list of items to be displayed in the dialog as the content, you will be notified of the selected item via the supplied listener.
+         *
+         * @param itemsId   A resource ID for the items (e.g. R.array.my_items)
+         * @param checkedItems	specifies which items are checked. It should be null in which case no items are checked. If non null it must be exactly the same length as the array of items.
+         * @param listener	notified when an item on the list is clicked. The dialog will not be dismissed when an item is clicked. It will only be dismissed if clicked on a button, if no buttons are supplied it's up to the user to dismiss the dialog.		 * @return
+         * @return This
+         */
+        public Builder setMultiChoiceItems(@ArrayRes int itemsId, @Nullable final boolean[] checkedItems, final DialogInterface.OnMultiChoiceClickListener listener) {
+            builder.items(itemsId);
+            setUpMultiChoiceCallback(checkedItems, listener);
+            return this;
+        }
+
 		/**
 		 * Set a list of items to be displayed in the dialog as the content, you will be notified of the selected item via the supplied listener.
 		 *
@@ -305,37 +336,45 @@ public class MaterialDialogCompat {
 		 * @param listener	notified when an item on the list is clicked. The dialog will not be dismissed when an item is clicked. It will only be dismissed if clicked on a button, if no buttons are supplied it's up to the user to dismiss the dialog.		 * @return
 		 * @return This
 		 */
-		public Builder setMultiChoiceItems(String[] items, final boolean[] checkedItems, final DialogInterface.OnMultiChoiceClickListener listener) {
+		public Builder setMultiChoiceItems(String[] items, @Nullable final boolean[] checkedItems, final DialogInterface.OnMultiChoiceClickListener listener) {
 			builder.items(items);
+            setUpMultiChoiceCallback(checkedItems, listener);
+			return this;
+		}
 
+        private void setUpMultiChoiceCallback(@Nullable final boolean[] checkedItems, final DialogInterface.OnMultiChoiceClickListener listener) {
+            Integer selectedIndicesArr[] = null;
 			/* Convert old style array of booleans-per-index to new list of indices */
-			ArrayList<Integer> selectedIndices = new ArrayList<>();
-			for(int i = 0; i < checkedItems.length; i++) {
-				if(checkedItems[i]) {
-					selectedIndices.add(i);
-				}
-			}
-			Integer selectedIndicesArr[] = new Integer[selectedIndices.size()];
-			selectedIndices.toArray(selectedIndicesArr);
-			builder.itemsCallbackMultiChoice(selectedIndicesArr, new MaterialDialog.ListCallbackMulti() {
-				@Override
-				public void onSelection(MaterialDialog dialog, Integer[] which, CharSequence[] text) {
+            if (checkedItems != null) {
+                ArrayList<Integer> selectedIndices = new ArrayList<>();
+                for (int i = 0; i < checkedItems.length; i++) {
+                    if (checkedItems[i]) {
+                        selectedIndices.add(i);
+                    }
+                }
+                selectedIndicesArr = selectedIndices.toArray(new Integer[selectedIndices.size()]);
+            }
+
+            builder.itemsCallbackMultiChoice(selectedIndicesArr, new MaterialDialog.ListCallbackMulti() {
+                @Override
+                public void onSelection(MaterialDialog dialog, Integer[] which, CharSequence[] text) {
 					/* which is a list of selected indices */
-					List<Integer> whichList = Arrays.asList(which);
-					for(int i = 0; i < checkedItems.length; i++) {
-						/* save old state */
-						boolean oldChecked = checkedItems[i];
-						/* Record new state */
-						checkedItems[i] = whichList.contains(i);
-						/* Fire the listener if it changed */
-						if(oldChecked != checkedItems[i]) {
-							listener.onClick(dialog, i, checkedItems[i]);
-						}
-					}
-				}
-			});
-			return this;
-		}
+                    List<Integer> whichList = Arrays.asList(which);
+                    if (checkedItems != null) {
+                        for(int i = 0; i < checkedItems.length; i++) {
+                            /* save old state */
+                            boolean oldChecked = checkedItems[i];
+                            /* Record new state */
+                            checkedItems[i] = whichList.contains(i);
+                            /* Fire the listener if it changed */
+                            if(oldChecked != checkedItems[i]) {
+                                listener.onClick(dialog, i, checkedItems[i]);
+                            }
+                        }
+                    }
+                }
+            });
+        }
 
 		/**
 		 * Set a list of items to be displayed in the dialog as the content, you will be notified of the selected item via the supplied listener.
@@ -364,9 +403,8 @@ public class MaterialDialogCompat {
 		 * @param listener	notified when an item on the list is clicked. The dialog will not be dismissed when an item is clicked. It will only be dismissed if clicked on a button, if no buttons are supplied it's up to the user to dismiss the dialog.
 		 * @return This
 		 */
-		public Builder setSingleChoiceItems(int itemsId, int checkedItem, final DialogInterface.OnClickListener listener) {
+		public Builder setSingleChoiceItems(@ArrayRes int itemsId, int checkedItem, final DialogInterface.OnClickListener listener) {
 			builder.items(itemsId);
-
 			builder.itemsCallbackSingleChoice(checkedItem, new MaterialDialog.ListCallback() {
 				@Override
 				public void onSelection(MaterialDialog dialog, View itemView, int which, CharSequence text) {
@@ -375,5 +413,25 @@ public class MaterialDialogCompat {
 			});
 			return this;
 		}
+
+        public Builder setOnCancelListener(DialogInterface.OnCancelListener listener) {
+            builder.cancelListener(listener);
+            return this;
+        }
+
+        public Builder setOnDismissListener(DialogInterface.OnDismissListener listener) {
+            builder.dismissListener(listener);
+            return this;
+        }
+
+        public Builder setOnShowListener(DialogInterface.OnShowListener listener) {
+            builder.showListener(listener);
+            return this;
+        }
+
+        public Builder setOnKeyListener(DialogInterface.OnKeyListener listener) {
+            builder.keyListener(listener);
+            return this;
+        }
 	}
 }

+ 1 - 0
sample/src/main/AndroidManifest.xml

@@ -7,6 +7,7 @@
         android:allowBackup="true"
         android:label="@string/app_name"
         android:icon="@drawable/ic_launcher"
+        android:supportsRtl="true"
         android:theme="@style/AppTheme">
 
         <activity

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

@@ -8,6 +8,7 @@ import android.text.Html;
 import android.text.InputType;
 import android.text.TextWatcher;
 import android.text.method.PasswordTransformationMethod;
+import android.view.Gravity;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
@@ -19,7 +20,6 @@ import android.widget.EditText;
 import android.widget.ListView;
 import android.widget.Toast;
 
-import com.afollestad.materialdialogs.Alignment;
 import com.afollestad.materialdialogs.DialogAction;
 import com.afollestad.materialdialogs.MaterialDialog;
 import com.afollestad.materialdialogs.Theme;
@@ -409,7 +409,7 @@ public class MainActivity extends ActionBarActivity implements FolderSelectorDia
                 .negativeText(R.string.disagree)
                 .positiveColorRes(R.color.material_red_400)
                 .negativeColorRes(R.color.material_red_400)
-                .titleAlignment(Alignment.CENTER)
+                .titleGravity(Gravity.CENTER_HORIZONTAL)
                 .titleColorRes(R.color.material_red_400)
                 .contentColorRes(android.R.color.white)
                 .theme(Theme.DARK)