Răsfoiți Sursa

Merge remote-tracking branch 'upstream/master'

Juan Ramon Gonzalez Gonzalez 10 ani în urmă
părinte
comite
56bee4d494

+ 15 - 10
README.md

@@ -1,21 +1,26 @@
 # Material Dialogs
 
-This library was designed to solve a personal problem with my apps, I use AppCompat to use
-Material theming on versions of Android below Lollipop. However, despite being able to theme everything else,
-AppCompat doesn't theme AlertDialogs with Material design. This library allows you to use consistently Material
-themed dialogs on all versions of Android, along with specific customizations that make it easier to brand the dialog.
-
 The code you see below is also found in the sample project. You can download a APK of the sample here: https://github.com/afollestad/material-dialogs/blob/master/sample/sample.apk. The sample's also available on Google Play: https://play.google.com/store/apps/details?id=com.afollestad.materialdialogssample.
 
 ---
 
+### What's New
+
+###### 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.
+
+---
+
 ### Gradle Dependency (jCenter)
 
 Easily reference the library in your Android projects using this dependency in your module's `build.gradle` file:
 
 ```Groovy
 dependencies {
-    compile 'com.afollestad:material-dialogs:0.1.2'
+    compile 'com.afollestad:material-dialogs:0.2.0'
 }
 ```
 
@@ -37,8 +42,8 @@ new MaterialDialog.Builder(this)
         .title("Use Google's Location Services?")
         .content("Let Google help apps determine location. This means sending anonymous location data to Google, even when no apps are running.")
         .theme(Theme.LIGHT)  // the default is light, so you don't need this line
-        .positiveText("Agree")  // the default for textual dialogs (not list or custom view dialogs) is 'OK'
-        .negativeText("Disagree")  // leaving this line out will remove the negative button
+        .positiveText("Agree")
+        .negativeText("Disagree")
         .build()
         .show();
 ```
@@ -59,7 +64,7 @@ Drawable d = // ... get from somewhere...
 new MaterialDialog.Builder(this)
         .title("Use Google's Location Services?")
         .content("Let Google help apps determine location. This means sending anonymous location data to Google, even when no apps are running.")
-        .positiveText("Agree")  // the default for textual dialogs (not list or custom view dialogs) is 'OK'
+        .positiveText("Agree")
         .icon(d)
         .build()
         .show();
@@ -237,7 +242,7 @@ new MaterialDialog.Builder(this)
 
 If you want to preselect item(s), pass an array of indices in place of null in `itemsCallbackSingleChoice()`.
 For an example, `new Integer[] { 2, 5 }`. If `autoDismiss` is turned off, then you must manually
-dismiss the dialog in the callback. Auto dismiss is on by default. When `positiveText()` is not used, the
+dismiss the dialog in the callback. Auto dismiss is on by default. When action buttons are not added, the
 callback will be called every time you select an item since no action is available to press, without the
 dialog being dismissed. You can pass `positiveText()` or the other action buttons to the builder to force
 it to display the action buttons below your list, however this is only useful in some specific cases.

+ 1 - 1
build.gradle

@@ -4,7 +4,7 @@ buildscript {
     }
     dependencies {
         classpath 'com.android.tools.build:gradle:0.14.4'
-        classpath 'com.novoda:android-bintray-release:0.2.3'
+        classpath 'com.novoda:bintray-release:0.2.4'
     }
 }
 

+ 6 - 6
library/build.gradle

@@ -1,5 +1,5 @@
 apply plugin: 'com.android.library'
-apply plugin: 'android-bintray-release'
+apply plugin: 'bintray-release'
 
 android {
     compileSdkVersion 21
@@ -7,10 +7,10 @@ android {
 
     defaultConfig {
         applicationId "com.afollestad.materialdialogs"
-        minSdkVersion 9
+        minSdkVersion 14
         targetSdkVersion 21
         versionCode 1
-        versionName "0.1.2"
+        versionName "0.2.0"
     }
     buildTypes {
         release {
@@ -25,15 +25,15 @@ android {
 
 dependencies {
     compile fileTree(dir: 'libs', include: ['*.jar'])
-    compile 'com.android.support:appcompat-v7:21.0.2'
-    compile 'com.android.support:support-annotations:21.0.2'
+    compile 'com.android.support:appcompat-v7:21.+'
+    compile 'com.android.support:support-annotations:21.+'
 }
 
 publish {
     userOrg = 'drummer-aidan'
     groupId = 'com.afollestad'
     artifactId = 'material-dialogs'
-    version = '0.1.2'
+    version = '0.2.0'
     description = 'A library for implementing Material design styled dialogs across all versions of Android.'
     website = 'https://github.com/afollestad/material-dialogs'
     issueTracker = "${website}/issues"

+ 57 - 28
library/src/main/java/com/afollestad/materialdialogs/MaterialDialog.java

@@ -25,6 +25,7 @@ import android.widget.CheckBox;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.RadioButton;
+import android.widget.RelativeLayout;
 import android.widget.ScrollView;
 import android.widget.TextView;
 
@@ -139,16 +140,14 @@ public class MaterialDialog extends DialogBase implements View.OnClickListener,
             icon.setVisibility(View.GONE);
         }
 
-        if ((negativeText != null || neutralText != null) && positiveText == null)
-            positiveText = getContext().getString(android.R.string.ok);
         if (items != null && items.length > 0)
             title = (TextView) view.findViewById(R.id.titleCustomView);
-        else if (positiveText == null && customView == null)
-            positiveText = getContext().getString(android.R.string.ok);
 
         // 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()) {
             titleFrame.setVisibility(View.GONE);
+            if (customView == null)
+                view.findViewById(R.id.titleFrameCustomView).setVisibility(View.GONE);
         } else {
             title.setText(builder.title);
             setTypeface(title, mediumFont);
@@ -272,7 +271,7 @@ public class MaterialDialog extends DialogBase implements View.OnClickListener,
         } else {
             listPaddingBottom = (int) getContext().getResources().getDimension(R.dimen.md_main_frame_margin);
         }
-        if (positiveText != null) listPaddingBottom = 0;
+        if (hasActionButtons()) listPaddingBottom = 0;
         customFrame.setPadding(customFrame.getPaddingLeft(), customFrame.getPaddingTop(),
                 customFrame.getPaddingRight(), listPaddingBottom);
 
@@ -333,33 +332,29 @@ public class MaterialDialog extends DialogBase implements View.OnClickListener,
         return (dialogWidth - sixteenDp - sixteenDp - eightDp) / 2;
     }
 
+    /**
+     * Detects whether or not the custom view or list content can be scrolled.
+     */
     private boolean canCustomViewScroll() {
-        /**
-         * Detects whether or not the custom view or list content can be scrolled.
-         */
         final ScrollView scrollView = (ScrollView) view.findViewById(R.id.customViewScroll);
         final int childHeight = view.findViewById(R.id.customViewFrame).getMeasuredHeight();
         return scrollView.getMeasuredHeight() < childHeight;
     }
 
+    /**
+     * Detects whether or not the content TextView can be scrolled.
+     */
     private boolean canContentScroll() {
-        /**
-         * Detects whether or not the custom view or list content can be scrolled.
-         */
         final ScrollView scrollView = (ScrollView) view.findViewById(R.id.contentScrollView);
         final int childHeight = view.findViewById(R.id.content).getMeasuredHeight();
         return scrollView.getMeasuredHeight() < childHeight;
     }
 
+    /**
+     * Measures the action button's and their text to decide whether or not the button should be stacked.
+     */
     private void checkIfStackingNeeded() {
-        /**
-         * Measures the action button's and their text to decide whether or not the button should be stacked.
-         */
-        if (((negativeButton == null || negativeButton.getVisibility() == View.GONE) &&
-                (neutralButton == null || neutralButton.getVisibility() == View.GONE))) {
-            // Stacking isn't necessary if you only have one button
-            return;
-        }
+        if (numberOfActionButtons() <= 1) return;
         final int maxWidth = calculateMaxButtonWidth();
         final Paint paint = positiveButton.getPaint();
         final int eightDp = (int) getContext().getResources().getDimension(R.dimen.md_button_padding_horizontal_external);
@@ -376,12 +371,12 @@ public class MaterialDialog extends DialogBase implements View.OnClickListener,
         invalidateActions();
     }
 
+    /**
+     * Invalidates the positive/neutral/negative action buttons. Decides whether they should be visible
+     * and sets their properties (such as height, text color, etc.).
+     */
     private boolean invalidateActions() {
-        /**
-         * Invalidates the positive/neutral/negative action buttons. Decides whether they should be visible
-         * and sets their properties (such as height, text color, etc.).
-         */
-        if (positiveText == null) {
+        if (!hasActionButtons()) {
             // If the dialog is a plain list dialog, no buttons are shown.
             view.findViewById(R.id.buttonDefaultFrame).setVisibility(View.GONE);
             view.findViewById(R.id.buttonStackedFrame).setVisibility(View.GONE);
@@ -434,6 +429,18 @@ public class MaterialDialog extends DialogBase implements View.OnClickListener,
             negativeButton.setText(this.negativeText);
             negativeButton.setTag(NEGATIVE);
             negativeButton.setOnClickListener(this);
+
+            if (!isStacked) {
+                RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
+                        RelativeLayout.LayoutParams.WRAP_CONTENT,
+                        (int) getContext().getResources().getDimension(R.dimen.md_button_height));
+                if (this.positiveText != null) {
+                    params.addRule(RelativeLayout.LEFT_OF, R.id.buttonDefaultPositive);
+                } else {
+                    params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
+                }
+                negativeButton.setLayoutParams(params);
+            }
         } else {
             negativeButton.setVisibility(View.GONE);
         }
@@ -456,8 +463,8 @@ public class MaterialDialog extends DialogBase implements View.OnClickListener,
     }
 
     private void sendMultichoiceCallback() {
-        List<Integer> selectedIndices = new ArrayList<>();
-        List<CharSequence> selectedTitles = new ArrayList<>();
+        List<Integer> selectedIndices = new ArrayList<Integer>();
+        List<CharSequence> selectedTitles = new ArrayList<CharSequence>();
         LinearLayout list = (LinearLayout) view.findViewById(R.id.customViewFrame);
         for (int i = 1; i < list.getChildCount(); i++) {
             View itemView = list.getChildAt(i);
@@ -508,14 +515,14 @@ public class MaterialDialog extends DialogBase implements View.OnClickListener,
                 if (!cb.isChecked())
                     cb.setChecked(true);
                 invalidateSingleChoice(index);
-                if (positiveText == null) {
+                if (!hasActionButtons()) {
                     // Immediately send the selection callback without dismissing if no action buttons are shown
                     sendSingleChoiceCallback(v);
                 }
             } else if (listCallbackMulti != null) {
                 CheckBox cb = (CheckBox) ((LinearLayout) v).getChildAt(0);
                 cb.setChecked(!cb.isChecked());
-                if (positiveText == null) {
+                if (!hasActionButtons()) {
                     // Immediately send the selection callback without dismissing if no action buttons are shown
                     sendMultichoiceCallback();
                 }
@@ -931,6 +938,28 @@ public class MaterialDialog extends DialogBase implements View.OnClickListener,
         setActionButton(which, getContext().getString(titleRes));
     }
 
+    /**
+     * Gets whether or not the positive, neutral, or negative action button is visible.
+     *
+     * @return Whether or not 1 or more action buttons is visible.
+     */
+    public final boolean hasActionButtons() {
+        return numberOfActionButtons() > 0;
+    }
+
+    /**
+     * Gets the number of visible action buttons.
+     *
+     * @return 0 through 3, depending on how many should be or are visible.
+     */
+    public final int numberOfActionButtons() {
+        int number = 0;
+        if (positiveText != null) number++;
+        if (neutralText != null) number++;
+        if (negativeText != null) number++;
+        return number;
+    }
+
     /**
      * Updates the dialog's title.
      */

+ 2 - 2
library/src/main/res/layout/md_dialog.xml

@@ -128,10 +128,10 @@
             android:layout_alignParentLeft="true"
             android:layout_marginLeft="@dimen/md_neutral_button_margin" />
 
+        <!-- toLeftOf rule added from invalidateActions() -->
         <TextView
             android:id="@+id/buttonDefaultNegative"
-            style="@style/MD_ActionButton"
-            android:layout_toLeftOf="@+id/buttonDefaultPositive" />
+            style="@style/MD_ActionButton" />
 
         <TextView
             android:id="@+id/buttonDefaultPositive"

+ 2 - 2
sample/build.gradle

@@ -8,8 +8,8 @@ android {
         applicationId "com.afollestad.materialdialogssample"
         minSdkVersion 14
         targetSdkVersion 21
-        versionCode 31
-        versionName "0.1.2"
+        versionCode 32
+        versionName "0.2.0"
     }
     buildTypes {
 //        release {

BIN
sample/sample.apk


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

@@ -132,8 +132,8 @@ public class MainActivity extends ActionBarActivity {
     private void showBasicNoTitle() {
         new MaterialDialog.Builder(this)
                 .content(R.string.shareLocationPrompt)
-                .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
+                .positiveText(R.string.agree)
+                .negativeText(R.string.disagree)
                 .build()
                 .show();
     }
@@ -142,8 +142,8 @@ public class MainActivity extends ActionBarActivity {
         new MaterialDialog.Builder(this)
                 .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
+                .positiveText(R.string.agree)
+                .negativeText(R.string.disagree)
                 .build()
                 .show();
     }
@@ -152,8 +152,8 @@ public class MainActivity extends ActionBarActivity {
         new MaterialDialog.Builder(this)
                 .title(R.string.useGoogleLocationServices)
                 .content(R.string.loremIpsum)
-                .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
+                .positiveText(R.string.agree)
+                .negativeText(R.string.disagree)
                 .build()
                 .show();
     }
@@ -163,8 +163,8 @@ public class MainActivity extends ActionBarActivity {
                 .icon(R.drawable.ic_launcher)
                 .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
+                .positiveText(R.string.agree)
+                .negativeText(R.string.disagree)
                 .build()
                 .show();
     }