Browse Source

Fixes to latest design guidelines, improved stacked algorithm, lists are scrollable, etc. ICS support limited due to padding issues.

Aidan Follestad 10 years ago
parent
commit
3755727365

+ 1 - 0
README.md

@@ -255,6 +255,7 @@ new MaterialDialog.Builder(this)
         .positiveText("Accept")
         .negativeText("Decline")
         .positiveColor(materialRed500)
+        .negativeColor(materialRed500)
         .titleAlignment(Alignment.CENTER)
         .titleColor(materialRed500)
         .theme(Theme.DARK)

+ 1 - 0
library/build.gradle

@@ -22,4 +22,5 @@ android {
 dependencies {
     compile fileTree(dir: 'libs', include: ['*.jar'])
     compile 'com.android.support:appcompat-v7:21.0.0'
+    compile 'org.lucasr.dspec:dspec:0.1.1'
 }

+ 1 - 0
library/library.iml

@@ -84,6 +84,7 @@
     <orderEntry type="sourceFolder" forTests="false" />
     <orderEntry type="library" exported="" name="support-annotations-21.0.0" level="project" />
     <orderEntry type="library" exported="" name="support-v4-21.0.0" level="project" />
+    <orderEntry type="library" exported="" name="dspec-0.1.1" level="project" />
     <orderEntry type="library" exported="" name="appcompat-v7-21.0.0" level="project" />
   </component>
 </module>

+ 133 - 47
library/src/main/java/com/afollestad/materialdialogs/MaterialDialog.java

@@ -22,9 +22,12 @@ import android.view.ViewGroup;
 import android.widget.CheckBox;
 import android.widget.LinearLayout;
 import android.widget.RadioButton;
+import android.widget.ScrollView;
 import android.widget.TextView;
 
 import com.afollestad.materialdialogs.base.DialogBase;
+import com.afollestad.materialdialogs.views.MeasureCallbackLinearLayout;
+import com.afollestad.materialdialogs.views.MeasureCallbackScrollView;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -33,7 +36,7 @@ import java.util.List;
 /**
  * @author Aidan Follestad (afollestad)
  */
-public class MaterialDialog extends DialogBase implements View.OnClickListener {
+public class MaterialDialog extends DialogBase implements View.OnClickListener, MeasureCallbackLinearLayout.Callback, MeasureCallbackScrollView.Callback {
 
     private Context mContext;
     private CharSequence positiveText;
@@ -44,25 +47,29 @@ public class MaterialDialog extends DialogBase implements View.OnClickListener {
     private TextView negativeButton;
     private View view;
     private int positiveColor;
+    private int negativeColor;
+    private int neutralColor;
     private SimpleCallback callback;
     private ListCallback listCallback;
     private ListCallback listCallbackSingle;
     private ListCallbackMulti listCallbackMulti;
     private View customView;
-    private float buttonHeight;
     private String[] items;
     private boolean isStacked;
     private int selectedIndex;
     private Integer[] selectedIndices;
+    private boolean mMeasuredScrollView;
 
     private Typeface regularFont;
     private Typeface mediumFont;
 
+
     MaterialDialog(Builder builder) {
         super(new ContextThemeWrapper(builder.context, builder.theme == Theme.LIGHT ? R.style.Light : R.style.Dark));
 
         this.mContext = builder.context;
         this.view = LayoutInflater.from(builder.context).inflate(R.layout.material_dialog, null);
+        ((MeasureCallbackLinearLayout) view).setCallback(this);
         this.customView = builder.customView;
         this.callback = builder.callback;
         this.listCallback = builder.listCallback;
@@ -72,6 +79,8 @@ public class MaterialDialog extends DialogBase implements View.OnClickListener {
         this.neutralText = builder.neutralText;
         this.negativeText = builder.negativeText;
         this.positiveColor = builder.positiveColor;
+        this.negativeColor = builder.negativeColor;
+        this.neutralColor = builder.neutralColor;
         this.items = builder.items;
         this.setCancelable(builder.cancelable);
         this.regularFont = Typeface.createFromAsset(getContext().getResources().getAssets(), "Roboto-Regular.ttf");
@@ -101,11 +110,7 @@ public class MaterialDialog extends DialogBase implements View.OnClickListener {
 
         if (customView != null) {
             title = (TextView) view.findViewById(R.id.titleCustomView);
-            buttonHeight = mContext.getResources().getDimension(R.dimen.button_height_customview);
-            view.findViewById(R.id.mainFrame).setVisibility(View.GONE);
-            view.findViewById(R.id.customViewScrollParent).setVisibility(View.VISIBLE);
-            view.findViewById(R.id.customViewDivider).setVisibility(View.VISIBLE);
-            view.findViewById(R.id.customViewDivider).setBackgroundColor(Utils.resolveColor(getContext(), R.attr.divider_color));
+            invalidateCustomViewAssociations();
             View firstChild = customView;
             View lastChild = customView;
             final int frameMargin = (int) mContext.getResources().getDimension(R.dimen.dialog_frame_margin);
@@ -119,12 +124,12 @@ public class MaterialDialog extends DialogBase implements View.OnClickListener {
             setMargin(lastChild, -1, frameMargin, -1, -1);
             ((LinearLayout) view.findViewById(R.id.customViewFrame)).addView(customView);
         } else {
-            buttonHeight = mContext.getResources().getDimension(R.dimen.button_height);
-            view.findViewById(R.id.mainFrame).setVisibility(View.VISIBLE);
-            view.findViewById(R.id.customViewScrollParent).setVisibility(View.GONE);
-            view.findViewById(R.id.customViewDivider).setVisibility(View.GONE);
+            invalidateCustomViewAssociations();
         }
 
+        if (items != null && items.length > 0)
+            title = (TextView) view.findViewById(R.id.titleCustomView);
+
         // Title is set after it's determined whether to use first title or custom view title
         if (builder.title == null || builder.title.toString().trim().isEmpty()) {
             title.setVisibility(View.GONE);
@@ -145,17 +150,46 @@ public class MaterialDialog extends DialogBase implements View.OnClickListener {
 
         invalidateList();
         invalidateActions();
-        checkIfStackingNeeded();
         setViewInternal(view);
     }
 
+    /**
+     * Invalidates visibility of views for the presence of a custom view or list content
+     */
+    private void invalidateCustomViewAssociations() {
+        if (customView != null || (items != null && items.length > 0)) {
+            view.findViewById(R.id.mainFrame).setVisibility(View.GONE);
+            view.findViewById(R.id.customViewScrollParent).setVisibility(View.VISIBLE);
+            if (!mMeasuredScrollView) {
+                // Wait until it's measured
+                ((MeasureCallbackScrollView) view.findViewById(R.id.customViewScroll)).setCallback(this);
+                return;
+            }
+            if (canCustomViewScroll()) {
+                view.findViewById(R.id.customViewDivider).setVisibility(View.VISIBLE);
+                view.findViewById(R.id.customViewDivider).setBackgroundColor(Utils.resolveColor(getContext(), R.attr.divider_color));
+                setMargin(view.findViewById(R.id.buttonStackedFrame), -1, 0, -1, -1);
+                setMargin(view.findViewById(R.id.buttonDefaultFrame), -1, 0, -1, -1);
+            } else {
+                final int bottomMargin = (int) mContext.getResources().getDimension(R.dimen.button_padding_frame_bottom);
+                setMargin(view.findViewById(R.id.buttonStackedFrame), -1, bottomMargin, -1, -1);
+                setMargin(view.findViewById(R.id.buttonDefaultFrame), -1, bottomMargin, -1, -1);
+            }
+        } else {
+            view.findViewById(R.id.mainFrame).setVisibility(View.VISIBLE);
+            view.findViewById(R.id.customViewScrollParent).setVisibility(View.GONE);
+            view.findViewById(R.id.customViewDivider).setVisibility(View.GONE);
+        }
+    }
+
     /**
      * Invalidates the radio buttons in the single choice mode list so that only the radio button that
      * was previous selected is checked.
      */
     private void invalidateSingleChoice(int newSelection) {
-        LinearLayout list = (LinearLayout) view.findViewById(R.id.listFrame);
-        for (int i = 0; i < list.getChildCount(); i++) {
+        newSelection++;
+        LinearLayout list = (LinearLayout) view.findViewById(R.id.customViewFrame);
+        for (int i = 1; i < list.getChildCount(); i++) {
             View v = list.getChildAt(i);
             @SuppressLint("WrongViewCast")
             RadioButton rb = (RadioButton) v.findViewById(R.id.control);
@@ -171,14 +205,9 @@ public class MaterialDialog extends DialogBase implements View.OnClickListener {
         if (items == null || items.length == 0) return;
         view.findViewById(R.id.content).setVisibility(View.GONE);
 
-        View title = view.findViewById(R.id.title);
-        setMargin(title, -1, (int) mContext.getResources().getDimension(R.dimen.button_padding), 0, 0);
-        View mainFrame = view.findViewById(R.id.mainFrame);
-        int dpPadding = (int) mContext.getResources().getDimension(R.dimen.button_frame_margin);
-        setMargin(mainFrame, dpPadding, 0, dpPadding, dpPadding);
-
-        view.findViewById(R.id.listFrameScrollParent).setVisibility(View.VISIBLE);
-        LinearLayout list = (LinearLayout) view.findViewById(R.id.listFrame);
+        view.findViewById(R.id.customViewScrollParent).setVisibility(View.VISIBLE);
+        LinearLayout list = (LinearLayout) view.findViewById(R.id.customViewFrame);
+        setMargin(list, -1, -1, 0, 0);
         LayoutInflater li = LayoutInflater.from(mContext);
 
         final int itemColor = Utils.resolveColor(getContext(), R.attr.item_color);
@@ -207,6 +236,25 @@ public class MaterialDialog extends DialogBase implements View.OnClickListener {
         }
     }
 
+    /**
+     * Max button width = (DialogWidth - 16dp - 16dp - 8dp) / 2
+     * From: http://www.google.com/design/spec/components/dialogs.html#dialogs-specs
+     */
+    private int calculateMaxButtonWidth() {
+        final int eightDp = (int) mContext.getResources().getDimension(R.dimen.button_padding_horizontal_external);
+        final int sixteenDp = (int) mContext.getResources().getDimension(R.dimen.button_padding_frame_side);
+        return (view.getMeasuredWidth() - sixteenDp - sixteenDp - eightDp) / 2;
+    }
+
+    /**
+     * Detects whether or not the custom view or list content can be scrolled.
+     */
+    private boolean canCustomViewScroll() {
+        final ScrollView scrollView = (ScrollView) view.findViewById(R.id.customViewScroll);
+        final int childHeight = view.findViewById(R.id.customViewFrame).getMeasuredHeight();
+        return scrollView.getMeasuredHeight() < childHeight;
+    }
+
     /**
      * Measures the action button's and their text to decide whether or not the button should be stacked.
      */
@@ -216,14 +264,19 @@ public class MaterialDialog extends DialogBase implements View.OnClickListener {
             // Stacking isn't necessary if you only have one button
             return;
         }
-        Paint paint = positiveButton.getPaint();
-        float buttonMinWidth = mContext.getResources().getDimension(R.dimen.button_min_width);
-        float totalWidth = paint.measureText(positiveButton.getText().toString());
-        if (this.neutralText != null)
-            totalWidth += paint.measureText(neutralButton.getText().toString());
-        if (this.negativeText != null)
-            totalWidth += paint.measureText(negativeButton.getText().toString());
-        isStacked = totalWidth > (buttonMinWidth * 3);
+        final int maxWidth = calculateMaxButtonWidth();
+        final Paint paint = positiveButton.getPaint();
+        final int eightDp = (int) mContext.getResources().getDimension(R.dimen.button_padding_horizontal_external);
+        final int positiveWidth = (int) paint.measureText(positiveButton.getText().toString()) + (eightDp * 2);
+        isStacked = positiveWidth > maxWidth;
+        if (!isStacked && this.neutralText != null) {
+            final int neutralWidth = (int) paint.measureText(neutralButton.getText().toString()) + (eightDp * 2);
+            isStacked = neutralWidth > maxWidth;
+        }
+        if (!isStacked && this.negativeText != null) {
+            final int negativeWidth = (int) paint.measureText(negativeButton.getText().toString()) + (eightDp * 2);
+            isStacked = negativeWidth > maxWidth;
+        }
         invalidateActions();
     }
 
@@ -239,38 +292,30 @@ public class MaterialDialog extends DialogBase implements View.OnClickListener {
             return;
         }
 
-        final int buttonFrameMargin = (int) mContext.getResources().getDimension(R.dimen.button_frame_margin);
         if (isStacked) {
             view.findViewById(R.id.buttonDefaultFrame).setVisibility(View.GONE);
             view.findViewById(R.id.buttonStackedFrame).setVisibility(View.VISIBLE);
-            if (customView == null)
-                setMargin(view.findViewById(R.id.buttonStackedFrame), -1, buttonFrameMargin, -1, -1);
         } else {
             view.findViewById(R.id.buttonDefaultFrame).setVisibility(View.VISIBLE);
             view.findViewById(R.id.buttonStackedFrame).setVisibility(View.GONE);
-            if (customView == null)
-                setMargin(view.findViewById(R.id.buttonDefaultFrame), -1, buttonFrameMargin, -1, -1);
         }
 
         positiveButton = (TextView) view.findViewById(
                 isStacked ? R.id.buttonStackedPositive : R.id.buttonDefaultPositive);
-        setHeight(positiveButton, buttonHeight);
         positiveButton.setTypeface(mediumFont);
         if (this.positiveText == null)
-            this.positiveText = mContext.getString(R.string.accept);
+            this.positiveText = mContext.getString(android.R.string.ok);
         positiveButton.setText(this.positiveText);
         positiveButton.setTextColor(getActionTextStateList(this.positiveColor));
-
         positiveButton.setTag(POSITIVE);
         positiveButton.setOnClickListener(this);
 
         neutralButton = (TextView) view.findViewById(
                 isStacked ? R.id.buttonStackedNeutral : R.id.buttonDefaultNeutral);
-        setHeight(neutralButton, buttonHeight);
         neutralButton.setTypeface(mediumFont);
         if (this.neutralText != null) {
             neutralButton.setVisibility(View.VISIBLE);
-            neutralButton.setTextColor(getActionTextStateList(0));
+            neutralButton.setTextColor(getActionTextStateList(this.neutralColor));
             neutralButton.setText(this.neutralText);
             neutralButton.setTag(NEUTRAL);
             neutralButton.setOnClickListener(this);
@@ -280,11 +325,10 @@ public class MaterialDialog extends DialogBase implements View.OnClickListener {
 
         negativeButton = (TextView) view.findViewById(
                 isStacked ? R.id.buttonStackedNegative : R.id.buttonDefaultNegative);
-        setHeight(negativeButton, buttonHeight);
         negativeButton.setTypeface(mediumFont);
         if (this.negativeText != null) {
             negativeButton.setVisibility(View.VISIBLE);
-            negativeButton.setTextColor(getActionTextStateList(0));
+            negativeButton.setTextColor(getActionTextStateList(this.negativeColor));
             negativeButton.setText(this.negativeText);
             negativeButton.setTag(NEGATIVE);
             negativeButton.setOnClickListener(this);
@@ -299,8 +343,8 @@ public class MaterialDialog extends DialogBase implements View.OnClickListener {
         if (tag.equals(POSITIVE)) {
             if (listCallbackSingle != null) {
                 dismiss();
-                LinearLayout list = (LinearLayout) view.findViewById(R.id.listFrame);
-                for (int i = 0; i < list.getChildCount(); i++) {
+                LinearLayout list = (LinearLayout) view.findViewById(R.id.customViewFrame);
+                for (int i = 1; i < list.getChildCount(); i++) {
                     View itemView = list.getChildAt(i);
                     @SuppressLint("WrongViewCast")
                     RadioButton rb = (RadioButton) itemView.findViewById(R.id.control);
@@ -313,8 +357,8 @@ public class MaterialDialog extends DialogBase implements View.OnClickListener {
                 dismiss();
                 List<Integer> selectedIndices = new ArrayList<Integer>();
                 List<String> selectedTitles = new ArrayList<String>();
-                LinearLayout list = (LinearLayout) view.findViewById(R.id.listFrame);
-                for (int i = 0; i < list.getChildCount(); i++) {
+                LinearLayout list = (LinearLayout) view.findViewById(R.id.customViewFrame);
+                for (int i = 1; i < list.getChildCount(); i++) {
                     View itemView = list.getChildAt(i);
                     CheckBox rb = (CheckBox) itemView.findViewById(R.id.control);
                     if (rb.isChecked()) {
@@ -356,6 +400,19 @@ public class MaterialDialog extends DialogBase implements View.OnClickListener {
         }
     }
 
+    @Override
+    public void onMeasureLinear(LinearLayout view) {
+        checkIfStackingNeeded();
+    }
+
+    @Override
+    public void onMeasureScroll(ScrollView view) {
+        if (view.getMeasuredWidth() > 0) {
+            mMeasuredScrollView = true;
+            invalidateCustomViewAssociations();
+        }
+    }
+
     /**
      * The class used to construct a MaterialDialog.
      */
@@ -373,6 +430,8 @@ public class MaterialDialog extends DialogBase implements View.OnClickListener {
         protected CharSequence negativeText;
         protected View customView;
         protected int positiveColor;
+        protected int negativeColor;
+        protected int neutralColor;
         protected SimpleCallback callback;
         protected ListCallback listCallback;
         protected ListCallback listCallbackSingle;
@@ -391,11 +450,28 @@ public class MaterialDialog extends DialogBase implements View.OnClickListener {
                 TypedArray a = context.getTheme().obtainStyledAttributes(new int[]{android.R.attr.colorAccent});
                 try {
                     this.positiveColor = a.getColor(0, materialBlue);
+                    this.negativeColor = a.getColor(0, materialBlue);
+                    this.neutralColor = a.getColor(0, materialBlue);
+                } catch (Exception e) {
+                    this.positiveColor = materialBlue;
+                    this.negativeColor = materialBlue;
+                    this.neutralColor = materialBlue;
                 } finally {
                     a.recycle();
                 }
             } else {
-                this.positiveColor = materialBlue;
+                TypedArray a = context.getTheme().obtainStyledAttributes(new int[]{R.attr.colorAccent});
+                try {
+                    this.positiveColor = a.getColor(0, materialBlue);
+                    this.negativeColor = a.getColor(0, materialBlue);
+                    this.neutralColor = a.getColor(0, materialBlue);
+                } catch (Exception e) {
+                    this.positiveColor = materialBlue;
+                    this.negativeColor = materialBlue;
+                    this.neutralColor = materialBlue;
+                } finally {
+                    a.recycle();
+                }
             }
         }
 
@@ -541,6 +617,16 @@ public class MaterialDialog extends DialogBase implements View.OnClickListener {
             return this;
         }
 
+        public Builder negativeColorRes(@ColorRes int colorRes) {
+            negativeColor(this.context.getResources().getColor(colorRes));
+            return this;
+        }
+
+        public Builder negativeColor(int color) {
+            this.negativeColor = color;
+            return this;
+        }
+
         public Builder callback(SimpleCallback callback) {
             this.callback = callback;
             return this;

+ 0 - 4
library/src/main/java/com/afollestad/materialdialogs/base/DialogBase.java

@@ -22,10 +22,6 @@ public class DialogBase extends AlertDialog {
         super(context);
     }
 
-    public static void setHeight(View view, float height) {
-        setMargin(view, -1, -1, -1, -1, (int) height);
-    }
-
     public static void setMargin(View view, int top, int bottom, int left, int right) {
         setMargin(view, top, bottom, left, right, -1);
     }

+ 40 - 0
library/src/main/java/com/afollestad/materialdialogs/views/MeasureCallbackLinearLayout.java

@@ -0,0 +1,40 @@
+package com.afollestad.materialdialogs.views;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.LinearLayout;
+
+/**
+ * @author Aidan Follestad (afollestad)
+ */
+public class MeasureCallbackLinearLayout extends LinearLayout {
+
+    public MeasureCallbackLinearLayout(Context context) {
+        super(context);
+    }
+
+    public MeasureCallbackLinearLayout(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public MeasureCallbackLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    public static interface Callback {
+        void onMeasureLinear(LinearLayout view);
+    }
+
+    private Callback mCallback;
+
+    public void setCallback(Callback mCallback) {
+        this.mCallback = mCallback;
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        if (mCallback != null)
+            mCallback.onMeasureLinear(this);
+    }
+}

+ 2 - 1
library/src/main/res/layout/dialog_listitem_multichoice.xml

@@ -15,8 +15,9 @@
         android:minHeight="@dimen/listitem_height"
         android:clickable="false"
         android:gravity="center_vertical"
+        android:background="@null"
         android:layout_marginLeft="@dimen/dialog_frame_margin"
-        android:layout_marginRight="@dimen/dialog_frame_margin" />
+        android:layout_marginRight="@dimen/listitem_control_margin" />
 
     <TextView
         android:id="@+id/title"

+ 2 - 1
library/src/main/res/layout/dialog_listitem_singlechoice.xml

@@ -15,8 +15,9 @@
         android:minHeight="@dimen/listitem_height"
         android:clickable="false"
         android:gravity="center_vertical"
+        android:background="@null"
         android:layout_marginLeft="@dimen/dialog_frame_margin"
-        android:layout_marginRight="@dimen/dialog_frame_margin" />
+        android:layout_marginRight="@dimen/listitem_control_margin" />
 
     <TextView
         android:id="@+id/title"

+ 18 - 38
library/src/main/res/layout/material_dialog.xml

@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<com.afollestad.materialdialogs.views.MeasureCallbackLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools"
     android:orientation="vertical"
     android:layout_width="match_parent"
@@ -11,7 +11,7 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_marginTop="@dimen/dialog_frame_margin"
-        android:layout_marginBottom="@dimen/button_frame_margin"
+        android:layout_marginBottom="@dimen/title_margin_bottom"
         android:layout_marginLeft="@dimen/dialog_frame_margin"
         android:layout_marginRight="@dimen/dialog_frame_margin">
 
@@ -19,9 +19,10 @@
             android:id="@+id/title"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_marginBottom="@dimen/button_frame_margin"
+            android:layout_marginBottom="@dimen/title_margin_bottom"
             android:textSize="@dimen/title_textsize"
-            tools:text="Title" />
+            tools:text="Title"
+            android:lineSpacingMultiplier="1.2" />
 
         <TextView
             android:id="@+id/content"
@@ -39,7 +40,8 @@
         android:layout_weight="1"
         android:visibility="gone">
 
-        <ScrollView
+        <com.afollestad.materialdialogs.views.MeasureCallbackScrollView
+            android:id="@+id/customViewScroll"
             android:layout_width="match_parent"
             android:layout_height="wrap_content">
 
@@ -56,13 +58,13 @@
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
                     android:layout_marginTop="@dimen/dialog_frame_margin"
-                    android:layout_marginBottom="@dimen/title_margin_customview"
+                    android:layout_marginBottom="@dimen/title_margin_bottom"
                     android:textSize="@dimen/title_textsize"
                     tools:text="Title" />
 
             </LinearLayout>
 
-        </ScrollView>
+        </com.afollestad.materialdialogs.views.MeasureCallbackScrollView>
 
     </LinearLayout>
 
@@ -72,38 +74,18 @@
         android:layout_height="1dp"
         android:visibility="gone" />
 
-    <LinearLayout
-        android:id="@+id/listFrameScrollParent"
-        android:layout_width="fill_parent"
-        android:layout_height="0dp"
-        android:layout_weight="1"
-        android:visibility="gone">
-
-        <ScrollView
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content">
-
-            <LinearLayout
-                android:id="@+id/listFrame"
-                android:orientation="vertical"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content" />
-
-        </ScrollView>
-
-    </LinearLayout>
-
     <RelativeLayout
         android:id="@+id/buttonDefaultFrame"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_marginLeft="@dimen/button_frame_margin"
-        android:layout_marginRight="@dimen/button_frame_margin">
+        android:layout_marginRight="@dimen/button_padding_frame_side"
+        android:layout_marginBottom="@dimen/button_padding_frame_bottom">
 
         <com.afollestad.materialdialogs.MaterialButton
             android:id="@+id/buttonDefaultNeutral"
             style="@style/ActionButton"
-            android:layout_alignParentLeft="true" />
+            android:layout_alignParentLeft="true"
+            android:layout_marginLeft="@dimen/neutral_button_margin" />
 
         <com.afollestad.materialdialogs.MaterialButton
             android:id="@+id/buttonDefaultNegative"
@@ -122,22 +104,20 @@
         android:orientation="vertical"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_marginLeft="@dimen/button_frame_margin"
-        android:layout_marginRight="@dimen/button_frame_margin"
-        android:gravity="right">
+        android:layout_marginBottom="@dimen/button_padding_frame_bottom">
 
         <com.afollestad.materialdialogs.MaterialButton
             android:id="@+id/buttonStackedPositive"
-            style="@style/ActionButton" />
+            style="@style/ActionButtonStacked" />
 
         <com.afollestad.materialdialogs.MaterialButton
             android:id="@+id/buttonStackedNegative"
-            style="@style/ActionButton" />
+            style="@style/ActionButtonStacked" />
 
         <com.afollestad.materialdialogs.MaterialButton
             android:id="@+id/buttonStackedNeutral"
-            style="@style/ActionButton" />
+            style="@style/ActionButtonStacked" />
 
     </LinearLayout>
 
-</LinearLayout>
+</com.afollestad.materialdialogs.views.MeasureCallbackLinearLayout>

+ 0 - 7
library/src/main/res/values-v14/dimens.xml

@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-
-    <!-- Regular button height + 4dp to compensate for padding issues on older versions -->
-    <dimen name="button_height">40dp</dimen>
-
-</resources>

+ 0 - 27
library/src/main/res/values-v14/styles.xml

@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-
-    <style name="Light" parent="android:Theme.Holo.Light">
-        <item name="android:actionModeStyle">@style/ActionModeStyle</item>
-
-        <item name="title_color">@color/title_light</item>
-        <item name="content_color">@color/content_light</item>
-        <item name="item_color">@color/item_light</item>
-        <item name="button_color">@color/button_light</item>
-        <item name="divider_color">@color/divider_black</item>
-    </style>
-
-    <style name="Dark" parent="android:Theme.Holo">
-        <item name="title_color">@color/title_dark</item>
-        <item name="content_color">@color/content_dark</item>
-        <item name="item_color">@color/item_dark</item>
-        <item name="button_color">@color/button_dark</item>
-        <item name="divider_color">@color/divider_white</item>
-    </style>
-
-    <style name="ActionButton" parent="@style/_ActionButtonParent">
-        <item name="android:layout_marginLeft">@dimen/button_padding</item>
-        <item name="android:layout_marginRight">@dimen/button_padding</item>
-    </style>
-
-</resources>

+ 0 - 6
library/src/main/res/values-v19/styles.xml

@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-
-    <style name="ActionButton" parent="@style/_ActionButtonParent" />
-
-</resources>

+ 0 - 2
library/src/main/res/values-v21/styles.xml

@@ -17,6 +17,4 @@
         <item name="divider_color">@color/divider_white</item>
     </style>
 
-    <style name="ActionButton" parent="@style/_ActionButtonParent" />
-
 </resources>

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

@@ -4,7 +4,7 @@
     <color name="title_light">#000000</color>
     <color name="title_dark">#FFFFFF</color>
 
-    <color name="content_light">#444444</color>
+    <color name="content_light">#5E5E5E</color>
     <color name="content_dark">#EDEDED</color>
 
     <color name="item_light">#535353</color>

+ 14 - 8
library/src/main/res/values/dimens.xml

@@ -1,20 +1,26 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
 
-    <dimen name="dialog_frame_margin">24dp</dimen>
+    <!-- See http://www.google.com/design/spec/components/dialogs.html#dialogs-specs -->
 
-    <dimen name="button_height">36dp</dimen>
-    <dimen name="button_height_customview">56dp</dimen>
+    <dimen name="dialog_frame_margin">24dp</dimen>
+    <dimen name="title_margin_bottom">16dp</dimen>
 
-    <dimen name="title_margin_customview">24dp</dimen>
-    <dimen name="button_frame_margin">16dp</dimen>
-    <dimen name="button_min_width">56dp</dimen>
-    <dimen name="button_padding">8dp</dimen>
+    <!-- Above and below buttons, 36+12=48 for the height of the button frame -->
+    <dimen name="button_padding_vertical">12dp</dimen>
+    <dimen name="button_padding_horizontal_internal">8dp</dimen>
+    <dimen name="button_padding_horizontal_external">8dp</dimen>
+    <dimen name="button_padding_horizontal_internalexternal">32dp</dimen>
+    <dimen name="button_padding_frame_side">16dp</dimen>
+    <dimen name="button_padding_frame_bottom">8dp</dimen>
+    <dimen name="button_height">48dp</dimen>
+    <dimen name="neutral_button_margin">16dp</dimen>
 
     <dimen name="title_textsize">20sp</dimen>
-    <dimen name="content_textsize">16sp</dimen>
+    <dimen name="content_textsize">18sp</dimen>
     <dimen name="button_textsize">14sp</dimen>
     <dimen name="listitem_textsize">16sp</dimen>
     <dimen name="listitem_height">48dp</dimen>
+    <dimen name="listitem_control_margin">16dp</dimen>
 
 </resources>

+ 0 - 8
library/src/main/res/values/strings.xml

@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-
-    <string name="decline">Decline</string>
-    <string name="accept">Accept</string>
-    <string name="more_info">More Info</string>
-
-</resources>

+ 20 - 6
library/src/main/res/values/styles.xml

@@ -19,17 +19,30 @@
         <item name="divider_color">@color/divider_white</item>
     </style>
 
-    <style name="ActionButton" parent="@style/_ActionButtonParent" />
+    <style name="ActionButtonStacked" parent="@style/ActionButton">
+        <item name="android:layout_width">match_parent</item>
+        <item name="android:gravity">right|center_vertical</item>
 
-    <style name="_ActionButtonParent">
+        <item name="android:paddingLeft">@dimen/button_padding_horizontal_internalexternal</item>
+        <item name="android:paddingRight">@dimen/button_padding_horizontal_internalexternal</item>
+        <item name="android:layout_marginLeft">0dp</item>
+    </style>
+
+    <style name="ActionButton">
         <item name="android:layout_width">wrap_content</item>
-        <item name="android:layout_height">@dimen/button_height</item>
-        <item name="android:text">@string/accept</item>
-        <item name="android:minWidth">@dimen/button_min_width</item>
+        <item name="android:text">@android:string/ok</item>
         <item name="android:textSize">@dimen/button_textsize</item>
         <item name="android:textAllCaps">true</item>
         <item name="android:gravity">center</item>
-        <item name="android:padding">@dimen/button_padding</item>
+
+        <item name="android:layout_height">@dimen/button_height</item>
+        <item name="android:minWidth">@dimen/button_min_width</item>
+
+        <item name="android:paddingTop">@dimen/button_padding_vertical</item>
+        <item name="android:paddingBottom">@dimen/button_padding_vertical</item>
+        <item name="android:paddingLeft">@dimen/button_padding_horizontal_internal</item>
+        <item name="android:paddingRight">@dimen/button_padding_horizontal_internal</item>
+        <item name="android:layout_marginLeft">@dimen/button_padding_horizontal_external</item>
     </style>
 
     <style name="ActionModeStyle" parent="Widget.AppCompat.ActionMode">
@@ -38,4 +51,5 @@
         <item name="android:actionModeCloseDrawable">@drawable/ic_action_close</item>
     </style>
 
+    <dimen name="button_min_width">64dp</dimen>
 </resources>

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

@@ -102,26 +102,26 @@ public class MainActivity extends ActionBarActivity {
     private void showBasicNoTitle() {
         new MaterialDialog.Builder(this)
                 .content(R.string.shareLocationPrompt)
-                .positiveText(R.string.accept)  // the default is 'Accept', this line could be left out
-                .negativeText(R.string.decline)  // leaving this line out will remove the negative button
+                .positiveText(R.string.agree)  // the default is 'Accept', this line could be left out
+                .negativeText(R.string.disagree)  // leaving this line out will remove the negative button
                 .build()
                 .show();
     }
 
     private void showBasic() {
         new MaterialDialog.Builder(this)
-                .title(R.string.permissions)
-                .content(R.string.permissionsContent)
-                .positiveText(R.string.accept)  // the default is 'Accept', this line could be left out
-                .negativeText(R.string.decline)  // leaving this line out will remove the negative button
+                .title(R.string.useGoogleLocationServices)
+                .content(R.string.useGoogleLocationServicesPrompt)
+                .positiveText(R.string.agree)  // the default is 'Accept', this line could be left out
+                .negativeText(R.string.disagree)  // leaving this line out will remove the negative button
                 .build()
                 .show();
     }
 
     private void showStacked() {
         new MaterialDialog.Builder(this)
-                .title(R.string.permissions)
-                .content(R.string.permissionsContent)
+                .title(R.string.useGoogleLocationServices)
+                .content(R.string.useGoogleLocationServicesPrompt)
                 .positiveText(R.string.speedBoost)
                 .negativeText(R.string.noThanks)
                 .build()
@@ -130,10 +130,10 @@ public class MainActivity extends ActionBarActivity {
 
     private void showNeutral() {
         new MaterialDialog.Builder(this)
-                .title(R.string.permissions)
-                .content(R.string.permissionsContent)
-                .positiveText(R.string.accept)
-                .negativeText(R.string.decline)
+                .title(R.string.useGoogleLocationServices)
+                .content(R.string.useGoogleLocationServicesPrompt)
+                .positiveText(R.string.agree)
+                .negativeText(R.string.disagree)
                 .neutralText(R.string.more_info)
                 .build()
                 .show();
@@ -141,10 +141,10 @@ public class MainActivity extends ActionBarActivity {
 
     private void showCallbacks() {
         new MaterialDialog.Builder(this)
-                .title(R.string.permissions)
-                .content(R.string.permissionsContent)
-                .positiveText(R.string.accept)
-                .negativeText(R.string.decline)
+                .title(R.string.useGoogleLocationServices)
+                .content(R.string.useGoogleLocationServicesPrompt)
+                .positiveText(R.string.agree)
+                .negativeText(R.string.disagree)
                 .neutralText(R.string.more_info)
                 .callback(new MaterialDialog.FullCallback() {
                     @Override
@@ -223,7 +223,7 @@ public class MainActivity extends ActionBarActivity {
     private void showCustomView() {
         MaterialDialog dialog = new MaterialDialog.Builder(this)
                 .title(R.string.googleWifi)
-                .positiveText(R.string.accept)
+                .positiveText(R.string.agree)
                 .customView(R.layout.dialog_customview)
                 .positiveText(R.string.connect)
                 .negativeText(android.R.string.cancel)
@@ -270,11 +270,12 @@ public class MainActivity extends ActionBarActivity {
 
     private void showThemed() {
         new MaterialDialog.Builder(this)
-                .title(R.string.permissions)
-                .content(R.string.permissionsContent)
-                .positiveText(R.string.accept)
-                .negativeText(R.string.decline)
+                .title(R.string.useGoogleLocationServices)
+                .content(R.string.useGoogleLocationServicesPrompt)
+                .positiveText(R.string.agree)
+                .negativeText(R.string.disagree)
                 .positiveColorRes(R.color.material_red_400)
+                .negativeColorRes(R.color.material_red_400)
                 .titleAlignment(Alignment.CENTER)
                 .titleColorRes(R.color.material_red_400)
                 .theme(Theme.DARK)

+ 17 - 2
sample/src/main/res/values/strings.xml

@@ -2,6 +2,10 @@
 
     <string name="app_name">MaterialDialogs</string>
 
+    <string name="agree">Agree</string>
+    <string name="disagree">Disagree</string>
+    <string name="more_info">More Info</string>
+
     <string name="basic">Basic</string>
     <string name="stacked">Stacked Buttons</string>
     <string name="neutral">Neutral Button</string>
@@ -17,8 +21,8 @@
     <string name="securityType">802.1x EAP</string>
     <string name="password">Password</string>
     <string name="showPassword">Show password</string>
-    <string name="permissions">Permissions</string>
-    <string name="permissionsContent">This app determines your phone\'s location and shares it with Google in order to serve personalized alerts to you. This allows for a better overall app experience.</string>
+    <string name="useGoogleLocationServices">Use Google\'s Location Services?</string>
+    <string name="useGoogleLocationServicesPrompt">Let Google help apps determine location. This means sending anonymous location data to Google, even when no apps are running.</string>
     <string name="socialNetworks">Social Networks</string>
     <string name="choose">Choose</string>
     <string name="speedBoost">Turn on speed boost</string>
@@ -44,6 +48,17 @@
         <item>Google+</item>
         <item>Instagram</item>
         <item>Facebook</item>
+        <item>Hello</item>
+        <item>Hello</item>
+        <item>Hello</item>
+        <item>Hello</item>
+        <item>Hello</item>
+        <item>Hello</item>
+        <item>Hello</item>
+        <item>Hello</item>
+        <item>Hello</item>
+        <item>Hello</item>
+        <item>Hello</item>
     </string-array>
 
 </resources>