├── versions.properties
├── sample
├── .gitignore
├── ic_web.png
├── sample.apk
├── keystore.jks
├── src
│ └── main
│ │ ├── res
│ │ ├── drawable-hdpi
│ │ │ ├── ic_check.png
│ │ │ ├── ic_launcher.png
│ │ │ ├── ic_circle_darker.png
│ │ │ └── ic_circle_lighter.png
│ │ ├── drawable-mdpi
│ │ │ ├── ic_check.png
│ │ │ ├── ic_launcher.png
│ │ │ ├── ic_circle_darker.png
│ │ │ └── ic_circle_lighter.png
│ │ ├── drawable-xhdpi
│ │ │ ├── ic_check.png
│ │ │ ├── ic_launcher.png
│ │ │ ├── ic_circle_darker.png
│ │ │ └── ic_circle_lighter.png
│ │ ├── drawable-xxhdpi
│ │ │ ├── ic_check.png
│ │ │ ├── ic_launcher.png
│ │ │ ├── ic_circle_darker.png
│ │ │ └── ic_circle_lighter.png
│ │ ├── drawable-xxxhdpi
│ │ │ └── ic_launcher.png
│ │ ├── values
│ │ │ ├── integers.xml
│ │ │ ├── colors.xml
│ │ │ ├── styles.xml
│ │ │ ├── dimens.xml
│ │ │ ├── arrays.xml
│ │ │ └── strings.xml
│ │ ├── values-land
│ │ │ └── integers.xml
│ │ ├── values-v21
│ │ │ ├── dimens.xml
│ │ │ └── styles.xml
│ │ ├── values-w720dp
│ │ │ └── dimens.xml
│ │ ├── menu
│ │ │ └── main.xml
│ │ ├── values-large
│ │ │ └── dimens.xml
│ │ ├── drawable-v21
│ │ │ ├── md_btn_selector_custom.xml
│ │ │ └── md_btn_selector_custom_holo.xml
│ │ ├── layout
│ │ │ ├── preference_activity_custom.xml
│ │ │ ├── dialog_webview.xml
│ │ │ ├── dialog_customlistitem.xml
│ │ │ ├── preference_custom.xml
│ │ │ ├── dialog_customview.xml
│ │ │ ├── preference_list_fragment.xml
│ │ │ └── activity_main.xml
│ │ ├── values-sw320dp
│ │ │ └── dimens.xml
│ │ ├── drawable
│ │ │ ├── md_btn_selector_custom.xml
│ │ │ ├── md_btn_selected_custom.xml
│ │ │ └── md_btn_unselected_custom.xml
│ │ ├── xml
│ │ │ └── preferences.xml
│ │ └── xml-v11
│ │ │ └── preferences.xml
│ │ ├── java
│ │ └── com
│ │ │ └── afollestad
│ │ │ └── materialdialogssample
│ │ │ ├── PreferenceActivityCompat.java
│ │ │ ├── PreferenceActivity.java
│ │ │ ├── ButtonItemAdapter.java
│ │ │ ├── ChangelogDialog.java
│ │ │ └── FolderSelectorDialog.java
│ │ ├── assets
│ │ └── changelog.html
│ │ └── AndroidManifest.xml
├── proguard-rules.pro
└── build.gradle
├── library
├── .gitignore
├── src
│ └── main
│ │ ├── AndroidManifest.xml
│ │ ├── res
│ │ ├── values
│ │ │ ├── bool.xml
│ │ │ ├── strings.xml
│ │ │ ├── colors.xml
│ │ │ ├── attrs.xml
│ │ │ ├── styles.xml
│ │ │ └── dimens.xml
│ │ ├── values-sw600dp
│ │ │ ├── bool.xml
│ │ │ └── dimens.xml
│ │ ├── values-sw720dp
│ │ │ ├── bool.xml
│ │ │ └── dimens.xml
│ │ ├── anim
│ │ │ ├── decelerate_cubic.xml
│ │ │ ├── popup_enter.xml
│ │ │ └── popup_exit.xml
│ │ ├── drawable
│ │ │ ├── md_item_selected.xml
│ │ │ ├── md_transparent.xml
│ │ │ ├── md_item_selected_dark.xml
│ │ │ ├── md_selector.xml
│ │ │ ├── md_btn_selector.xml
│ │ │ ├── md_selector_dark.xml
│ │ │ ├── md_btn_selector_dark.xml
│ │ │ ├── md_btn_selected.xml
│ │ │ └── md_btn_selected_dark.xml
│ │ ├── drawable-v21
│ │ │ ├── md_btn_selector_ripple.xml
│ │ │ ├── md_btn_selector_ripple_dark.xml
│ │ │ └── md_btn_shape.xml
│ │ ├── layout
│ │ │ ├── md_dialog_custom.xml
│ │ │ ├── md_dialog_progress_indeterminate.xml
│ │ │ ├── md_stub_actionbuttons.xml
│ │ │ ├── md_stub_progress_indeterminate_horizontal.xml
│ │ │ ├── md_listitem.xml
│ │ │ ├── md_dialog_progress.xml
│ │ │ ├── md_dialog_progress_indeterminate_horizontal.xml
│ │ │ ├── md_stub_inputpref.xml
│ │ │ ├── md_stub_titleframe.xml
│ │ │ ├── md_stub_progress_indeterminate.xml
│ │ │ ├── md_dialog_basic.xml
│ │ │ ├── md_simplelist_item.xml
│ │ │ ├── md_listitem_multichoice.xml
│ │ │ ├── md_listitem_singlechoice.xml
│ │ │ ├── md_dialog_list.xml
│ │ │ ├── md_stub_progress.xml
│ │ │ └── md_dialog_input.xml
│ │ ├── layout-ldrtl
│ │ │ ├── md_simplelist_item.xml
│ │ │ ├── md_listitem_multichoice.xml
│ │ │ └── md_listitem_singlechoice.xml
│ │ ├── values-v21
│ │ │ └── styles.xml
│ │ └── values-v11
│ │ │ └── styles.xml
│ │ └── java
│ │ └── com
│ │ └── afollestad
│ │ └── materialdialogs
│ │ ├── ProgressStyle.java
│ │ ├── Theme.java
│ │ ├── DialogAction.java
│ │ ├── GravityEnum.java
│ │ ├── util
│ │ ├── TypefaceHelper.java
│ │ └── DialogUtils.java
│ │ ├── simplelist
│ │ ├── MaterialSimpleListItem.java
│ │ └── MaterialSimpleListAdapter.java
│ │ ├── ThemeSingleton.java
│ │ ├── DialogBase.java
│ │ ├── internal
│ │ ├── MDButton.java
│ │ ├── MDTintHelper.java
│ │ └── CircleView.java
│ │ ├── MaterialDialogAdapter.java
│ │ ├── prefs
│ │ ├── MaterialDialogPreference.java
│ │ ├── MaterialListPreference.java
│ │ ├── MaterialMultiSelectListPreference.java
│ │ └── MaterialEditTextPreference.java
│ │ └── progress
│ │ └── CircularProgressDrawable.java
├── proguard-rules.pro
└── build.gradle
├── settings.gradle
├── art
└── mdshowcase.png
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── LICENSE.txt
├── .gitignore
├── gradlew.bat
└── gradlew
/versions.properties:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/sample/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/library/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':library', ':sample'
2 |
--------------------------------------------------------------------------------
/sample/ic_web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PDDStudio/material-dialogs/master/sample/ic_web.png
--------------------------------------------------------------------------------
/sample/sample.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PDDStudio/material-dialogs/master/sample/sample.apk
--------------------------------------------------------------------------------
/art/mdshowcase.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PDDStudio/material-dialogs/master/art/mdshowcase.png
--------------------------------------------------------------------------------
/sample/keystore.jks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PDDStudio/material-dialogs/master/sample/keystore.jks
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PDDStudio/material-dialogs/master/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/library/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/library/src/main/res/values/bool.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | false
4 |
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-hdpi/ic_check.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PDDStudio/material-dialogs/master/sample/src/main/res/drawable-hdpi/ic_check.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-mdpi/ic_check.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PDDStudio/material-dialogs/master/sample/src/main/res/drawable-mdpi/ic_check.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xhdpi/ic_check.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PDDStudio/material-dialogs/master/sample/src/main/res/drawable-xhdpi/ic_check.png
--------------------------------------------------------------------------------
/library/src/main/res/values-sw600dp/bool.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | true
4 |
--------------------------------------------------------------------------------
/library/src/main/res/values-sw720dp/bool.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | true
4 |
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PDDStudio/material-dialogs/master/sample/src/main/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PDDStudio/material-dialogs/master/sample/src/main/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxhdpi/ic_check.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PDDStudio/material-dialogs/master/sample/src/main/res/drawable-xxhdpi/ic_check.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PDDStudio/material-dialogs/master/sample/src/main/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PDDStudio/material-dialogs/master/sample/src/main/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PDDStudio/material-dialogs/master/sample/src/main/res/drawable-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-hdpi/ic_circle_darker.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PDDStudio/material-dialogs/master/sample/src/main/res/drawable-hdpi/ic_circle_darker.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-mdpi/ic_circle_darker.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PDDStudio/material-dialogs/master/sample/src/main/res/drawable-mdpi/ic_circle_darker.png
--------------------------------------------------------------------------------
/library/src/main/res/values-sw600dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 446dp
4 |
--------------------------------------------------------------------------------
/library/src/main/res/values-sw720dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 480dp
4 |
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-hdpi/ic_circle_lighter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PDDStudio/material-dialogs/master/sample/src/main/res/drawable-hdpi/ic_circle_lighter.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-mdpi/ic_circle_lighter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PDDStudio/material-dialogs/master/sample/src/main/res/drawable-mdpi/ic_circle_lighter.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xhdpi/ic_circle_darker.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PDDStudio/material-dialogs/master/sample/src/main/res/drawable-xhdpi/ic_circle_darker.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xhdpi/ic_circle_lighter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PDDStudio/material-dialogs/master/sample/src/main/res/drawable-xhdpi/ic_circle_lighter.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxhdpi/ic_circle_darker.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PDDStudio/material-dialogs/master/sample/src/main/res/drawable-xxhdpi/ic_circle_darker.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxhdpi/ic_circle_lighter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PDDStudio/material-dialogs/master/sample/src/main/res/drawable-xxhdpi/ic_circle_lighter.png
--------------------------------------------------------------------------------
/sample/src/main/res/values/integers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 4
5 |
6 |
--------------------------------------------------------------------------------
/library/src/main/java/com/afollestad/materialdialogs/ProgressStyle.java:
--------------------------------------------------------------------------------
1 | package com.afollestad.materialdialogs;
2 |
3 | public enum ProgressStyle {
4 | CIRCULAR, HORIZONTAL
5 | }
--------------------------------------------------------------------------------
/sample/src/main/res/values-land/integers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 5
5 |
6 |
--------------------------------------------------------------------------------
/library/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Back
4 | Done
5 |
--------------------------------------------------------------------------------
/library/src/main/res/anim/decelerate_cubic.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/library/src/main/java/com/afollestad/materialdialogs/Theme.java:
--------------------------------------------------------------------------------
1 | package com.afollestad.materialdialogs;
2 |
3 | /**
4 | * @author Aidan Follestad (afollestad)
5 | */
6 | public enum Theme {
7 | LIGHT, DARK
8 | }
--------------------------------------------------------------------------------
/sample/src/main/res/values-v21/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 8dp
6 |
7 |
--------------------------------------------------------------------------------
/sample/src/main/res/values-w720dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 32dp
6 |
7 |
--------------------------------------------------------------------------------
/sample/src/main/res/menu/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/library/src/main/res/drawable/md_item_selected.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
--------------------------------------------------------------------------------
/library/src/main/res/drawable/md_transparent.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
--------------------------------------------------------------------------------
/sample/src/main/res/values-large/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 8dp
4 | 32dp
5 | 32dp
6 |
7 |
8 |
--------------------------------------------------------------------------------
/library/src/main/java/com/afollestad/materialdialogs/DialogAction.java:
--------------------------------------------------------------------------------
1 | package com.afollestad.materialdialogs;
2 |
3 | /**
4 | * @author Aidan Follestad (afollestad)
5 | */
6 | public enum DialogAction {
7 | POSITIVE,
8 | NEUTRAL,
9 | NEGATIVE
10 | }
--------------------------------------------------------------------------------
/library/src/main/res/drawable/md_item_selected_dark.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-v21/md_btn_selector_custom.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Nov 28 16:53:41 CST 2014
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.5-all.zip
7 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/preference_activity_custom.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/library/src/main/res/drawable-v21/md_btn_selector_ripple.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
7 |
8 |
--------------------------------------------------------------------------------
/library/src/main/res/drawable-v21/md_btn_selector_ripple_dark.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
7 |
8 |
--------------------------------------------------------------------------------
/sample/src/main/res/values-sw320dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 0dp
6 |
7 | 16dp
8 |
9 |
--------------------------------------------------------------------------------
/library/src/main/res/anim/popup_enter.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
9 |
--------------------------------------------------------------------------------
/library/src/main/res/anim/popup_exit.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
9 |
--------------------------------------------------------------------------------
/sample/src/main/res/drawable/md_btn_selector_custom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-v21/md_btn_selector_custom_holo.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/sample/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | #3F51B5
6 | #3949AB
7 | #009688
8 | #EF5350
9 |
10 |
--------------------------------------------------------------------------------
/sample/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
--------------------------------------------------------------------------------
/library/src/main/res/drawable/md_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/library/src/main/res/drawable/md_btn_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/library/src/main/res/drawable/md_selector_dark.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/library/src/main/res/drawable/md_btn_selector_dark.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/dialog_webview.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
13 |
14 |
--------------------------------------------------------------------------------
/sample/src/main/res/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/md_dialog_custom.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/md_dialog_progress_indeterminate.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/library/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/aidanfollestad/Documents/android-sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/sample/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 | 14sp
6 | 18sp
7 | 2dp
8 |
9 |
10 | 0dp
11 |
12 | 16dp
13 |
14 | 0x02000000
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/sample/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/aidanfollestad/Documents/android-sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | -keep class !android.support.v7.internal.view.menu.**,** {*;}
20 | -dontwarn
21 | -ignorewarnings
--------------------------------------------------------------------------------
/library/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | #33969696
12 | #40CBCBCB
13 |
14 | #10000000
15 | #10FFFFFF
16 |
17 | #1E88E5
18 | #1565C0
19 |
20 | #DD2C00
21 |
22 |
--------------------------------------------------------------------------------
/library/src/main/res/drawable-v21/md_btn_shape.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
15 |
16 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/afollestad/materialdialogssample/PreferenceActivityCompat.java:
--------------------------------------------------------------------------------
1 | package com.afollestad.materialdialogssample;
2 |
3 | import android.annotation.TargetApi;
4 | import android.os.Build;
5 | import android.os.Bundle;
6 | import android.view.MenuItem;
7 |
8 | @TargetApi(Build.VERSION_CODES.GINGERBREAD_MR1)
9 | public class PreferenceActivityCompat extends android.preference.PreferenceActivity {
10 |
11 | @Override
12 | protected void onCreate(Bundle savedInstanceState) {
13 | super.onCreate(savedInstanceState);
14 | addPreferencesFromResource(R.xml.preferences);
15 | }
16 |
17 | @Override
18 | public boolean onOptionsItemSelected(MenuItem item) {
19 | if (item.getItemId() == android.R.id.home) {
20 | onBackPressed();
21 | return true;
22 | }
23 | return super.onOptionsItemSelected(item);
24 | }
25 | }
--------------------------------------------------------------------------------
/library/src/main/res/drawable/md_btn_selected.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
9 |
10 |
11 |
16 |
17 |
--------------------------------------------------------------------------------
/library/src/main/res/drawable/md_btn_selected_dark.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
9 |
10 |
11 |
16 |
17 |
--------------------------------------------------------------------------------
/sample/src/main/res/drawable/md_btn_selected_custom.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
9 |
10 |
11 |
16 |
17 |
--------------------------------------------------------------------------------
/sample/src/main/res/drawable/md_btn_unselected_custom.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
9 |
10 |
11 |
16 |
17 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/md_stub_actionbuttons.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
9 |
10 |
16 |
17 |
23 |
24 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/md_stub_progress_indeterminate_horizontal.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
16 |
17 |
23 |
24 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/md_listitem.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
22 |
23 |
--------------------------------------------------------------------------------
/sample/src/main/res/values/arrays.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | - #3F51B5
6 | - #9E9E9E
7 | - #424242
8 | - #1F1F1F
9 | - #607D8B
10 | - #795548
11 | - #D32F2F
12 | - #E91E63
13 | - #9C27B0
14 | - #5E35B1
15 | - #1E88E5
16 | - #03A9F4
17 | - #00BCD4
18 | - #009688
19 | - #4CAF50
20 | - #8BC34A
21 | - #CDDC39
22 | - #FFEB3B
23 | - #FFC107
24 | - #FF9800
25 | - #FF5722
26 |
27 |
28 |
29 | - Twitter
30 | - Google
31 | - Instagram
32 | - Facebook
33 |
34 |
35 |
--------------------------------------------------------------------------------
/sample/src/main/assets/changelog.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
23 |
24 |
25 |
26 | WebView Custom View
27 |
28 |
29 | - NEW: Hey!
30 | - IMPROVE: Hello!
31 | - FIX: Hi!
32 | - FIX: Hey again!
33 | - FIX: What?
34 | - FIX: This is an example.
35 | - MISC: How are you?
36 |
37 | Material guidelines for dialogs:
38 | http://www.google.com/design/spec/components/dialogs.html.
39 |
40 |
41 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/md_dialog_progress.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/library/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'com.novoda.bintray-release'
3 |
4 | android {
5 | compileSdkVersion 23
6 | buildToolsVersion "23.0.0"
7 |
8 | defaultConfig {
9 | minSdkVersion 8
10 | targetSdkVersion 23
11 | versionCode 1
12 | versionName "0.7.9.0"
13 | }
14 | lintOptions {
15 | abortOnError false
16 | }
17 | }
18 |
19 | dependencies {
20 | compile fileTree(dir: 'libs', include: ['*.jar'])
21 | compile 'com.android.support:support-v4:23.0.0'
22 | compile 'com.android.support:appcompat-v7:23.0.0'
23 | compile 'com.android.support:recyclerview-v7:23.0.0'
24 | compile 'com.android.support:support-annotations:23.0.0'
25 | }
26 |
27 | publish {
28 | userOrg = 'drummer-aidan'
29 | groupId = 'com.afollestad'
30 | artifactId = 'material-dialogs'
31 | version = '0.7.9.0'
32 | description = 'A library for implementing Material design styled dialogs across all versions of Android.'
33 | website = 'https://github.com/afollestad/material-dialogs'
34 | issueTracker = "${website}/issues"
35 | repository = "${website}.git"
36 | }
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Aidan Michael Follestad
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/library/src/main/java/com/afollestad/materialdialogs/GravityEnum.java:
--------------------------------------------------------------------------------
1 | package com.afollestad.materialdialogs;
2 |
3 | import android.os.Build;
4 | import android.view.Gravity;
5 | import android.view.View;
6 |
7 | public enum GravityEnum {
8 | START, CENTER, END;
9 |
10 | private static final boolean HAS_RTL = Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1;
11 |
12 | public int getGravityInt() {
13 | switch (this) {
14 | case START:
15 | return HAS_RTL ? Gravity.START : Gravity.LEFT;
16 | case CENTER:
17 | return Gravity.CENTER_HORIZONTAL;
18 | case END:
19 | return HAS_RTL ? Gravity.END : Gravity.RIGHT;
20 | default:
21 | throw new IllegalStateException("Invalid gravity constant");
22 | }
23 | }
24 |
25 | public int getTextAlignment() {
26 | switch (this) {
27 | case CENTER:
28 | return View.TEXT_ALIGNMENT_CENTER;
29 | case END:
30 | return View.TEXT_ALIGNMENT_VIEW_END;
31 | default:
32 | return View.TEXT_ALIGNMENT_VIEW_START;
33 | }
34 | }
35 | }
--------------------------------------------------------------------------------
/library/src/main/res/layout/md_dialog_progress_indeterminate_horizontal.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/md_stub_inputpref.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
26 |
27 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/md_stub_titleframe.xml:
--------------------------------------------------------------------------------
1 |
12 |
13 |
21 |
22 |
28 |
29 |
--------------------------------------------------------------------------------
/sample/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion "23.0.0"
6 |
7 | signingConfigs {
8 | production {
9 | keyAlias 'afollestad'
10 | keyPassword 'aidan1995'
11 | storeFile file('./keystore.jks')
12 | storePassword 'aidan1995'
13 | }
14 | }
15 |
16 | defaultConfig {
17 | applicationId "com.afollestad.materialdialogssample"
18 | minSdkVersion 9
19 | targetSdkVersion 23
20 | versionCode 138
21 | versionName "0.7.9.0"
22 | }
23 | lintOptions {
24 | abortOnError false
25 | }
26 | buildTypes {
27 | debug {
28 | signingConfig signingConfigs.production
29 | }
30 | release {
31 | signingConfig signingConfigs.production
32 | minifyEnabled true
33 | shrinkResources true
34 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
35 | }
36 | }
37 | }
38 |
39 | dependencies {
40 | compile fileTree(dir: 'libs', include: ['*.jar'])
41 | compile project(':library')
42 | compile 'com.android.support:gridlayout-v7:23.0.0'
43 | }
--------------------------------------------------------------------------------
/sample/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
15 |
16 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
28 |
29 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/md_stub_progress_indeterminate.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
18 |
19 |
31 |
32 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/md_dialog_basic.xml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
19 |
20 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/dialog_customlistitem.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
19 |
20 |
32 |
33 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/afollestad/materialdialogssample/PreferenceActivity.java:
--------------------------------------------------------------------------------
1 | package com.afollestad.materialdialogssample;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.os.Bundle;
5 | import android.preference.PreferenceFragment;
6 | import android.support.v7.app.AppCompatActivity;
7 | import android.view.MenuItem;
8 |
9 | @SuppressLint("NewApi")
10 | public class PreferenceActivity extends AppCompatActivity {
11 |
12 | public static class SettingsFragment extends PreferenceFragment {
13 | @Override
14 | public void onCreate(Bundle savedInstanceState) {
15 | super.onCreate(savedInstanceState);
16 | addPreferencesFromResource(R.xml.preferences);
17 | }
18 | }
19 |
20 | @Override
21 | protected void onCreate(Bundle savedInstanceState) {
22 | super.onCreate(savedInstanceState);
23 | setContentView(R.layout.preference_activity_custom);
24 | getSupportActionBar().setDisplayHomeAsUpEnabled(true);
25 |
26 | if (getFragmentManager().findFragmentById(R.id.content_frame) == null) {
27 | getFragmentManager().beginTransaction().replace(R.id.content_frame, new SettingsFragment()).commit();
28 | }
29 | }
30 |
31 | @Override
32 | public boolean onOptionsItemSelected(MenuItem item) {
33 | if (item.getItemId() == android.R.id.home) {
34 | onBackPressed();
35 | return true;
36 | }
37 | return super.onOptionsItemSelected(item);
38 | }
39 | }
--------------------------------------------------------------------------------
/library/src/main/res/layout/md_simplelist_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
25 |
26 |
32 |
33 |
--------------------------------------------------------------------------------
/library/src/main/res/layout-ldrtl/md_simplelist_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
22 |
23 |
32 |
33 |
--------------------------------------------------------------------------------
/library/src/main/res/layout-ldrtl/md_listitem_multichoice.xml:
--------------------------------------------------------------------------------
1 |
12 |
13 |
24 |
25 |
34 |
35 |
--------------------------------------------------------------------------------
/library/src/main/res/layout-ldrtl/md_listitem_singlechoice.xml:
--------------------------------------------------------------------------------
1 |
12 |
13 |
24 |
25 |
34 |
35 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/md_listitem_multichoice.xml:
--------------------------------------------------------------------------------
1 |
12 |
13 |
22 |
23 |
34 |
35 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/md_listitem_singlechoice.xml:
--------------------------------------------------------------------------------
1 |
12 |
13 |
22 |
23 |
34 |
35 |
--------------------------------------------------------------------------------
/library/src/main/res/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
15 |
16 |
27 |
28 |
--------------------------------------------------------------------------------
/sample/src/main/res/xml/preferences.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
13 |
14 |
22 |
23 |
33 |
34 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by https://www.gitignore.io
2 |
3 | ### Android ###
4 |
5 | # Files for the Dalvik VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # Generated files
12 | bin/
13 | gen/
14 |
15 | # Gradle files
16 | .gradle/
17 | build/
18 |
19 | # Local configuration file (sdk path, etc)
20 | local.properties
21 |
22 | # Proguard folder generated by Eclipse
23 | proguard/
24 |
25 | # Log Files
26 | *.log
27 |
28 |
29 | ### Intellij ###
30 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm
31 |
32 | *.iml
33 |
34 | ## Directory-based project format:
35 | .idea/
36 | # if you remove the above rule, at least ignore the following:
37 |
38 | # User-specific stuff:
39 | # .idea/workspace.xml
40 | # .idea/tasks.xml
41 | # .idea/dictionaries
42 |
43 | # Sensitive or high-churn files:
44 | # .idea/dataSources.ids
45 | # .idea/dataSources.xml
46 | # .idea/sqlDataSources.xml
47 | # .idea/dynamic.xml
48 | # .idea/uiDesigner.xml
49 |
50 | # Gradle:
51 | # .idea/gradle.xml
52 | # .idea/libraries
53 |
54 | # Mongo Explorer plugin:
55 | # .idea/mongoSettings.xml
56 |
57 | ## File-based project format:
58 | *.ipr
59 | *.iws
60 |
61 | ## Plugin-specific files:
62 |
63 | # IntelliJ
64 | out/
65 |
66 | # mpeltonen/sbt-idea plugin
67 | .idea_modules/
68 |
69 | # JIRA plugin
70 | atlassian-ide-plugin.xml
71 |
72 | # Crashlytics plugin (for Android Studio and IntelliJ)
73 | com_crashlytics_export_strings.xml
74 |
75 | # Ignore Gradle GUI config
76 | gradle-app.setting
77 |
78 | # Mobile Tools for Java (J2ME)
79 | .mtj.tmp/
80 |
81 | # Package Files #
82 | *.war
83 | *.ear
84 |
85 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
86 | hs_err_pid*
87 |
88 | *.DS_Store
89 |
--------------------------------------------------------------------------------
/library/src/main/java/com/afollestad/materialdialogs/util/TypefaceHelper.java:
--------------------------------------------------------------------------------
1 | package com.afollestad.materialdialogs.util;
2 |
3 | import android.content.Context;
4 | import android.graphics.Typeface;
5 | import android.support.v4.util.SimpleArrayMap;
6 |
7 | /*
8 | Each call to Typeface.createFromAsset will load a new instance of the typeface into memory,
9 | and this memory is not consistently get garbage collected
10 | http://code.google.com/p/android/issues/detail?id=9904
11 | (It states released but even on Lollipop you can see the typefaces accumulate even after
12 | multiple GC passes)
13 |
14 | You can detect this by running:
15 | adb shell dumpsys meminfo com.your.packagenage
16 |
17 | You will see output like:
18 |
19 | Asset Allocations
20 | zip:/data/app/com.your.packagenage-1.apk:/assets/Roboto-Medium.ttf: 125K
21 | zip:/data/app/com.your.packagenage-1.apk:/assets/Roboto-Medium.ttf: 125K
22 | zip:/data/app/com.your.packagenage-1.apk:/assets/Roboto-Medium.ttf: 125K
23 | zip:/data/app/com.your.packagenage-1.apk:/assets/Roboto-Regular.ttf: 123K
24 | zip:/data/app/com.your.packagenage-1.apk:/assets/Roboto-Medium.ttf: 125K
25 |
26 | */
27 | public class TypefaceHelper {
28 |
29 | private static final SimpleArrayMap cache = new SimpleArrayMap<>();
30 |
31 | public static Typeface get(Context c, String name) {
32 | synchronized (cache) {
33 | if (!cache.containsKey(name)) {
34 | try {
35 | Typeface t = Typeface.createFromAsset(
36 | c.getAssets(), String.format("fonts/%s", name));
37 | cache.put(name, t);
38 | return t;
39 | } catch (RuntimeException e) {
40 | return null;
41 | }
42 | }
43 | return cache.get(name);
44 | }
45 | }
46 | }
47 |
48 |
--------------------------------------------------------------------------------
/library/src/main/java/com/afollestad/materialdialogs/simplelist/MaterialSimpleListItem.java:
--------------------------------------------------------------------------------
1 | package com.afollestad.materialdialogs.simplelist;
2 |
3 | import android.content.Context;
4 | import android.graphics.drawable.Drawable;
5 | import android.support.annotation.DrawableRes;
6 | import android.support.annotation.StringRes;
7 | import android.support.v4.content.ContextCompat;
8 |
9 | /**
10 | * @author Aidan Follestad (afollestad)
11 | */
12 | public class MaterialSimpleListItem {
13 |
14 | private Builder mBuilder;
15 |
16 | private MaterialSimpleListItem(Builder builder) {
17 | mBuilder = builder;
18 | }
19 |
20 | public Drawable getIcon() {
21 | return mBuilder.mIcon;
22 | }
23 |
24 | public CharSequence getContent() {
25 | return mBuilder.mContent;
26 | }
27 |
28 | public static class Builder {
29 |
30 | private Context mContext;
31 | protected Drawable mIcon;
32 | protected CharSequence mContent;
33 |
34 | public Builder(Context context) {
35 | mContext = context;
36 | }
37 |
38 | public Builder icon(Drawable icon) {
39 | this.mIcon = icon;
40 | return this;
41 | }
42 |
43 | public Builder icon(@DrawableRes int iconRes) {
44 | return icon(ContextCompat.getDrawable(mContext, iconRes));
45 | }
46 |
47 | public Builder content(CharSequence content) {
48 | this.mContent = content;
49 | return this;
50 | }
51 |
52 | public Builder content(@StringRes int contentRes) {
53 | return content(mContext.getString(contentRes));
54 | }
55 |
56 | public MaterialSimpleListItem build() {
57 | return new MaterialSimpleListItem(this);
58 | }
59 | }
60 |
61 | @Override
62 | public String toString() {
63 | if (getContent() != null)
64 | return getContent().toString();
65 | else return "(no content)";
66 | }
67 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/afollestad/materialdialogs/ThemeSingleton.java:
--------------------------------------------------------------------------------
1 | package com.afollestad.materialdialogs;
2 |
3 | import android.content.res.ColorStateList;
4 | import android.graphics.drawable.Drawable;
5 | import android.support.annotation.ColorInt;
6 | import android.support.annotation.DrawableRes;
7 |
8 | /**
9 | * Use of this is discouraged for now; for internal use only. See the Global Theming section of the README.
10 | */
11 | public class ThemeSingleton {
12 |
13 | private static ThemeSingleton singleton;
14 |
15 | public static ThemeSingleton get(boolean createIfNull) {
16 | if (singleton == null && createIfNull)
17 | singleton = new ThemeSingleton();
18 | return singleton;
19 | }
20 |
21 | public static ThemeSingleton get() {
22 | return get(true);
23 | }
24 |
25 | public boolean darkTheme = false;
26 | @ColorInt
27 | public int titleColor = 0;
28 | @ColorInt
29 | public int contentColor = 0;
30 | @ColorInt
31 | public ColorStateList positiveColor = null;
32 | @ColorInt
33 | public ColorStateList neutralColor = null;
34 | @ColorInt
35 | public ColorStateList negativeColor = null;
36 | @ColorInt
37 | public int widgetColor = 0;
38 | @ColorInt
39 | public int itemColor = 0;
40 | public Drawable icon = null;
41 | @ColorInt
42 | public int backgroundColor = 0;
43 | @ColorInt
44 | public int dividerColor = 0;
45 |
46 | @DrawableRes
47 | public int listSelector = 0;
48 | @DrawableRes
49 | public int btnSelectorStacked = 0;
50 | @DrawableRes
51 | public int btnSelectorPositive = 0;
52 | @DrawableRes
53 | public int btnSelectorNeutral = 0;
54 | @DrawableRes
55 | public int btnSelectorNegative = 0;
56 |
57 | public GravityEnum titleGravity = GravityEnum.START;
58 | public GravityEnum contentGravity = GravityEnum.START;
59 | public GravityEnum btnStackedGravity = GravityEnum.END;
60 | public GravityEnum itemsGravity = GravityEnum.START;
61 | public GravityEnum buttonsGravity = GravityEnum.START;
62 | }
--------------------------------------------------------------------------------
/sample/src/main/res/xml-v11/preferences.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
13 |
14 |
22 |
23 |
31 |
32 |
42 |
43 |
--------------------------------------------------------------------------------
/library/src/main/java/com/afollestad/materialdialogs/DialogBase.java:
--------------------------------------------------------------------------------
1 | package com.afollestad.materialdialogs;
2 |
3 | import android.app.Dialog;
4 | import android.content.Context;
5 | import android.content.DialogInterface;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 |
9 | import com.afollestad.materialdialogs.internal.MDRootLayout;
10 |
11 | /**
12 | * @author Aidan Follestad (afollestad)
13 | */
14 | class DialogBase extends Dialog implements DialogInterface.OnShowListener {
15 |
16 | protected MDRootLayout view;
17 | private OnShowListener mShowListener;
18 |
19 | protected DialogBase(Context context, int theme) {
20 | super(context, theme);
21 | }
22 |
23 | @Override
24 | public View findViewById(int id) {
25 | return view.findViewById(id);
26 | }
27 |
28 | @Override
29 | public final void setOnShowListener(OnShowListener listener) {
30 | mShowListener = listener;
31 | }
32 |
33 | protected final void setOnShowListenerInternal() {
34 | super.setOnShowListener(this);
35 | }
36 |
37 | protected final void setViewInternal(View view) {
38 | super.setContentView(view);
39 | }
40 |
41 | @Override
42 | public void onShow(DialogInterface dialog) {
43 | if (mShowListener != null)
44 | mShowListener.onShow(dialog);
45 | }
46 |
47 | @Override
48 | @Deprecated
49 | public void setContentView(int layoutResID) throws IllegalAccessError {
50 | throw new IllegalAccessError("setContentView() is not supported in MaterialDialog. Specify a custom view in the Builder instead.");
51 | }
52 |
53 | @Override
54 | @Deprecated
55 | public void setContentView(View view) throws IllegalAccessError {
56 | throw new IllegalAccessError("setContentView() is not supported in MaterialDialog. Specify a custom view in the Builder instead.");
57 | }
58 |
59 | @Override
60 | @Deprecated
61 | public void setContentView(View view, ViewGroup.LayoutParams params) throws IllegalAccessError {
62 | throw new IllegalAccessError("setContentView() is not supported in MaterialDialog. Specify a custom view in the Builder instead.");
63 | }
64 | }
--------------------------------------------------------------------------------
/library/src/main/res/values-v11/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
21 |
22 |
39 |
40 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/md_dialog_list.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
14 |
15 |
20 |
21 |
31 |
32 |
33 |
34 |
38 |
39 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/md_stub_progress.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
16 |
17 |
20 |
21 |
27 |
28 |
41 |
42 |
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/afollestad/materialdialogssample/ButtonItemAdapter.java:
--------------------------------------------------------------------------------
1 | package com.afollestad.materialdialogssample;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.content.Context;
5 | import android.support.annotation.ArrayRes;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 | import android.widget.BaseAdapter;
9 | import android.widget.Button;
10 | import android.widget.TextView;
11 | import android.widget.Toast;
12 |
13 | /**
14 | * Simple adapter example for custom items in the dialog
15 | */
16 | class ButtonItemAdapter extends BaseAdapter implements View.OnClickListener {
17 |
18 | private Toast mToast;
19 | private final Context mContext;
20 | private final CharSequence[] mItems;
21 |
22 | public ButtonItemAdapter(Context context, @ArrayRes int arrayResId) {
23 | this(context, context.getResources().getTextArray(arrayResId));
24 | }
25 |
26 | private ButtonItemAdapter(Context context, CharSequence[] items) {
27 | this.mContext = context;
28 | this.mItems = items;
29 | }
30 |
31 | @Override
32 | public int getCount() {
33 | return mItems.length;
34 | }
35 |
36 | @Override
37 | public CharSequence getItem(int position) {
38 | return mItems[position];
39 | }
40 |
41 | @Override
42 | public long getItemId(int position) {
43 | return position;
44 | }
45 |
46 | @Override
47 | public boolean hasStableIds() {
48 | return true;
49 | }
50 |
51 | @SuppressLint("ViewHolder")
52 | @Override
53 | public View getView(int position, View convertView, ViewGroup parent) {
54 | if (convertView == null)
55 | convertView = View.inflate(mContext, R.layout.dialog_customlistitem, null);
56 | ((TextView) convertView.findViewById(R.id.title)).setText(mItems[position] + " (" + position + ")");
57 | Button button = (Button) convertView.findViewById(R.id.button);
58 | button.setTag(position);
59 | button.setOnClickListener(this);
60 | return convertView;
61 | }
62 |
63 | @Override
64 | public void onClick(View v) {
65 | Integer index = (Integer) v.getTag();
66 | if (mToast != null) mToast.cancel();
67 | mToast = Toast.makeText(mContext, "Clicked button " + index, Toast.LENGTH_SHORT);
68 | mToast.show();
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/preference_custom.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
23 |
24 |
35 |
36 |
49 |
50 |
51 |
52 |
53 |
59 |
60 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/library/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/dialog_customview.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
13 |
14 |
21 |
22 |
29 |
30 |
37 |
38 |
45 |
46 |
53 |
54 |
61 |
62 |
70 |
71 |
79 |
80 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/md_dialog_input.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 |
20 |
21 |
32 |
33 |
36 |
37 |
46 |
47 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/library/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
14 |
15 |
26 |
27 |
36 |
37 |
43 |
44 |
55 |
56 |
60 |
61 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/preference_list_fragment.xml:
--------------------------------------------------------------------------------
1 |
18 |
23 |
24 |
38 |
39 |
46 |
47 |
53 |
54 |
62 |
63 |
69 |
70 |
77 |
78 |
84 |
85 |
86 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/afollestad/materialdialogssample/ChangelogDialog.java:
--------------------------------------------------------------------------------
1 | package com.afollestad.materialdialogssample;
2 |
3 | import android.app.Dialog;
4 | import android.graphics.Color;
5 | import android.os.Bundle;
6 | import android.support.annotation.NonNull;
7 | import android.support.v4.app.DialogFragment;
8 | import android.view.InflateException;
9 | import android.view.LayoutInflater;
10 | import android.view.View;
11 | import android.webkit.WebView;
12 |
13 | import com.afollestad.materialdialogs.MaterialDialog;
14 | import com.afollestad.materialdialogs.Theme;
15 |
16 | import java.io.BufferedReader;
17 | import java.io.InputStream;
18 | import java.io.InputStreamReader;
19 |
20 | /**
21 | * @author Aidan Follestad (afollestad)
22 | */
23 | public class ChangelogDialog extends DialogFragment {
24 |
25 | public static ChangelogDialog create(boolean darkTheme, int accentColor) {
26 | ChangelogDialog dialog = new ChangelogDialog();
27 | Bundle args = new Bundle();
28 | args.putBoolean("dark_theme", darkTheme);
29 | args.putInt("accent_color", accentColor);
30 | dialog.setArguments(args);
31 | return dialog;
32 | }
33 |
34 | @NonNull
35 | @Override
36 | public Dialog onCreateDialog(Bundle savedInstanceState) {
37 | final View customView;
38 | try {
39 | customView = LayoutInflater.from(getActivity()).inflate(R.layout.dialog_webview, null);
40 | } catch (InflateException e) {
41 | throw new IllegalStateException("This device does not support Web Views.");
42 | }
43 | MaterialDialog dialog = new MaterialDialog.Builder(getActivity())
44 | .theme(getArguments().getBoolean("dark_theme") ? Theme.DARK : Theme.LIGHT)
45 | .title(R.string.changelog)
46 | .customView(customView, false)
47 | .positiveText(android.R.string.ok)
48 | .build();
49 |
50 | final WebView webView = (WebView) customView.findViewById(R.id.webview);
51 | try {
52 | // Load from changelog.html in the assets folder
53 | StringBuilder buf = new StringBuilder();
54 | InputStream json = getActivity().getAssets().open("changelog.html");
55 | BufferedReader in = new BufferedReader(new InputStreamReader(json, "UTF-8"));
56 | String str;
57 | while ((str = in.readLine()) != null)
58 | buf.append(str);
59 | in.close();
60 |
61 | // Inject color values for WebView body background and links
62 | final int accentColor = getArguments().getInt("accent_color");
63 | webView.loadData(buf.toString()
64 | .replace("{style-placeholder}", getArguments().getBoolean("dark_theme") ?
65 | "body { background-color: #444444; color: #fff; }" :
66 | "body { background-color: #fff; color: #000; }")
67 | .replace("{link-color}", colorToHex(shiftColor(accentColor, true)))
68 | .replace("{link-color-active}", colorToHex(accentColor))
69 | , "text/html", "UTF-8");
70 | } catch (Throwable e) {
71 | webView.loadData("Unable to load
" + e.getLocalizedMessage() + "
", "text/html", "UTF-8");
72 | }
73 | return dialog;
74 | }
75 |
76 | private String colorToHex(int color) {
77 | return Integer.toHexString(color).substring(2);
78 | }
79 |
80 | private int shiftColor(int color, boolean up) {
81 | float[] hsv = new float[3];
82 | Color.colorToHSV(color, hsv);
83 | hsv[2] *= (up ? 1.1f : 0.9f); // value component
84 | return Color.HSVToColor(hsv);
85 | }
86 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/afollestad/materialdialogs/internal/MDButton.java:
--------------------------------------------------------------------------------
1 | package com.afollestad.materialdialogs.internal;
2 |
3 | import android.annotation.TargetApi;
4 | import android.content.Context;
5 | import android.graphics.drawable.Drawable;
6 | import android.os.Build;
7 | import android.support.v7.internal.text.AllCapsTransformationMethod;
8 | import android.util.AttributeSet;
9 | import android.view.Gravity;
10 | import android.widget.TextView;
11 |
12 | import com.afollestad.materialdialogs.GravityEnum;
13 | import com.afollestad.materialdialogs.R;
14 | import com.afollestad.materialdialogs.util.DialogUtils;
15 |
16 | /**
17 | * @author Kevin Barry (teslacoil) 4/02/2015
18 | */
19 | public class MDButton extends TextView {
20 |
21 | private boolean mStacked = false;
22 | private GravityEnum mStackedGravity;
23 |
24 | private int mStackedEndPadding;
25 | private Drawable mStackedBackground;
26 | private Drawable mDefaultBackground;
27 |
28 | public MDButton(Context context, AttributeSet attrs) {
29 | super(context, attrs);
30 | init(context, attrs, 0, 0);
31 | }
32 |
33 | public MDButton(Context context, AttributeSet attrs, int defStyleAttr) {
34 | super(context, attrs, defStyleAttr);
35 | init(context, attrs, defStyleAttr, 0);
36 | }
37 |
38 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
39 | public MDButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
40 | super(context, attrs, defStyleAttr, defStyleRes);
41 | init(context, attrs, defStyleAttr, defStyleRes);
42 | }
43 |
44 | private void init(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
45 | mStackedEndPadding = context.getResources()
46 | .getDimensionPixelSize(R.dimen.md_dialog_frame_margin);
47 | mStackedGravity = GravityEnum.END;
48 | }
49 |
50 | /**
51 | * Set if the button should be displayed in stacked mode.
52 | * This should only be called from MDRootLayout's onMeasure, and we must be measured
53 | * after calling this.
54 | */
55 | /* package */ void setStacked(boolean stacked, boolean force) {
56 | if (mStacked != stacked || force) {
57 |
58 | setGravity(stacked ? (Gravity.CENTER_VERTICAL | mStackedGravity.getGravityInt()) : Gravity.CENTER);
59 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
60 | //noinspection ResourceType
61 | setTextAlignment(stacked ? mStackedGravity.getTextAlignment() : TEXT_ALIGNMENT_CENTER);
62 | }
63 |
64 | DialogUtils.setBackgroundCompat(this, stacked ? mStackedBackground : mDefaultBackground);
65 | if (stacked) {
66 | setPadding(mStackedEndPadding, getPaddingTop(), mStackedEndPadding, getPaddingBottom());
67 | } /* Else the padding was properly reset by the drawable */
68 |
69 | mStacked = stacked;
70 | }
71 | }
72 |
73 | public void setStackedGravity(GravityEnum gravity) {
74 | mStackedGravity = gravity;
75 | }
76 |
77 | public void setStackedSelector(Drawable d) {
78 | mStackedBackground = d;
79 | if (mStacked)
80 | setStacked(true, true);
81 | }
82 |
83 | public void setDefaultSelector(Drawable d) {
84 | mDefaultBackground = d;
85 | if (!mStacked)
86 | setStacked(false, true);
87 | }
88 |
89 | public void setAllCapsCompat(boolean allCaps) {
90 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
91 | setAllCaps(allCaps);
92 | } else {
93 | if (allCaps)
94 | setTransformationMethod(new AllCapsTransformationMethod(getContext()));
95 | else
96 | setTransformationMethod(null);
97 | }
98 | }
99 | }
--------------------------------------------------------------------------------
/library/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
31 |
32 |
33 | 24dp
34 |
35 | 12dp
36 |
38 | 16dp
39 |
40 | 8dp
41 | 8dp
42 |
43 | 72dp
44 |
45 | 6dp
46 | 4dp
47 | 1dp
48 | 8dp
49 | 4dp
50 | 32dp
51 |
52 | 12dp
53 | 12dp
54 |
55 |
56 | 8dp
57 | 8dp
58 | 48dp
59 | 20sp
60 | 16sp
61 | 14sp
62 | 16sp
63 | 48dp
64 | 6dp
65 | 16dp
66 | 48dp
67 | 24dp
68 | 2dp
69 | 1dp
70 |
71 | 40dp
72 | 16dp
73 |
74 | 2dp
75 | 4dp
76 | 0dp
77 |
78 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/afollestad/materialdialogssample/FolderSelectorDialog.java:
--------------------------------------------------------------------------------
1 | package com.afollestad.materialdialogssample;
2 |
3 | import android.app.Activity;
4 | import android.app.Dialog;
5 | import android.os.Bundle;
6 | import android.os.Environment;
7 | import android.support.v4.app.DialogFragment;
8 | import android.support.v7.app.AppCompatActivity;
9 | import android.view.View;
10 |
11 | import com.afollestad.materialdialogs.MaterialDialog;
12 |
13 | import java.io.File;
14 | import java.util.ArrayList;
15 | import java.util.Collections;
16 | import java.util.Comparator;
17 | import java.util.List;
18 |
19 | /**
20 | * @author Aidan Follestad (afollestad)
21 | */
22 | public class FolderSelectorDialog extends DialogFragment implements MaterialDialog.ListCallback {
23 |
24 | private File parentFolder;
25 | private File[] parentContents;
26 | private boolean canGoUp = true;
27 | private FolderSelectCallback mCallback;
28 |
29 | private final MaterialDialog.ButtonCallback mButtonCallback = new MaterialDialog.ButtonCallback() {
30 | @Override
31 | public void onPositive(MaterialDialog materialDialog) {
32 | materialDialog.dismiss();
33 | mCallback.onFolderSelection(parentFolder);
34 | }
35 |
36 | @Override
37 | public void onNegative(MaterialDialog materialDialog) {
38 | materialDialog.dismiss();
39 | }
40 | };
41 |
42 | public interface FolderSelectCallback {
43 | void onFolderSelection(File folder);
44 | }
45 |
46 | public FolderSelectorDialog() {
47 | parentFolder = Environment.getExternalStorageDirectory();
48 | parentContents = listFiles();
49 | }
50 |
51 | String[] getContentsArray() {
52 | String[] results = new String[parentContents.length + (canGoUp ? 1 : 0)];
53 | if (canGoUp) results[0] = "...";
54 | for (int i = 0; i < parentContents.length; i++)
55 | results[canGoUp ? i + 1 : i] = parentContents[i].getName();
56 | return results;
57 | }
58 |
59 | File[] listFiles() {
60 | File[] contents = parentFolder.listFiles();
61 | List results = new ArrayList<>();
62 | for (File fi : contents) {
63 | if (fi.isDirectory()) results.add(fi);
64 | }
65 | Collections.sort(results, new FolderSorter());
66 | return results.toArray(new File[results.size()]);
67 | }
68 |
69 | @Override
70 | public Dialog onCreateDialog(Bundle savedInstanceState) {
71 | return new MaterialDialog.Builder(getActivity())
72 | .title(parentFolder.getAbsolutePath())
73 | .items(getContentsArray())
74 | .itemsCallback(this)
75 | .callback(mButtonCallback)
76 | .autoDismiss(false)
77 | .positiveText(R.string.choose)
78 | .negativeText(android.R.string.cancel)
79 | .build();
80 | }
81 |
82 | @Override
83 | public void onSelection(MaterialDialog materialDialog, View view, int i, CharSequence s) {
84 | if (canGoUp && i == 0) {
85 | parentFolder = parentFolder.getParentFile();
86 | canGoUp = parentFolder.getParent() != null;
87 | } else {
88 | parentFolder = parentContents[canGoUp ? i - 1 : i];
89 | canGoUp = true;
90 | }
91 | parentContents = listFiles();
92 | MaterialDialog dialog = (MaterialDialog) getDialog();
93 | dialog.setTitle(parentFolder.getAbsolutePath());
94 | dialog.setItems(getContentsArray());
95 | }
96 |
97 | @Override
98 | public void onAttach(Activity activity) {
99 | super.onAttach(activity);
100 | mCallback = (FolderSelectCallback) activity;
101 | }
102 |
103 | public void show(AppCompatActivity context) {
104 | show(context.getSupportFragmentManager(), "FOLDER_SELECTOR");
105 | }
106 |
107 | private static class FolderSorter implements Comparator {
108 | @Override
109 | public int compare(File lhs, File rhs) {
110 | return lhs.getName().compareTo(rhs.getName());
111 | }
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/library/src/main/java/com/afollestad/materialdialogs/simplelist/MaterialSimpleListAdapter.java:
--------------------------------------------------------------------------------
1 | package com.afollestad.materialdialogs.simplelist;
2 |
3 | import android.annotation.TargetApi;
4 | import android.content.Context;
5 | import android.content.res.Configuration;
6 | import android.os.Build;
7 | import android.view.Gravity;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 | import android.widget.ArrayAdapter;
11 | import android.widget.CompoundButton;
12 | import android.widget.ImageView;
13 | import android.widget.LinearLayout;
14 | import android.widget.TextView;
15 |
16 | import com.afollestad.materialdialogs.GravityEnum;
17 | import com.afollestad.materialdialogs.MaterialDialog;
18 | import com.afollestad.materialdialogs.R;
19 |
20 | /**
21 | * @author Aidan Follestad (afollestad)
22 | */
23 | public class MaterialSimpleListAdapter extends ArrayAdapter {
24 |
25 | private MaterialDialog dialog;
26 |
27 | public void setDialog(MaterialDialog dialog) {
28 | setDialog(dialog, true);
29 | }
30 |
31 | public void setDialog(MaterialDialog dialog, boolean notifyDataSetChanged) {
32 | this.dialog = dialog;
33 | if (notifyDataSetChanged)
34 | notifyDataSetChanged();
35 | }
36 |
37 | public MaterialSimpleListAdapter(Context context) {
38 | super(context, R.layout.md_simplelist_item, android.R.id.title);
39 | }
40 |
41 | @Override
42 | public boolean hasStableIds() {
43 | return true;
44 | }
45 |
46 | @Override
47 | public long getItemId(int position) {
48 | return position;
49 | }
50 |
51 | @Override
52 | public View getView(final int index, View convertView, ViewGroup parent) {
53 | final View view = super.getView(index, convertView, parent);
54 | if (dialog != null) {
55 | final MaterialSimpleListItem item = getItem(index);
56 | ImageView ic = (ImageView) view.findViewById(android.R.id.icon);
57 | if (item.getIcon() != null)
58 | ic.setImageDrawable(item.getIcon());
59 | else
60 | ic.setVisibility(View.GONE);
61 | TextView tv = (TextView) view.findViewById(android.R.id.title);
62 | tv.setTextColor(dialog.getBuilder().getItemColor());
63 | tv.setText(item.getContent());
64 | dialog.setTypeface(tv, dialog.getBuilder().getRegularFont());
65 | setupGravity((ViewGroup) view);
66 | }
67 | return view;
68 | }
69 |
70 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
71 | private void setupGravity(ViewGroup view) {
72 | final LinearLayout itemRoot = (LinearLayout) view;
73 | final GravityEnum gravity = dialog.getBuilder().getItemsGravity();
74 | final int gravityInt = gravity.getGravityInt();
75 | itemRoot.setGravity(gravityInt | Gravity.CENTER_VERTICAL);
76 |
77 | if (view.getChildCount() == 2) {
78 | if (dialog.getBuilder().getItemsGravity() == GravityEnum.END && !isRTL() && view.getChildAt(0) instanceof ImageView) {
79 | CompoundButton first = (CompoundButton) view.getChildAt(0);
80 | view.removeView(first);
81 |
82 | TextView second = (TextView) view.getChildAt(0);
83 | view.removeView(second);
84 | second.setPadding(second.getPaddingRight(), second.getPaddingTop(),
85 | second.getPaddingLeft(), second.getPaddingBottom());
86 |
87 | view.addView(second);
88 | view.addView(first);
89 | } else if (gravity == GravityEnum.START && isRTL() && view.getChildAt(1) instanceof ImageView) {
90 | CompoundButton first = (CompoundButton) view.getChildAt(1);
91 | view.removeView(first);
92 |
93 | TextView second = (TextView) view.getChildAt(0);
94 | view.removeView(second);
95 | second.setPadding(second.getPaddingRight(), second.getPaddingTop(),
96 | second.getPaddingRight(), second.getPaddingBottom());
97 |
98 | view.addView(first);
99 | view.addView(second);
100 | }
101 | }
102 | }
103 |
104 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
105 | private boolean isRTL() {
106 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1)
107 | return false;
108 | Configuration config = getContext().getResources().getConfiguration();
109 | return config.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
110 | }
111 | }
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/library/src/main/java/com/afollestad/materialdialogs/MaterialDialogAdapter.java:
--------------------------------------------------------------------------------
1 | package com.afollestad.materialdialogs;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.annotation.TargetApi;
5 | import android.content.res.Configuration;
6 | import android.os.Build;
7 | import android.support.annotation.LayoutRes;
8 | import android.view.Gravity;
9 | import android.view.LayoutInflater;
10 | import android.view.View;
11 | import android.view.ViewGroup;
12 | import android.widget.BaseAdapter;
13 | import android.widget.CheckBox;
14 | import android.widget.CompoundButton;
15 | import android.widget.LinearLayout;
16 | import android.widget.RadioButton;
17 | import android.widget.TextView;
18 |
19 | import com.afollestad.materialdialogs.internal.MDTintHelper;
20 |
21 | class MaterialDialogAdapter extends BaseAdapter {
22 |
23 | private final MaterialDialog dialog;
24 | @LayoutRes
25 | private final int layout;
26 |
27 | private final GravityEnum itemGravity;
28 | public RadioButton mRadioButton;
29 | public boolean mInitRadio;
30 |
31 | public MaterialDialogAdapter(MaterialDialog dialog, @LayoutRes int layout) {
32 | this.dialog = dialog;
33 | this.layout = layout;
34 | this.itemGravity = dialog.mBuilder.itemsGravity;
35 | }
36 |
37 | @Override
38 | public boolean hasStableIds() {
39 | return true;
40 | }
41 |
42 | @Override
43 | public int getCount() {
44 | return dialog.mBuilder.items != null ? dialog.mBuilder.items.length : 0;
45 | }
46 |
47 | @Override
48 | public Object getItem(int position) {
49 | return dialog.mBuilder.items[position];
50 | }
51 |
52 | @Override
53 | public long getItemId(int position) {
54 | return position;
55 | }
56 |
57 | @SuppressLint("WrongViewCast")
58 | @Override
59 | public View getView(final int index, View view, ViewGroup parent) {
60 | if (view == null)
61 | view = LayoutInflater.from(dialog.getContext()).inflate(layout, parent, false);
62 |
63 | TextView tv = (TextView) view.findViewById(R.id.title);
64 | switch (dialog.listType) {
65 | case SINGLE: {
66 | @SuppressLint("CutPasteId")
67 | RadioButton radio = (RadioButton) view.findViewById(R.id.control);
68 | boolean selected = dialog.mBuilder.selectedIndex == index;
69 | MDTintHelper.setTint(radio, dialog.mBuilder.widgetColor);
70 | radio.setChecked(selected);
71 | if (selected && mInitRadio)
72 | mRadioButton = radio;
73 | break;
74 | }
75 | case MULTI: {
76 | @SuppressLint("CutPasteId")
77 | CheckBox checkbox = (CheckBox) view.findViewById(R.id.control);
78 | boolean selected = dialog.selectedIndicesList.contains(index);
79 | MDTintHelper.setTint(checkbox, dialog.mBuilder.widgetColor);
80 | checkbox.setChecked(selected);
81 | break;
82 | }
83 | }
84 | tv.setText(dialog.mBuilder.items[index]);
85 | tv.setTextColor(dialog.mBuilder.itemColor);
86 | dialog.setTypeface(tv, dialog.mBuilder.regularFont);
87 |
88 | view.setTag(index + ":" + dialog.mBuilder.items[index]);
89 | setupGravity((ViewGroup) view);
90 |
91 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
92 | ViewGroup group = (ViewGroup) view;
93 | if (group.getChildCount() == 2) {
94 | // Remove circular selector from check boxes and radio buttons on Lollipop
95 | if (group.getChildAt(0) instanceof CompoundButton)
96 | group.getChildAt(0).setBackground(null);
97 | else if (group.getChildAt(1) instanceof CompoundButton)
98 | group.getChildAt(1).setBackground(null);
99 | }
100 | }
101 |
102 | return view;
103 | }
104 |
105 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
106 | private void setupGravity(ViewGroup view) {
107 | final LinearLayout itemRoot = (LinearLayout) view;
108 | final int gravityInt = itemGravity.getGravityInt();
109 | itemRoot.setGravity(gravityInt | Gravity.CENTER_VERTICAL);
110 |
111 | if (view.getChildCount() == 2) {
112 | if (itemGravity == GravityEnum.END && !isRTL() && view.getChildAt(0) instanceof CompoundButton) {
113 | CompoundButton first = (CompoundButton) view.getChildAt(0);
114 | view.removeView(first);
115 |
116 | TextView second = (TextView) view.getChildAt(0);
117 | view.removeView(second);
118 | second.setPadding(second.getPaddingRight(), second.getPaddingTop(),
119 | second.getPaddingLeft(), second.getPaddingBottom());
120 |
121 | view.addView(second);
122 | view.addView(first);
123 | } else if (itemGravity == GravityEnum.START && isRTL() && view.getChildAt(1) instanceof CompoundButton) {
124 | CompoundButton first = (CompoundButton) view.getChildAt(1);
125 | view.removeView(first);
126 |
127 | TextView second = (TextView) view.getChildAt(0);
128 | view.removeView(second);
129 | second.setPadding(second.getPaddingRight(), second.getPaddingTop(),
130 | second.getPaddingRight(), second.getPaddingBottom());
131 |
132 | view.addView(first);
133 | view.addView(second);
134 | }
135 | }
136 | }
137 |
138 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
139 | private boolean isRTL() {
140 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1)
141 | return false;
142 | Configuration config = dialog.getBuilder().getContext().getResources().getConfiguration();
143 | return config.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
144 | }
145 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/afollestad/materialdialogs/internal/MDTintHelper.java:
--------------------------------------------------------------------------------
1 | package com.afollestad.materialdialogs.internal;
2 |
3 | import android.content.Context;
4 | import android.content.res.ColorStateList;
5 | import android.graphics.PorterDuff;
6 | import android.graphics.drawable.Drawable;
7 | import android.os.Build;
8 | import android.support.v4.content.ContextCompat;
9 | import android.support.v4.graphics.drawable.DrawableCompat;
10 | import android.support.v7.widget.AppCompatEditText;
11 | import android.widget.CheckBox;
12 | import android.widget.EditText;
13 | import android.widget.ProgressBar;
14 | import android.widget.RadioButton;
15 | import android.widget.SeekBar;
16 |
17 | import com.afollestad.materialdialogs.R;
18 | import com.afollestad.materialdialogs.util.DialogUtils;
19 |
20 | /**
21 | * Tints widgets
22 | */
23 | public class MDTintHelper {
24 |
25 | public static void setTint(RadioButton radioButton, int color) {
26 | ColorStateList sl = new ColorStateList(new int[][]{
27 | new int[]{-android.R.attr.state_checked},
28 | new int[]{android.R.attr.state_checked}
29 | }, new int[]{
30 | DialogUtils.resolveColor(radioButton.getContext(), R.attr.colorControlNormal),
31 | color
32 | });
33 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
34 | radioButton.setButtonTintList(sl);
35 | } else {
36 | Drawable d = DrawableCompat.wrap(ContextCompat.getDrawable(radioButton.getContext(), R.drawable.abc_btn_radio_material));
37 | DrawableCompat.setTintList(d, sl);
38 | radioButton.setButtonDrawable(d);
39 | }
40 | }
41 |
42 | public static void setTint(SeekBar seekBar, int color) {
43 | ColorStateList s1 = ColorStateList.valueOf(color);
44 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
45 | seekBar.setThumbTintList(s1);
46 | seekBar.setProgressTintList(s1);
47 | } else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.GINGERBREAD_MR1) {
48 | Drawable progressDrawable = DrawableCompat.wrap(seekBar.getProgressDrawable());
49 | seekBar.setProgressDrawable(progressDrawable);
50 | DrawableCompat.setTintList(progressDrawable, s1);
51 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
52 | Drawable thumbDrawable = DrawableCompat.wrap(seekBar.getThumb());
53 | DrawableCompat.setTintList(thumbDrawable, s1);
54 | seekBar.setThumb(thumbDrawable);
55 | }
56 | } else {
57 | PorterDuff.Mode mode = PorterDuff.Mode.SRC_IN;
58 | if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) {
59 | mode = PorterDuff.Mode.MULTIPLY;
60 | }
61 | if (seekBar.getIndeterminateDrawable() != null)
62 | seekBar.getIndeterminateDrawable().setColorFilter(color, mode);
63 | if (seekBar.getProgressDrawable() != null)
64 | seekBar.getProgressDrawable().setColorFilter(color, mode);
65 | }
66 | }
67 |
68 | public static void setTint(ProgressBar progressBar, int color) {
69 | setTint(progressBar, color, false);
70 | }
71 |
72 | public static void setTint(ProgressBar progressBar, int color, boolean skipIndeterminate) {
73 | ColorStateList sl = ColorStateList.valueOf(color);
74 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
75 | progressBar.setProgressTintList(sl);
76 | progressBar.setSecondaryProgressTintList(sl);
77 | if (!skipIndeterminate)
78 | progressBar.setIndeterminateTintList(sl);
79 | } else {
80 | PorterDuff.Mode mode = PorterDuff.Mode.SRC_IN;
81 | if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) {
82 | mode = PorterDuff.Mode.MULTIPLY;
83 | }
84 | if (!skipIndeterminate && progressBar.getIndeterminateDrawable() != null)
85 | progressBar.getIndeterminateDrawable().setColorFilter(color, mode);
86 | if (progressBar.getProgressDrawable() != null)
87 | progressBar.getProgressDrawable().setColorFilter(color, mode);
88 | }
89 | }
90 |
91 | private static ColorStateList createEditTextColorStateList(Context context, int color) {
92 | int[][] states = new int[3][];
93 | int[] colors = new int[3];
94 | int i = 0;
95 | states[i] = new int[]{-android.R.attr.state_enabled};
96 | colors[i] = DialogUtils.resolveColor(context, R.attr.colorControlNormal);
97 | i++;
98 | states[i] = new int[]{-android.R.attr.state_pressed, -android.R.attr.state_focused};
99 | colors[i] = DialogUtils.resolveColor(context, R.attr.colorControlNormal);
100 | i++;
101 | states[i] = new int[]{};
102 | colors[i] = color;
103 | return new ColorStateList(states, colors);
104 | }
105 |
106 | public static void setTint(EditText editText, int color) {
107 | ColorStateList editTextColorStateList = createEditTextColorStateList(editText.getContext(), color);
108 | if (editText instanceof AppCompatEditText) {
109 | ((AppCompatEditText) editText).setSupportBackgroundTintList(editTextColorStateList);
110 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
111 | editText.setBackgroundTintList(editTextColorStateList);
112 | }
113 | }
114 |
115 | public static void setTint(CheckBox box, int color) {
116 | ColorStateList sl = new ColorStateList(new int[][]{
117 | new int[]{-android.R.attr.state_checked},
118 | new int[]{android.R.attr.state_checked}
119 | }, new int[]{
120 | DialogUtils.resolveColor(box.getContext(), R.attr.colorControlNormal),
121 | color
122 | });
123 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
124 | box.setButtonTintList(sl);
125 | } else {
126 | Drawable drawable = DrawableCompat.wrap(ContextCompat.getDrawable(box.getContext(), R.drawable.abc_btn_check_material));
127 | DrawableCompat.setTintList(drawable, sl);
128 | box.setButtonDrawable(drawable);
129 | }
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/library/src/main/java/com/afollestad/materialdialogs/prefs/MaterialDialogPreference.java:
--------------------------------------------------------------------------------
1 | package com.afollestad.materialdialogs.prefs;
2 |
3 | import android.annotation.TargetApi;
4 | import android.app.Dialog;
5 | import android.content.Context;
6 | import android.content.DialogInterface;
7 | import android.os.Build;
8 | import android.os.Bundle;
9 | import android.os.Parcel;
10 | import android.os.Parcelable;
11 | import android.preference.DialogPreference;
12 | import android.preference.PreferenceManager;
13 | import android.support.annotation.NonNull;
14 | import android.util.AttributeSet;
15 | import android.view.View;
16 |
17 | import com.afollestad.materialdialogs.MaterialDialog;
18 |
19 | import java.lang.reflect.Method;
20 |
21 | /**
22 | * @author Aidan Follestad (afollestad)
23 | */
24 | public class MaterialDialogPreference extends DialogPreference {
25 |
26 | private Context context;
27 | private MaterialDialog mDialog;
28 |
29 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
30 | public MaterialDialogPreference(Context context) {
31 | super(context);
32 | init(context);
33 | }
34 |
35 | public MaterialDialogPreference(Context context, AttributeSet attrs) {
36 | super(context, attrs);
37 | init(context);
38 | }
39 |
40 | private void init(Context context) {
41 | this.context = context;
42 | }
43 |
44 | @Override
45 | public Dialog getDialog() {
46 | return mDialog;
47 | }
48 |
49 | @Override
50 | protected void showDialog(Bundle state) {
51 | MaterialDialog.Builder builder = new MaterialDialog.Builder(context)
52 | .title(getDialogTitle())
53 | .content(getDialogMessage())
54 | .icon(getDialogIcon())
55 | .dismissListener(this)
56 | .callback(new MaterialDialog.ButtonCallback() {
57 | @Override
58 | public void onNeutral(MaterialDialog dialog) {
59 | onClick(dialog, DialogInterface.BUTTON_NEUTRAL);
60 | }
61 |
62 | @Override
63 | public void onNegative(MaterialDialog dialog) {
64 | onClick(dialog, DialogInterface.BUTTON_NEGATIVE);
65 | }
66 |
67 | @Override
68 | public void onPositive(MaterialDialog dialog) {
69 | onClick(dialog, DialogInterface.BUTTON_POSITIVE);
70 | }
71 | })
72 | .positiveText(getPositiveButtonText())
73 | .negativeText(getNegativeButtonText())
74 | .autoDismiss(true); // immediately close the dialog after selection
75 |
76 | final View contentView = onCreateDialogView();
77 | if (contentView != null) {
78 | onBindDialogView(contentView);
79 | builder.customView(contentView, false);
80 | } else {
81 | builder.content(getDialogMessage());
82 | }
83 |
84 | try {
85 | PreferenceManager pm = getPreferenceManager();
86 | Method method = pm.getClass().getDeclaredMethod(
87 | "registerOnActivityDestroyListener",
88 | PreferenceManager.OnActivityDestroyListener.class);
89 | method.setAccessible(true);
90 | method.invoke(pm, this);
91 | } catch (Exception ignored) {
92 | }
93 |
94 | mDialog = builder.build();
95 | if (state != null)
96 | mDialog.onRestoreInstanceState(state);
97 | mDialog.show();
98 | }
99 |
100 | @Override
101 | public void onDismiss(DialogInterface dialog) {
102 | super.onDismiss(dialog);
103 | try {
104 | PreferenceManager pm = getPreferenceManager();
105 | Method method = pm.getClass().getDeclaredMethod(
106 | "unregisterOnActivityDestroyListener",
107 | PreferenceManager.OnActivityDestroyListener.class);
108 | method.setAccessible(true);
109 | method.invoke(pm, this);
110 | } catch (Exception ignored) {
111 | }
112 | }
113 |
114 | @Override
115 | public void onActivityDestroy() {
116 | super.onActivityDestroy();
117 | if (mDialog != null && mDialog.isShowing())
118 | mDialog.dismiss();
119 | }
120 |
121 | @Override
122 | protected Parcelable onSaveInstanceState() {
123 | final Parcelable superState = super.onSaveInstanceState();
124 | Dialog dialog = getDialog();
125 | if (dialog == null || !dialog.isShowing()) {
126 | return superState;
127 | }
128 |
129 | final SavedState myState = new SavedState(superState);
130 | myState.isDialogShowing = true;
131 | myState.dialogBundle = dialog.onSaveInstanceState();
132 | return myState;
133 | }
134 |
135 | @Override
136 | protected void onRestoreInstanceState(Parcelable state) {
137 | if (state == null || !state.getClass().equals(SavedState.class)) {
138 | // Didn't save state for us in onSaveInstanceState
139 | super.onRestoreInstanceState(state);
140 | return;
141 | }
142 |
143 | SavedState myState = (SavedState) state;
144 | super.onRestoreInstanceState(myState.getSuperState());
145 | if (myState.isDialogShowing) {
146 | showDialog(myState.dialogBundle);
147 | }
148 | }
149 |
150 | // From DialogPreference
151 | private static class SavedState extends BaseSavedState {
152 | boolean isDialogShowing;
153 | Bundle dialogBundle;
154 |
155 | public SavedState(Parcel source) {
156 | super(source);
157 | isDialogShowing = source.readInt() == 1;
158 | dialogBundle = source.readBundle();
159 | }
160 |
161 | @Override
162 | public void writeToParcel(@NonNull Parcel dest, int flags) {
163 | super.writeToParcel(dest, flags);
164 | dest.writeInt(isDialogShowing ? 1 : 0);
165 | dest.writeBundle(dialogBundle);
166 | }
167 |
168 | public SavedState(Parcelable superState) {
169 | super(superState);
170 | }
171 |
172 | public static final Creator CREATOR =
173 | new Creator() {
174 | public SavedState createFromParcel(Parcel in) {
175 | return new SavedState(in);
176 | }
177 |
178 | public SavedState[] newArray(int size) {
179 | return new SavedState[size];
180 | }
181 | };
182 | }
183 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/afollestad/materialdialogs/progress/CircularProgressDrawable.java:
--------------------------------------------------------------------------------
1 | package com.afollestad.materialdialogs.progress;
2 |
3 | import android.animation.Animator;
4 | import android.animation.ObjectAnimator;
5 | import android.animation.ValueAnimator;
6 | import android.annotation.TargetApi;
7 | import android.graphics.Canvas;
8 | import android.graphics.ColorFilter;
9 | import android.graphics.Paint;
10 | import android.graphics.PixelFormat;
11 | import android.graphics.Rect;
12 | import android.graphics.RectF;
13 | import android.graphics.drawable.Animatable;
14 | import android.graphics.drawable.Drawable;
15 | import android.os.Build;
16 | import android.util.Property;
17 | import android.view.animation.DecelerateInterpolator;
18 | import android.view.animation.Interpolator;
19 | import android.view.animation.LinearInterpolator;
20 |
21 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
22 | public class CircularProgressDrawable extends Drawable
23 | implements Animatable {
24 |
25 | private static final Interpolator ANGLE_INTERPOLATOR = new LinearInterpolator();
26 | private static final Interpolator SWEEP_INTERPOLATOR = new DecelerateInterpolator();
27 | private static final int ANGLE_ANIMATOR_DURATION = 2000;
28 | private static final int SWEEP_ANIMATOR_DURATION = 600;
29 | private static final int MIN_SWEEP_ANGLE = 30;
30 | private final RectF fBounds = new RectF();
31 |
32 | private ObjectAnimator mObjectAnimatorSweep;
33 | private ObjectAnimator mObjectAnimatorAngle;
34 | private boolean mModeAppearing;
35 | private Paint mPaint;
36 | private float mCurrentGlobalAngleOffset;
37 | private float mCurrentGlobalAngle;
38 | private float mCurrentSweepAngle;
39 | private float mBorderWidth;
40 | private boolean mRunning;
41 |
42 | public CircularProgressDrawable(int color, float borderWidth) {
43 | mBorderWidth = borderWidth;
44 |
45 | mPaint = new Paint();
46 | mPaint.setAntiAlias(true);
47 | mPaint.setStyle(Paint.Style.STROKE);
48 | mPaint.setStrokeWidth(borderWidth);
49 | mPaint.setColor(color);
50 |
51 | setupAnimations();
52 | }
53 |
54 | @Override
55 | public void draw(Canvas canvas) {
56 | float startAngle = mCurrentGlobalAngle - mCurrentGlobalAngleOffset;
57 | float sweepAngle = mCurrentSweepAngle;
58 | if (!mModeAppearing) {
59 | startAngle = startAngle + sweepAngle;
60 | sweepAngle = 360 - sweepAngle - MIN_SWEEP_ANGLE;
61 | } else {
62 | sweepAngle += MIN_SWEEP_ANGLE;
63 | }
64 | canvas.drawArc(fBounds, startAngle, sweepAngle, false, mPaint);
65 | }
66 |
67 | @Override
68 | public void setAlpha(int alpha) {
69 | mPaint.setAlpha(alpha);
70 | }
71 |
72 | @Override
73 | public void setColorFilter(ColorFilter cf) {
74 | mPaint.setColorFilter(cf);
75 | }
76 |
77 | @Override
78 | public int getOpacity() {
79 | return PixelFormat.TRANSPARENT;
80 | }
81 |
82 | @Override
83 | public void start() {
84 | if (isRunning()) {
85 | return;
86 | }
87 | mRunning = true;
88 | mObjectAnimatorAngle.start();
89 | mObjectAnimatorSweep.start();
90 | invalidateSelf();
91 | }
92 |
93 | @Override
94 | public void stop() {
95 | if (!isRunning()) {
96 | return;
97 | }
98 | mRunning = false;
99 | mObjectAnimatorAngle.cancel();
100 | mObjectAnimatorSweep.cancel();
101 | invalidateSelf();
102 | }
103 |
104 | @Override
105 | public boolean isRunning() {
106 | return mRunning;
107 | }
108 |
109 | @Override
110 | protected void onBoundsChange(Rect bounds) {
111 | super.onBoundsChange(bounds);
112 | fBounds.left = bounds.left + mBorderWidth / 2f + .5f;
113 | fBounds.right = bounds.right - mBorderWidth / 2f - .5f;
114 | fBounds.top = bounds.top + mBorderWidth / 2f + .5f;
115 | fBounds.bottom = bounds.bottom - mBorderWidth / 2f - .5f;
116 | }
117 |
118 | public void setCurrentGlobalAngle(float currentGlobalAngle) {
119 | mCurrentGlobalAngle = currentGlobalAngle;
120 | invalidateSelf();
121 | }
122 |
123 | public float getCurrentGlobalAngle() {
124 | return mCurrentGlobalAngle;
125 | }
126 |
127 | public void setCurrentSweepAngle(float currentSweepAngle) {
128 | mCurrentSweepAngle = currentSweepAngle;
129 | invalidateSelf();
130 | }
131 |
132 | public float getCurrentSweepAngle() {
133 | return mCurrentSweepAngle;
134 | }
135 |
136 | private void toggleAppearingMode() {
137 | mModeAppearing = !mModeAppearing;
138 | if (mModeAppearing) {
139 | mCurrentGlobalAngleOffset = (mCurrentGlobalAngleOffset + MIN_SWEEP_ANGLE * 2) % 360;
140 | }
141 | }
142 |
143 | //////////////////////////////////////////////////////////////////////////////
144 | //////////////// Animation
145 |
146 | private Property mAngleProperty
147 | = new Property(Float.class, "angle") {
148 | @Override
149 | public Float get(CircularProgressDrawable object) {
150 | return object.getCurrentGlobalAngle();
151 | }
152 |
153 | @Override
154 | public void set(CircularProgressDrawable object, Float value) {
155 | object.setCurrentGlobalAngle(value);
156 | }
157 | };
158 |
159 | private Property mSweepProperty
160 | = new Property(Float.class, "arc") {
161 | @Override
162 | public Float get(CircularProgressDrawable object) {
163 | return object.getCurrentSweepAngle();
164 | }
165 |
166 | @Override
167 | public void set(CircularProgressDrawable object, Float value) {
168 | object.setCurrentSweepAngle(value);
169 | }
170 | };
171 |
172 | private void setupAnimations() {
173 | mObjectAnimatorAngle = ObjectAnimator.ofFloat(this, mAngleProperty, 360f);
174 | mObjectAnimatorAngle.setInterpolator(ANGLE_INTERPOLATOR);
175 | mObjectAnimatorAngle.setDuration(ANGLE_ANIMATOR_DURATION);
176 | mObjectAnimatorAngle.setRepeatMode(ValueAnimator.RESTART);
177 | mObjectAnimatorAngle.setRepeatCount(ValueAnimator.INFINITE);
178 |
179 | mObjectAnimatorSweep = ObjectAnimator.ofFloat(this, mSweepProperty, 360f - MIN_SWEEP_ANGLE * 2);
180 | mObjectAnimatorSweep.setInterpolator(SWEEP_INTERPOLATOR);
181 | mObjectAnimatorSweep.setDuration(SWEEP_ANIMATOR_DURATION);
182 | mObjectAnimatorSweep.setRepeatMode(ValueAnimator.RESTART);
183 | mObjectAnimatorSweep.setRepeatCount(ValueAnimator.INFINITE);
184 | mObjectAnimatorSweep.addListener(new Animator.AnimatorListener() {
185 | @Override
186 | public void onAnimationStart(Animator animation) {
187 |
188 | }
189 |
190 | @Override
191 | public void onAnimationEnd(Animator animation) {
192 |
193 | }
194 |
195 | @Override
196 | public void onAnimationCancel(Animator animation) {
197 |
198 | }
199 |
200 | @Override
201 | public void onAnimationRepeat(Animator animation) {
202 | toggleAppearingMode();
203 | }
204 | });
205 | }
206 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/afollestad/materialdialogs/internal/CircleView.java:
--------------------------------------------------------------------------------
1 | package com.afollestad.materialdialogs.internal;
2 |
3 | import android.content.Context;
4 | import android.content.res.ColorStateList;
5 | import android.content.res.Resources;
6 | import android.graphics.Canvas;
7 | import android.graphics.Color;
8 | import android.graphics.Paint;
9 | import android.graphics.drawable.Drawable;
10 | import android.graphics.drawable.RippleDrawable;
11 | import android.graphics.drawable.ShapeDrawable;
12 | import android.graphics.drawable.StateListDrawable;
13 | import android.graphics.drawable.shapes.OvalShape;
14 | import android.os.Build;
15 | import android.support.annotation.ColorInt;
16 | import android.support.annotation.ColorRes;
17 | import android.support.annotation.FloatRange;
18 | import android.support.v4.content.ContextCompat;
19 | import android.util.AttributeSet;
20 | import android.util.TypedValue;
21 | import android.widget.FrameLayout;
22 |
23 |
24 | public class CircleView extends FrameLayout {
25 |
26 | private final int borderWidthSmall;
27 | private final int borderWidthLarge;
28 |
29 | private Paint outerPaint;
30 | private Paint whitePaint;
31 | private Paint innerPaint;
32 | private boolean mSelected;
33 |
34 | public CircleView(Context context) {
35 | this(context, null, 0);
36 | }
37 |
38 | public CircleView(Context context, AttributeSet attrs) {
39 | this(context, attrs, 0);
40 | }
41 |
42 | public CircleView(Context context, AttributeSet attrs, int defStyleAttr) {
43 | super(context, attrs, defStyleAttr);
44 | final Resources r = getResources();
45 | borderWidthSmall = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 3, r.getDisplayMetrics());
46 | borderWidthLarge = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, r.getDisplayMetrics());
47 |
48 | whitePaint = new Paint();
49 | whitePaint.setAntiAlias(true);
50 | whitePaint.setColor(Color.WHITE);
51 | innerPaint = new Paint();
52 | innerPaint.setAntiAlias(true);
53 | outerPaint = new Paint();
54 | outerPaint.setAntiAlias(true);
55 |
56 | update(Color.DKGRAY);
57 | setWillNotDraw(false);
58 | }
59 |
60 | private void update(@ColorInt int color) {
61 | innerPaint.setColor(color);
62 | outerPaint.setColor(shiftColorDown(color));
63 |
64 | Drawable selector = createSelector(color);
65 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
66 | int[][] states = new int[][]{
67 | new int[]{android.R.attr.state_pressed}
68 | };
69 | int[] colors = new int[]{shiftColorUp(color)};
70 | ColorStateList rippleColors = new ColorStateList(states, colors);
71 | setForeground(new RippleDrawable(rippleColors, selector, null));
72 | } else {
73 | setForeground(selector);
74 | }
75 | }
76 |
77 | @Override
78 | public void setBackgroundColor(@ColorInt int color) {
79 | update(color);
80 | requestLayout();
81 | invalidate();
82 | }
83 |
84 | @Override
85 | public void setBackgroundResource(@ColorRes int color) {
86 | setBackgroundColor(ContextCompat.getColor(getContext(), color));
87 | }
88 |
89 | /**
90 | * @deprecated
91 | */
92 | @Deprecated
93 | @Override
94 | public void setBackground(Drawable background) {
95 | throw new IllegalStateException("Cannot use setBackground() on CircleView.");
96 | }
97 |
98 | /**
99 | * @deprecated
100 | */
101 | @SuppressWarnings("deprecation")
102 | @Deprecated
103 | @Override
104 | public void setBackgroundDrawable(Drawable background) {
105 | throw new IllegalStateException("Cannot use setBackgroundDrawable() on CircleView.");
106 | }
107 |
108 | /**
109 | * @deprecated
110 | */
111 | @SuppressWarnings("deprecation")
112 | @Deprecated
113 | @Override
114 | public void setActivated(boolean activated) {
115 | throw new IllegalStateException("Cannot use setActivated() on CircleView.");
116 | }
117 |
118 | public void setSelected(boolean selected) {
119 | mSelected = selected;
120 | requestLayout();
121 | invalidate();
122 | }
123 |
124 | @Override
125 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
126 | int widthMode = MeasureSpec.getMode(widthMeasureSpec);
127 | int heightMode = MeasureSpec.getMode(heightMeasureSpec);
128 | if (widthMode == MeasureSpec.EXACTLY && heightMode != MeasureSpec.EXACTLY) {
129 | int width = MeasureSpec.getSize(widthMeasureSpec);
130 | //noinspection SuspiciousNameCombination
131 | int height = width;
132 | if (heightMode == MeasureSpec.AT_MOST)
133 | height = Math.min(height, MeasureSpec.getSize(heightMeasureSpec));
134 | setMeasuredDimension(width, height);
135 | } else {
136 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
137 | }
138 | }
139 |
140 | @Override
141 | protected void onDraw(Canvas canvas) {
142 | super.onDraw(canvas);
143 | final int outerRadius = getMeasuredWidth() / 2;
144 | if(mSelected) {
145 | final int whiteRadius = outerRadius - borderWidthLarge;
146 | final int innerRadius = whiteRadius - borderWidthSmall;
147 | canvas.drawCircle(getMeasuredWidth() / 2,
148 | getMeasuredHeight() / 2,
149 | outerRadius,
150 | outerPaint);
151 | canvas.drawCircle(getMeasuredWidth() / 2,
152 | getMeasuredHeight() / 2,
153 | whiteRadius,
154 | whitePaint);
155 | canvas.drawCircle(getMeasuredWidth() / 2,
156 | getMeasuredHeight() / 2,
157 | innerRadius,
158 | innerPaint);
159 | } else {
160 | canvas.drawCircle(getMeasuredWidth() / 2,
161 | getMeasuredHeight() / 2,
162 | outerRadius,
163 | innerPaint);
164 | }
165 | }
166 |
167 | @ColorInt
168 | private static int translucentColor(int color) {
169 | final float factor = 0.7f;
170 | int alpha = Math.round(Color.alpha(color) * factor);
171 | int red = Color.red(color);
172 | int green = Color.green(color);
173 | int blue = Color.blue(color);
174 | return Color.argb(alpha, red, green, blue);
175 | }
176 |
177 | private Drawable createSelector(int color) {
178 | ShapeDrawable darkerCircle = new ShapeDrawable(new OvalShape());
179 | darkerCircle.getPaint().setColor(translucentColor(shiftColorUp(color)));
180 | StateListDrawable stateListDrawable = new StateListDrawable();
181 | stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, darkerCircle);
182 | return stateListDrawable;
183 | }
184 |
185 | @ColorInt
186 | public static int shiftColor(@ColorInt int color, @FloatRange(from = 0.0f, to = 2.0f) float by) {
187 | if (by == 1f) return color;
188 | float[] hsv = new float[3];
189 | Color.colorToHSV(color, hsv);
190 | hsv[2] *= by; // value component
191 | return Color.HSVToColor(hsv);
192 | }
193 |
194 | @ColorInt
195 | public static int shiftColorDown(@ColorInt int color) {
196 | return shiftColor(color, 0.9f);
197 | }
198 |
199 | @ColorInt
200 | public static int shiftColorUp(@ColorInt int color) {
201 | return shiftColor(color, 1.1f);
202 | }
203 | }
204 |
--------------------------------------------------------------------------------
/library/src/main/java/com/afollestad/materialdialogs/prefs/MaterialListPreference.java:
--------------------------------------------------------------------------------
1 | package com.afollestad.materialdialogs.prefs;
2 |
3 | import android.app.Dialog;
4 | import android.content.Context;
5 | import android.content.DialogInterface;
6 | import android.os.Build;
7 | import android.os.Bundle;
8 | import android.os.Parcel;
9 | import android.os.Parcelable;
10 | import android.preference.ListPreference;
11 | import android.preference.PreferenceManager;
12 | import android.support.annotation.NonNull;
13 | import android.util.AttributeSet;
14 | import android.view.View;
15 |
16 | import com.afollestad.materialdialogs.MaterialDialog;
17 |
18 | import java.lang.reflect.Field;
19 | import java.lang.reflect.Method;
20 |
21 | /**
22 | * @author Marc Holder Kluver (marchold), Aidan Follestad (afollestad)
23 | */
24 | public class MaterialListPreference extends ListPreference {
25 |
26 | private Context context;
27 | private MaterialDialog mDialog;
28 |
29 | public MaterialListPreference(Context context) {
30 | super(context);
31 | init(context);
32 | }
33 |
34 | public MaterialListPreference(Context context, AttributeSet attrs) {
35 | super(context, attrs);
36 | init(context);
37 | }
38 |
39 | private void init(Context context) {
40 | this.context = context;
41 | if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1)
42 | setWidgetLayoutResource(0);
43 | }
44 |
45 | @Override
46 | public void setEntries(CharSequence[] entries) {
47 | super.setEntries(entries);
48 | if (mDialog != null)
49 | mDialog.setItems(entries);
50 | }
51 |
52 | @Override
53 | public Dialog getDialog() {
54 | return mDialog;
55 | }
56 |
57 | @Override
58 | protected void showDialog(Bundle state) {
59 | if (getEntries() == null || getEntryValues() == null) {
60 | throw new IllegalStateException(
61 | "ListPreference requires an entries array and an entryValues array.");
62 | }
63 |
64 | int preselect = findIndexOfValue(getValue());
65 | MaterialDialog.Builder builder = new MaterialDialog.Builder(context)
66 | .title(getDialogTitle())
67 | .content(getDialogMessage())
68 | .icon(getDialogIcon())
69 | .dismissListener(this)
70 | .callback(new MaterialDialog.ButtonCallback() {
71 | @Override
72 | public void onNeutral(MaterialDialog dialog) {
73 | onClick(dialog, DialogInterface.BUTTON_NEUTRAL);
74 | }
75 |
76 | @Override
77 | public void onNegative(MaterialDialog dialog) {
78 | onClick(dialog, DialogInterface.BUTTON_NEGATIVE);
79 | }
80 |
81 | @Override
82 | public void onPositive(MaterialDialog dialog) {
83 | onClick(dialog, DialogInterface.BUTTON_POSITIVE);
84 | }
85 | })
86 | .negativeText(getNegativeButtonText())
87 | .items(getEntries())
88 | .autoDismiss(true) // immediately close the dialog after selection
89 | .itemsCallbackSingleChoice(preselect, new MaterialDialog.ListCallbackSingleChoice() {
90 | @Override
91 | public boolean onSelection(MaterialDialog dialog, View itemView, int which, CharSequence text) {
92 | onClick(null, DialogInterface.BUTTON_POSITIVE);
93 | if (which >= 0 && getEntryValues() != null) {
94 | try {
95 | Field clickedIndex = ListPreference.class.getDeclaredField("mClickedDialogEntryIndex");
96 | clickedIndex.setAccessible(true);
97 | clickedIndex.set(MaterialListPreference.this, which);
98 | } catch (Exception e) {
99 | e.printStackTrace();
100 | }
101 | }
102 | return true;
103 | }
104 | });
105 |
106 | final View contentView = onCreateDialogView();
107 | if (contentView != null) {
108 | onBindDialogView(contentView);
109 | builder.customView(contentView, false);
110 | } else {
111 | builder.content(getDialogMessage());
112 | }
113 |
114 | try {
115 | PreferenceManager pm = getPreferenceManager();
116 | Method method = pm.getClass().getDeclaredMethod(
117 | "registerOnActivityDestroyListener",
118 | PreferenceManager.OnActivityDestroyListener.class);
119 | method.setAccessible(true);
120 | method.invoke(pm, this);
121 | } catch (Exception ignored) {
122 | }
123 |
124 | mDialog = builder.build();
125 | if (state != null)
126 | mDialog.onRestoreInstanceState(state);
127 | mDialog.show();
128 | }
129 |
130 | @Override
131 | public void onDismiss(DialogInterface dialog) {
132 | super.onDismiss(dialog);
133 | try {
134 | PreferenceManager pm = getPreferenceManager();
135 | Method method = pm.getClass().getDeclaredMethod(
136 | "unregisterOnActivityDestroyListener",
137 | PreferenceManager.OnActivityDestroyListener.class);
138 | method.setAccessible(true);
139 | method.invoke(pm, this);
140 | } catch (Exception ignored) {
141 | }
142 | }
143 |
144 | @Override
145 | public void onActivityDestroy() {
146 | super.onActivityDestroy();
147 | if (mDialog != null && mDialog.isShowing())
148 | mDialog.dismiss();
149 | }
150 |
151 | @Override
152 | protected Parcelable onSaveInstanceState() {
153 | final Parcelable superState = super.onSaveInstanceState();
154 | Dialog dialog = getDialog();
155 | if (dialog == null || !dialog.isShowing()) {
156 | return superState;
157 | }
158 |
159 | final SavedState myState = new SavedState(superState);
160 | myState.isDialogShowing = true;
161 | myState.dialogBundle = dialog.onSaveInstanceState();
162 | return myState;
163 | }
164 |
165 | @Override
166 | protected void onRestoreInstanceState(Parcelable state) {
167 | if (state == null || !state.getClass().equals(SavedState.class)) {
168 | // Didn't save state for us in onSaveInstanceState
169 | super.onRestoreInstanceState(state);
170 | return;
171 | }
172 |
173 | SavedState myState = (SavedState) state;
174 | super.onRestoreInstanceState(myState.getSuperState());
175 | if (myState.isDialogShowing) {
176 | showDialog(myState.dialogBundle);
177 | }
178 | }
179 |
180 | // From DialogPreference
181 | private static class SavedState extends BaseSavedState {
182 | boolean isDialogShowing;
183 | Bundle dialogBundle;
184 |
185 | public SavedState(Parcel source) {
186 | super(source);
187 | isDialogShowing = source.readInt() == 1;
188 | dialogBundle = source.readBundle();
189 | }
190 |
191 | @Override
192 | public void writeToParcel(@NonNull Parcel dest, int flags) {
193 | super.writeToParcel(dest, flags);
194 | dest.writeInt(isDialogShowing ? 1 : 0);
195 | dest.writeBundle(dialogBundle);
196 | }
197 |
198 | public SavedState(Parcelable superState) {
199 | super(superState);
200 | }
201 |
202 | public static final Parcelable.Creator CREATOR =
203 | new Parcelable.Creator() {
204 | public SavedState createFromParcel(Parcel in) {
205 | return new SavedState(in);
206 | }
207 |
208 | public SavedState[] newArray(int size) {
209 | return new SavedState[size];
210 | }
211 | };
212 | }
213 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/afollestad/materialdialogs/prefs/MaterialMultiSelectListPreference.java:
--------------------------------------------------------------------------------
1 | package com.afollestad.materialdialogs.prefs;
2 |
3 | import android.annotation.TargetApi;
4 | import android.app.Dialog;
5 | import android.content.Context;
6 | import android.content.DialogInterface;
7 | import android.os.Build;
8 | import android.os.Bundle;
9 | import android.os.Parcel;
10 | import android.os.Parcelable;
11 | import android.preference.MultiSelectListPreference;
12 | import android.preference.PreferenceManager;
13 | import android.support.annotation.NonNull;
14 | import android.util.AttributeSet;
15 | import android.view.View;
16 |
17 | import com.afollestad.materialdialogs.MaterialDialog;
18 |
19 | import java.lang.reflect.Method;
20 | import java.util.ArrayList;
21 | import java.util.HashSet;
22 | import java.util.List;
23 | import java.util.Set;
24 |
25 | /**
26 | * This class only works on Honeycomb (API 11) and above.
27 | *
28 | * @author Aidan Follestad (afollestad)
29 | */
30 | @TargetApi(Build.VERSION_CODES.HONEYCOMB)
31 | public class MaterialMultiSelectListPreference extends MultiSelectListPreference {
32 |
33 | private Context context;
34 | private MaterialDialog mDialog;
35 |
36 | public MaterialMultiSelectListPreference(Context context) {
37 | this(context, null);
38 | }
39 |
40 | public MaterialMultiSelectListPreference(Context context, AttributeSet attrs) {
41 | super(context, attrs);
42 | init(context);
43 | }
44 |
45 | @Override
46 | public void setEntries(CharSequence[] entries) {
47 | super.setEntries(entries);
48 | if (mDialog != null)
49 | mDialog.setItems(entries);
50 | }
51 |
52 | private void init(Context context) {
53 | this.context = context;
54 | if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1)
55 | setWidgetLayoutResource(0);
56 | }
57 |
58 | @Override
59 | public Dialog getDialog() {
60 | return mDialog;
61 | }
62 |
63 | @Override
64 | protected void showDialog(Bundle state) {
65 | List indices = new ArrayList<>();
66 | for (String s : getValues()) {
67 | int index = findIndexOfValue(s);
68 | if (index >= 0)
69 | indices.add(findIndexOfValue(s));
70 | }
71 | MaterialDialog.Builder builder = new MaterialDialog.Builder(context)
72 | .title(getDialogTitle())
73 | .content(getDialogMessage())
74 | .icon(getDialogIcon())
75 | .negativeText(getNegativeButtonText())
76 | .positiveText(getPositiveButtonText())
77 | .callback(new MaterialDialog.ButtonCallback() {
78 | @Override
79 | public void onNeutral(MaterialDialog dialog) {
80 | onClick(dialog, DialogInterface.BUTTON_NEUTRAL);
81 | }
82 |
83 | @Override
84 | public void onNegative(MaterialDialog dialog) {
85 | onClick(dialog, DialogInterface.BUTTON_NEGATIVE);
86 | }
87 |
88 | @Override
89 | public void onPositive(MaterialDialog dialog) {
90 | onClick(dialog, DialogInterface.BUTTON_POSITIVE);
91 | }
92 | })
93 | .items(getEntries())
94 | .itemsCallbackMultiChoice(indices.toArray(new Integer[indices.size()]), new MaterialDialog.ListCallbackMultiChoice() {
95 | @Override
96 | public boolean onSelection(MaterialDialog dialog, Integer[] which, CharSequence[] text) {
97 | onClick(null, DialogInterface.BUTTON_POSITIVE);
98 | dialog.dismiss();
99 | final Set values = new HashSet<>();
100 | for (int i : which) {
101 | values.add(getEntryValues()[i].toString());
102 | }
103 | if (callChangeListener(values))
104 | setValues(values);
105 | return true;
106 | }
107 | })
108 | .dismissListener(this);
109 |
110 | final View contentView = onCreateDialogView();
111 | if (contentView != null) {
112 | onBindDialogView(contentView);
113 | builder.customView(contentView, false);
114 | } else {
115 | builder.content(getDialogMessage());
116 | }
117 |
118 | try {
119 | PreferenceManager pm = getPreferenceManager();
120 | Method method = pm.getClass().getDeclaredMethod(
121 | "registerOnActivityDestroyListener",
122 | PreferenceManager.OnActivityDestroyListener.class);
123 | method.setAccessible(true);
124 | method.invoke(pm, this);
125 | } catch (Exception ignored) {
126 | }
127 |
128 | mDialog = builder.build();
129 | if (state != null)
130 | mDialog.onRestoreInstanceState(state);
131 | mDialog.show();
132 | }
133 |
134 | @Override
135 | public void onDismiss(DialogInterface dialog) {
136 | super.onDismiss(dialog);
137 | try {
138 | PreferenceManager pm = getPreferenceManager();
139 | Method method = pm.getClass().getDeclaredMethod(
140 | "unregisterOnActivityDestroyListener",
141 | PreferenceManager.OnActivityDestroyListener.class);
142 | method.setAccessible(true);
143 | method.invoke(pm, this);
144 | } catch (Exception ignored) {
145 | }
146 | }
147 |
148 | @Override
149 | public void onActivityDestroy() {
150 | super.onActivityDestroy();
151 | if (mDialog != null && mDialog.isShowing())
152 | mDialog.dismiss();
153 | }
154 |
155 | @Override
156 | protected Parcelable onSaveInstanceState() {
157 | final Parcelable superState = super.onSaveInstanceState();
158 | Dialog dialog = getDialog();
159 | if (dialog == null || !dialog.isShowing()) {
160 | return superState;
161 | }
162 |
163 | final SavedState myState = new SavedState(superState);
164 | myState.isDialogShowing = true;
165 | myState.dialogBundle = dialog.onSaveInstanceState();
166 | return myState;
167 | }
168 |
169 | @Override
170 | protected void onRestoreInstanceState(Parcelable state) {
171 | if (state == null || !state.getClass().equals(SavedState.class)) {
172 | // Didn't save state for us in onSaveInstanceState
173 | super.onRestoreInstanceState(state);
174 | return;
175 | }
176 |
177 | SavedState myState = (SavedState) state;
178 | super.onRestoreInstanceState(myState.getSuperState());
179 | if (myState.isDialogShowing) {
180 | showDialog(myState.dialogBundle);
181 | }
182 | }
183 |
184 | // From DialogPreference
185 | private static class SavedState extends BaseSavedState {
186 | boolean isDialogShowing;
187 | Bundle dialogBundle;
188 |
189 | public SavedState(Parcel source) {
190 | super(source);
191 | isDialogShowing = source.readInt() == 1;
192 | dialogBundle = source.readBundle();
193 | }
194 |
195 | @Override
196 | public void writeToParcel(@NonNull Parcel dest, int flags) {
197 | super.writeToParcel(dest, flags);
198 | dest.writeInt(isDialogShowing ? 1 : 0);
199 | dest.writeBundle(dialogBundle);
200 | }
201 |
202 | public SavedState(Parcelable superState) {
203 | super(superState);
204 | }
205 |
206 | public static final Parcelable.Creator CREATOR =
207 | new Parcelable.Creator() {
208 | public SavedState createFromParcel(Parcel in) {
209 | return new SavedState(in);
210 | }
211 |
212 | public SavedState[] newArray(int size) {
213 | return new SavedState[size];
214 | }
215 | };
216 | }
217 | }
218 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
12 |
13 |
18 |
19 |
25 |
26 |
32 |
33 |
39 |
40 |
46 |
47 |
53 |
54 |
60 |
61 |
67 |
68 |
74 |
75 |
81 |
82 |
88 |
89 |
95 |
96 |
102 |
103 |
109 |
110 |
116 |
117 |
123 |
124 |
130 |
131 |
137 |
138 |
144 |
145 |
151 |
152 |
158 |
159 |
165 |
166 |
172 |
173 |
179 |
180 |
186 |
187 |
193 |
194 |
200 |
201 |
207 |
208 |
209 |
210 |
--------------------------------------------------------------------------------
/library/src/main/java/com/afollestad/materialdialogs/util/DialogUtils.java:
--------------------------------------------------------------------------------
1 | package com.afollestad.materialdialogs.util;
2 |
3 | import android.content.Context;
4 | import android.content.DialogInterface;
5 | import android.content.res.ColorStateList;
6 | import android.content.res.TypedArray;
7 | import android.graphics.Color;
8 | import android.graphics.drawable.Drawable;
9 | import android.os.Build;
10 | import android.support.annotation.AttrRes;
11 | import android.support.annotation.ColorRes;
12 | import android.util.TypedValue;
13 | import android.view.View;
14 | import android.view.inputmethod.InputMethodManager;
15 |
16 | import com.afollestad.materialdialogs.GravityEnum;
17 | import com.afollestad.materialdialogs.MaterialDialog;
18 |
19 | /**
20 | * @author Aidan Follestad (afollestad)
21 | */
22 | public class DialogUtils {
23 |
24 | public static int adjustAlpha(int color, @SuppressWarnings("SameParameterValue") float factor) {
25 | int alpha = Math.round(Color.alpha(color) * factor);
26 | int red = Color.red(color);
27 | int green = Color.green(color);
28 | int blue = Color.blue(color);
29 | return Color.argb(alpha, red, green, blue);
30 | }
31 |
32 | public static int resolveColor(Context context, @AttrRes int attr) {
33 | return resolveColor(context, attr, 0);
34 | }
35 |
36 | public static int resolveColor(Context context, @AttrRes int attr, int fallback) {
37 | TypedArray a = context.getTheme().obtainStyledAttributes(new int[]{attr});
38 | try {
39 | return a.getColor(0, fallback);
40 | } finally {
41 | a.recycle();
42 | }
43 | }
44 |
45 | // Try to resolve the colorAttr attribute.
46 | public static ColorStateList resolveActionTextColorStateList(Context context, @AttrRes int colorAttr, ColorStateList fallback) {
47 | TypedArray a = context.getTheme().obtainStyledAttributes(new int[]{colorAttr});
48 | try {
49 | final TypedValue value = a.peekValue(0);
50 | if (value == null) {
51 | return fallback;
52 | }
53 | if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT && value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
54 | return getActionTextStateList(context, value.data);
55 | } else {
56 | final ColorStateList stateList = a.getColorStateList(0);
57 | if (stateList != null) {
58 | return stateList;
59 | } else {
60 | return fallback;
61 | }
62 | }
63 | } finally {
64 | a.recycle();
65 | }
66 | }
67 |
68 | // Get the specified color resource, creating a ColorStateList if the resource
69 | // points to a color value.
70 | public static ColorStateList getActionTextColorStateList(Context context, @ColorRes int colorId) {
71 | final TypedValue value = new TypedValue();
72 | context.getResources().getValue(colorId, value, true);
73 | if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT && value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
74 | return getActionTextStateList(context, value.data);
75 | } else {
76 | return context.getResources().getColorStateList(colorId);
77 | }
78 | }
79 |
80 | public static String resolveString(Context context, @AttrRes int attr) {
81 | TypedValue v = new TypedValue();
82 | context.getTheme().resolveAttribute(attr, v, true);
83 | return (String) v.string;
84 | }
85 |
86 | private static int gravityEnumToAttrInt(GravityEnum value) {
87 | switch (value) {
88 | case CENTER:
89 | return 1;
90 | case END:
91 | return 2;
92 | default:
93 | return 0;
94 | }
95 | }
96 |
97 | public static GravityEnum resolveGravityEnum(Context context, @AttrRes int attr, GravityEnum defaultGravity) {
98 | TypedArray a = context.getTheme().obtainStyledAttributes(new int[]{attr});
99 | try {
100 | switch (a.getInt(0, gravityEnumToAttrInt(defaultGravity))) {
101 | case 1:
102 | return GravityEnum.CENTER;
103 | case 2:
104 | return GravityEnum.END;
105 | default:
106 | return GravityEnum.START;
107 | }
108 | } finally {
109 | a.recycle();
110 | }
111 | }
112 |
113 | public static Drawable resolveDrawable(Context context, @AttrRes int attr) {
114 | return resolveDrawable(context, attr, null);
115 | }
116 |
117 | private static Drawable resolveDrawable(Context context, @AttrRes int attr, @SuppressWarnings("SameParameterValue") Drawable fallback) {
118 | TypedArray a = context.getTheme().obtainStyledAttributes(new int[]{attr});
119 | try {
120 | Drawable d = a.getDrawable(0);
121 | if (d == null && fallback != null)
122 | d = fallback;
123 | return d;
124 | } finally {
125 | a.recycle();
126 | }
127 | }
128 |
129 | public static int resolveDimension(Context context, @AttrRes int attr) {
130 | return resolveDimension(context, attr, -1);
131 | }
132 |
133 | private static int resolveDimension(Context context, @AttrRes int attr, int fallback) {
134 | TypedArray a = context.getTheme().obtainStyledAttributes(new int[]{attr});
135 | try {
136 | return a.getDimensionPixelSize(0, fallback);
137 | } finally {
138 | a.recycle();
139 | }
140 | }
141 |
142 | public static boolean resolveBoolean(Context context, @AttrRes int attr, boolean fallback) {
143 | TypedArray a = context.getTheme().obtainStyledAttributes(new int[]{attr});
144 | try {
145 | return a.getBoolean(0, fallback);
146 | } finally {
147 | a.recycle();
148 | }
149 | }
150 |
151 | public static boolean resolveBoolean(Context context, @AttrRes int attr) {
152 | return resolveBoolean(context, attr, false);
153 | }
154 |
155 | public static boolean isColorDark(int color) {
156 | double darkness = 1 - (0.299 * Color.red(color) + 0.587 * Color.green(color) + 0.114 * Color.blue(color)) / 255;
157 | return darkness >= 0.5;
158 | }
159 |
160 | public static void setBackgroundCompat(View view, Drawable d) {
161 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
162 | //noinspection deprecation
163 | view.setBackgroundDrawable(d);
164 | } else {
165 | view.setBackground(d);
166 | }
167 | }
168 |
169 | public static void showKeyboard(DialogInterface di, final MaterialDialog.Builder builder) {
170 | final MaterialDialog dialog = (MaterialDialog) di;
171 | if (dialog.getInputEditText() == null) return;
172 | dialog.getInputEditText().post(new Runnable() {
173 | @Override
174 | public void run() {
175 | dialog.getInputEditText().requestFocus();
176 | InputMethodManager imm = (InputMethodManager) builder.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
177 | if (imm != null)
178 | imm.showSoftInput(dialog.getInputEditText(), InputMethodManager.SHOW_IMPLICIT);
179 | }
180 | });
181 | }
182 |
183 | public static void hideKeyboard(DialogInterface di, final MaterialDialog.Builder builder) {
184 | final MaterialDialog dialog = (MaterialDialog) di;
185 | if (dialog.getInputEditText() == null) return;
186 | dialog.getInputEditText().post(new Runnable() {
187 | @Override
188 | public void run() {
189 | dialog.getInputEditText().requestFocus();
190 | InputMethodManager imm = (InputMethodManager) builder.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
191 | if (imm != null)
192 | imm.hideSoftInputFromWindow(dialog.getInputEditText().getWindowToken(), 0);
193 | }
194 | });
195 | }
196 |
197 |
198 | public static ColorStateList getActionTextStateList(Context context, int newPrimaryColor) {
199 | final int fallBackButtonColor = DialogUtils.resolveColor(context, android.R.attr.textColorPrimary);
200 | if (newPrimaryColor == 0) newPrimaryColor = fallBackButtonColor;
201 | int[][] states = new int[][]{
202 | new int[]{-android.R.attr.state_enabled}, // disabled
203 | new int[]{} // enabled
204 | };
205 | int[] colors = new int[]{
206 | DialogUtils.adjustAlpha(newPrimaryColor, 0.4f),
207 | newPrimaryColor
208 | };
209 | return new ColorStateList(states, colors);
210 | }
211 | }
212 |
--------------------------------------------------------------------------------
/sample/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | MaterialDialogs
4 |
5 | Agree
6 | Disagree
7 | More Info
8 |
9 | Basic
10 | Stacked Buttons
11 | Neutral Button
12 | Callbacks
13 | Basic List
14 | Single Choice
15 | Multi Choice
16 | Custom View
17 | Themed
18 | Signal strength
19 | Excellent
20 | Security
21 | 802.1x EAP
22 | Password
23 | Show password
24 | Use Google\'s Location Services?
25 | Let Google help apps determine location. This means sending anonymous location data to Google, even when no apps are running.
26 | Social Networks
27 | Choose
28 | Turn on speed boost now!
29 | No thanks
30 | Google Wifi
31 | Connect
32 |
33 | About
34 | Aidan Follestad.
36 | Website
37 | Twitter
38 | Google+
39 | GitHub
40 | LinkedIn
41 | ]]>
42 | Dismiss
43 | Basic (No Title)
44 | This app wants to access your location.
45 | Basic Long List
46 | States
47 | A button!
48 | Custom Adapter
49 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur vitae metus nec sapien elementum interdum ac mollis tortor. Nunc porttitor metus placerat orci auctor, sed dictum magna dapibus. Morbi a lacus ante. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Proin posuere nisl imperdiet lectus elementum accumsan. Etiam lacinia nisi ut nulla fermentum tempus. Integer ornare lacinia diam non maximus. Vestibulum iaculis urna eu elementum scelerisque. Etiam nisl erat, bibendum vitae magna nec, convallis malesuada erat. Cras non porttitor nibh. Pellentesque rhoncus sem luctus felis tincidunt bibendum. Pellentesque vulputate eros at nulla sollicitudin volutpat. Pellentesque laoreet est sit amet erat laoreet, id molestie nulla efficitur. Interdum et malesuada fames ac ante ipsum primis in faucibus. Sed varius nisl at imperdiet facilisis.
50 | Basic (Long Content)
51 | Basic (Icon)
52 | Basic List (No Title)
53 | Folder Chooser
54 | Show/Cancel/Dismiss Callbacks
55 | Changelog
56 | Custom View No Scroll #1
57 | Color Chooser Primary
58 | Color Chooser Accent
59 | SSID
60 | Material Dialogs
61 |
62 |
63 | - Twitter
64 | - Google+
65 | - Instagram
66 | - Facebook
67 |
68 |
69 |
70 | - Alabama
71 | - Alaska
72 | - American Samoa
73 | - Arizona
74 | - Arkansas
75 | - California
76 | - Colorado
77 | - Connecticut
78 | - Delaware
79 | - District of Columbia
80 | - Florida
81 | - Georgia
82 | - Guam
83 | - Hawaii
84 | - Idaho
85 | - Illinois
86 | - Indiana
87 | - Iowa
88 | - Kansas
89 | - Kentucky
90 | - Louisiana
91 | - Maine
92 | - Maryland
93 | - Massachusetts
94 | - Michigan
95 | - Minnesota
96 | - Mississippi
97 | - Missouri
98 | - Montana
99 | - Nebraska
100 | - Nevada
101 | - New Hampshire
102 | - New Jersey
103 | - New Mexico
104 | - New York
105 | - North Carolina
106 | - North Dakota
107 | - Northern Marianas Islands
108 | - Ohio
109 | - Oklahoma
110 | - Oregon
111 | - Pennsylvania
112 | - Puerto Rico
113 | - Rhode Island
114 | - South Carolina
115 | - South Dakota
116 | - Tennessee
117 | - Texas
118 | - Utah
119 | - Vermont
120 | - Virginia
121 | - Virgin Islands
122 | - Washington
123 | - West Virginia
124 | - Wisconsin
125 | - Wyoming
126 |
127 |
128 | Preference Dialogs
129 | List Preference
130 | This is an example of a list preference that automatically uses Material Dialogs to show the list dialog.
131 | Multi Select List Preference
132 | This is an example of a multi select list preference that automatically uses Material Dialogs to show the list dialog.
133 | EditText Preference
134 | This is an example of an EditText preference that automatically uses Material Dialogs to show the input dialog.
135 | Enter a Name
136 | Default value
137 | Progress Dialog (Indeterminate)
138 | Progress Dialog (Horizontal Indeterminate)
139 | Progress Dialog
140 | Please wait…
141 | Done
142 | This is an optional dialog message.
143 | Multi Choice (Limit Selections)
144 | Selection limit reached!
145 |
146 |
147 | Back
148 | Next
149 |
150 |
151 | Skip
152 | Input
153 | Input (Custom Invalidation)
154 | John Appleseed
155 | What\'s your name?
156 | Simple Dialog (Guidelines Spec)
157 | Set backup account
158 | Add account
159 | Submit
160 | This is an example of a dialog message.
161 | Dialog Title
162 | Dialog Preference
163 | This is an example of a basic dialog preference that automatically uses Material Dialogs to show the dialog.
164 | Do not type hello, or else!
165 | Clear
166 | Back
167 | Color Palette
168 | Colors
169 |
170 |
171 |
--------------------------------------------------------------------------------
/library/src/main/java/com/afollestad/materialdialogs/prefs/MaterialEditTextPreference.java:
--------------------------------------------------------------------------------
1 | package com.afollestad.materialdialogs.prefs;
2 |
3 | import android.app.Dialog;
4 | import android.content.Context;
5 | import android.content.DialogInterface;
6 | import android.os.Build;
7 | import android.os.Bundle;
8 | import android.os.Parcel;
9 | import android.os.Parcelable;
10 | import android.preference.EditTextPreference;
11 | import android.preference.PreferenceManager;
12 | import android.support.annotation.NonNull;
13 | import android.support.v7.widget.AppCompatEditText;
14 | import android.util.AttributeSet;
15 | import android.view.LayoutInflater;
16 | import android.view.View;
17 | import android.view.ViewGroup;
18 | import android.view.ViewParent;
19 | import android.view.Window;
20 | import android.view.WindowManager;
21 | import android.widget.EditText;
22 | import android.widget.LinearLayout;
23 | import android.widget.TextView;
24 |
25 | import com.afollestad.materialdialogs.MaterialDialog;
26 | import com.afollestad.materialdialogs.MaterialDialog.Builder;
27 | import com.afollestad.materialdialogs.MaterialDialog.ButtonCallback;
28 | import com.afollestad.materialdialogs.R;
29 | import com.afollestad.materialdialogs.internal.MDTintHelper;
30 | import com.afollestad.materialdialogs.util.DialogUtils;
31 |
32 | import java.lang.reflect.Method;
33 |
34 | /**
35 | * @author Aidan Follestad (afollestad)
36 | */
37 | public class MaterialEditTextPreference extends EditTextPreference {
38 |
39 | private int mColor = 0;
40 | private MaterialDialog mDialog;
41 | private EditText mEditText;
42 |
43 | public MaterialEditTextPreference(Context context, AttributeSet attrs) {
44 | super(context, attrs);
45 | int fallback;
46 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
47 | fallback = DialogUtils.resolveColor(context, android.R.attr.colorAccent);
48 | else fallback = 0;
49 | fallback = DialogUtils.resolveColor(context, R.attr.colorAccent, fallback);
50 | mColor = DialogUtils.resolveColor(context, R.attr.md_widget_color, fallback);
51 |
52 | mEditText = new AppCompatEditText(context, attrs);
53 | // Give it an ID so it can be saved/restored
54 | mEditText.setId(android.R.id.edit);
55 | mEditText.setEnabled(true);
56 | }
57 |
58 | public MaterialEditTextPreference(Context context) {
59 | this(context, null);
60 | }
61 |
62 | @Override
63 | protected void onAddEditTextToDialogView(@NonNull View dialogView, @NonNull EditText editText) {
64 | ((ViewGroup) dialogView).addView(editText, new LinearLayout.LayoutParams(
65 | ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
66 | }
67 |
68 | @Override
69 | protected void onBindDialogView(@NonNull View view) {
70 | EditText editText = mEditText;
71 | editText.setText(getText());
72 | // Initialize cursor to end of text
73 | if (editText.getText().length() > 0)
74 | editText.setSelection(editText.length());
75 | ViewParent oldParent = editText.getParent();
76 | if (oldParent != view) {
77 | if (oldParent != null)
78 | ((ViewGroup) oldParent).removeView(editText);
79 | onAddEditTextToDialogView(view, editText);
80 | }
81 | }
82 |
83 | @Override
84 | protected void onDialogClosed(boolean positiveResult) {
85 | if (positiveResult) {
86 | String value = mEditText.getText().toString();
87 | if (callChangeListener(value))
88 | setText(value);
89 | }
90 | }
91 |
92 | @Override
93 | public EditText getEditText() {
94 | return mEditText;
95 | }
96 |
97 | @Override
98 | public Dialog getDialog() {
99 | return mDialog;
100 | }
101 |
102 | @Override
103 | protected void showDialog(Bundle state) {
104 | Builder mBuilder = new MaterialDialog.Builder(getContext())
105 | .title(getDialogTitle())
106 | .icon(getDialogIcon())
107 | .positiveText(getPositiveButtonText())
108 | .negativeText(getNegativeButtonText())
109 | .dismissListener(this)
110 | .callback(callback)
111 | .dismissListener(this);
112 |
113 | View layout = LayoutInflater.from(getContext()).inflate(R.layout.md_stub_inputpref, null);
114 | onBindDialogView(layout);
115 |
116 | MDTintHelper.setTint(mEditText, mColor);
117 |
118 | TextView message = (TextView) layout.findViewById(android.R.id.message);
119 | if (getDialogMessage() != null && getDialogMessage().toString().length() > 0) {
120 | message.setVisibility(View.VISIBLE);
121 | message.setText(getDialogMessage());
122 | } else {
123 | message.setVisibility(View.GONE);
124 | }
125 | mBuilder.customView(layout, false);
126 |
127 | try {
128 | PreferenceManager pm = getPreferenceManager();
129 | Method method = pm.getClass().getDeclaredMethod(
130 | "registerOnActivityDestroyListener",
131 | PreferenceManager.OnActivityDestroyListener.class);
132 | method.setAccessible(true);
133 | method.invoke(pm, this);
134 | } catch (Exception ignored) {
135 | }
136 |
137 | mDialog = mBuilder.build();
138 | if (state != null)
139 | mDialog.onRestoreInstanceState(state);
140 | requestInputMethod(mDialog);
141 |
142 | mDialog.show();
143 | }
144 |
145 | @Override
146 | public void onDismiss(DialogInterface dialog) {
147 | super.onDismiss(dialog);
148 | try {
149 | PreferenceManager pm = getPreferenceManager();
150 | Method method = pm.getClass().getDeclaredMethod(
151 | "unregisterOnActivityDestroyListener",
152 | PreferenceManager.OnActivityDestroyListener.class);
153 | method.setAccessible(true);
154 | method.invoke(pm, this);
155 | } catch (Exception ignored) {
156 | }
157 | }
158 |
159 | /**
160 | * Callback listener for the MaterialDialog. Positive button checks with
161 | * OnPreferenceChangeListener before committing user entered text
162 | */
163 | private final ButtonCallback callback = new ButtonCallback() {
164 | @Override
165 | public void onPositive(MaterialDialog dialog) {
166 | onClick(dialog, DialogInterface.BUTTON_POSITIVE);
167 | String value = mEditText.getText().toString();
168 | if (callChangeListener(value) && isPersistent())
169 | setText(value);
170 | }
171 |
172 | @Override
173 | public void onNeutral(MaterialDialog dialog) {
174 | onClick(dialog, DialogInterface.BUTTON_NEUTRAL);
175 | }
176 |
177 | @Override
178 | public void onNegative(MaterialDialog dialog) {
179 | onClick(dialog, DialogInterface.BUTTON_NEGATIVE);
180 | }
181 | };
182 |
183 | /**
184 | * Copied from DialogPreference.java
185 | */
186 | private void requestInputMethod(Dialog dialog) {
187 | Window window = dialog.getWindow();
188 | window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
189 | }
190 |
191 | @Override
192 | public void onActivityDestroy() {
193 | super.onActivityDestroy();
194 | if (mDialog != null && mDialog.isShowing())
195 | mDialog.dismiss();
196 | }
197 |
198 | @Override
199 | protected Parcelable onSaveInstanceState() {
200 | final Parcelable superState = super.onSaveInstanceState();
201 | Dialog dialog = getDialog();
202 | if (dialog == null || !dialog.isShowing()) {
203 | return superState;
204 | }
205 |
206 | final SavedState myState = new SavedState(superState);
207 | myState.isDialogShowing = true;
208 | myState.dialogBundle = dialog.onSaveInstanceState();
209 | return myState;
210 | }
211 |
212 | @Override
213 | protected void onRestoreInstanceState(Parcelable state) {
214 | if (state == null || !state.getClass().equals(SavedState.class)) {
215 | // Didn't save state for us in onSaveInstanceState
216 | super.onRestoreInstanceState(state);
217 | return;
218 | }
219 |
220 | SavedState myState = (SavedState) state;
221 | super.onRestoreInstanceState(myState.getSuperState());
222 | if (myState.isDialogShowing) {
223 | showDialog(myState.dialogBundle);
224 | }
225 | }
226 |
227 | // From DialogPreference
228 | private static class SavedState extends BaseSavedState {
229 | boolean isDialogShowing;
230 | Bundle dialogBundle;
231 |
232 | public SavedState(Parcel source) {
233 | super(source);
234 | isDialogShowing = source.readInt() == 1;
235 | dialogBundle = source.readBundle();
236 | }
237 |
238 | @Override
239 | public void writeToParcel(@NonNull Parcel dest, int flags) {
240 | super.writeToParcel(dest, flags);
241 | dest.writeInt(isDialogShowing ? 1 : 0);
242 | dest.writeBundle(dialogBundle);
243 | }
244 |
245 | public SavedState(Parcelable superState) {
246 | super(superState);
247 | }
248 |
249 | public static final Parcelable.Creator CREATOR =
250 | new Parcelable.Creator() {
251 | public SavedState createFromParcel(Parcel in) {
252 | return new SavedState(in);
253 | }
254 |
255 | public SavedState[] newArray(int size) {
256 | return new SavedState[size];
257 | }
258 | };
259 | }
260 | }
--------------------------------------------------------------------------------