├── .gitignore
├── .idea
├── .name
├── compiler.xml
├── copyright
│ └── profiles_settings.xml
├── dictionaries
│ └── Administrator.xml
├── encodings.xml
├── gradle.xml
├── misc.xml
├── modules.xml
└── runConfigurations.xml
├── .tgitconfig
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── itheima
│ │ └── materialdialog
│ │ └── demo
│ │ └── ApplicationTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── itheima
│ │ │ └── materialdialog
│ │ │ └── demo
│ │ │ └── MainActivity.java
│ └── res
│ │ ├── layout
│ │ └── activity_main.xml
│ │ ├── mipmap-hdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-mdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxxhdpi
│ │ └── ic_launcher.png
│ │ ├── values-w820dp
│ │ └── dimens.xml
│ │ └── values
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── itheima
│ └── materialdialog
│ └── demo
│ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── library
├── .gitignore
├── build.gradle
├── progress-proguard.txt
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── itheima
│ │ └── materialdialogs
│ │ ├── DefaultRvAdapter.java
│ │ ├── DialogAction.java
│ │ ├── DialogBase.java
│ │ ├── DialogInit.java
│ │ ├── GravityEnum.java
│ │ ├── MaterialDialog.java
│ │ ├── StackingBehavior.java
│ │ ├── Theme.java
│ │ ├── internal
│ │ ├── MDAdapter.java
│ │ ├── MDButton.java
│ │ ├── MDRootLayout.java
│ │ ├── MDTintHelper.java
│ │ └── ThemeSingleton.java
│ │ └── util
│ │ ├── DialogUtils.java
│ │ ├── RippleHelper.java
│ │ └── TypefaceHelper.java
│ └── res
│ ├── anim
│ ├── decelerate_cubic.xml
│ ├── popup_enter.xml
│ └── popup_exit.xml
│ ├── drawable-v21
│ ├── md_btn_selector_ripple.xml
│ ├── md_btn_selector_ripple_dark.xml
│ └── md_btn_shape.xml
│ ├── drawable
│ ├── md_btn_selected.xml
│ ├── md_btn_selected_dark.xml
│ ├── md_btn_selector.xml
│ ├── md_btn_selector_dark.xml
│ ├── md_item_selected.xml
│ ├── md_item_selected_dark.xml
│ ├── md_nav_back.xml
│ ├── md_selector.xml
│ ├── md_selector_dark.xml
│ └── md_transparent.xml
│ ├── layout-ldrtl
│ ├── md_listitem_multichoice.xml
│ └── md_listitem_singlechoice.xml
│ ├── layout-v14
│ ├── md_stub_progress.xml
│ ├── md_stub_progress_indeterminate.xml
│ └── md_stub_progress_indeterminate_horizontal.xml
│ ├── layout
│ ├── md_dialog_basic.xml
│ ├── md_dialog_basic_check.xml
│ ├── md_dialog_custom.xml
│ ├── md_dialog_input.xml
│ ├── md_dialog_input_check.xml
│ ├── md_dialog_list.xml
│ ├── md_dialog_list_check.xml
│ ├── md_dialog_progress.xml
│ ├── md_dialog_progress_indeterminate.xml
│ ├── md_dialog_progress_indeterminate_horizontal.xml
│ ├── md_listitem.xml
│ ├── md_listitem_multichoice.xml
│ ├── md_listitem_singlechoice.xml
│ ├── md_stub_actionbuttons.xml
│ ├── md_stub_progress.xml
│ ├── md_stub_progress_indeterminate.xml
│ ├── md_stub_progress_indeterminate_horizontal.xml
│ ├── md_stub_titleframe.xml
│ └── md_stub_titleframe_lesspadding.xml
│ ├── values-sw600dp
│ ├── bool.xml
│ └── dimens.xml
│ ├── values-sw720dp-land
│ └── dimens.xml
│ ├── values-sw720dp
│ ├── bool.xml
│ └── dimens.xml
│ ├── values-v11
│ └── styles.xml
│ ├── values-v14
│ └── styles.xml
│ ├── values-v21
│ └── styles.xml
│ └── values
│ ├── attrs.xml
│ ├── bool.xml
│ ├── colors.xml
│ ├── dimens.xml
│ └── styles.xml
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 |
--------------------------------------------------------------------------------
/.idea/.name:
--------------------------------------------------------------------------------
1 | MaterialDialog
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/dictionaries/Administrator.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
24 |
25 |
--------------------------------------------------------------------------------
/.idea/misc.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 | Android
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 | 1.7
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.tgitconfig:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/open-android/MaterailDialog/9e8f7bff23c53cc56bcb4dfb5c88ed1afa5a39e0/.tgitconfig
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 最火Android开源项目MaterialDialog使用
2 | ---
3 | 开源地址:[https://github.com/open-android/MaterialDialog](https://github.com/open-android/MaterialDialog "开源项目地址")
4 |
5 | PS:如果觉得文章太长,你也可观看该课程的[视频](https://www.boxuegu.com/web/html/video.html?courseId=172§ionId=8a2c9bed5a3a4c7e015a3bbffc6107ed&chapterId=8a2c9bed5a3a4c7e015a3bc0868907ee&vId=8a2c9bed5a3a4c7e015a3bc0c0fe07ef&videoId=77F5A9A54F83BBED9C33DC5901307461),亲,里面还有高清,无码的福利喔
6 |
7 | # 运行效果
8 | 
9 |
10 |
11 | ## 使用步骤
12 |
13 | ### 1. 在project的build.gradle添加如下代码(如下图)
14 |
15 | allprojects {
16 | repositories {
17 | ...
18 | maven { url 'https://jitpack.io' }
19 | }
20 | }
21 |
22 | 
23 |
24 |
25 | ### 2. 在Module的build.gradle添加依赖
26 |
27 | compile 'com.github.open-android:MaterailDialog:v1.0.2'
28 |
29 |
30 | ### 3. 复制如下代码到xml
31 |
32 |
37 |
38 | ###4 . 复制如下代码到Activity
39 |
40 | public void showDialog(View view){
41 | new MaterialDialog.Builder(this)
42 | .title("这是标题")
43 | .content("这是描述的内容")
44 | .positiveText("确定")
45 | .negativeText("取消")
46 | .show();
47 | }
48 |
49 | #### 细节注意:
50 |
51 | 1. 支持链式调用
52 | 2. 基本用法与官方的AlertDialog 基本相似
53 | 3. 取消对话框,可以使用 dismiss方法
54 |
55 |
56 |
57 |
58 | 欢迎关注微信公众号
59 |
60 | 
61 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion "24.0.1"
6 |
7 | defaultConfig {
8 | applicationId "com.itheima.materialdialog.demo"
9 | minSdkVersion 16
10 | targetSdkVersion 23
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(dir: 'libs', include: ['*.jar'])
24 | testCompile 'junit:junit:4.12'
25 | compile 'com.android.support:appcompat-v7:23.4.0'
26 | compile project(':library')
27 | }
28 |
--------------------------------------------------------------------------------
/app/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 C:\android\android_studio\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 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/itheima/materialdialog/demo/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.itheima.materialdialog.demo;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/java/com/itheima/materialdialog/demo/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.itheima.materialdialog.demo;
2 |
3 | import android.os.Bundle;
4 | import android.support.v7.app.AppCompatActivity;
5 | import android.view.View;
6 |
7 | import com.itheima.materialdialogs.MaterialDialog;
8 |
9 | public class MainActivity extends AppCompatActivity {
10 |
11 | @Override
12 | protected void onCreate(Bundle savedInstanceState) {
13 | super.onCreate(savedInstanceState);
14 | setContentView(R.layout.activity_main);
15 | }
16 |
17 | public void showDialog(View view){
18 |
19 |
20 | new MaterialDialog.Builder(this)
21 | .title("这是标题")
22 | .content("这是描述的内容")
23 | .positiveText("确定")
24 | .negativeText("取消")
25 | .show();
26 |
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/open-android/MaterailDialog/9e8f7bff23c53cc56bcb4dfb5c88ed1afa5a39e0/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/open-android/MaterailDialog/9e8f7bff23c53cc56bcb4dfb5c88ed1afa5a39e0/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/open-android/MaterailDialog/9e8f7bff23c53cc56bcb4dfb5c88ed1afa5a39e0/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/open-android/MaterailDialog/9e8f7bff23c53cc56bcb4dfb5c88ed1afa5a39e0/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/open-android/MaterailDialog/9e8f7bff23c53cc56bcb4dfb5c88ed1afa5a39e0/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | MaterialDialog
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/test/java/com/itheima/materialdialog/demo/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.itheima.materialdialog.demo;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:2.1.0'
9 | classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' // Add this line
10 |
11 | // NOTE: Do not place your application dependencies here; they belong
12 | // in the individual module build.gradle files
13 | }
14 | }
15 |
16 | allprojects {
17 | repositories {
18 | jcenter()
19 | }
20 | }
21 |
22 | task clean(type: Delete) {
23 | delete rootProject.buildDir
24 | }
25 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/open-android/MaterailDialog/9e8f7bff23c53cc56bcb4dfb5c88ed1afa5a39e0/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Dec 28 10:00:20 PST 2015
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.10-all.zip
7 |
--------------------------------------------------------------------------------
/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 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/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/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/library/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'com.github.dcendents.android-maven'
3 | group='com.github.itcastsh'
4 |
5 | ext {
6 |
7 | PUBLISH_VERSION = '0.9.2.3'
8 | SUPPORT_LIBRARY_VERSION = '23.3.0'
9 | BUILD_TOOLS = "23.0.3"
10 | TARGET_SDK = 23
11 | }
12 |
13 | android {
14 | compileSdkVersion TARGET_SDK
15 | buildToolsVersion BUILD_TOOLS
16 |
17 | defaultConfig {
18 | minSdkVersion 13
19 | targetSdkVersion TARGET_SDK
20 | versionCode 1
21 | versionName PUBLISH_VERSION
22 | consumerProguardFiles 'progress-proguard.txt'
23 | }
24 | lintOptions {
25 | abortOnError false
26 | checkReleaseBuilds false
27 | }
28 | }
29 |
30 | dependencies {
31 | compile "com.android.support:support-v13:$SUPPORT_LIBRARY_VERSION"
32 | compile "com.android.support:appcompat-v7:$SUPPORT_LIBRARY_VERSION"
33 | compile "com.android.support:recyclerview-v7:$SUPPORT_LIBRARY_VERSION"
34 | compile "com.android.support:support-annotations:$SUPPORT_LIBRARY_VERSION"
35 | compile "me.zhanghai.android.materialprogressbar:library:1.3.0"
36 | }
37 |
38 | //apply from: 'https://raw.githubusercontent.com/afollestad/aidanfollestad.com/master/android-lib-release.gradle'
39 |
--------------------------------------------------------------------------------
/library/progress-proguard.txt:
--------------------------------------------------------------------------------
1 | -keep class me.zhanghai.android.materialprogressbar.** { *; }
--------------------------------------------------------------------------------
/library/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/library/src/main/java/com/itheima/materialdialogs/DefaultRvAdapter.java:
--------------------------------------------------------------------------------
1 | package com.itheima.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.support.v7.widget.RecyclerView;
9 | import android.view.Gravity;
10 | import android.view.LayoutInflater;
11 | import android.view.View;
12 | import android.view.ViewGroup;
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.itheima.materialdialogs.internal.MDTintHelper;
20 | import com.itheima.materialdialogs.util.DialogUtils;
21 |
22 | /**
23 | * @author Aidan Follestad (afollestad)
24 | */
25 | class DefaultRvAdapter extends RecyclerView.Adapter {
26 |
27 | interface InternalListCallback {
28 |
29 | boolean onItemSelected(MaterialDialog dialog, View itemView, int position, CharSequence text, boolean longPress);
30 | }
31 |
32 | private final MaterialDialog dialog;
33 | @LayoutRes
34 | private final int layout;
35 | private final GravityEnum itemGravity;
36 | private InternalListCallback callback;
37 |
38 | DefaultRvAdapter(MaterialDialog dialog, @LayoutRes int layout) {
39 | this.dialog = dialog;
40 | this.layout = layout;
41 | this.itemGravity = dialog.builder.itemsGravity;
42 | }
43 |
44 | void setCallback(InternalListCallback callback) {
45 | this.callback = callback;
46 | }
47 |
48 | @Override
49 | public DefaultVH onCreateViewHolder(ViewGroup parent, int viewType) {
50 | final View view = LayoutInflater.from(parent.getContext())
51 | .inflate(layout, parent, false);
52 | DialogUtils.setBackgroundCompat(view, dialog.getListSelector());
53 | return new DefaultVH(view, this);
54 | }
55 |
56 | @Override
57 | public void onBindViewHolder(DefaultVH holder, int index) {
58 | final View view = holder.itemView;
59 | boolean disabled = DialogUtils.isIn(index, dialog.builder.disabledIndices);
60 | switch (dialog.listType) {
61 | case SINGLE: {
62 | @SuppressLint("CutPasteId")
63 | RadioButton radio = (RadioButton) holder.control;
64 | boolean selected = dialog.builder.selectedIndex == index;
65 | if (dialog.builder.choiceWidgetColor != null) {
66 | MDTintHelper.setTint(radio, dialog.builder.choiceWidgetColor);
67 | } else {
68 | MDTintHelper.setTint(radio, dialog.builder.widgetColor);
69 | }
70 | radio.setChecked(selected);
71 | radio.setEnabled(!disabled);
72 | break;
73 | }
74 | case MULTI: {
75 | @SuppressLint("CutPasteId")
76 | CheckBox checkbox = (CheckBox) holder.control;
77 | boolean selected = dialog.selectedIndicesList.contains(index);
78 | if (dialog.builder.choiceWidgetColor != null) {
79 | MDTintHelper.setTint(checkbox, dialog.builder.choiceWidgetColor);
80 | } else {
81 | MDTintHelper.setTint(checkbox, dialog.builder.widgetColor);
82 | }
83 | checkbox.setChecked(selected);
84 | checkbox.setEnabled(!disabled);
85 | break;
86 | }
87 | }
88 |
89 | holder.title.setText(dialog.builder.items.get(index));
90 | holder.title.setTextColor(dialog.builder.itemColor);
91 | dialog.setTypeface(holder.title, dialog.builder.regularFont);
92 |
93 | setupGravity((ViewGroup) view);
94 |
95 | if (dialog.builder.itemIds != null) {
96 | if (index < dialog.builder.itemIds.length)
97 | view.setId(dialog.builder.itemIds[index]);
98 | else view.setId(-1);
99 | }
100 |
101 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
102 | ViewGroup group = (ViewGroup) view;
103 | if (group.getChildCount() == 2) {
104 | // Remove circular selector from check boxes and radio buttons on Lollipop
105 | if (group.getChildAt(0) instanceof CompoundButton)
106 | group.getChildAt(0).setBackground(null);
107 | else if (group.getChildAt(1) instanceof CompoundButton)
108 | group.getChildAt(1).setBackground(null);
109 | }
110 | }
111 | }
112 |
113 | @Override
114 | public int getItemCount() {
115 | return dialog.builder.items != null ? dialog.builder.items.size() : 0;
116 | }
117 |
118 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
119 | private void setupGravity(ViewGroup view) {
120 | final LinearLayout itemRoot = (LinearLayout) view;
121 | final int gravityInt = itemGravity.getGravityInt();
122 | itemRoot.setGravity(gravityInt | Gravity.CENTER_VERTICAL);
123 |
124 | if (view.getChildCount() == 2) {
125 | if (itemGravity == GravityEnum.END && !isRTL() && view.getChildAt(0) instanceof CompoundButton) {
126 | CompoundButton first = (CompoundButton) view.getChildAt(0);
127 | view.removeView(first);
128 |
129 | TextView second = (TextView) view.getChildAt(0);
130 | view.removeView(second);
131 | second.setPadding(second.getPaddingRight(), second.getPaddingTop(),
132 | second.getPaddingLeft(), second.getPaddingBottom());
133 |
134 | view.addView(second);
135 | view.addView(first);
136 | } else if (itemGravity == GravityEnum.START && isRTL() && view.getChildAt(1) instanceof CompoundButton) {
137 | CompoundButton first = (CompoundButton) view.getChildAt(1);
138 | view.removeView(first);
139 |
140 | TextView second = (TextView) view.getChildAt(0);
141 | view.removeView(second);
142 | second.setPadding(second.getPaddingRight(), second.getPaddingTop(),
143 | second.getPaddingRight(), second.getPaddingBottom());
144 |
145 | view.addView(first);
146 | view.addView(second);
147 | }
148 | }
149 | }
150 |
151 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
152 | private boolean isRTL() {
153 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1)
154 | return false;
155 | Configuration config = dialog.getBuilder().getContext().getResources().getConfiguration();
156 | return config.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
157 | }
158 |
159 | static class DefaultVH extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
160 |
161 | final CompoundButton control;
162 | final TextView title;
163 | final DefaultRvAdapter adapter;
164 |
165 | DefaultVH(View itemView, DefaultRvAdapter adapter) {
166 | super(itemView);
167 | control = (CompoundButton) itemView.findViewById(R.id.md_control);
168 | title = (TextView) itemView.findViewById(R.id.md_title);
169 | this.adapter = adapter;
170 | itemView.setOnClickListener(this);
171 | if (adapter.dialog.builder.listLongCallback != null)
172 | itemView.setOnLongClickListener(this);
173 | }
174 |
175 | @Override
176 | public void onClick(View view) {
177 | if (adapter.callback != null && getAdapterPosition()!=RecyclerView.NO_POSITION) {
178 | CharSequence text = null;
179 | if (adapter.dialog.builder.items != null && getAdapterPosition() < adapter.dialog.builder.items.size())
180 | text = adapter.dialog.builder.items.get(getAdapterPosition());
181 | adapter.callback.onItemSelected(adapter.dialog, view, getAdapterPosition(), text, false);
182 | }
183 | }
184 |
185 | @Override
186 | public boolean onLongClick(View view) {
187 | if (adapter.callback != null && getAdapterPosition()!=RecyclerView.NO_POSITION) {
188 | CharSequence text = null;
189 | if (adapter.dialog.builder.items != null && getAdapterPosition() < adapter.dialog.builder.items.size())
190 | text = adapter.dialog.builder.items.get(getAdapterPosition());
191 | return adapter.callback.onItemSelected(adapter.dialog, view, getAdapterPosition(), text, true);
192 | }
193 | return false;
194 | }
195 | }
196 | }
197 |
--------------------------------------------------------------------------------
/library/src/main/java/com/itheima/materialdialogs/DialogAction.java:
--------------------------------------------------------------------------------
1 | package com.itheima.materialdialogs;
2 |
3 | /**
4 | * @author Aidan Follestad (afollestad)
5 | */
6 | public enum DialogAction {
7 | POSITIVE,
8 | NEUTRAL,
9 | NEGATIVE
10 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/itheima/materialdialogs/DialogBase.java:
--------------------------------------------------------------------------------
1 | package com.itheima.materialdialogs;
2 |
3 | import android.app.Dialog;
4 | import android.content.Context;
5 | import android.content.DialogInterface;
6 | import android.support.annotation.NonNull;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 |
10 | import com.itheima.materialdialogs.internal.MDRootLayout;
11 |
12 | /**
13 | * @author Aidan Follestad (afollestad)
14 | */
15 | class DialogBase extends Dialog implements DialogInterface.OnShowListener {
16 |
17 | protected MDRootLayout view;
18 | private OnShowListener showListener;
19 |
20 | DialogBase(Context context, int theme) {
21 | super(context, theme);
22 | }
23 |
24 | @Override
25 | public View findViewById(int id) {
26 | return view.findViewById(id);
27 | }
28 |
29 | @Override
30 | public final void setOnShowListener(OnShowListener listener) {
31 | showListener = listener;
32 | }
33 |
34 | final void setOnShowListenerInternal() {
35 | super.setOnShowListener(this);
36 | }
37 |
38 | final void setViewInternal(View view) {
39 | super.setContentView(view);
40 | }
41 |
42 | @Override
43 | public void onShow(DialogInterface dialog) {
44 | if (showListener != null)
45 | showListener.onShow(dialog);
46 | }
47 |
48 | @Override
49 | @Deprecated
50 | public void setContentView(int layoutResID) throws IllegalAccessError {
51 | throw new IllegalAccessError("setContentView() is not supported in MaterialDialog. Specify a custom view in the Builder instead.");
52 | }
53 |
54 | @Override
55 | @Deprecated
56 | public void setContentView(@NonNull View view) throws IllegalAccessError {
57 | throw new IllegalAccessError("setContentView() is not supported in MaterialDialog. Specify a custom view in the Builder instead.");
58 | }
59 |
60 | @Override
61 | @Deprecated
62 | public void setContentView(@NonNull View view, ViewGroup.LayoutParams params) throws IllegalAccessError {
63 | throw new IllegalAccessError("setContentView() is not supported in MaterialDialog. Specify a custom view in the Builder instead.");
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/library/src/main/java/com/itheima/materialdialogs/DialogInit.java:
--------------------------------------------------------------------------------
1 | package com.itheima.materialdialogs;
2 |
3 | import android.content.res.Resources;
4 | import android.graphics.Point;
5 | import android.graphics.drawable.Drawable;
6 | import android.graphics.drawable.GradientDrawable;
7 | import android.os.Build;
8 | import android.support.annotation.LayoutRes;
9 | import android.support.annotation.NonNull;
10 | import android.support.annotation.StyleRes;
11 | import android.support.annotation.UiThread;
12 | import android.support.v7.widget.RecyclerView;
13 | import android.text.InputType;
14 | import android.text.method.LinkMovementMethod;
15 | import android.text.method.PasswordTransformationMethod;
16 | import android.view.Display;
17 | import android.view.View;
18 | import android.view.ViewGroup;
19 | import android.view.WindowManager;
20 | import android.widget.CheckBox;
21 | import android.widget.EditText;
22 | import android.widget.FrameLayout;
23 | import android.widget.ImageView;
24 | import android.widget.ProgressBar;
25 | import android.widget.ScrollView;
26 | import android.widget.TextView;
27 |
28 | import com.itheima.materialdialogs.internal.MDAdapter;
29 | import com.itheima.materialdialogs.internal.MDButton;
30 | import com.itheima.materialdialogs.internal.MDRootLayout;
31 | import com.itheima.materialdialogs.internal.MDTintHelper;
32 | import com.itheima.materialdialogs.util.DialogUtils;
33 |
34 | import java.util.ArrayList;
35 | import java.util.Arrays;
36 |
37 | import me.zhanghai.android.materialprogressbar.HorizontalProgressDrawable;
38 | import me.zhanghai.android.materialprogressbar.IndeterminateHorizontalProgressDrawable;
39 | import me.zhanghai.android.materialprogressbar.IndeterminateProgressDrawable;
40 |
41 | /**
42 | * Used by MaterialDialog while initializing the dialog. Offloads some of the code to make the main
43 | * class cleaner and easier to read/maintain.
44 | *
45 | * @author Aidan Follestad (afollestad)
46 | */
47 | class DialogInit {
48 |
49 | @StyleRes
50 | static int getTheme(@NonNull MaterialDialog.Builder builder) {
51 | boolean darkTheme = DialogUtils.resolveBoolean(builder.context, R.attr.md_dark_theme, builder.theme == Theme.DARK);
52 | builder.theme = darkTheme ? Theme.DARK : Theme.LIGHT;
53 | return darkTheme ? R.style.MD_Dark : R.style.MD_Light;
54 | }
55 |
56 | @LayoutRes
57 | static int getInflateLayout(MaterialDialog.Builder builder) {
58 | if (builder.customView != null) {
59 | return R.layout.md_dialog_custom;
60 | } else if (builder.items != null && builder.items.size() > 0 || builder.adapter != null) {
61 | if (builder.checkBoxPrompt != null)
62 | return R.layout.md_dialog_list_check;
63 | return R.layout.md_dialog_list;
64 | } else if (builder.progress > -2) {
65 | return R.layout.md_dialog_progress;
66 | } else if (builder.indeterminateProgress) {
67 | if (builder.indeterminateIsHorizontalProgress)
68 | return R.layout.md_dialog_progress_indeterminate_horizontal;
69 | return R.layout.md_dialog_progress_indeterminate;
70 | } else if (builder.inputCallback != null) {
71 | if (builder.checkBoxPrompt != null)
72 | return R.layout.md_dialog_input_check;
73 | return R.layout.md_dialog_input;
74 | } else if (builder.checkBoxPrompt != null) {
75 | return R.layout.md_dialog_basic_check;
76 | } else {
77 | return R.layout.md_dialog_basic;
78 | }
79 | }
80 |
81 | @SuppressWarnings("ConstantConditions")
82 | @UiThread
83 | public static void init(final MaterialDialog dialog) {
84 | final MaterialDialog.Builder builder = dialog.builder;
85 |
86 | // Set cancelable flag and dialog background color
87 | dialog.setCancelable(builder.cancelable);
88 | dialog.setCanceledOnTouchOutside(builder.canceledOnTouchOutside);
89 | if (builder.backgroundColor == 0)
90 | builder.backgroundColor = DialogUtils.resolveColor(builder.context, R.attr.md_background_color,
91 | DialogUtils.resolveColor(dialog.getContext(), R.attr.colorBackgroundFloating));
92 | if (builder.backgroundColor != 0) {
93 | GradientDrawable drawable = new GradientDrawable();
94 | drawable.setCornerRadius(builder.context.getResources().getDimension(R.dimen.md_bg_corner_radius));
95 | drawable.setColor(builder.backgroundColor);
96 | dialog.getWindow().setBackgroundDrawable(drawable);
97 | }
98 |
99 | // Retrieve color theme attributes
100 | if (!builder.positiveColorSet)
101 | builder.positiveColor = DialogUtils.resolveActionTextColorStateList(builder.context, R.attr.md_positive_color, builder.positiveColor);
102 | if (!builder.neutralColorSet)
103 | builder.neutralColor = DialogUtils.resolveActionTextColorStateList(builder.context, R.attr.md_neutral_color, builder.neutralColor);
104 | if (!builder.negativeColorSet)
105 | builder.negativeColor = DialogUtils.resolveActionTextColorStateList(builder.context, R.attr.md_negative_color, builder.negativeColor);
106 | if (!builder.widgetColorSet)
107 | builder.widgetColor = DialogUtils.resolveColor(builder.context, R.attr.md_widget_color, builder.widgetColor);
108 |
109 | // Retrieve default title/content colors
110 | if (!builder.titleColorSet) {
111 | final int titleColorFallback = DialogUtils.resolveColor(dialog.getContext(), android.R.attr.textColorPrimary);
112 | builder.titleColor = DialogUtils.resolveColor(builder.context, R.attr.md_title_color, titleColorFallback);
113 | }
114 | if (!builder.contentColorSet) {
115 | final int contentColorFallback = DialogUtils.resolveColor(dialog.getContext(), android.R.attr.textColorSecondary);
116 | builder.contentColor = DialogUtils.resolveColor(builder.context, R.attr.md_content_color, contentColorFallback);
117 | }
118 | if (!builder.itemColorSet)
119 | builder.itemColor = DialogUtils.resolveColor(builder.context, R.attr.md_item_color, builder.contentColor);
120 |
121 | // Retrieve references to views
122 | dialog.title = (TextView) dialog.view.findViewById(R.id.md_title);
123 | dialog.icon = (ImageView) dialog.view.findViewById(R.id.md_icon);
124 | dialog.titleFrame = dialog.view.findViewById(R.id.md_titleFrame);
125 | dialog.content = (TextView) dialog.view.findViewById(R.id.md_content);
126 | dialog.recyclerView = (RecyclerView) dialog.view.findViewById(R.id.md_contentRecyclerView);
127 | dialog.checkBoxPrompt = (CheckBox) dialog.view.findViewById(R.id.md_promptCheckbox);
128 |
129 | // Button views initially used by checkIfStackingNeeded()
130 | dialog.positiveButton = (MDButton) dialog.view.findViewById(R.id.md_buttonDefaultPositive);
131 | dialog.neutralButton = (MDButton) dialog.view.findViewById(R.id.md_buttonDefaultNeutral);
132 | dialog.negativeButton = (MDButton) dialog.view.findViewById(R.id.md_buttonDefaultNegative);
133 |
134 | // Don't allow the submit button to not be shown for input dialogs
135 | if (builder.inputCallback != null && builder.positiveText == null)
136 | builder.positiveText = builder.context.getText(android.R.string.ok);
137 |
138 | // Set up the initial visibility of action buttons based on whether or not text was set
139 | dialog.positiveButton.setVisibility(builder.positiveText != null ? View.VISIBLE : View.GONE);
140 | dialog.neutralButton.setVisibility(builder.neutralText != null ? View.VISIBLE : View.GONE);
141 | dialog.negativeButton.setVisibility(builder.negativeText != null ? View.VISIBLE : View.GONE);
142 |
143 | // Setup icon
144 | if (builder.icon != null) {
145 | dialog.icon.setVisibility(View.VISIBLE);
146 | dialog.icon.setImageDrawable(builder.icon);
147 | } else {
148 | Drawable d = DialogUtils.resolveDrawable(builder.context, R.attr.md_icon);
149 | if (d != null) {
150 | dialog.icon.setVisibility(View.VISIBLE);
151 | dialog.icon.setImageDrawable(d);
152 | } else {
153 | dialog.icon.setVisibility(View.GONE);
154 | }
155 | }
156 |
157 | // Setup icon size limiting
158 | int maxIconSize = builder.maxIconSize;
159 | if (maxIconSize == -1)
160 | maxIconSize = DialogUtils.resolveDimension(builder.context, R.attr.md_icon_max_size);
161 | if (builder.limitIconToDefaultSize || DialogUtils.resolveBoolean(builder.context, R.attr.md_icon_limit_icon_to_default_size))
162 | maxIconSize = builder.context.getResources().getDimensionPixelSize(R.dimen.md_icon_max_size);
163 | if (maxIconSize > -1) {
164 | dialog.icon.setAdjustViewBounds(true);
165 | dialog.icon.setMaxHeight(maxIconSize);
166 | dialog.icon.setMaxWidth(maxIconSize);
167 | dialog.icon.requestLayout();
168 | }
169 |
170 | // Setup divider color in case content scrolls
171 | if (!builder.dividerColorSet) {
172 | final int dividerFallback = DialogUtils.resolveColor(dialog.getContext(), R.attr.md_divider);
173 | builder.dividerColor = DialogUtils.resolveColor(builder.context, R.attr.md_divider_color, dividerFallback);
174 | }
175 | dialog.view.setDividerColor(builder.dividerColor);
176 |
177 | // Setup title and title frame
178 | if (dialog.title != null) {
179 | dialog.setTypeface(dialog.title, builder.mediumFont);
180 | dialog.title.setTextColor(builder.titleColor);
181 | dialog.title.setGravity(builder.titleGravity.getGravityInt());
182 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
183 | //noinspection ResourceType
184 | dialog.title.setTextAlignment(builder.titleGravity.getTextAlignment());
185 | }
186 |
187 | if (builder.title == null) {
188 | dialog.titleFrame.setVisibility(View.GONE);
189 | } else {
190 | dialog.title.setText(builder.title);
191 | dialog.titleFrame.setVisibility(View.VISIBLE);
192 | }
193 | }
194 |
195 | // Setup content
196 | if (dialog.content != null) {
197 | dialog.content.setMovementMethod(new LinkMovementMethod());
198 | dialog.setTypeface(dialog.content, builder.regularFont);
199 | dialog.content.setLineSpacing(0f, builder.contentLineSpacingMultiplier);
200 | if (builder.linkColor == null)
201 | dialog.content.setLinkTextColor(DialogUtils.resolveColor(dialog.getContext(), android.R.attr.textColorPrimary));
202 | else dialog.content.setLinkTextColor(builder.linkColor);
203 | dialog.content.setTextColor(builder.contentColor);
204 | dialog.content.setGravity(builder.contentGravity.getGravityInt());
205 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
206 | //noinspection ResourceType
207 | dialog.content.setTextAlignment(builder.contentGravity.getTextAlignment());
208 | }
209 |
210 | if (builder.content != null) {
211 | dialog.content.setText(builder.content);
212 | dialog.content.setVisibility(View.VISIBLE);
213 | } else {
214 | dialog.content.setVisibility(View.GONE);
215 | }
216 | }
217 |
218 | // Setup prompt checkbox
219 | if (dialog.checkBoxPrompt != null) {
220 | dialog.checkBoxPrompt.setText(builder.checkBoxPrompt);
221 | dialog.checkBoxPrompt.setChecked(builder.checkBoxPromptInitiallyChecked);
222 | dialog.checkBoxPrompt.setOnCheckedChangeListener(builder.checkBoxPromptListener);
223 | dialog.setTypeface(dialog.checkBoxPrompt, builder.regularFont);
224 | dialog.checkBoxPrompt.setTextColor(builder.contentColor);
225 | MDTintHelper.setTint(dialog.checkBoxPrompt, builder.widgetColor);
226 | }
227 |
228 | // Setup action buttons
229 | dialog.view.setButtonGravity(builder.buttonsGravity);
230 | dialog.view.setButtonStackedGravity(builder.btnStackedGravity);
231 | dialog.view.setStackingBehavior(builder.stackingBehavior);
232 | boolean textAllCaps;
233 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
234 | textAllCaps = DialogUtils.resolveBoolean(builder.context, android.R.attr.textAllCaps, true);
235 | if (textAllCaps)
236 | textAllCaps = DialogUtils.resolveBoolean(builder.context, R.attr.textAllCaps, true);
237 | } else {
238 | textAllCaps = DialogUtils.resolveBoolean(builder.context, R.attr.textAllCaps, true);
239 | }
240 |
241 | MDButton positiveTextView = dialog.positiveButton;
242 | dialog.setTypeface(positiveTextView, builder.mediumFont);
243 | positiveTextView.setAllCapsCompat(textAllCaps);
244 | positiveTextView.setText(builder.positiveText);
245 | positiveTextView.setTextColor(builder.positiveColor);
246 | dialog.positiveButton.setStackedSelector(dialog.getButtonSelector(DialogAction.POSITIVE, true));
247 | dialog.positiveButton.setDefaultSelector(dialog.getButtonSelector(DialogAction.POSITIVE, false));
248 | dialog.positiveButton.setTag(DialogAction.POSITIVE);
249 | dialog.positiveButton.setOnClickListener(dialog);
250 | dialog.positiveButton.setVisibility(View.VISIBLE);
251 |
252 | MDButton negativeTextView = dialog.negativeButton;
253 | dialog.setTypeface(negativeTextView, builder.mediumFont);
254 | negativeTextView.setAllCapsCompat(textAllCaps);
255 | negativeTextView.setText(builder.negativeText);
256 | negativeTextView.setTextColor(builder.negativeColor);
257 | dialog.negativeButton.setStackedSelector(dialog.getButtonSelector(DialogAction.NEGATIVE, true));
258 | dialog.negativeButton.setDefaultSelector(dialog.getButtonSelector(DialogAction.NEGATIVE, false));
259 | dialog.negativeButton.setTag(DialogAction.NEGATIVE);
260 | dialog.negativeButton.setOnClickListener(dialog);
261 | dialog.negativeButton.setVisibility(View.VISIBLE);
262 |
263 | MDButton neutralTextView = dialog.neutralButton;
264 | dialog.setTypeface(neutralTextView, builder.mediumFont);
265 | neutralTextView.setAllCapsCompat(textAllCaps);
266 | neutralTextView.setText(builder.neutralText);
267 | neutralTextView.setTextColor(builder.neutralColor);
268 | dialog.neutralButton.setStackedSelector(dialog.getButtonSelector(DialogAction.NEUTRAL, true));
269 | dialog.neutralButton.setDefaultSelector(dialog.getButtonSelector(DialogAction.NEUTRAL, false));
270 | dialog.neutralButton.setTag(DialogAction.NEUTRAL);
271 | dialog.neutralButton.setOnClickListener(dialog);
272 | dialog.neutralButton.setVisibility(View.VISIBLE);
273 |
274 | // Setup list dialog stuff
275 | if (builder.listCallbackMultiChoice != null)
276 | dialog.selectedIndicesList = new ArrayList<>();
277 | if (dialog.recyclerView != null) {
278 | if (builder.adapter == null) {
279 | // Determine list type
280 | if (builder.listCallbackSingleChoice != null) {
281 | dialog.listType = MaterialDialog.ListType.SINGLE;
282 | } else if (builder.listCallbackMultiChoice != null) {
283 | dialog.listType = MaterialDialog.ListType.MULTI;
284 | if (builder.selectedIndices != null) {
285 | dialog.selectedIndicesList = new ArrayList<>(Arrays.asList(builder.selectedIndices));
286 | builder.selectedIndices = null;
287 | }
288 | } else {
289 | dialog.listType = MaterialDialog.ListType.REGULAR;
290 | }
291 | builder.adapter = new DefaultRvAdapter(dialog,
292 | MaterialDialog.ListType.getLayoutForType(dialog.listType));
293 | } else if (builder.adapter instanceof MDAdapter) {
294 | // Notify simple list adapter of the dialog it belongs to
295 | ((MDAdapter) builder.adapter).setDialog(dialog);
296 | }
297 | }
298 |
299 | // Setup progress dialog stuff if needed
300 | setupProgressDialog(dialog);
301 |
302 | // Setup input dialog stuff if needed
303 | setupInputDialog(dialog);
304 |
305 | // Setup custom views
306 | if (builder.customView != null) {
307 | ((MDRootLayout) dialog.view.findViewById(R.id.md_root)).noTitleNoPadding();
308 | FrameLayout frame = (FrameLayout) dialog.view.findViewById(R.id.md_customViewFrame);
309 | dialog.customViewFrame = frame;
310 | View innerView = builder.customView;
311 | if (innerView.getParent() != null)
312 | ((ViewGroup) innerView.getParent()).removeView(innerView);
313 | if (builder.wrapCustomViewInScroll) {
314 | /* Apply the frame padding to the content, this allows the ScrollView to draw it's
315 | over scroll glow without clipping */
316 | final Resources r = dialog.getContext().getResources();
317 | final int framePadding = r.getDimensionPixelSize(R.dimen.md_dialog_frame_margin);
318 | final ScrollView sv = new ScrollView(dialog.getContext());
319 | int paddingTop = r.getDimensionPixelSize(R.dimen.md_content_padding_top);
320 | int paddingBottom = r.getDimensionPixelSize(R.dimen.md_content_padding_bottom);
321 | sv.setClipToPadding(false);
322 | if (innerView instanceof EditText) {
323 | // Setting padding to an EditText causes visual errors, set it to the parent instead
324 | sv.setPadding(framePadding, paddingTop, framePadding, paddingBottom);
325 | } else {
326 | // Setting padding to scroll view pushes the scroll bars out, don't do it if not necessary (like above)
327 | sv.setPadding(0, paddingTop, 0, paddingBottom);
328 | innerView.setPadding(framePadding, 0, framePadding, 0);
329 | }
330 | sv.addView(innerView, new ScrollView.LayoutParams(
331 | ViewGroup.LayoutParams.MATCH_PARENT,
332 | ViewGroup.LayoutParams.WRAP_CONTENT));
333 | innerView = sv;
334 | }
335 | frame.addView(innerView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
336 | ViewGroup.LayoutParams.WRAP_CONTENT));
337 | }
338 |
339 | // Setup user listeners
340 | if (builder.showListener != null)
341 | dialog.setOnShowListener(builder.showListener);
342 | if (builder.cancelListener != null)
343 | dialog.setOnCancelListener(builder.cancelListener);
344 | if (builder.dismissListener != null)
345 | dialog.setOnDismissListener(builder.dismissListener);
346 | if (builder.keyListener != null)
347 | dialog.setOnKeyListener(builder.keyListener);
348 |
349 | // Setup internal show listener
350 | dialog.setOnShowListenerInternal();
351 |
352 | // Other internal initialization
353 | dialog.invalidateList();
354 | dialog.setViewInternal(dialog.view);
355 | dialog.checkIfListInitScroll();
356 |
357 | // Min height and max width calculations
358 | WindowManager wm = dialog.getWindow().getWindowManager();
359 | Display display = wm.getDefaultDisplay();
360 | Point size = new Point();
361 | display.getSize(size);
362 | final int windowWidth = size.x;
363 | final int windowHeight = size.y;
364 |
365 | final int windowVerticalPadding = builder.context.getResources().getDimensionPixelSize(R.dimen.md_dialog_vertical_margin);
366 | final int windowHorizontalPadding = builder.context.getResources().getDimensionPixelSize(R.dimen.md_dialog_horizontal_margin);
367 | final int maxWidth = builder.context.getResources().getDimensionPixelSize(R.dimen.md_dialog_max_width);
368 | final int calculatedWidth = windowWidth - (windowHorizontalPadding * 2);
369 |
370 | dialog.view.setMaxHeight(windowHeight - windowVerticalPadding * 2);
371 | WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
372 | lp.copyFrom(dialog.getWindow().getAttributes());
373 | lp.width = Math.min(maxWidth, calculatedWidth);
374 | dialog.getWindow().setAttributes(lp);
375 | }
376 |
377 | private static void fixCanvasScalingWhenHardwareAccelerated(ProgressBar pb) {
378 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB &&
379 | Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
380 | // Canvas scaling when hardware accelerated results in artifacts on older API levels, so
381 | // we need to use software rendering
382 | if (pb.isHardwareAccelerated() && pb.getLayerType() != View.LAYER_TYPE_SOFTWARE) {
383 | pb.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
384 | }
385 | }
386 | }
387 |
388 | private static void setupProgressDialog(final MaterialDialog dialog) {
389 | final MaterialDialog.Builder builder = dialog.builder;
390 | if (builder.indeterminateProgress || builder.progress > -2) {
391 | dialog.progressBar = (ProgressBar) dialog.view.findViewById(android.R.id.progress);
392 | if (dialog.progressBar == null) return;
393 |
394 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
395 | if (builder.indeterminateProgress) {
396 | if (builder.indeterminateIsHorizontalProgress) {
397 | IndeterminateHorizontalProgressDrawable d = new IndeterminateHorizontalProgressDrawable(builder.getContext());
398 | d.setTint(builder.widgetColor);
399 | dialog.progressBar.setProgressDrawable(d);
400 | dialog.progressBar.setIndeterminateDrawable(d);
401 | } else {
402 | IndeterminateProgressDrawable d = new IndeterminateProgressDrawable(builder.getContext());
403 | d.setTint(builder.widgetColor);
404 | dialog.progressBar.setProgressDrawable(d);
405 | dialog.progressBar.setIndeterminateDrawable(d);
406 | }
407 | } else {
408 | HorizontalProgressDrawable d = new HorizontalProgressDrawable(builder.getContext());
409 | d.setTint(builder.widgetColor);
410 | dialog.progressBar.setProgressDrawable(d);
411 | dialog.progressBar.setIndeterminateDrawable(d);
412 | }
413 | } else {
414 | MDTintHelper.setTint(dialog.progressBar, builder.widgetColor);
415 | }
416 |
417 | if (!builder.indeterminateProgress || builder.indeterminateIsHorizontalProgress) {
418 | dialog.progressBar.setIndeterminate(builder.indeterminateProgress && builder.indeterminateIsHorizontalProgress);
419 | dialog.progressBar.setProgress(0);
420 | dialog.progressBar.setMax(builder.progressMax);
421 | dialog.progressLabel = (TextView) dialog.view.findViewById(R.id.md_label);
422 | if (dialog.progressLabel != null) {
423 | dialog.progressLabel.setTextColor(builder.contentColor);
424 | dialog.setTypeface(dialog.progressLabel, builder.mediumFont);
425 | dialog.progressLabel.setText(builder.progressPercentFormat.format(0));
426 | }
427 | dialog.progressMinMax = (TextView) dialog.view.findViewById(R.id.md_minMax);
428 | if (dialog.progressMinMax != null) {
429 | dialog.progressMinMax.setTextColor(builder.contentColor);
430 | dialog.setTypeface(dialog.progressMinMax, builder.regularFont);
431 |
432 | if (builder.showMinMax) {
433 | dialog.progressMinMax.setVisibility(View.VISIBLE);
434 | dialog.progressMinMax.setText(String.format(builder.progressNumberFormat,
435 | 0, builder.progressMax));
436 | ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) dialog.progressBar.getLayoutParams();
437 | lp.leftMargin = 0;
438 | lp.rightMargin = 0;
439 | } else {
440 | dialog.progressMinMax.setVisibility(View.GONE);
441 | }
442 | } else {
443 | builder.showMinMax = false;
444 | }
445 | }
446 | }
447 |
448 | if (dialog.progressBar != null) {
449 | fixCanvasScalingWhenHardwareAccelerated(dialog.progressBar);
450 | }
451 | }
452 |
453 | private static void setupInputDialog(final MaterialDialog dialog) {
454 | final MaterialDialog.Builder builder = dialog.builder;
455 | dialog.input = (EditText) dialog.view.findViewById(android.R.id.input);
456 | if (dialog.input == null) return;
457 | dialog.setTypeface(dialog.input, builder.regularFont);
458 | if (builder.inputPrefill != null)
459 | dialog.input.setText(builder.inputPrefill);
460 | dialog.setInternalInputCallback();
461 | dialog.input.setHint(builder.inputHint);
462 | dialog.input.setSingleLine();
463 | dialog.input.setTextColor(builder.contentColor);
464 | dialog.input.setHintTextColor(DialogUtils.adjustAlpha(builder.contentColor, 0.3f));
465 | MDTintHelper.setTint(dialog.input, dialog.builder.widgetColor);
466 |
467 | if (builder.inputType != -1) {
468 | dialog.input.setInputType(builder.inputType);
469 | if (builder.inputType != InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD &&
470 | (builder.inputType & InputType.TYPE_TEXT_VARIATION_PASSWORD) == InputType.TYPE_TEXT_VARIATION_PASSWORD) {
471 | // If the flags contain TYPE_TEXT_VARIATION_PASSWORD, apply the password transformation method automatically
472 | dialog.input.setTransformationMethod(PasswordTransformationMethod.getInstance());
473 | }
474 | }
475 |
476 | dialog.inputMinMax = (TextView) dialog.view.findViewById(R.id.md_minMax);
477 | if (builder.inputMinLength > 0 || builder.inputMaxLength > -1) {
478 | dialog.invalidateInputMinMaxIndicator(dialog.input.getText().toString().length(),
479 | !builder.inputAllowEmpty);
480 | } else {
481 | dialog.inputMinMax.setVisibility(View.GONE);
482 | dialog.inputMinMax = null;
483 | }
484 | }
485 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/itheima/materialdialogs/GravityEnum.java:
--------------------------------------------------------------------------------
1 | package com.itheima.materialdialogs;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.annotation.TargetApi;
5 | import android.os.Build;
6 | import android.view.Gravity;
7 | import android.view.View;
8 |
9 | public enum GravityEnum {
10 | START, CENTER, END;
11 |
12 | private static final boolean HAS_RTL = Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1;
13 |
14 | @SuppressLint("RtlHardcoded")
15 | public int getGravityInt() {
16 | switch (this) {
17 | case START:
18 | return HAS_RTL ? Gravity.START : Gravity.LEFT;
19 | case CENTER:
20 | return Gravity.CENTER_HORIZONTAL;
21 | case END:
22 | return HAS_RTL ? Gravity.END : Gravity.RIGHT;
23 | default:
24 | throw new IllegalStateException("Invalid gravity constant");
25 | }
26 | }
27 |
28 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
29 | public int getTextAlignment() {
30 | switch (this) {
31 | case CENTER:
32 | return View.TEXT_ALIGNMENT_CENTER;
33 | case END:
34 | return View.TEXT_ALIGNMENT_VIEW_END;
35 | default:
36 | return View.TEXT_ALIGNMENT_VIEW_START;
37 | }
38 | }
39 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/itheima/materialdialogs/StackingBehavior.java:
--------------------------------------------------------------------------------
1 | package com.itheima.materialdialogs;
2 |
3 | /**
4 | * @author Aidan Follestad (afollestad)
5 | */
6 | public enum StackingBehavior {
7 | /**
8 | * The action buttons are always stacked vertically.
9 | */
10 | ALWAYS,
11 | /**
12 | * The action buttons are stacked vertically IF it is necessary for them to fit in the dialog.
13 | */
14 | ADAPTIVE,
15 | /**
16 | * The action buttons are never stacked, even if they should be.
17 | */
18 | NEVER
19 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/itheima/materialdialogs/Theme.java:
--------------------------------------------------------------------------------
1 | package com.itheima.materialdialogs;
2 |
3 | /**
4 | * @author Aidan Follestad (afollestad)
5 | */
6 | public enum Theme {
7 | LIGHT, DARK
8 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/itheima/materialdialogs/internal/MDAdapter.java:
--------------------------------------------------------------------------------
1 | package com.itheima.materialdialogs.internal;
2 |
3 | import com.itheima.materialdialogs.MaterialDialog;
4 |
5 | /**
6 | * @author Aidan Follestad (afollestad)
7 | */
8 | public interface MDAdapter {
9 |
10 | void setDialog(MaterialDialog dialog);
11 | }
12 |
--------------------------------------------------------------------------------
/library/src/main/java/com/itheima/materialdialogs/internal/MDButton.java:
--------------------------------------------------------------------------------
1 | package com.itheima.materialdialogs.internal;
2 |
3 | import android.content.Context;
4 | import android.graphics.drawable.Drawable;
5 | import android.os.Build;
6 | import android.support.v7.text.AllCapsTransformationMethod;
7 | import android.util.AttributeSet;
8 | import android.view.Gravity;
9 | import android.widget.TextView;
10 |
11 | import com.itheima.materialdialogs.GravityEnum;
12 | import com.itheima.materialdialogs.R;
13 | import com.itheima.materialdialogs.util.DialogUtils;
14 |
15 | /**
16 | * @author Kevin Barry (teslacoil) 4/02/2015
17 | */
18 | public class MDButton extends TextView {
19 |
20 | private boolean stacked = false;
21 | private GravityEnum stackedGravity;
22 |
23 | private int stackedEndPadding;
24 | private Drawable stackedBackground;
25 | private Drawable defaultBackground;
26 |
27 | public MDButton(Context context, AttributeSet attrs) {
28 | super(context, attrs);
29 | init(context);
30 | }
31 |
32 | public MDButton(Context context, AttributeSet attrs, int defStyleAttr) {
33 | super(context, attrs, defStyleAttr);
34 | init(context);
35 | }
36 |
37 | private void init(Context context) {
38 | stackedEndPadding = context.getResources()
39 | .getDimensionPixelSize(R.dimen.md_dialog_frame_margin);
40 | stackedGravity = GravityEnum.END;
41 | }
42 |
43 | /**
44 | * Set if the button should be displayed in stacked mode.
45 | * This should only be called from MDRootLayout's onMeasure, and we must be measured
46 | * after calling this.
47 | */
48 | /* package */ void setStacked(boolean stacked, boolean force) {
49 | if (this.stacked != stacked || force) {
50 |
51 | setGravity(stacked ? (Gravity.CENTER_VERTICAL | stackedGravity.getGravityInt()) : Gravity.CENTER);
52 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
53 | //noinspection ResourceType
54 | setTextAlignment(stacked ? stackedGravity.getTextAlignment() : TEXT_ALIGNMENT_CENTER);
55 | }
56 |
57 | DialogUtils.setBackgroundCompat(this, stacked ? stackedBackground : defaultBackground);
58 | if (stacked) {
59 | setPadding(stackedEndPadding, getPaddingTop(), stackedEndPadding, getPaddingBottom());
60 | } /* Else the padding was properly reset by the drawable */
61 |
62 | this.stacked = stacked;
63 | }
64 | }
65 |
66 | public void setStackedGravity(GravityEnum gravity) {
67 | stackedGravity = gravity;
68 | }
69 |
70 | public void setStackedSelector(Drawable d) {
71 | stackedBackground = d;
72 | if (stacked)
73 | setStacked(true, true);
74 | }
75 |
76 | public void setDefaultSelector(Drawable d) {
77 | defaultBackground = d;
78 | if (!stacked)
79 | setStacked(false, true);
80 | }
81 |
82 | public void setAllCapsCompat(boolean allCaps) {
83 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
84 | setAllCaps(allCaps);
85 | } else {
86 | if (allCaps)
87 | setTransformationMethod(new AllCapsTransformationMethod(getContext()));
88 | else
89 | setTransformationMethod(null);
90 | }
91 | }
92 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/itheima/materialdialogs/internal/MDRootLayout.java:
--------------------------------------------------------------------------------
1 | package com.itheima.materialdialogs.internal;
2 |
3 | import android.annotation.TargetApi;
4 | import android.content.Context;
5 | import android.content.res.Configuration;
6 | import android.content.res.Resources;
7 | import android.content.res.TypedArray;
8 | import android.graphics.Canvas;
9 | import android.graphics.Paint;
10 | import android.os.Build;
11 | import android.support.annotation.Nullable;
12 | import android.support.v7.widget.RecyclerView;
13 | import android.util.AttributeSet;
14 | import android.view.View;
15 | import android.view.ViewGroup;
16 | import android.view.ViewTreeObserver;
17 | import android.webkit.WebView;
18 | import android.widget.AdapterView;
19 | import android.widget.ScrollView;
20 |
21 | import com.itheima.materialdialogs.GravityEnum;
22 | import com.itheima.materialdialogs.R;
23 | import com.itheima.materialdialogs.StackingBehavior;
24 | import com.itheima.materialdialogs.util.DialogUtils;
25 |
26 | /**
27 | * @author Kevin Barry (teslacoil) 4/02/2015 This is the top level view for all MaterialDialogs It
28 | * handles the layout of: titleFrame (md_stub_titleframe) content (text, custom view,
29 | * listview, etc) buttonDefault... (either stacked or horizontal)
30 | */
31 | public class MDRootLayout extends ViewGroup {
32 |
33 | private static final int INDEX_NEUTRAL = 0;
34 | private static final int INDEX_NEGATIVE = 1;
35 | private static final int INDEX_POSITIVE = 2;
36 |
37 | private int maxHeight;
38 | private View titleBar;
39 | private View content;
40 |
41 | private boolean drawTopDivider = false;
42 | private boolean drawBottomDivider = false;
43 | private final MDButton[] buttons = new MDButton[3];
44 | private StackingBehavior stackBehavior = StackingBehavior.ADAPTIVE;
45 | private boolean isStacked = false;
46 | private boolean useFullPadding = true;
47 | private boolean reducePaddingNoTitleNoButtons;
48 | private boolean noTitleNoPadding;
49 |
50 | private int noTitlePaddingFull;
51 | private int buttonPaddingFull;
52 | private int buttonBarHeight;
53 |
54 | private GravityEnum buttonGravity = GravityEnum.START;
55 |
56 | /* Margin from dialog frame to first button */
57 | private int buttonHorizontalEdgeMargin;
58 |
59 | private Paint dividerPaint;
60 |
61 | private ViewTreeObserver.OnScrollChangedListener topOnScrollChangedListener;
62 | private ViewTreeObserver.OnScrollChangedListener bottomOnScrollChangedListener;
63 | private int dividerWidth;
64 |
65 | public MDRootLayout(Context context) {
66 | super(context);
67 | init(context, null, 0);
68 | }
69 |
70 | public MDRootLayout(Context context, AttributeSet attrs) {
71 | super(context, attrs);
72 | init(context, attrs, 0);
73 | }
74 |
75 | @TargetApi(Build.VERSION_CODES.HONEYCOMB)
76 | public MDRootLayout(Context context, AttributeSet attrs, int defStyleAttr) {
77 | super(context, attrs, defStyleAttr);
78 | init(context, attrs, defStyleAttr);
79 | }
80 |
81 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
82 | public MDRootLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
83 | super(context, attrs, defStyleAttr, defStyleRes);
84 | init(context, attrs, defStyleAttr);
85 | }
86 |
87 | private void init(Context context, AttributeSet attrs, int defStyleAttr) {
88 | Resources r = context.getResources();
89 |
90 | TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MDRootLayout, defStyleAttr, 0);
91 | reducePaddingNoTitleNoButtons = a.getBoolean(R.styleable.MDRootLayout_md_reduce_padding_no_title_no_buttons, true);
92 | a.recycle();
93 |
94 | noTitlePaddingFull = r.getDimensionPixelSize(R.dimen.md_notitle_vertical_padding);
95 | buttonPaddingFull = r.getDimensionPixelSize(R.dimen.md_button_frame_vertical_padding);
96 |
97 | buttonHorizontalEdgeMargin = r.getDimensionPixelSize(R.dimen.md_button_padding_frame_side);
98 | buttonBarHeight = r.getDimensionPixelSize(R.dimen.md_button_height);
99 |
100 | dividerPaint = new Paint();
101 | dividerWidth = r.getDimensionPixelSize(R.dimen.md_divider_height);
102 | dividerPaint.setColor(DialogUtils.resolveColor(context, R.attr.md_divider_color));
103 | setWillNotDraw(false);
104 | }
105 |
106 | public void setMaxHeight(int maxHeight) {
107 | this.maxHeight = maxHeight;
108 | }
109 |
110 | public void noTitleNoPadding() {
111 | noTitleNoPadding = true;
112 | }
113 |
114 | @Override
115 | public void onFinishInflate() {
116 | super.onFinishInflate();
117 | for (int i = 0; i < getChildCount(); i++) {
118 | View v = getChildAt(i);
119 | if (v.getId() == R.id.md_titleFrame) {
120 | titleBar = v;
121 | } else if (v.getId() == R.id.md_buttonDefaultNeutral) {
122 | buttons[INDEX_NEUTRAL] = (MDButton) v;
123 | } else if (v.getId() == R.id.md_buttonDefaultNegative) {
124 | buttons[INDEX_NEGATIVE] = (MDButton) v;
125 | } else if (v.getId() == R.id.md_buttonDefaultPositive) {
126 | buttons[INDEX_POSITIVE] = (MDButton) v;
127 | } else {
128 | content = v;
129 | }
130 | }
131 | }
132 |
133 | @Override
134 | public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
135 | int width = MeasureSpec.getSize(widthMeasureSpec);
136 | int height = MeasureSpec.getSize(heightMeasureSpec);
137 |
138 | if (height > maxHeight) {
139 | height = maxHeight;
140 | }
141 |
142 | useFullPadding = true;
143 | boolean hasButtons = false;
144 |
145 | final boolean stacked;
146 | if (stackBehavior == StackingBehavior.ALWAYS) {
147 | stacked = true;
148 | } else if (stackBehavior == StackingBehavior.NEVER) {
149 | stacked = false;
150 | } else {
151 | int buttonsWidth = 0;
152 | for (MDButton button : buttons) {
153 | if (button != null && isVisible(button)) {
154 | button.setStacked(false, false);
155 | measureChild(button, widthMeasureSpec, heightMeasureSpec);
156 | buttonsWidth += button.getMeasuredWidth();
157 | hasButtons = true;
158 | }
159 | }
160 |
161 | int buttonBarPadding = getContext().getResources()
162 | .getDimensionPixelSize(R.dimen.md_neutral_button_margin);
163 | final int buttonFrameWidth = width - 2 * buttonBarPadding;
164 | stacked = buttonsWidth > buttonFrameWidth;
165 | }
166 |
167 | int stackedHeight = 0;
168 | isStacked = stacked;
169 | if (stacked) {
170 | for (MDButton button : buttons) {
171 | if (button != null && isVisible(button)) {
172 | button.setStacked(true, false);
173 | measureChild(button, widthMeasureSpec, heightMeasureSpec);
174 | stackedHeight += button.getMeasuredHeight();
175 | hasButtons = true;
176 | }
177 | }
178 | }
179 |
180 | int availableHeight = height;
181 | int fullPadding = 0;
182 | int minPadding = 0;
183 | if (hasButtons) {
184 | if (isStacked) {
185 | availableHeight -= stackedHeight;
186 | fullPadding += 2 * buttonPaddingFull;
187 | minPadding += 2 * buttonPaddingFull;
188 | } else {
189 | availableHeight -= buttonBarHeight;
190 | fullPadding += 2 * buttonPaddingFull;
191 | /* No minPadding */
192 | }
193 | } else {
194 | /* Content has 8dp, we add 16dp and get 24dp, the frame margin */
195 | fullPadding += 2 * buttonPaddingFull;
196 | }
197 |
198 | if (isVisible(titleBar)) {
199 | titleBar.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
200 | MeasureSpec.UNSPECIFIED);
201 | availableHeight -= titleBar.getMeasuredHeight();
202 | } else if (!noTitleNoPadding) {
203 | fullPadding += noTitlePaddingFull;
204 | }
205 |
206 | if (isVisible(content)) {
207 | content.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
208 | MeasureSpec.makeMeasureSpec(availableHeight - minPadding, MeasureSpec.AT_MOST));
209 |
210 | if (content.getMeasuredHeight() <= availableHeight - fullPadding) {
211 | if (!reducePaddingNoTitleNoButtons || isVisible(titleBar) || hasButtons) {
212 | useFullPadding = true;
213 | availableHeight -= content.getMeasuredHeight() + fullPadding;
214 | } else {
215 | useFullPadding = false;
216 | availableHeight -= content.getMeasuredHeight() + minPadding;
217 | }
218 | } else {
219 | useFullPadding = false;
220 | availableHeight = 0;
221 | }
222 |
223 | }
224 |
225 | setMeasuredDimension(width, height - availableHeight);
226 | }
227 |
228 | private static boolean isVisible(View v) {
229 | boolean visible = v != null && v.getVisibility() != View.GONE;
230 | if (visible && v instanceof MDButton)
231 | visible = ((MDButton) v).getText().toString().trim().length() > 0;
232 | return visible;
233 | }
234 |
235 | @Override
236 | public void onDraw(Canvas canvas) {
237 | super.onDraw(canvas);
238 |
239 | if (content != null) {
240 | if (drawTopDivider) {
241 | int y = content.getTop();
242 | canvas.drawRect(0, y - dividerWidth, getMeasuredWidth(), y, dividerPaint);
243 | }
244 |
245 | if (drawBottomDivider) {
246 | int y = content.getBottom();
247 | canvas.drawRect(0, y, getMeasuredWidth(), y + dividerWidth, dividerPaint);
248 | }
249 | }
250 | }
251 |
252 | @Override
253 | protected void onLayout(boolean changed, final int l, int t, final int r, int b) {
254 | if (isVisible(titleBar)) {
255 | int height = titleBar.getMeasuredHeight();
256 | titleBar.layout(l, t, r, t + height);
257 | t += height;
258 | } else if (!noTitleNoPadding && useFullPadding) {
259 | t += noTitlePaddingFull;
260 | }
261 |
262 | if (isVisible(content))
263 | content.layout(l, t, r, t + content.getMeasuredHeight());
264 |
265 | if (isStacked) {
266 | b -= buttonPaddingFull;
267 | for (MDButton mButton : buttons) {
268 | if (isVisible(mButton)) {
269 | mButton.layout(l, b - mButton.getMeasuredHeight(), r, b);
270 | b -= mButton.getMeasuredHeight();
271 | }
272 | }
273 | } else {
274 | int barTop;
275 | int barBottom = b;
276 | if (useFullPadding)
277 | barBottom -= buttonPaddingFull;
278 | barTop = barBottom - buttonBarHeight;
279 | /* START:
280 | Neutral Negative Positive
281 |
282 | CENTER:
283 | Negative Neutral Positive
284 |
285 | END:
286 | Positive Negative Neutral
287 |
288 | (With no Positive, Negative takes it's place except for CENTER)
289 | */
290 | int offset = buttonHorizontalEdgeMargin;
291 |
292 | /* Used with CENTER gravity */
293 | int neutralLeft = -1;
294 | int neutralRight = -1;
295 |
296 | if (isVisible(buttons[INDEX_POSITIVE])) {
297 | int bl, br;
298 | if (buttonGravity == GravityEnum.END) {
299 | bl = l + offset;
300 | br = bl + buttons[INDEX_POSITIVE].getMeasuredWidth();
301 | } else { /* START || CENTER */
302 | br = r - offset;
303 | bl = br - buttons[INDEX_POSITIVE].getMeasuredWidth();
304 | neutralRight = bl;
305 | }
306 | buttons[INDEX_POSITIVE].layout(bl, barTop, br, barBottom);
307 | offset += buttons[INDEX_POSITIVE].getMeasuredWidth();
308 | }
309 |
310 | if (isVisible(buttons[INDEX_NEGATIVE])) {
311 | int bl, br;
312 | if (buttonGravity == GravityEnum.END) {
313 | bl = l + offset;
314 | br = bl + buttons[INDEX_NEGATIVE].getMeasuredWidth();
315 | } else if (buttonGravity == GravityEnum.START) {
316 | br = r - offset;
317 | bl = br - buttons[INDEX_NEGATIVE].getMeasuredWidth();
318 | } else { /* CENTER */
319 | bl = l + buttonHorizontalEdgeMargin;
320 | br = bl + buttons[INDEX_NEGATIVE].getMeasuredWidth();
321 | neutralLeft = br;
322 | }
323 | buttons[INDEX_NEGATIVE].layout(bl, barTop, br, barBottom);
324 | }
325 |
326 | if (isVisible(buttons[INDEX_NEUTRAL])) {
327 | int bl, br;
328 | if (buttonGravity == GravityEnum.END) {
329 | br = r - buttonHorizontalEdgeMargin;
330 | bl = br - buttons[INDEX_NEUTRAL].getMeasuredWidth();
331 | } else if (buttonGravity == GravityEnum.START) {
332 | bl = l + buttonHorizontalEdgeMargin;
333 | br = bl + buttons[INDEX_NEUTRAL].getMeasuredWidth();
334 | } else { /* CENTER */
335 | if (neutralLeft == -1 && neutralRight != -1) {
336 | neutralLeft = neutralRight - buttons[INDEX_NEUTRAL].getMeasuredWidth();
337 | } else if (neutralRight == -1 && neutralLeft != -1) {
338 | neutralRight = neutralLeft + buttons[INDEX_NEUTRAL].getMeasuredWidth();
339 | } else if (neutralRight == -1) {
340 | neutralLeft = (r - l) / 2 - buttons[INDEX_NEUTRAL].getMeasuredWidth() / 2;
341 | neutralRight = neutralLeft + buttons[INDEX_NEUTRAL].getMeasuredWidth();
342 | }
343 | bl = neutralLeft;
344 | br = neutralRight;
345 | }
346 |
347 | buttons[INDEX_NEUTRAL].layout(bl, barTop, br, barBottom);
348 | }
349 | }
350 |
351 | setUpDividersVisibility(content, true, true);
352 | }
353 |
354 | public void setStackingBehavior(StackingBehavior behavior) {
355 | stackBehavior = behavior;
356 | invalidate();
357 | }
358 |
359 | public void setDividerColor(int color) {
360 | dividerPaint.setColor(color);
361 | invalidate();
362 | }
363 |
364 | public void setButtonGravity(GravityEnum gravity) {
365 | buttonGravity = gravity;
366 | invertGravityIfNecessary();
367 | }
368 |
369 | private void invertGravityIfNecessary() {
370 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) return;
371 | Configuration config = getResources().getConfiguration();
372 | if (config.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
373 | switch (buttonGravity) {
374 | case START:
375 | buttonGravity = GravityEnum.END;
376 | break;
377 | case END:
378 | buttonGravity = GravityEnum.START;
379 | break;
380 | }
381 | }
382 | }
383 |
384 | public void setButtonStackedGravity(GravityEnum gravity) {
385 | for (MDButton mButton : buttons) {
386 | if (mButton != null)
387 | mButton.setStackedGravity(gravity);
388 | }
389 | }
390 |
391 | private void setUpDividersVisibility(final View view, final boolean setForTop, final boolean setForBottom) {
392 | if (view == null)
393 | return;
394 | if (view instanceof ScrollView) {
395 | final ScrollView sv = (ScrollView) view;
396 | if (canScrollViewScroll(sv)) {
397 | addScrollListener(sv, setForTop, setForBottom);
398 | } else {
399 | if (setForTop)
400 | drawTopDivider = false;
401 | if (setForBottom)
402 | drawBottomDivider = false;
403 | }
404 | } else if (view instanceof AdapterView) {
405 | final AdapterView sv = (AdapterView) view;
406 | if (canAdapterViewScroll(sv)) {
407 | addScrollListener(sv, setForTop, setForBottom);
408 | } else {
409 | if (setForTop)
410 | drawTopDivider = false;
411 | if (setForBottom)
412 | drawBottomDivider = false;
413 | }
414 | } else if (view instanceof WebView) {
415 | view.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
416 | @Override
417 | public boolean onPreDraw() {
418 | if (view.getMeasuredHeight() != 0) {
419 | if (!canWebViewScroll((WebView) view)) {
420 | if (setForTop)
421 | drawTopDivider = false;
422 | if (setForBottom)
423 | drawBottomDivider = false;
424 | } else {
425 | addScrollListener((ViewGroup) view, setForTop, setForBottom);
426 | }
427 | view.getViewTreeObserver().removeOnPreDrawListener(this);
428 | }
429 | return true;
430 | }
431 | });
432 | } else if (view instanceof RecyclerView) {
433 | boolean canScroll = canRecyclerViewScroll((RecyclerView) view);
434 | if (setForTop)
435 | drawTopDivider = canScroll;
436 | if (setForBottom)
437 | drawBottomDivider = canScroll;
438 | if (canScroll)
439 | addScrollListener((ViewGroup) view, setForTop, setForBottom);
440 | } else if (view instanceof ViewGroup) {
441 | View topView = getTopView((ViewGroup) view);
442 | setUpDividersVisibility(topView, setForTop, setForBottom);
443 | View bottomView = getBottomView((ViewGroup) view);
444 | if (bottomView != topView) {
445 | setUpDividersVisibility(bottomView, false, true);
446 | }
447 | }
448 | }
449 |
450 | private void addScrollListener(final ViewGroup vg, final boolean setForTop, final boolean setForBottom) {
451 | if ((!setForBottom && topOnScrollChangedListener == null
452 | || (setForBottom && bottomOnScrollChangedListener == null))) {
453 | if (vg instanceof RecyclerView) {
454 | RecyclerView.OnScrollListener scrollListener = new RecyclerView.OnScrollListener() {
455 | @Override
456 | public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
457 | super.onScrolled(recyclerView, dx, dy);
458 | boolean hasButtons = false;
459 | for (MDButton button : buttons) {
460 | if (button != null && button.getVisibility() != View.GONE) {
461 | hasButtons = true;
462 | break;
463 | }
464 | }
465 | invalidateDividersForScrollingView(vg, setForTop, setForBottom, hasButtons);
466 | invalidate();
467 | }
468 | };
469 | ((RecyclerView) vg).addOnScrollListener(scrollListener);
470 | scrollListener.onScrolled((RecyclerView) vg, 0, 0);
471 | } else {
472 | ViewTreeObserver.OnScrollChangedListener onScrollChangedListener = new ViewTreeObserver.OnScrollChangedListener() {
473 | @Override
474 | public void onScrollChanged() {
475 | boolean hasButtons = false;
476 | for (MDButton button : buttons) {
477 | if (button != null && button.getVisibility() != View.GONE) {
478 | hasButtons = true;
479 | break;
480 | }
481 | }
482 | if (vg instanceof WebView) {
483 | invalidateDividersForWebView((WebView) vg, setForTop, setForBottom, hasButtons);
484 | } else {
485 | invalidateDividersForScrollingView(vg, setForTop, setForBottom, hasButtons);
486 | }
487 | invalidate();
488 | }
489 | };
490 | if (!setForBottom) {
491 | topOnScrollChangedListener = onScrollChangedListener;
492 | vg.getViewTreeObserver().addOnScrollChangedListener(topOnScrollChangedListener);
493 | } else {
494 | bottomOnScrollChangedListener = onScrollChangedListener;
495 | vg.getViewTreeObserver().addOnScrollChangedListener(bottomOnScrollChangedListener);
496 | }
497 | onScrollChangedListener.onScrollChanged();
498 | }
499 | }
500 | }
501 |
502 | private void invalidateDividersForScrollingView(ViewGroup view, final boolean setForTop, boolean setForBottom, boolean hasButtons) {
503 | if (setForTop && view.getChildCount() > 0) {
504 | drawTopDivider = titleBar != null &&
505 | titleBar.getVisibility() != View.GONE &&
506 | //Not scrolled to the top.
507 | view.getScrollY() + view.getPaddingTop() > view.getChildAt(0).getTop();
508 |
509 | }
510 | if (setForBottom && view.getChildCount() > 0) {
511 | drawBottomDivider = hasButtons &&
512 | view.getScrollY() + view.getHeight() - view.getPaddingBottom() < view.getChildAt(view.getChildCount() - 1).getBottom();
513 | }
514 | }
515 |
516 | private void invalidateDividersForWebView(WebView view, final boolean setForTop, boolean setForBottom, boolean hasButtons) {
517 | if (setForTop) {
518 | drawTopDivider = titleBar != null &&
519 | titleBar.getVisibility() != View.GONE &&
520 | //Not scrolled to the top.
521 | view.getScrollY() + view.getPaddingTop() > 0;
522 | }
523 | if (setForBottom) {
524 | //noinspection deprecation
525 | drawBottomDivider = hasButtons &&
526 | view.getScrollY() + view.getMeasuredHeight() - view.getPaddingBottom() < view.getContentHeight() * view.getScale();
527 | }
528 | }
529 |
530 | public static boolean canRecyclerViewScroll(RecyclerView view) {
531 | return view != null && view.getLayoutManager() != null && view.getLayoutManager().canScrollVertically();
532 | }
533 |
534 | private static boolean canScrollViewScroll(ScrollView sv) {
535 | if (sv.getChildCount() == 0)
536 | return false;
537 | final int childHeight = sv.getChildAt(0).getMeasuredHeight();
538 | return sv.getMeasuredHeight() - sv.getPaddingTop() - sv.getPaddingBottom() < childHeight;
539 | }
540 |
541 | private static boolean canWebViewScroll(WebView view) {
542 | //noinspection deprecation
543 | return view.getMeasuredHeight() < view.getContentHeight() * view.getScale();
544 | }
545 |
546 | private static boolean canAdapterViewScroll(AdapterView lv) {
547 | /* Force it to layout it's children */
548 | if (lv.getLastVisiblePosition() == -1)
549 | return false;
550 |
551 | /* We can scroll if the first or last item is not visible */
552 | boolean firstItemVisible = lv.getFirstVisiblePosition() == 0;
553 | boolean lastItemVisible = lv.getLastVisiblePosition() == lv.getCount() - 1;
554 |
555 | if (firstItemVisible && lastItemVisible && lv.getChildCount() > 0) {
556 | /* Or the first item's top is above or own top */
557 | if (lv.getChildAt(0).getTop() < lv.getPaddingTop())
558 | return true;
559 | /* or the last item's bottom is beyond our own bottom */
560 | return lv.getChildAt(lv.getChildCount() - 1).getBottom() >
561 | lv.getHeight() - lv.getPaddingBottom();
562 | }
563 |
564 | return true;
565 | }
566 |
567 | /**
568 | * Find the view touching the bottom of this ViewGroup. Non visible children are ignored,
569 | * however getChildDrawingOrder is not taking into account for simplicity and because it behaves
570 | * inconsistently across platform versions.
571 | *
572 | * @return View touching the bottom of this ViewGroup or null
573 | */
574 | @Nullable
575 | private static View getBottomView(ViewGroup viewGroup) {
576 | if (viewGroup == null || viewGroup.getChildCount() == 0)
577 | return null;
578 | View bottomView = null;
579 | for (int i = viewGroup.getChildCount() - 1; i >= 0; i--) {
580 | View child = viewGroup.getChildAt(i);
581 | if (child.getVisibility() == View.VISIBLE && child.getBottom() == viewGroup.getMeasuredHeight()) {
582 | bottomView = child;
583 | break;
584 | }
585 | }
586 | return bottomView;
587 | }
588 |
589 | @Nullable
590 | private static View getTopView(ViewGroup viewGroup) {
591 | if (viewGroup == null || viewGroup.getChildCount() == 0)
592 | return null;
593 | View topView = null;
594 | for (int i = viewGroup.getChildCount() - 1; i >= 0; i--) {
595 | View child = viewGroup.getChildAt(i);
596 | if (child.getVisibility() == View.VISIBLE && child.getTop() == 0) {
597 | topView = child;
598 | break;
599 | }
600 | }
601 | return topView;
602 | }
603 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/itheima/materialdialogs/internal/MDTintHelper.java:
--------------------------------------------------------------------------------
1 | package com.itheima.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.annotation.ColorInt;
9 | import android.support.annotation.NonNull;
10 | import android.support.v4.content.ContextCompat;
11 | import android.support.v4.graphics.drawable.DrawableCompat;
12 | import android.support.v7.widget.AppCompatEditText;
13 | import android.widget.CheckBox;
14 | import android.widget.EditText;
15 | import android.widget.ProgressBar;
16 | import android.widget.RadioButton;
17 | import android.widget.SeekBar;
18 | import android.widget.TextView;
19 |
20 | import com.itheima.materialdialogs.R;
21 | import com.itheima.materialdialogs.util.DialogUtils;
22 |
23 | import java.lang.reflect.Field;
24 |
25 | /**
26 | * Tints widgets
27 | */
28 | public class MDTintHelper {
29 |
30 | public static void setTint(@NonNull RadioButton radioButton, @NonNull ColorStateList colors) {
31 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
32 | radioButton.setButtonTintList(colors);
33 | } else {
34 | Drawable radioDrawable = ContextCompat.getDrawable(radioButton.getContext(), R.drawable.abc_btn_radio_material);
35 | Drawable d = DrawableCompat.wrap(radioDrawable);
36 | DrawableCompat.setTintList(d, colors);
37 | radioButton.setButtonDrawable(d);
38 | }
39 | }
40 |
41 | public static void setTint(@NonNull RadioButton radioButton, @ColorInt int color) {
42 | final int disabledColor = DialogUtils.getDisabledColor(radioButton.getContext());
43 | ColorStateList sl = new ColorStateList(new int[][]{
44 | new int[]{android.R.attr.state_enabled, -android.R.attr.state_checked},
45 | new int[]{android.R.attr.state_enabled, android.R.attr.state_checked},
46 | new int[]{-android.R.attr.state_enabled, -android.R.attr.state_checked},
47 | new int[]{-android.R.attr.state_enabled, android.R.attr.state_checked}
48 | }, new int[]{
49 | DialogUtils.resolveColor(radioButton.getContext(), R.attr.colorControlNormal),
50 | color,
51 | disabledColor,
52 | disabledColor
53 | });
54 | setTint(radioButton, sl);
55 | }
56 |
57 | public static void setTint(@NonNull CheckBox box, @NonNull ColorStateList colors) {
58 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
59 | box.setButtonTintList(colors);
60 | } else {
61 | Drawable checkDrawable = ContextCompat.getDrawable(box.getContext(), R.drawable.abc_btn_check_material);
62 | Drawable drawable = DrawableCompat.wrap(checkDrawable);
63 | DrawableCompat.setTintList(drawable, colors);
64 | box.setButtonDrawable(drawable);
65 | }
66 | }
67 |
68 | public static void setTint(@NonNull CheckBox box, @ColorInt int color) {
69 | final int disabledColor = DialogUtils.getDisabledColor(box.getContext());
70 | ColorStateList sl = new ColorStateList(new int[][]{
71 | new int[]{android.R.attr.state_enabled, -android.R.attr.state_checked},
72 | new int[]{android.R.attr.state_enabled, android.R.attr.state_checked},
73 | new int[]{-android.R.attr.state_enabled, -android.R.attr.state_checked},
74 | new int[]{-android.R.attr.state_enabled, android.R.attr.state_checked}
75 | }, new int[]{
76 | DialogUtils.resolveColor(box.getContext(), R.attr.colorControlNormal),
77 | color,
78 | disabledColor,
79 | disabledColor
80 | });
81 | setTint(box, sl);
82 | }
83 |
84 | public static void setTint(@NonNull SeekBar seekBar, @ColorInt int color) {
85 | ColorStateList s1 = ColorStateList.valueOf(color);
86 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
87 | seekBar.setThumbTintList(s1);
88 | seekBar.setProgressTintList(s1);
89 | } else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.GINGERBREAD_MR1) {
90 | Drawable progressDrawable = DrawableCompat.wrap(seekBar.getProgressDrawable());
91 | seekBar.setProgressDrawable(progressDrawable);
92 | DrawableCompat.setTintList(progressDrawable, s1);
93 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
94 | Drawable thumbDrawable = DrawableCompat.wrap(seekBar.getThumb());
95 | DrawableCompat.setTintList(thumbDrawable, s1);
96 | seekBar.setThumb(thumbDrawable);
97 | }
98 | } else {
99 | PorterDuff.Mode mode = PorterDuff.Mode.SRC_IN;
100 | if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) {
101 | mode = PorterDuff.Mode.MULTIPLY;
102 | }
103 | if (seekBar.getIndeterminateDrawable() != null)
104 | seekBar.getIndeterminateDrawable().setColorFilter(color, mode);
105 | if (seekBar.getProgressDrawable() != null)
106 | seekBar.getProgressDrawable().setColorFilter(color, mode);
107 | }
108 | }
109 |
110 | public static void setTint(@NonNull ProgressBar progressBar, @ColorInt int color) {
111 | setTint(progressBar, color, false);
112 | }
113 |
114 | public static void setTint(@NonNull ProgressBar progressBar, @ColorInt int color, boolean skipIndeterminate) {
115 | ColorStateList sl = ColorStateList.valueOf(color);
116 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
117 | progressBar.setProgressTintList(sl);
118 | progressBar.setSecondaryProgressTintList(sl);
119 | if (!skipIndeterminate)
120 | progressBar.setIndeterminateTintList(sl);
121 | } else {
122 | PorterDuff.Mode mode = PorterDuff.Mode.SRC_IN;
123 | if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) {
124 | mode = PorterDuff.Mode.MULTIPLY;
125 | }
126 | if (!skipIndeterminate && progressBar.getIndeterminateDrawable() != null)
127 | progressBar.getIndeterminateDrawable().setColorFilter(color, mode);
128 | if (progressBar.getProgressDrawable() != null)
129 | progressBar.getProgressDrawable().setColorFilter(color, mode);
130 | }
131 | }
132 |
133 | private static ColorStateList createEditTextColorStateList(@NonNull Context context, @ColorInt int color) {
134 | int[][] states = new int[3][];
135 | int[] colors = new int[3];
136 | int i = 0;
137 | states[i] = new int[]{-android.R.attr.state_enabled};
138 | colors[i] = DialogUtils.resolveColor(context, R.attr.colorControlNormal);
139 | i++;
140 | states[i] = new int[]{-android.R.attr.state_pressed, -android.R.attr.state_focused};
141 | colors[i] = DialogUtils.resolveColor(context, R.attr.colorControlNormal);
142 | i++;
143 | states[i] = new int[]{};
144 | colors[i] = color;
145 | return new ColorStateList(states, colors);
146 | }
147 |
148 | public static void setTint(@NonNull EditText editText, @ColorInt int color) {
149 | ColorStateList editTextColorStateList = createEditTextColorStateList(editText.getContext(), color);
150 | if (editText instanceof AppCompatEditText) {
151 | ((AppCompatEditText) editText).setSupportBackgroundTintList(editTextColorStateList);
152 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
153 | editText.setBackgroundTintList(editTextColorStateList);
154 | }
155 | setCursorTint(editText, color);
156 | }
157 |
158 | private static void setCursorTint(@NonNull EditText editText, @ColorInt int color) {
159 | try {
160 | Field fCursorDrawableRes = TextView.class.getDeclaredField("mCursorDrawableRes");
161 | fCursorDrawableRes.setAccessible(true);
162 | int mCursorDrawableRes = fCursorDrawableRes.getInt(editText);
163 | Field fEditor = TextView.class.getDeclaredField("mEditor");
164 | fEditor.setAccessible(true);
165 | Object editor = fEditor.get(editText);
166 | Class> clazz = editor.getClass();
167 | Field fCursorDrawable = clazz.getDeclaredField("mCursorDrawable");
168 | fCursorDrawable.setAccessible(true);
169 | Drawable[] drawables = new Drawable[2];
170 | drawables[0] = ContextCompat.getDrawable(editText.getContext(), mCursorDrawableRes);
171 | drawables[1] = ContextCompat.getDrawable(editText.getContext(), mCursorDrawableRes);
172 | drawables[0].setColorFilter(color, PorterDuff.Mode.SRC_IN);
173 | drawables[1].setColorFilter(color, PorterDuff.Mode.SRC_IN);
174 | fCursorDrawable.set(editor, drawables);
175 | } catch (Exception e) {
176 | e.printStackTrace();
177 | }
178 | }
179 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/itheima/materialdialogs/internal/ThemeSingleton.java:
--------------------------------------------------------------------------------
1 | package com.itheima.materialdialogs.internal;
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 | import com.itheima.materialdialogs.GravityEnum;
9 |
10 | /**
11 | * Use of this is discouraged for now; for internal use only. See the Global Theming section of the README.
12 | */
13 | public class ThemeSingleton {
14 |
15 | private static ThemeSingleton singleton;
16 |
17 | public static ThemeSingleton get(boolean createIfNull) {
18 | if (singleton == null && createIfNull)
19 | singleton = new ThemeSingleton();
20 | return singleton;
21 | }
22 |
23 | public static ThemeSingleton get() {
24 | return get(true);
25 | }
26 |
27 | public boolean darkTheme = false;
28 | @ColorInt
29 | public int titleColor = 0;
30 | @ColorInt
31 | public int contentColor = 0;
32 | @ColorInt
33 | public ColorStateList positiveColor = null;
34 | @ColorInt
35 | public ColorStateList neutralColor = null;
36 | @ColorInt
37 | public ColorStateList negativeColor = null;
38 | @ColorInt
39 | public int widgetColor = 0;
40 | @ColorInt
41 | public int itemColor = 0;
42 | public Drawable icon = null;
43 | @ColorInt
44 | public int backgroundColor = 0;
45 | @ColorInt
46 | public int dividerColor = 0;
47 | @ColorInt
48 | public ColorStateList linkColor = null;
49 |
50 | @DrawableRes
51 | public int listSelector = 0;
52 | @DrawableRes
53 | public int btnSelectorStacked = 0;
54 | @DrawableRes
55 | public int btnSelectorPositive = 0;
56 | @DrawableRes
57 | public int btnSelectorNeutral = 0;
58 | @DrawableRes
59 | public int btnSelectorNegative = 0;
60 |
61 | public GravityEnum titleGravity = GravityEnum.START;
62 | public GravityEnum contentGravity = GravityEnum.START;
63 | public GravityEnum btnStackedGravity = GravityEnum.END;
64 | public GravityEnum itemsGravity = GravityEnum.START;
65 | public GravityEnum buttonsGravity = GravityEnum.START;
66 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/itheima/materialdialogs/util/DialogUtils.java:
--------------------------------------------------------------------------------
1 | package com.itheima.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.os.IBinder;
11 | import android.support.annotation.ArrayRes;
12 | import android.support.annotation.AttrRes;
13 | import android.support.annotation.ColorInt;
14 | import android.support.annotation.ColorRes;
15 | import android.support.annotation.NonNull;
16 | import android.support.annotation.Nullable;
17 | import android.support.v4.content.ContextCompat;
18 | import android.util.TypedValue;
19 | import android.view.View;
20 | import android.view.inputmethod.InputMethodManager;
21 |
22 | import com.itheima.materialdialogs.GravityEnum;
23 | import com.itheima.materialdialogs.MaterialDialog;
24 |
25 | /**
26 | * @author Aidan Follestad (afollestad)
27 | */
28 | public class DialogUtils {
29 |
30 | // @SuppressWarnings("ConstantConditions")
31 | // public static float resolveFloat(Context context, int attr) {
32 | // TypedArray a = context.obtainStyledAttributes(null, new int[]{attr});
33 | // try {
34 | // return a.getFloat(0, 0);
35 | // } finally {
36 | // a.recycle();
37 | // }
38 | // }
39 |
40 | @ColorInt
41 | public static int getDisabledColor(Context context) {
42 | final int primaryColor = resolveColor(context, android.R.attr.textColorPrimary);
43 | final int disabledColor = isColorDark(primaryColor) ? Color.BLACK : Color.WHITE;
44 | return adjustAlpha(disabledColor, 0.3f);
45 | }
46 |
47 | @ColorInt
48 | public static int adjustAlpha(@ColorInt int color, @SuppressWarnings("SameParameterValue") float factor) {
49 | int alpha = Math.round(Color.alpha(color) * factor);
50 | int red = Color.red(color);
51 | int green = Color.green(color);
52 | int blue = Color.blue(color);
53 | return Color.argb(alpha, red, green, blue);
54 | }
55 |
56 | @ColorInt
57 | public static int resolveColor(Context context, @AttrRes int attr) {
58 | return resolveColor(context, attr, 0);
59 | }
60 |
61 | @ColorInt
62 | public static int resolveColor(Context context, @AttrRes int attr, int fallback) {
63 | TypedArray a = context.getTheme().obtainStyledAttributes(new int[]{attr});
64 | try {
65 | return a.getColor(0, fallback);
66 | } finally {
67 | a.recycle();
68 | }
69 | }
70 |
71 | // Try to resolve the colorAttr attribute.
72 | public static ColorStateList resolveActionTextColorStateList(Context context, @AttrRes int colorAttr, ColorStateList fallback) {
73 | TypedArray a = context.getTheme().obtainStyledAttributes(new int[]{colorAttr});
74 | try {
75 | final TypedValue value = a.peekValue(0);
76 | if (value == null) {
77 | return fallback;
78 | }
79 | if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT && value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
80 | return getActionTextStateList(context, value.data);
81 | } else {
82 | final ColorStateList stateList = a.getColorStateList(0);
83 | if (stateList != null) {
84 | return stateList;
85 | } else {
86 | return fallback;
87 | }
88 | }
89 | } finally {
90 | a.recycle();
91 | }
92 | }
93 |
94 | // Get the specified color resource, creating a ColorStateList if the resource
95 | // points to a color value.
96 | public static ColorStateList getActionTextColorStateList(Context context, @ColorRes int colorId) {
97 | final TypedValue value = new TypedValue();
98 | context.getResources().getValue(colorId, value, true);
99 | if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT && value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
100 | return getActionTextStateList(context, value.data);
101 | } else {
102 |
103 | if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP_MR1) {
104 | //noinspection deprecation
105 | return context.getResources().getColorStateList(colorId);
106 | } else {
107 | return context.getColorStateList(colorId);
108 | }
109 | }
110 | }
111 |
112 | /**
113 | * Returns a color associated with a particular resource ID
114 | *
115 | * Starting in {@link android.os.Build.VERSION_CODES#M}, the returned
116 | * color will be styled for the specified Context's theme.
117 | *
118 | * @param colorId The desired resource identifier, as generated by the aapt
119 | * tool. This integer encodes the package, type, and resource
120 | * entry. The value 0 is an invalid identifier.
121 | * @return A single color value in the form 0xAARRGGBB.
122 | */
123 | @ColorInt
124 | public static int getColor(Context context, @ColorRes int colorId) {
125 | return ContextCompat.getColor(context, colorId);
126 | }
127 |
128 | public static String resolveString(Context context, @AttrRes int attr) {
129 | TypedValue v = new TypedValue();
130 | context.getTheme().resolveAttribute(attr, v, true);
131 | return (String) v.string;
132 | }
133 |
134 | private static int gravityEnumToAttrInt(GravityEnum value) {
135 | switch (value) {
136 | case CENTER:
137 | return 1;
138 | case END:
139 | return 2;
140 | default:
141 | return 0;
142 | }
143 | }
144 |
145 | public static GravityEnum resolveGravityEnum(Context context, @AttrRes int attr, GravityEnum defaultGravity) {
146 | TypedArray a = context.getTheme().obtainStyledAttributes(new int[]{attr});
147 | try {
148 | switch (a.getInt(0, gravityEnumToAttrInt(defaultGravity))) {
149 | case 1:
150 | return GravityEnum.CENTER;
151 | case 2:
152 | return GravityEnum.END;
153 | default:
154 | return GravityEnum.START;
155 | }
156 | } finally {
157 | a.recycle();
158 | }
159 | }
160 |
161 | public static Drawable resolveDrawable(Context context, @AttrRes int attr) {
162 | return resolveDrawable(context, attr, null);
163 | }
164 |
165 | private static Drawable resolveDrawable(Context context, @AttrRes int attr, @SuppressWarnings("SameParameterValue") Drawable fallback) {
166 | TypedArray a = context.getTheme().obtainStyledAttributes(new int[]{attr});
167 | try {
168 | Drawable d = a.getDrawable(0);
169 | if (d == null && fallback != null)
170 | d = fallback;
171 | return d;
172 | } finally {
173 | a.recycle();
174 | }
175 | }
176 |
177 | public static int resolveDimension(Context context, @AttrRes int attr) {
178 | return resolveDimension(context, attr, -1);
179 | }
180 |
181 | private static int resolveDimension(Context context, @AttrRes int attr, int fallback) {
182 | TypedArray a = context.getTheme().obtainStyledAttributes(new int[]{attr});
183 | try {
184 | return a.getDimensionPixelSize(0, fallback);
185 | } finally {
186 | a.recycle();
187 | }
188 | }
189 |
190 | public static boolean resolveBoolean(Context context, @AttrRes int attr, boolean fallback) {
191 | TypedArray a = context.getTheme().obtainStyledAttributes(new int[]{attr});
192 | try {
193 | return a.getBoolean(0, fallback);
194 | } finally {
195 | a.recycle();
196 | }
197 | }
198 |
199 | public static boolean resolveBoolean(Context context, @AttrRes int attr) {
200 | return resolveBoolean(context, attr, false);
201 | }
202 |
203 | public static boolean isColorDark(@ColorInt int color) {
204 | double darkness = 1 - (0.299 * Color.red(color) + 0.587 * Color.green(color) + 0.114 * Color.blue(color)) / 255;
205 | return darkness >= 0.5;
206 | }
207 |
208 | public static void setBackgroundCompat(View view, Drawable d) {
209 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
210 | //noinspection deprecation
211 | view.setBackgroundDrawable(d);
212 | } else {
213 | view.setBackground(d);
214 | }
215 | }
216 |
217 | public static void showKeyboard(@NonNull final DialogInterface di, @NonNull final MaterialDialog.Builder builder) {
218 | final MaterialDialog dialog = (MaterialDialog) di;
219 | if (dialog.getInputEditText() == null) return;
220 | dialog.getInputEditText().post(new Runnable() {
221 | @Override
222 | public void run() {
223 | dialog.getInputEditText().requestFocus();
224 | InputMethodManager imm = (InputMethodManager) builder.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
225 | if (imm != null)
226 | imm.showSoftInput(dialog.getInputEditText(), InputMethodManager.SHOW_IMPLICIT);
227 | }
228 | });
229 | }
230 |
231 | public static void hideKeyboard(@NonNull final DialogInterface di, @NonNull final MaterialDialog.Builder builder) {
232 | final MaterialDialog dialog = (MaterialDialog) di;
233 | if (dialog.getInputEditText() == null) return;
234 | InputMethodManager imm = (InputMethodManager) builder.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
235 | if (imm != null) {
236 | final View currentFocus = dialog.getCurrentFocus();
237 | final IBinder windowToken = currentFocus != null ?
238 | currentFocus.getWindowToken() : dialog.getView().getWindowToken();
239 | if (windowToken != null) {
240 | imm.hideSoftInputFromWindow(windowToken, 0);
241 | }
242 | }
243 | }
244 |
245 | public static ColorStateList getActionTextStateList(Context context, int newPrimaryColor) {
246 | final int fallBackButtonColor = DialogUtils.resolveColor(context, android.R.attr.textColorPrimary);
247 | if (newPrimaryColor == 0) newPrimaryColor = fallBackButtonColor;
248 | int[][] states = new int[][]{
249 | new int[]{-android.R.attr.state_enabled}, // disabled
250 | new int[]{} // enabled
251 | };
252 | int[] colors = new int[]{
253 | DialogUtils.adjustAlpha(newPrimaryColor, 0.4f),
254 | newPrimaryColor
255 | };
256 | return new ColorStateList(states, colors);
257 | }
258 |
259 | public static int[] getColorArray(@NonNull Context context, @ArrayRes int array) {
260 | if (array == 0) return null;
261 | TypedArray ta = context.getResources().obtainTypedArray(array);
262 | int[] colors = new int[ta.length()];
263 | for (int i = 0; i < ta.length(); i++)
264 | colors[i] = ta.getColor(i, 0);
265 | ta.recycle();
266 | return colors;
267 | }
268 |
269 | public static boolean isIn(@NonNull T find, @Nullable T[] ary) {
270 | if (ary == null || ary.length == 0)
271 | return false;
272 | for (T item : ary) {
273 | if (item.equals(find))
274 | return true;
275 | }
276 | return false;
277 | }
278 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/itheima/materialdialogs/util/RippleHelper.java:
--------------------------------------------------------------------------------
1 | package com.itheima.materialdialogs.util;
2 |
3 | import android.annotation.TargetApi;
4 | import android.content.res.ColorStateList;
5 | import android.graphics.drawable.Drawable;
6 | import android.graphics.drawable.RippleDrawable;
7 | import android.os.Build;
8 | import android.support.annotation.ColorInt;
9 |
10 | /**
11 | * @author Aidan Follestad (afollestad)
12 | */
13 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
14 | public class RippleHelper {
15 |
16 | public static void applyColor(Drawable d, @ColorInt int color) {
17 | if (d instanceof RippleDrawable)
18 | ((RippleDrawable) d).setColor(ColorStateList.valueOf(color));
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/library/src/main/java/com/itheima/materialdialogs/util/TypefaceHelper.java:
--------------------------------------------------------------------------------
1 | package com.itheima.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/res/anim/decelerate_cubic.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/library/src/main/res/anim/popup_enter.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
9 |
--------------------------------------------------------------------------------
/library/src/main/res/anim/popup_exit.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
9 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/library/src/main/res/drawable-v21/md_btn_shape.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
15 |
16 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/library/src/main/res/drawable/md_btn_selector.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 |
--------------------------------------------------------------------------------
/library/src/main/res/drawable/md_item_selected.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
--------------------------------------------------------------------------------
/library/src/main/res/drawable/md_item_selected_dark.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
--------------------------------------------------------------------------------
/library/src/main/res/drawable/md_nav_back.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/library/src/main/res/drawable/md_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_transparent.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
--------------------------------------------------------------------------------
/library/src/main/res/layout-ldrtl/md_listitem_multichoice.xml:
--------------------------------------------------------------------------------
1 |
14 |
15 |
27 |
28 |
38 |
39 |
--------------------------------------------------------------------------------
/library/src/main/res/layout-ldrtl/md_listitem_singlechoice.xml:
--------------------------------------------------------------------------------
1 |
14 |
15 |
27 |
28 |
38 |
39 |
--------------------------------------------------------------------------------
/library/src/main/res/layout-v14/md_stub_progress.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
16 |
17 |
20 |
21 |
26 |
27 |
40 |
41 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/library/src/main/res/layout-v14/md_stub_progress_indeterminate.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
19 |
20 |
32 |
33 |
--------------------------------------------------------------------------------
/library/src/main/res/layout-v14/md_stub_progress_indeterminate_horizontal.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
16 |
17 |
23 |
24 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/md_dialog_basic.xml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
19 |
20 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/md_dialog_basic_check.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 |
15 |
16 |
23 |
24 |
33 |
34 |
35 |
36 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/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_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/layout/md_dialog_input_check.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 |
18 |
19 |
32 |
33 |
38 |
39 |
48 |
49 |
65 |
66 |
67 |
68 |
75 |
76 |
77 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/md_dialog_list.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
14 |
15 |
20 |
21 |
31 |
32 |
33 |
34 |
38 |
39 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/md_dialog_list_check.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
14 |
15 |
20 |
21 |
31 |
32 |
33 |
34 |
38 |
39 |
48 |
49 |
50 |
51 |
58 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/md_dialog_progress.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/md_dialog_progress_indeterminate.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/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_listitem.xml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
24 |
25 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/md_listitem_multichoice.xml:
--------------------------------------------------------------------------------
1 |
14 |
15 |
24 |
25 |
38 |
39 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/md_listitem_singlechoice.xml:
--------------------------------------------------------------------------------
1 |
14 |
15 |
24 |
25 |
38 |
39 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/md_stub_actionbuttons.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
8 |
9 |
15 |
16 |
22 |
23 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/md_stub_progress_indeterminate.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
18 |
19 |
31 |
32 |
--------------------------------------------------------------------------------
/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_stub_titleframe.xml:
--------------------------------------------------------------------------------
1 |
12 |
13 |
21 |
22 |
28 |
29 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/md_stub_titleframe_lesspadding.xml:
--------------------------------------------------------------------------------
1 |
12 |
13 |
21 |
22 |
28 |
29 |
--------------------------------------------------------------------------------
/library/src/main/res/values-sw600dp/bool.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | true
4 |
--------------------------------------------------------------------------------
/library/src/main/res/values-sw600dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 446dp
5 |
6 |
--------------------------------------------------------------------------------
/library/src/main/res/values-sw720dp-land/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 564dp
5 |
6 |
--------------------------------------------------------------------------------
/library/src/main/res/values-sw720dp/bool.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | true
4 |
--------------------------------------------------------------------------------
/library/src/main/res/values-sw720dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 496dp
5 |
6 |
--------------------------------------------------------------------------------
/library/src/main/res/values-v11/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
21 |
22 |
39 |
40 |
--------------------------------------------------------------------------------
/library/src/main/res/values-v14/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
10 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
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 |
--------------------------------------------------------------------------------
/library/src/main/res/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
15 |
16 |
27 |
28 |
--------------------------------------------------------------------------------
/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 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/library/src/main/res/values/bool.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | false
4 |
--------------------------------------------------------------------------------
/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 | #2196F3
18 | #1565C0
19 |
20 | #DD2C00
21 |
22 |
--------------------------------------------------------------------------------
/library/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
31 |
32 |
33 | 24dp
34 |
35 | 12dp
36 | 6dp
37 |
39 | 16dp
40 |
41 | 20dp
42 |
43 | 8dp
44 | 8dp
45 |
46 | 72dp
47 |
48 | 6dp
49 | 4dp
50 | 1dp
51 | 8dp
52 | 4dp
53 | 32dp
54 |
55 | 12dp
56 | 12dp
57 |
58 |
59 | 8dp
60 | 8dp
61 | 48dp
62 | 20sp
63 | 16sp
64 | 14sp
65 | 16sp
66 | 48dp
67 | 6dp
68 | 16dp
69 | 48dp
70 | 24dp
71 | 2dp
72 | 1dp
73 |
74 | 2dp
75 | 4dp
76 | 12dp
77 | 8dp
78 |
79 | 356dp
80 | 52dp
81 | 28dp
82 |
83 |
--------------------------------------------------------------------------------
/library/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
14 |
15 |
26 |
27 |
36 |
37 |
43 |
44 |
55 |
56 |
60 |
61 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':library'
2 |
--------------------------------------------------------------------------------