Browse Source

0.8.6.2, resolved #1116, resolved #1119, resolved #1112

Aidan Follestad 8 years ago
parent
commit
769e613a8e

+ 14 - 4
README.md

@@ -19,7 +19,8 @@
 5. [Dismissing Dialogs](https://github.com/afollestad/material-dialogs#dismissing-dialogs)
 5. [Migration from AlertDialogs](https://github.com/afollestad/material-dialogs#migration-from-alertdialogs)
 6. [Displaying an Icon](https://github.com/afollestad/material-dialogs#displaying-an-icon)
-7. [Stacked Action Buttons](https://github.com/afollestad/material-dialogs#stacked-action-buttons)
+7. [Stacked Action Buttons](https://github.com/afollestad/material-dialogs#s1tacked-action-buttons)
+    1. [Stacking Behavior](https://github.com/afollestad/material-dialogs#stacking-behavior)
 8. [Neutral Action Button](https://github.com/afollestad/material-dialogs#neutral-action-button)
 9. [Callbacks](https://github.com/afollestad/material-dialogs#callbacks)
 10. [List Dialogs](https://github.com/afollestad/material-dialogs#list-dialogs)
@@ -98,7 +99,7 @@ You can create basic, list, single/multi choice, progress, input, etc. dialogs w
 ```gradle
 dependencies {
 	// ... other dependencies here
-    compile 'com.afollestad.material-dialogs:core:0.8.6.1'
+    compile 'com.afollestad.material-dialogs:core:0.8.6.2'
 }
 ```
 
@@ -110,7 +111,7 @@ The *commons* module contains extensions to the library that not everyone may ne
 ```gradle
 dependencies {
     // ... other dependencies here
-    compile 'com.afollestad.material-dialogs:commons:0.8.6.1'
+    compile 'com.afollestad.material-dialogs:commons:0.8.6.2'
 }
 ```
 
@@ -250,7 +251,16 @@ new MaterialDialog.Builder(this)
         .show();
 ```
 
-You can also force the dialog to stack its buttons with the `forceStacking()` method of the `Builder`.
+### Stacking Behavior
+
+You can set stacking behavior from the `Builder`:
+
+```java
+new MaterialDialog.Builder(this)
+    ...
+    .stackingBehavior(StackingBehavior.ADAPTIVE)  // the default value
+    .show();
+```
 
 ---
 

+ 3 - 3
commons/build.gradle

@@ -3,8 +3,8 @@ apply plugin: 'com.android.library'
 ext {
     PUBLISH_GROUP_ID = 'com.afollestad.material-dialogs'
     PUBLISH_ARTIFACT_ID = 'commons'
-    PUBLISH_VERSION = '0.8.6.1'
-    SUPPORT_LIBRARY_VERSION = '24.0.0'
+    PUBLISH_VERSION = '0.8.6.2'
+    SUPPORT_LIBRARY_VERSION = '24.1.0'
     BUILD_TOOLS = "24.0.0"
     TARGET_SDK = 24
 }
@@ -26,7 +26,7 @@ android {
 }
 
 dependencies {
-    compile "com.android.support:appcompat-v7:${SUPPORT_LIBRARY_VERSION}"
+    compile "com.android.support:appcompat-v7:$SUPPORT_LIBRARY_VERSION"
 //    compile "com.afollestad.material-dialogs:core:${PUBLISH_VERSION}"
     compile project(':core')
 }

+ 7 - 7
core/build.gradle

@@ -3,8 +3,8 @@ apply plugin: 'com.android.library'
 ext {
     PUBLISH_GROUP_ID = 'com.afollestad.material-dialogs'
     PUBLISH_ARTIFACT_ID = 'core'
-    PUBLISH_VERSION = '0.8.6.1'
-    SUPPORT_LIBRARY_VERSION = '24.0.0'
+    PUBLISH_VERSION = '0.8.6.2'
+    SUPPORT_LIBRARY_VERSION = '24.1.0'
     BUILD_TOOLS = "24.0.0"
     TARGET_SDK = 24
 }
@@ -27,11 +27,11 @@ android {
 }
 
 dependencies {
-    compile "com.android.support:support-v4:${SUPPORT_LIBRARY_VERSION}"
-    compile "com.android.support:appcompat-v7:${SUPPORT_LIBRARY_VERSION}"
-    compile "com.android.support:recyclerview-v7:${SUPPORT_LIBRARY_VERSION}"
-    compile "com.android.support:support-annotations:${SUPPORT_LIBRARY_VERSION}"
-    compile "me.zhanghai.android.materialprogressbar:library:1.1.6"
+    compile "com.android.support:support-v4:$SUPPORT_LIBRARY_VERSION"
+    compile "com.android.support:appcompat-v7:$SUPPORT_LIBRARY_VERSION"
+    compile "com.android.support:recyclerview-v7:$SUPPORT_LIBRARY_VERSION"
+    compile "com.android.support:support-annotations:$SUPPORT_LIBRARY_VERSION"
+    compile "me.zhanghai.android.materialprogressbar:library:1.1.7"
 }
 
 apply from: 'https://raw.githubusercontent.com/afollestad/aidanfollestad.com/master/android-lib-release.gradle'

+ 5 - 0
core/src/main/java/com/afollestad/materialdialogs/DefaultAdapter.java

@@ -17,6 +17,7 @@ import android.widget.RadioButton;
 import android.widget.TextView;
 
 import com.afollestad.materialdialogs.internal.MDTintHelper;
+import com.afollestad.materialdialogs.util.DialogUtils;
 
 class DefaultAdapter extends BaseAdapter {
 
@@ -57,6 +58,7 @@ class DefaultAdapter extends BaseAdapter {
     public View getView(final int index, View view, ViewGroup parent) {
         if (view == null)
             view = LayoutInflater.from(dialog.getContext()).inflate(layout, parent, false);
+        boolean disabled = DialogUtils.isIn(index, dialog.mBuilder.disabledIndices);
 
         TextView tv = (TextView) view.findViewById(R.id.title);
         switch (dialog.listType) {
@@ -66,6 +68,7 @@ class DefaultAdapter extends BaseAdapter {
                 boolean selected = dialog.mBuilder.selectedIndex == index;
                 MDTintHelper.setTint(radio, dialog.mBuilder.widgetColor);
                 radio.setChecked(selected);
+                radio.setEnabled(!disabled);
                 break;
             }
             case MULTI: {
@@ -74,9 +77,11 @@ class DefaultAdapter extends BaseAdapter {
                 boolean selected = dialog.selectedIndicesList.contains(index);
                 MDTintHelper.setTint(checkbox, dialog.mBuilder.widgetColor);
                 checkbox.setChecked(selected);
+                checkbox.setEnabled(!disabled);
                 break;
             }
         }
+
         tv.setText(dialog.mBuilder.items[index]);
         tv.setTextColor(dialog.mBuilder.itemColor);
         dialog.setTypeface(tv, dialog.mBuilder.regularFont);

+ 17 - 2
core/src/main/java/com/afollestad/materialdialogs/DialogInit.java

@@ -222,7 +222,7 @@ class DialogInit {
         // Setup action buttons
         dialog.view.setButtonGravity(builder.buttonsGravity);
         dialog.view.setButtonStackedGravity(builder.btnStackedGravity);
-        dialog.view.setForceStack(builder.forceStacking);
+        dialog.view.setStackingBehavior(builder.stackingBehavior);
         boolean textAllCaps;
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
             textAllCaps = DialogUtils.resolveBoolean(builder.context, android.R.attr.textAllCaps, true);
@@ -353,6 +353,17 @@ class DialogInit {
         dialog.checkIfListInitScroll();
     }
 
+    private static void fixCanvasScalingWhenHardwareAccelerated(ProgressBar pb) {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB &&
+                Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
+            // Canvas scaling when hardware accelerated results in artifacts on older API levels, so
+            // we need to use software rendering
+            if (pb.isHardwareAccelerated() && pb.getLayerType() != View.LAYER_TYPE_SOFTWARE) {
+                pb.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
+            }
+        }
+    }
+
     private static void setupProgressDialog(final MaterialDialog dialog) {
         final MaterialDialog.Builder builder = dialog.mBuilder;
         if (builder.indeterminateProgress || builder.progress > -2) {
@@ -412,6 +423,10 @@ class DialogInit {
                 }
             }
         }
+
+        if (dialog.mProgress != null) {
+            fixCanvasScalingWhenHardwareAccelerated(dialog.mProgress);
+        }
     }
 
     private static void setupInputDialog(final MaterialDialog dialog) {
@@ -430,7 +445,7 @@ class DialogInit {
 
         if (builder.inputType != -1) {
             dialog.input.setInputType(builder.inputType);
-            if (builder.inputType != InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD  &&
+            if (builder.inputType != InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD &&
                     (builder.inputType & InputType.TYPE_TEXT_VARIATION_PASSWORD) == InputType.TYPE_TEXT_VARIATION_PASSWORD) {
                 // If the flags contain TYPE_TEXT_VARIATION_PASSWORD, apply the password transformation method automatically
                 dialog.input.setTransformationMethod(PasswordTransformationMethod.getInstance());

+ 44 - 8
core/src/main/java/com/afollestad/materialdialogs/MaterialDialog.java

@@ -163,11 +163,16 @@ public class MaterialDialog extends DialogBase implements
 
     @Override
     public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+        if (!view.isEnabled()) return;
         if (mBuilder.listCallbackCustom != null) {
             // Custom adapter
             CharSequence text = null;
-            if (view instanceof TextView)
+            if (view instanceof TextView) {
                 text = ((TextView) view).getText();
+            } else {
+                final TextView tv = (TextView) view.findViewById(android.R.id.title);
+                if (tv != null) text = tv.getText();
+            }
             mBuilder.listCallbackCustom.onSelection(this, view, position, text);
         } else if (listType == null || listType == ListType.REGULAR) {
             // Default adapter, non choice mode
@@ -181,8 +186,9 @@ public class MaterialDialog extends DialogBase implements
         } else {
             // Default adapter, choice mode
             if (listType == ListType.MULTI) {
-                final boolean shouldBeChecked = !selectedIndicesList.contains(position);
                 final CheckBox cb = (CheckBox) view.findViewById(R.id.control);
+                if (!cb.isEnabled()) return;
+                final boolean shouldBeChecked = !selectedIndicesList.contains(position);
                 if (shouldBeChecked) {
                     // Add the selection to the states first so the callback includes it (when alwaysCallMultiChoiceCallback)
                     selectedIndicesList.add(position);
@@ -206,9 +212,10 @@ public class MaterialDialog extends DialogBase implements
                         sendMultichoiceCallback();
                 }
             } else if (listType == ListType.SINGLE) {
+                final RadioButton radio = (RadioButton) view.findViewById(R.id.control);
+                if (!radio.isEnabled()) return;
                 boolean allowSelection = true;
                 final DefaultAdapter adapter = (DefaultAdapter) mBuilder.adapter;
-                final RadioButton radio = (RadioButton) view.findViewById(R.id.control);
 
                 if (mBuilder.autoDismiss && mBuilder.positiveText == null) {
                     // If auto dismiss is enabled, and no action button is visible to approve the selection, dismiss the dialog
@@ -350,7 +357,7 @@ public class MaterialDialog extends DialogBase implements
                 }
                 if (mBuilder.onNegativeCallback != null)
                     mBuilder.onNegativeCallback.onClick(this, tag);
-                if (mBuilder.autoDismiss) dismiss();
+                if (mBuilder.autoDismiss) cancel();
                 break;
             }
             case NEUTRAL: {
@@ -411,6 +418,7 @@ public class MaterialDialog extends DialogBase implements
         protected float contentLineSpacingMultiplier = 1.2f;
         protected int selectedIndex = -1;
         protected Integer[] selectedIndices = null;
+        protected Integer[] disabledIndices = null;
         protected boolean autoDismiss = true;
         protected Typeface regularFont;
         protected Typeface mediumFont;
@@ -422,7 +430,7 @@ public class MaterialDialog extends DialogBase implements
         protected OnCancelListener cancelListener;
         protected OnKeyListener keyListener;
         protected OnShowListener showListener;
-        protected boolean forceStacking;
+        protected StackingBehavior stackingBehavior;
         protected boolean wrapCustomViewInScroll;
         protected int dividerColor;
         protected int backgroundColor;
@@ -851,6 +859,18 @@ public class MaterialDialog extends DialogBase implements
             return this;
         }
 
+        /**
+         * Sets indices of items that are not clickable. If they are checkboxes or radio buttons,
+         * they will not be toggleable.
+         *
+         * @param disabledIndices The item indices that will be disabled from selection.
+         * @return The Builder instance so you can chain calls to it.
+         */
+        public Builder itemsDisabledIndices(@Nullable Integer... disabledIndices) {
+            this.disabledIndices = disabledIndices;
+            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
@@ -1101,7 +1121,7 @@ public class MaterialDialog extends DialogBase implements
         }
 
         public Builder widgetColorAttr(@AttrRes int colorAttr) {
-            return widgetColorRes(DialogUtils.resolveColor(this.context, colorAttr));
+            return widgetColor(DialogUtils.resolveColor(this.context, colorAttr));
         }
 
         public Builder dividerColor(@ColorInt int color) {
@@ -1237,11 +1257,27 @@ public class MaterialDialog extends DialogBase implements
             return this;
         }
 
-        public Builder forceStacking(boolean stacked) {
-            this.forceStacking = stacked;
+        /**
+         * Sets action button stacking behavior.
+         *
+         * @param behavior The behavior of the action button stacking logic.
+         * @return The Builder instance so you can chain calls to it.
+         */
+        public Builder stackingBehavior(@NonNull StackingBehavior behavior) {
+            this.stackingBehavior = behavior;
             return this;
         }
 
+        /**
+         * @param stacked When true, action button stacking is forced.
+         * @return The Builder instance so you can chain calls to it.
+         * @deprecated Use {@link #stackingBehavior(StackingBehavior)} instead.
+         */
+        @Deprecated
+        public Builder forceStacking(boolean stacked) {
+            return stackingBehavior(stacked ? StackingBehavior.ALWAYS : StackingBehavior.ADAPTIVE);
+        }
+
         public Builder input(@Nullable CharSequence hint, @Nullable CharSequence prefill, boolean allowEmptyInput, @NonNull InputCallback callback) {
             if (this.customView != null)
                 throw new IllegalStateException("You cannot set content() when you're using a custom view.");

+ 19 - 0
core/src/main/java/com/afollestad/materialdialogs/StackingBehavior.java

@@ -0,0 +1,19 @@
+package com.afollestad.materialdialogs;
+
+/**
+ * @author Aidan Follestad (afollestad)
+ */
+public enum StackingBehavior {
+    /**
+     * The action buttons are always stacked vertically.
+     */
+    ALWAYS,
+    /**
+     * The action buttons are stacked vertically IF it is necessary for them to fit in the dialog.
+     */
+    ADAPTIVE,
+    /**
+     * The action buttons are never stacked, even if they should be.
+     */
+    NEVER
+}

+ 9 - 6
core/src/main/java/com/afollestad/materialdialogs/internal/MDRootLayout.java

@@ -22,6 +22,7 @@ import android.widget.ScrollView;
 import com.afollestad.materialdialogs.GravityEnum;
 import com.afollestad.materialdialogs.MaterialDialog;
 import com.afollestad.materialdialogs.R;
+import com.afollestad.materialdialogs.StackingBehavior;
 import com.afollestad.materialdialogs.util.DialogUtils;
 
 /**
@@ -43,7 +44,7 @@ public class MDRootLayout extends ViewGroup {
     private boolean mDrawTopDivider = false;
     private boolean mDrawBottomDivider = false;
     private final MDButton[] mButtons = new MDButton[3];
-    private boolean mForceStack = false;
+    private StackingBehavior mStackBehavior = StackingBehavior.ADAPTIVE;
     private boolean mIsStacked = false;
     private boolean mUseFullPadding = true;
     private boolean mReducePaddingNoTitleNoButtons;
@@ -137,7 +138,11 @@ public class MDRootLayout extends ViewGroup {
         boolean hasButtons = false;
 
         final boolean stacked;
-        if (!mForceStack) {
+        if (mStackBehavior == StackingBehavior.ALWAYS) {
+            stacked = true;
+        } else if (mStackBehavior == StackingBehavior.NEVER) {
+            stacked = false;
+        } else {
             int buttonsWidth = 0;
             for (MDButton button : mButtons) {
                 if (button != null && isVisible(button)) {
@@ -152,8 +157,6 @@ public class MDRootLayout extends ViewGroup {
                     .getDimensionPixelSize(R.dimen.md_neutral_button_margin);
             final int buttonFrameWidth = width - 2 * buttonBarPadding;
             stacked = buttonsWidth > buttonFrameWidth;
-        } else {
-            stacked = true;
         }
 
         int stackedHeight = 0;
@@ -343,8 +346,8 @@ public class MDRootLayout extends ViewGroup {
         setUpDividersVisibility(mContent, true, true);
     }
 
-    public void setForceStack(boolean forceStack) {
-        mForceStack = forceStack;
+    public void setStackingBehavior(StackingBehavior behavior) {
+        mStackBehavior = behavior;
         invalidate();
     }
 

+ 16 - 6
core/src/main/java/com/afollestad/materialdialogs/internal/MDTintHelper.java

@@ -28,12 +28,17 @@ import java.lang.reflect.Field;
 public class MDTintHelper {
 
     public static void setTint(@NonNull RadioButton radioButton, @ColorInt int color) {
+        final int disabledColor = DialogUtils.getDisabledColor(radioButton.getContext());
         ColorStateList sl = new ColorStateList(new int[][]{
-                new int[]{-android.R.attr.state_checked},
-                new int[]{android.R.attr.state_checked}
+                new int[]{android.R.attr.state_enabled, -android.R.attr.state_checked},
+                new int[]{android.R.attr.state_enabled, android.R.attr.state_checked},
+                new int[]{-android.R.attr.state_enabled, -android.R.attr.state_checked},
+                new int[]{-android.R.attr.state_enabled, android.R.attr.state_checked}
         }, new int[]{
                 DialogUtils.resolveColor(radioButton.getContext(), R.attr.colorControlNormal),
-                color
+                color,
+                disabledColor,
+                disabledColor
         });
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
             radioButton.setButtonTintList(sl);
@@ -120,12 +125,17 @@ public class MDTintHelper {
     }
 
     public static void setTint(@NonNull CheckBox box, @ColorInt int color) {
+        final int disabledColor = DialogUtils.getDisabledColor(box.getContext());
         ColorStateList sl = new ColorStateList(new int[][]{
-                new int[]{-android.R.attr.state_checked},
-                new int[]{android.R.attr.state_checked}
+                new int[]{android.R.attr.state_enabled, -android.R.attr.state_checked},
+                new int[]{android.R.attr.state_enabled, android.R.attr.state_checked},
+                new int[]{-android.R.attr.state_enabled, -android.R.attr.state_checked},
+                new int[]{-android.R.attr.state_enabled, android.R.attr.state_checked}
         }, new int[]{
                 DialogUtils.resolveColor(box.getContext(), R.attr.colorControlNormal),
-                color
+                color,
+                disabledColor,
+                disabledColor
         });
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
             box.setButtonTintList(sl);

+ 25 - 2
core/src/main/java/com/afollestad/materialdialogs/util/DialogUtils.java

@@ -10,8 +10,10 @@ import android.os.Build;
 import android.os.IBinder;
 import android.support.annotation.ArrayRes;
 import android.support.annotation.AttrRes;
+import android.support.annotation.ColorInt;
 import android.support.annotation.ColorRes;
 import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
 import android.util.TypedValue;
 import android.view.View;
 import android.view.inputmethod.InputMethodManager;
@@ -34,7 +36,15 @@ public class DialogUtils {
 //        }
 //    }
 
-    public static int adjustAlpha(int color, @SuppressWarnings("SameParameterValue") float factor) {
+    @ColorInt
+    public static int getDisabledColor(Context context) {
+        final int primaryColor = resolveColor(context, android.R.attr.textColorPrimary);
+        final int disabledColor = isColorDark(primaryColor) ? Color.BLACK : Color.WHITE;
+        return adjustAlpha(disabledColor, 0.3f);
+    }
+
+    @ColorInt
+    public static int adjustAlpha(@ColorInt int color, @SuppressWarnings("SameParameterValue") float factor) {
         int alpha = Math.round(Color.alpha(color) * factor);
         int red = Color.red(color);
         int green = Color.green(color);
@@ -42,10 +52,12 @@ public class DialogUtils {
         return Color.argb(alpha, red, green, blue);
     }
 
+    @ColorInt
     public static int resolveColor(Context context, @AttrRes int attr) {
         return resolveColor(context, attr, 0);
     }
 
+    @ColorInt
     public static int resolveColor(Context context, @AttrRes int attr, int fallback) {
         TypedArray a = context.getTheme().obtainStyledAttributes(new int[]{attr});
         try {
@@ -107,6 +119,7 @@ public class DialogUtils {
      *                entry. The value 0 is an invalid identifier.
      * @return A single color value in the form 0xAARRGGBB.
      */
+    @ColorInt
     public static int getColor(Context context, @ColorRes int colorId) {
         if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP_MR1) {
             //noinspection deprecation
@@ -191,7 +204,7 @@ public class DialogUtils {
         return resolveBoolean(context, attr, false);
     }
 
-    public static boolean isColorDark(int color) {
+    public static boolean isColorDark(@ColorInt int color) {
         double darkness = 1 - (0.299 * Color.red(color) + 0.587 * Color.green(color) + 0.114 * Color.blue(color)) / 255;
         return darkness >= 0.5;
     }
@@ -256,4 +269,14 @@ public class DialogUtils {
         ta.recycle();
         return colors;
     }
+
+    public static <T> boolean isIn(@NonNull T find, @Nullable T[] ary) {
+        if (ary == null || ary.length == 0)
+            return false;
+        for (T item : ary) {
+            if (item.equals(find))
+                return true;
+        }
+        return false;
+    }
 }

+ 1 - 1
core/src/main/res/values/colors.xml

@@ -14,7 +14,7 @@
     <color name="md_divider_black">#10000000</color>
     <color name="md_divider_white">#10FFFFFF</color>
 
-    <color name="md_material_blue_600">#1E88E5</color>
+    <color name="md_material_blue_600">#2196F3</color>
     <color name="md_material_blue_800">#1565C0</color>
 
     <color name="md_edittext_error">#DD2C00</color>

+ 3 - 3
sample/build.gradle

@@ -11,8 +11,8 @@ apply plugin: 'com.android.application'
 apply plugin: 'com.neenbedankt.android-apt'
 
 ext {
-    PUBLISH_VERSION = '0.8.6.1'
-    SUPPORT_LIBRARY_VERSION = '24.0.0'
+    PUBLISH_VERSION = '0.8.6.2'
+    SUPPORT_LIBRARY_VERSION = '24.1.0'
     BUILD_TOOLS = "24.0.0"
     TARGET_SDK = 24
 }
@@ -25,7 +25,7 @@ android {
         applicationId "com.afollestad.materialdialogssample"
         minSdkVersion 9
         targetSdkVersion TARGET_SDK
-        versionCode 163
+        versionCode 164
         versionName PUBLISH_VERSION
     }
     lintOptions {

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

@@ -31,6 +31,7 @@ import android.widget.Toast;
 import com.afollestad.materialdialogs.DialogAction;
 import com.afollestad.materialdialogs.GravityEnum;
 import com.afollestad.materialdialogs.MaterialDialog;
+import com.afollestad.materialdialogs.StackingBehavior;
 import com.afollestad.materialdialogs.Theme;
 import com.afollestad.materialdialogs.color.CircleView;
 import com.afollestad.materialdialogs.color.ColorChooserDialog;
@@ -163,7 +164,7 @@ public class MainActivity extends AppCompatActivity implements
                 .positiveText(R.string.speedBoost)
                 .negativeText(R.string.noThanks)
                 .btnStackedGravity(GravityEnum.END)
-                .forceStacking(true)  // this generally should not be forced, but is used for demo purposes
+                .stackingBehavior(StackingBehavior.ALWAYS)  // this generally should not be forced, but is used for demo purposes
                 .show();
     }
 
@@ -358,6 +359,39 @@ public class MainActivity extends AppCompatActivity implements
                 .show();
     }
 
+    @OnClick(R.id.multiChoice_disabledItems)
+    public void showMultiChoiceDisabledItems() {
+        new MaterialDialog.Builder(this)
+                .title(R.string.socialNetworks)
+                .items(R.array.socialNetworks)
+                .itemsCallbackMultiChoice(new Integer[]{0, 1, 2}, new MaterialDialog.ListCallbackMultiChoice() {
+                    @Override
+                    public boolean onSelection(MaterialDialog dialog, Integer[] which, CharSequence[] text) {
+                        StringBuilder str = new StringBuilder();
+                        for (int i = 0; i < which.length; i++) {
+                            if (i > 0) str.append('\n');
+                            str.append(which[i]);
+                            str.append(": ");
+                            str.append(text[i]);
+                        }
+                        showToast(str.toString());
+                        return true; // allow selection
+                    }
+                })
+                .onNeutral(new MaterialDialog.SingleButtonCallback() {
+                    @Override
+                    public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
+                        dialog.clearSelectedIndices();
+                    }
+                })
+                .alwaysCallMultiChoiceCallback()
+                .positiveText(R.string.md_choose_label)
+                .autoDismiss(false)
+                .neutralText(R.string.clear_selection)
+                .itemsDisabledIndices(0, 1)
+                .show();
+    }
+
     @OnClick(R.id.simpleList)
     public void showSimpleList() {
         final MaterialSimpleListAdapter adapter = new MaterialSimpleListAdapter(this);
@@ -448,10 +482,10 @@ public class MainActivity extends AppCompatActivity implements
 
         int widgetColor = ThemeSingleton.get().widgetColor;
         MDTintHelper.setTint(checkbox,
-                widgetColor == 0 ? ContextCompat.getColor(this, R.color.material_teal_a400) : widgetColor);
+                widgetColor == 0 ? ContextCompat.getColor(this, R.color.material_blue) : widgetColor);
 
         MDTintHelper.setTint(passwordInput,
-                widgetColor == 0 ? ContextCompat.getColor(this, R.color.material_teal_a400) : widgetColor);
+                widgetColor == 0 ? ContextCompat.getColor(this, R.color.material_blue) : widgetColor);
 
         dialog.show();
         positiveAction.setEnabled(false); // disabled by default
@@ -461,7 +495,7 @@ public class MainActivity extends AppCompatActivity implements
     public void showCustomWebView() {
         int accentColor = ThemeSingleton.get().widgetColor;
         if (accentColor == 0)
-            accentColor = ContextCompat.getColor(this, R.color.material_teal_a400);
+            accentColor = ContextCompat.getColor(this, R.color.material_blue);
         ChangelogDialog.create(false, accentColor)
                 .show(getSupportFragmentManager(), "changelog");
     }
@@ -543,7 +577,7 @@ public class MainActivity extends AppCompatActivity implements
                 .titleColorRes(R.color.material_red_400)
                 .contentColorRes(android.R.color.white)
                 .backgroundColorRes(R.color.material_blue_grey_800)
-                .dividerColorRes(R.color.material_teal_a400)
+                .dividerColorRes(R.color.material_blue)
                 .btnSelector(R.drawable.md_btn_selector_custom, DialogAction.POSITIVE)
                 .positiveColor(Color.WHITE)
                 .negativeColorAttr(android.R.attr.textColorSecondaryInverse)

+ 7 - 0
sample/src/main/res/layout/activity_main.xml

@@ -146,6 +146,13 @@
             android:layout_marginTop="@dimen/sample_button_spacing"
             android:text="@string/multiChoice_longItems" />
 
+        <Button
+            android:id="@+id/multiChoice_disabledItems"
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/sample_button_height"
+            android:layout_marginTop="@dimen/sample_button_spacing"
+            android:text="@string/multiChoice_disabledItems" />
+
         <!-- Advanced Lists -->
 
         <TextView

+ 1 - 1
sample/src/main/res/values-v21/styles.xml

@@ -4,7 +4,7 @@
     <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
         <item name="colorPrimary">@color/material_indigo_500</item>
         <item name="colorPrimaryDark">@color/material_indigo_600</item>
-        <item name="colorAccent">@color/material_teal_a400</item>
+        <item name="colorAccent">@color/material_blue</item>
 
         <item name="android:navigationBarColor">@color/material_indigo_500</item>
     </style>

+ 1 - 1
sample/src/main/res/values/colors.xml

@@ -4,7 +4,7 @@
     <!-- http://www.google.com/design/spec/style/color.html#color-color-palette -->
     <color name="material_indigo_500">#3F51B5</color>
     <color name="material_indigo_600">#3949AB</color>
-    <color name="material_teal_a400">#1DE9B6</color>
+    <color name="material_blue">#2196F3</color>
     <color name="material_red_400">#EF5350</color>
 
 </resources>

+ 1 - 0
sample/src/main/res/values/strings.xml

@@ -183,6 +183,7 @@
     <string name="choice_lists">Choice Lists</string>
     <string name="advanced_lists">Advanced Lists</string>
     <string name="list_longItems">Basic List (Long Items)</string>
+    <string name="multiChoice_disabledItems">Multi Choice (Disabled Items)</string>
     <string name="singleChoice_longItems">Single Choice (Long Items)</string>
     <string name="multiChoice_longItems">Multi Choice (Long Items)</string>
     <string name="file_chooser">File Chooser</string>

+ 1 - 1
sample/src/main/res/values/styles.xml

@@ -4,7 +4,7 @@
     <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
         <item name="colorPrimary">@color/material_indigo_500</item>
         <item name="colorPrimaryDark">@color/material_indigo_600</item>
-        <item name="colorAccent">@color/material_teal_a400</item>
+        <item name="colorAccent">@color/material_blue</item>
     </style>
 
     <style name="SampleHeader">