├── .gitignore
├── LICENSE
├── MaterialDialog
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── common
│ │ └── design
│ │ ├── CheckBox.java
│ │ ├── CheckGroup.java
│ │ ├── CheckView.java
│ │ ├── ListItemAdapter.java
│ │ ├── MaterialDialog.java
│ │ ├── MaterialParams.java
│ │ ├── Utils.java
│ │ └── entity
│ │ ├── Option.java
│ │ └── OptionWrapper.java
│ └── res
│ ├── anim
│ ├── material_dialog_in_anim.xml
│ └── material_dialog_out_anim.xml
│ ├── drawable-v21
│ └── button.xml
│ ├── drawable
│ ├── bg_button_normal.xml
│ ├── bg_button_pressed.xml
│ ├── button.xml
│ └── material_card.xml
│ ├── layout
│ ├── checkbox.xml
│ ├── material_dialog_layout.xml
│ ├── material_dialog_list_item_layout.xml
│ └── material_dialog_listview_layout.xml
│ └── values
│ ├── attrs.xml
│ ├── color.xml
│ ├── dimens.xml
│ ├── strings.xml
│ └── styles.xml
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── example
│ │ └── app
│ │ └── ApplicationTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── app
│ │ │ └── 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
│ └── example
│ └── app
│ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── screenRecord
└── screen.gif
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 |
3 | .idea
4 |
5 | build
6 |
7 | .gradle/2.10/taskArtifacts/cache.properties
8 |
9 | .gradle/2.10/taskArtifacts/cache.properties.lock
10 |
11 | *.iml
12 |
13 |
14 | local.properties
15 |
16 | MaterialDialog/bintrayUpload.txt
17 |
18 | .DS_Store
19 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/MaterialDialog/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 28
5 |
6 | defaultConfig {
7 | minSdkVersion 14
8 | targetSdkVersion 28
9 | versionCode 1
10 | versionName "1.0"
11 | }
12 | buildTypes {
13 | release {
14 | minifyEnabled false
15 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
16 | }
17 | }
18 | }
19 |
20 | dependencies {
21 | implementation fileTree(dir: 'libs', include: ['*.jar'])
22 | }
23 |
24 |
--------------------------------------------------------------------------------
/MaterialDialog/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/liujingxing/Documents/software/android-sdk_r24.0.2/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 |
--------------------------------------------------------------------------------
/MaterialDialog/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/MaterialDialog/src/main/java/com/common/design/CheckBox.java:
--------------------------------------------------------------------------------
1 | package com.common.design;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.graphics.Color;
6 | import android.util.AttributeSet;
7 | import android.util.TypedValue;
8 | import android.view.Gravity;
9 | import android.view.View;
10 | import android.widget.LinearLayout;
11 | import android.widget.TextView;
12 |
13 | /**
14 | * 本视图包含标题功能
15 | *
16 | * @author liujingxing on 16/7/18.
17 | */
18 | public class CheckBox extends LinearLayout {
19 |
20 | protected final String NAME_SPACE = "http://schemas.android.com/apk/res/android";
21 |
22 | public int mDefaultSize;
23 |
24 | private TextView mTextView;
25 | private CheckView mCheckView;
26 |
27 | private OnCheckedChangeListener mListener;
28 |
29 | public CheckBox(Context context) {
30 | this(context, null);
31 | }
32 |
33 | public CheckBox(Context context, AttributeSet attrs) {
34 | super(context, attrs);
35 | setOrientation(HORIZONTAL);
36 | setGravity(Gravity.CENTER_VERTICAL);
37 | if (getBackground() == null)
38 | setBackgroundResource(R.drawable.button);
39 | mDefaultSize = dp2px(context, 10);
40 | initView(context, attrs);
41 | }
42 |
43 |
44 | private void initView(Context context, AttributeSet attrs) {
45 | boolean clickable = attrs.getAttributeBooleanValue(NAME_SPACE, "clickable", true);
46 | setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), getPaddingBottom());
47 | setClickable(clickable);
48 |
49 | TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.CheckBox);
50 | String text = ta.getString(R.styleable.CheckBox_text);
51 | int textColor = ta.getColor(R.styleable.CheckBox_textColor, Color.BLACK);
52 | float textSize = ta.getDimension(R.styleable.CheckBox_textSize, dp2px(context, 17));
53 | int middlePadding = ta.getDimensionPixelOffset(R.styleable.CheckBox_middlePadding, mDefaultSize);
54 | int checkBoxWidth = ta.getDimensionPixelOffset(R.styleable.CheckBox_checkBoxWidth, mDefaultSize * 2);
55 | int checkBoxHeight = ta.getDimensionPixelOffset(R.styleable.CheckBox_checkBoxHeight, mDefaultSize * 2);
56 | ta.recycle();
57 |
58 | LayoutParams mCheckParams = new LayoutParams(checkBoxWidth, checkBoxHeight);
59 | mCheckView = new CheckView(context, attrs);
60 |
61 | LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
62 | mTextView = new TextView(context);
63 | params.leftMargin = middlePadding;
64 | mTextView.setLayoutParams(params);
65 | mTextView.setText(text);
66 | mTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
67 | mTextView.setTextColor(textColor);
68 |
69 | addView(mCheckView, mCheckParams);
70 | addView(mTextView, params);
71 |
72 | if (!isClickable()) return;
73 | setOnClickListener(new OnClickListener() {
74 | @Override
75 | public void onClick(View v) {
76 | mCheckView.toggle(true);
77 | if (mListener != null) {
78 | mListener.onCheckedChanged(CheckBox.this, mCheckView.isChecked());
79 | }
80 | }
81 | });
82 | }
83 |
84 | @Override
85 | public void setPadding(int left, int top, int right, int bottom) {
86 | int defaultPadding = dp2px(getContext(), 10);
87 | if (left == 0) left = defaultPadding;
88 | if (top == 0) top = defaultPadding;
89 | if (right == 0) right = defaultPadding;
90 | if (bottom == 0) bottom = defaultPadding;
91 | super.setPadding(left, top, right, bottom);
92 | }
93 |
94 | public int dp2px(Context context, float dipValue) {
95 | final float scale = context.getResources().getDisplayMetrics().density;
96 | return (int) (dipValue * scale + 0.5f);
97 | }
98 |
99 | public void toggle() {
100 | toggle(false);
101 | }
102 |
103 | public void toggle(boolean anim) {
104 | mCheckView.toggle(anim);
105 | }
106 |
107 | public boolean isChecked() {
108 | return mCheckView.isChecked();
109 | }
110 |
111 | public void setChecked(boolean checked) {
112 | setChecked(checked, false);
113 | }
114 |
115 | public void setChecked(boolean checked, boolean anim) {
116 | mCheckView.setChecked(checked, anim);
117 | if (mListener != null) {
118 | mListener.onCheckedChanged(this, mCheckView.isChecked());
119 | }
120 | }
121 |
122 | public void setCheckedColor(int checkedColor) {
123 | mCheckView.setCheckedColor(checkedColor);
124 | }
125 |
126 | public void setShape(int shape) {
127 | mCheckView.setShape(shape);
128 | }
129 |
130 | public void setText(CharSequence text) {
131 | mTextView.setText(text);
132 | }
133 |
134 | public String getText(String text) {
135 | return mTextView.getText().toString();
136 | }
137 |
138 | public void setOnCheckedChangeListener(OnCheckedChangeListener l) {
139 | this.mListener = l;
140 | }
141 |
142 | public interface OnCheckedChangeListener {
143 | void onCheckedChanged(CheckBox checkBox, boolean isChecked);
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/MaterialDialog/src/main/java/com/common/design/CheckGroup.java:
--------------------------------------------------------------------------------
1 | package com.common.design;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.util.AttributeSet;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 | import android.widget.AdapterView;
10 | import android.widget.BaseAdapter;
11 | import android.widget.ListView;
12 |
13 | import com.common.design.entity.Option;
14 | import com.common.design.entity.OptionWrapper;
15 |
16 | import java.util.List;
17 |
18 | /**
19 | * 获取本实例后调用setOptionWrapper方法传入选项集合即可
20 | *
21 | * @author liujingxing on 16/7/19.
22 | * @see #setOptionWrapper(OptionWrapper)
23 | */
24 | public class CheckGroup extends ListView implements AdapterView.OnItemClickListener {
25 |
26 | public static final int CIRCLE = 0;//画圆
27 | public static final int SQUARE = 1;//画正方形
28 |
29 | public int mShape = CIRCLE;
30 |
31 | private Context mContext;
32 |
33 | private OptionWrapper mOptionWrapper;
34 |
35 | /**
36 | * 选项适配器
37 | */
38 | private OptionsAdapter mAdapter;
39 |
40 | /**
41 | * 选中时的颜色
42 | */
43 | private int mCheckedColor = -1;
44 |
45 | private int leftPadding;
46 |
47 |
48 | public CheckGroup(Context context) {
49 | this(context, null);
50 | }
51 |
52 | public CheckGroup(Context context, AttributeSet attrs) {
53 | super(context, attrs);
54 | mContext = context;
55 | setDividerHeight(0);
56 | setOnItemClickListener(this);
57 | mOptionWrapper = new OptionWrapper();
58 | mAdapter = new OptionsAdapter(mOptionWrapper.getOptions(), attrs);
59 |
60 | TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CheckBox);
61 | mShape = typedArray.getInt(R.styleable.CheckBox_shape, CIRCLE);
62 | typedArray.recycle();
63 | }
64 |
65 | /**
66 | * 传入一个选项集合的封装类后,就可正常显示CheckGroup
67 | *
68 | * @param wrapper 选项集合的封装类
69 | */
70 | public void setOptionWrapper(OptionWrapper wrapper) {
71 | if (wrapper == null) return;
72 | mOptionWrapper.set(wrapper);
73 | setAdapter(mAdapter);
74 | }
75 |
76 | @Override
77 | public void onItemClick(AdapterView> parent, View view, int position, long id) {
78 | if (!mOptionWrapper.isEnabled()) return;
79 | if (mOptionWrapper.isSingleChoice()) {
80 | handleSingleChoice(parent, view, position);
81 | } else {
82 | handleMultiChoice((CheckBox) view, position);
83 | }
84 | if (mOnChangeListener != null)
85 | mOnChangeListener.onChange(parent, view, position);
86 | }
87 |
88 | private void handleMultiChoice(CheckBox checkBox, int position) {
89 | checkBox.toggle(true);
90 | mOptionWrapper.getOptionAt(position).toggle();
91 | }
92 |
93 | /**
94 | * 处理单选时的情况,可能有人会问:
95 | * 为什么要那么麻烦,为什么不直接循环实体类集合,并将当前单击的item设为true,其他一概设为false,然后刷新适配器即可
96 | *
原因:重新刷新适配器的话,所有的item都需要重新绘制一遍,这样就会加大cup的工作量
97 | *
而通过以下方法的话,只要刷新两个item即可
98 | */
99 | private void handleSingleChoice(AdapterView> parent, View view, int position) {
100 | CheckBox checkBox;
101 | boolean isSet = false;//用于判断有没有将当前单击的item设为true
102 | int chileCount = parent.getChildCount();//得到item条数
103 | for (int i = 0; i < chileCount; i++) {
104 | View v = parent.getChildAt(i);
105 | checkBox = (CheckBox) v;
106 | boolean isCheck = checkBox.isChecked();
107 | if (i == position && !isCheck) {
108 | //如果是当前单击的item且没有被选中,则设为选中
109 | checkBox.setChecked(true, true);
110 | mOptionWrapper.getOptionAt(i).setCheck(true);
111 | isSet = true;
112 | } else if (i != position && isCheck) {
113 | //如果不是当前单击的item且被选中,则设为不选中,即将上次选中的置为false,并结束循环
114 | checkBox.setChecked(false, true);
115 | mOptionWrapper.getOptionAt(i).setCheck(false);
116 | break;
117 | }
118 | }
119 | if (!isSet) {//如果没有将当前单击的item设为true,则直接通过View找到并设为true
120 | checkBox = (CheckBox) view;
121 | checkBox.setChecked(true, true);
122 | mOptionWrapper.getOptionAt(position).setCheck(true);
123 | }
124 | }
125 |
126 | /**
127 | * 设置选中时CheckBox的颜色
128 | *
129 | * @param checkedColor 选中时的颜色
130 | */
131 | public void setCheckedColor(int checkedColor) {
132 | mCheckedColor = checkedColor;
133 | }
134 |
135 | /**
136 | * @return 选中的item集合
137 | */
138 | public List getChecked() {
139 | return mOptionWrapper.getChecked();
140 | }
141 |
142 |
143 | /**
144 | * @return 选中item的文本集合
145 | */
146 | public List getCheckedText() {
147 | return mOptionWrapper.getCheckedText();
148 | }
149 |
150 | /**
151 | * @return 选中item的position 集合
152 | */
153 | public List getCheckedIndex() {
154 | return mOptionWrapper.getCheckedIndex();
155 | }
156 |
157 | public void setShape(int shape) {
158 | mShape = shape;
159 | }
160 |
161 | public void setLeftPadding(int leftPadding) {
162 | this.leftPadding = leftPadding;
163 | }
164 |
165 | class OptionsAdapter extends BaseAdapter {
166 |
167 | List mOptions;
168 |
169 | AttributeSet attrs;
170 |
171 | public OptionsAdapter(List options, AttributeSet attrs) {
172 | mOptions = options;
173 | this.attrs = attrs;
174 | }
175 |
176 | @Override
177 | public int getCount() {
178 | return mOptions.size();
179 | }
180 |
181 | @Override
182 | public Object getItem(int position) {
183 | return mOptions.get(position);
184 | }
185 |
186 | @Override
187 | public long getItemId(int position) {
188 | return position;
189 | }
190 |
191 | @Override
192 | public View getView(int position, View convertView, ViewGroup parent) {
193 | ViewHolder holder;
194 | if (convertView == null) {
195 | convertView = LayoutInflater.from(mContext).inflate(R.layout.checkbox, parent, false);
196 | convertView.setPadding(leftPadding, convertView.getPaddingTop(), convertView.getPaddingRight(), convertView.getPaddingBottom());
197 | holder = new ViewHolder(convertView);
198 | holder.checkBox.setShape(mShape);
199 | convertView.setTag(holder);
200 | } else {
201 | holder = (ViewHolder) convertView.getTag();
202 | }
203 |
204 | Option option = mOptions.get(position);
205 | if (mCheckedColor != -1)
206 | holder.checkBox.setCheckedColor(mCheckedColor);
207 | holder.checkBox.setChecked(option.isCheck());
208 | holder.checkBox.setText(option.getTitle());
209 | holder.checkBox.setShape(mShape);
210 | return convertView;
211 | }
212 | }
213 |
214 | class ViewHolder {
215 | CheckBox checkBox;
216 |
217 | public ViewHolder(View view) {
218 | this.checkBox = (CheckBox) view;
219 | }
220 | }
221 |
222 |
223 | /**
224 | * 外界调用的item监听器
225 | */
226 | private OnChangeListener mOnChangeListener;
227 |
228 | public interface OnChangeListener {
229 | void onChange(AdapterView> parent, View view, int position);
230 | }
231 |
232 | public void setOnChangeListener(OnChangeListener onChangeListener) {
233 | mOnChangeListener = onChangeListener;
234 | }
235 |
236 | }
237 |
--------------------------------------------------------------------------------
/MaterialDialog/src/main/java/com/common/design/CheckView.java:
--------------------------------------------------------------------------------
1 | /**
2 | * * Copyright 2016 andy
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.common.design;
18 |
19 | import android.animation.ValueAnimator;
20 | import android.annotation.TargetApi;
21 | import android.content.Context;
22 | import android.content.res.TypedArray;
23 | import android.graphics.Canvas;
24 | import android.graphics.Color;
25 | import android.graphics.Paint;
26 | import android.graphics.Path;
27 | import android.graphics.Point;
28 | import android.graphics.RectF;
29 | import android.os.Build;
30 | import android.os.Bundle;
31 | import android.os.Parcelable;
32 | import android.util.AttributeSet;
33 | import android.view.View;
34 | import android.view.animation.LinearInterpolator;
35 | import android.widget.Checkable;
36 |
37 |
38 | /**
39 | * 本视图仅仅是一个框,不带有标题功能
40 | *
41 | * @author liujingxing 2016/07/02
42 | */
43 |
44 | class CheckView extends View implements Checkable {
45 | private static final String KEY_INSTANCE_STATE = "InstanceState";
46 |
47 |
48 | private static final int COLOR_TICK = Color.WHITE;
49 | private static final int COLOR_UNCHECKED = Color.WHITE;
50 | private static final int COLOR_CHECKED = Color.parseColor("#FB4846");
51 | private static final int COLOR_FLOOR_UNCHECKED = Color.parseColor("#828282");
52 |
53 | private static final int DEF_DRAW_SIZE = 20;
54 | private static final int DEF_ANIM_DURATION = 300;
55 |
56 | public static final int CIRCLE = 0;//画圆
57 | public static final int SQUARE = 1;//画正方形
58 | public int mShape = CIRCLE;
59 |
60 | private Paint mPaint, mTickPaint, mFloorPaint;
61 | private Point[] mTickPoints;
62 | private Point mCenterPoint;
63 | private Path mTickPath;
64 |
65 | private float mLeftLineDistance, mRightLineDistance, mDrewDistance;
66 | private float mScaleVal = 1.0f, mFloorScale = 1.0f;
67 | private int mWidth, mAnimDuration, mStrokeWidth;
68 | private int mCheckedColor, mUnCheckedColor, mFloorColor, mFloorUnCheckedColor;
69 | private int mRadius;//矩形圆角度数
70 |
71 | private boolean mChecked;
72 | private boolean mTickDrawing;
73 |
74 | public CheckView(Context context) {
75 | this(context, null);
76 | }
77 |
78 | public CheckView(Context context, AttributeSet attrs) {
79 | this(context, attrs, 0);
80 | }
81 |
82 | public CheckView(Context context, AttributeSet attrs, int defStyleAttr) {
83 | super(context, attrs, defStyleAttr);
84 | init(attrs);
85 | }
86 |
87 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
88 | public CheckView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
89 | super(context, attrs, defStyleAttr, defStyleRes);
90 | init(attrs);
91 | }
92 |
93 | private void init(AttributeSet attrs) {
94 |
95 | TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.CheckBox);
96 | int tickColor = ta.getColor(R.styleable.CheckBox_colorTick, COLOR_TICK);
97 | mAnimDuration = ta.getInt(R.styleable.CheckBox_duration, DEF_ANIM_DURATION);
98 | mFloorColor = ta.getColor(R.styleable.CheckBox_colorUncheckedStroke, COLOR_FLOOR_UNCHECKED);
99 | mCheckedColor = ta.getColor(R.styleable.CheckBox_colorChecked, COLOR_CHECKED);
100 | mUnCheckedColor = ta.getColor(R.styleable.CheckBox_colorUnchecked, COLOR_UNCHECKED);
101 | mStrokeWidth = ta.getDimensionPixelSize(R.styleable.CheckBox_strokeWidth, dp2px(getContext(), 2));
102 | mRadius = ta.getDimensionPixelSize(R.styleable.CheckBox_radius, dp2px(getContext(), 2));
103 | mShape = ta.getInt(R.styleable.CheckBox_shape, 0);
104 | ta.recycle();
105 |
106 | mFloorUnCheckedColor = mFloorColor;
107 | mTickPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
108 | mTickPaint.setStyle(Paint.Style.STROKE);
109 | mTickPaint.setStrokeCap(Paint.Cap.ROUND);
110 | mTickPaint.setColor(tickColor);
111 |
112 | mFloorPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
113 | mFloorPaint.setStyle(Paint.Style.FILL);
114 | mFloorPaint.setStrokeCap(Paint.Cap.ROUND);
115 | mFloorPaint.setStrokeWidth(mStrokeWidth);
116 | mFloorPaint.setColor(mFloorColor);
117 |
118 | mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
119 | mPaint.setStyle(Paint.Style.FILL);
120 | mPaint.setColor(mCheckedColor);
121 |
122 | mTickPath = new Path();
123 | mCenterPoint = new Point();
124 | mTickPoints = new Point[3];
125 | mTickPoints[0] = new Point();
126 | mTickPoints[1] = new Point();
127 | mTickPoints[2] = new Point();
128 |
129 | }
130 |
131 | @Override
132 | protected Parcelable onSaveInstanceState() {
133 | Bundle bundle = new Bundle();
134 | bundle.putParcelable(KEY_INSTANCE_STATE, super.onSaveInstanceState());
135 | bundle.putBoolean(KEY_INSTANCE_STATE, isChecked());
136 | return bundle;
137 | }
138 |
139 | @Override
140 | protected void onRestoreInstanceState(Parcelable state) {
141 | if (state instanceof Bundle) {
142 | Bundle bundle = (Bundle) state;
143 | boolean isChecked = bundle.getBoolean(KEY_INSTANCE_STATE);
144 | setChecked(isChecked);
145 | super.onRestoreInstanceState(bundle.getParcelable(KEY_INSTANCE_STATE));
146 | return;
147 | }
148 | super.onRestoreInstanceState(state);
149 | }
150 |
151 | @Override
152 | public boolean isChecked() {
153 | return mChecked;
154 | }
155 |
156 | @Override
157 | public void toggle() {
158 | this.setChecked(!isChecked());
159 | }
160 |
161 | public void toggle(boolean animate) {
162 | this.setChecked(!isChecked(), animate);
163 | }
164 |
165 | @Override
166 | public void setChecked(boolean checked) {
167 | mChecked = checked;
168 | reset();
169 | invalidate();
170 | }
171 |
172 | /**
173 | * checked with animation
174 | *
175 | * @param checked checked
176 | * @param animate change with animation
177 | */
178 | public void setChecked(boolean checked, boolean animate) {
179 | if (animate) {
180 | mTickDrawing = false;
181 | mChecked = checked;
182 | mDrewDistance = 0f;
183 | if (checked) {
184 | startCheckedAnimation();
185 | } else {
186 | startUnCheckedAnimation();
187 | }
188 | } else {
189 | this.setChecked(checked);
190 | }
191 | }
192 |
193 | public void setShape(int shape) {
194 | mShape = shape;
195 | }
196 |
197 | public void setCheckedColor(int checkedColor) {
198 | mCheckedColor = checkedColor;
199 | }
200 |
201 | private void reset() {
202 | mTickDrawing = true;
203 | mFloorScale = 1.0f;
204 | mScaleVal = isChecked() ? 0f : 1.0f;
205 | mFloorColor = isChecked() ? mCheckedColor : mFloorUnCheckedColor;
206 | mDrewDistance = isChecked() ? (mLeftLineDistance + mRightLineDistance) : 0;
207 | }
208 |
209 | private int measureSize(int measureSpec) {
210 | int defSize = dp2px(getContext(), DEF_DRAW_SIZE);
211 | int specSize = MeasureSpec.getSize(measureSpec);
212 | int specMode = MeasureSpec.getMode(measureSpec);
213 |
214 | int result = 0;
215 | switch (specMode) {
216 | case MeasureSpec.UNSPECIFIED:
217 | case MeasureSpec.AT_MOST:
218 | result = Math.min(defSize, specSize);
219 | break;
220 | case MeasureSpec.EXACTLY:
221 | result = specSize;
222 | break;
223 | }
224 | return result;
225 | }
226 |
227 | @Override
228 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
229 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
230 | setMeasuredDimension(measureSize(widthMeasureSpec), measureSize(heightMeasureSpec));
231 | }
232 |
233 | @Override
234 | protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
235 | mWidth = getMeasuredWidth();
236 | mCenterPoint.x = mWidth / 2;
237 | mCenterPoint.y = getMeasuredHeight() / 2;
238 |
239 | mTickPoints[0].x = Math.round((float) getMeasuredWidth() / 30 * 7);
240 | mTickPoints[0].y = Math.round((float) getMeasuredHeight() / 30 * 14);
241 | mTickPoints[1].x = Math.round((float) getMeasuredWidth() / 30 * 13);
242 | mTickPoints[1].y = Math.round((float) getMeasuredHeight() / 30 * 20);
243 | mTickPoints[2].x = Math.round((float) getMeasuredWidth() / 30 * 22);
244 | mTickPoints[2].y = Math.round((float) getMeasuredHeight() / 30 * 10);
245 |
246 | mLeftLineDistance = (float) Math.sqrt(Math.pow(mTickPoints[1].x - mTickPoints[0].x, 2) +
247 | Math.pow(mTickPoints[1].y - mTickPoints[0].y, 2));
248 | mRightLineDistance = (float) Math.sqrt(Math.pow(mTickPoints[2].x - mTickPoints[1].x, 2) +
249 | Math.pow(mTickPoints[2].y - mTickPoints[1].y, 2));
250 | mTickPaint.setStrokeWidth(mStrokeWidth);
251 | }
252 |
253 | @Override
254 | protected void onDraw(Canvas canvas) {
255 | drawCenter(canvas);
256 | drawBorder(canvas);
257 | drawTick(canvas);
258 | }
259 |
260 | private void drawCenter(Canvas canvas) {
261 | mPaint.setColor(mUnCheckedColor);
262 | float radius = (mCenterPoint.x - mStrokeWidth / 2) * mScaleVal;
263 | if (mShape == CIRCLE) {
264 | canvas.drawCircle(mCenterPoint.x, mCenterPoint.y, radius, mPaint);
265 | } else {
266 | RectF rectf = new RectF(mCenterPoint.x - radius, mCenterPoint.y - radius, mCenterPoint.x + radius, mCenterPoint.y + radius);
267 | canvas.drawRoundRect(rectf, mRadius, mRadius, mPaint);
268 | }
269 | }
270 |
271 | private void drawBorder(Canvas canvas) {
272 | mFloorPaint.setColor(mFloorColor);
273 | mFloorPaint.setStyle(isChecked() ? Paint.Style.FILL : Paint.Style.STROKE);
274 | int radius = mCenterPoint.x;
275 | if (mShape == CIRCLE) {
276 | radius -= (mChecked ? 0 : mStrokeWidth / 2);
277 | canvas.drawCircle(mCenterPoint.x, mCenterPoint.y, radius * mFloorScale, mFloorPaint);
278 | } else {
279 | float scale = radius * mFloorScale;
280 | float left = mCenterPoint.x - scale + (mChecked ? 0 : mStrokeWidth / 2);
281 | float top = mCenterPoint.y - scale + (mChecked ? 0 : mStrokeWidth / 2);
282 | float right = mCenterPoint.x + scale - (mChecked ? 0 : mStrokeWidth / 2);
283 | float bottom = mCenterPoint.y + scale - (mChecked ? 0 : mStrokeWidth / 2);
284 | RectF rectf = new RectF(left, top, right, bottom);
285 | canvas.drawRoundRect(rectf, mRadius, mRadius, mFloorPaint);
286 | }
287 | }
288 |
289 | private void drawTick(Canvas canvas) {
290 | if (mTickDrawing && isChecked()) {
291 | drawTickPath(canvas);
292 | }
293 | }
294 |
295 | private void drawTickPath(Canvas canvas) {
296 | mTickPath.reset();
297 | // draw left of the tick
298 | if (mDrewDistance < mLeftLineDistance) {
299 | float step = (mWidth / 20.0f) < 3 ? 3 : (mWidth / 20.0f);
300 | mDrewDistance += step;
301 | float stopX = mTickPoints[0].x + (mTickPoints[1].x - mTickPoints[0].x) * mDrewDistance / mLeftLineDistance;
302 | float stopY = mTickPoints[0].y + (mTickPoints[1].y - mTickPoints[0].y) * mDrewDistance / mLeftLineDistance;
303 |
304 | mTickPath.moveTo(mTickPoints[0].x, mTickPoints[0].y);
305 | mTickPath.lineTo(stopX, stopY);
306 | canvas.drawPath(mTickPath, mTickPaint);
307 |
308 | if (mDrewDistance > mLeftLineDistance) {
309 | mDrewDistance = mLeftLineDistance;
310 | }
311 | } else {
312 |
313 | mTickPath.moveTo(mTickPoints[0].x, mTickPoints[0].y);
314 | mTickPath.lineTo(mTickPoints[1].x, mTickPoints[1].y);
315 | canvas.drawPath(mTickPath, mTickPaint);
316 |
317 | // draw right of the tick
318 | if (mDrewDistance < mLeftLineDistance + mRightLineDistance) {
319 | float stopX = mTickPoints[1].x + (mTickPoints[2].x - mTickPoints[1].x) * (mDrewDistance - mLeftLineDistance) / mRightLineDistance;
320 | float stopY = mTickPoints[1].y - (mTickPoints[1].y - mTickPoints[2].y) * (mDrewDistance - mLeftLineDistance) / mRightLineDistance;
321 |
322 | mTickPath.reset();
323 | mTickPath.moveTo(mTickPoints[1].x, mTickPoints[1].y);
324 | mTickPath.lineTo(stopX, stopY);
325 | canvas.drawPath(mTickPath, mTickPaint);
326 |
327 | float step = (mWidth / 20) < 3 ? 3 : (mWidth / 20);
328 | mDrewDistance += step;
329 | } else {
330 | mTickPath.reset();
331 | mTickPath.moveTo(mTickPoints[1].x, mTickPoints[1].y);
332 | mTickPath.lineTo(mTickPoints[2].x, mTickPoints[2].y);
333 | canvas.drawPath(mTickPath, mTickPaint);
334 | }
335 | }
336 |
337 | // invalidate
338 | if (mDrewDistance < mLeftLineDistance + mRightLineDistance) {
339 | postDelayed(new Runnable() {
340 | @Override
341 | public void run() {
342 | postInvalidate();
343 | }
344 | }, 10);
345 | }
346 | }
347 |
348 | private void startCheckedAnimation() {
349 | ValueAnimator animator = ValueAnimator.ofFloat(1.0f, 0f);
350 | animator.setDuration(mAnimDuration / 3 * 2);
351 | animator.setInterpolator(new LinearInterpolator());
352 | animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
353 | @Override
354 | public void onAnimationUpdate(ValueAnimator animation) {
355 | mScaleVal = (float) animation.getAnimatedValue();
356 | mFloorColor = getGradientColor(mUnCheckedColor, mCheckedColor, 1 - mScaleVal);
357 | }
358 | });
359 | animator.start();
360 |
361 | ValueAnimator floorAnimator = ValueAnimator.ofFloat(1.0f, 0.8f, 1.0f);
362 | floorAnimator.setDuration(mAnimDuration);
363 | floorAnimator.setInterpolator(new LinearInterpolator());
364 | floorAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
365 | @Override
366 | public void onAnimationUpdate(ValueAnimator animation) {
367 | mFloorScale = (float) animation.getAnimatedValue();
368 | postInvalidate();
369 | }
370 | });
371 | floorAnimator.start();
372 |
373 | drawTickDelayed();
374 | }
375 |
376 | private void startUnCheckedAnimation() {
377 | ValueAnimator animator = ValueAnimator.ofFloat(0f, 1.0f);
378 | animator.setDuration(mAnimDuration);
379 | animator.setInterpolator(new LinearInterpolator());
380 | animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
381 | @Override
382 | public void onAnimationUpdate(ValueAnimator animation) {
383 | mScaleVal = (float) animation.getAnimatedValue();
384 | mFloorColor = getGradientColor(mCheckedColor, mFloorUnCheckedColor, mScaleVal);
385 | postInvalidate();
386 | }
387 | });
388 | animator.start();
389 | if (mUnCheckedColor == Color.TRANSPARENT) return;
390 | ValueAnimator floorAnimator = ValueAnimator.ofFloat(1.0f, 0.8f, 1.0f);
391 | floorAnimator.setDuration(mAnimDuration);
392 | floorAnimator.setInterpolator(new LinearInterpolator());
393 | floorAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
394 | @Override
395 | public void onAnimationUpdate(ValueAnimator animation) {
396 | mFloorScale = (float) animation.getAnimatedValue();
397 | }
398 | });
399 | floorAnimator.start();
400 | }
401 |
402 | private void drawTickDelayed() {
403 | postDelayed(new Runnable() {
404 | @Override
405 | public void run() {
406 | mTickDrawing = true;
407 | postInvalidate();
408 | }
409 | }, mAnimDuration);
410 | }
411 |
412 | private static int getGradientColor(int startColor, int endColor, float percent) {
413 | int sr = (startColor & 0xff0000) >> 0x10;
414 | int sg = (startColor & 0xff00) >> 0x8;
415 | int sb = (startColor & 0xff);
416 |
417 | int er = (endColor & 0xff0000) >> 0x10;
418 | int eg = (endColor & 0xff00) >> 0x8;
419 | int eb = (endColor & 0xff);
420 |
421 | int cr = (int) (sr * (1 - percent) + er * percent);
422 | int cg = (int) (sg * (1 - percent) + eg * percent);
423 | int cb = (int) (sb * (1 - percent) + eb * percent);
424 | return Color.argb(0xff, cr, cg, cb);
425 | }
426 |
427 | public int dp2px(Context context, float dipValue) {
428 | final float scale = context.getResources().getDisplayMetrics().density;
429 | return (int) (dipValue * scale + 0.5f);
430 | }
431 | }
432 |
--------------------------------------------------------------------------------
/MaterialDialog/src/main/java/com/common/design/ListItemAdapter.java:
--------------------------------------------------------------------------------
1 | package com.common.design;
2 |
3 | import android.content.Context;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.widget.BaseAdapter;
8 | import android.widget.TextView;
9 |
10 | import java.util.Arrays;
11 | import java.util.List;
12 |
13 | /**
14 | * @author liujingxing on 16/4/21.
15 | */
16 | class ListItemAdapter extends BaseAdapter {
17 | private Context mContext;
18 | private List extends CharSequence> mDataList;
19 |
20 | public ListItemAdapter(Context context, CharSequence[] data) {
21 | this(context, Arrays.asList(data));
22 | }
23 |
24 | public ListItemAdapter(Context context, List extends CharSequence> data) {
25 | mContext = context;
26 | mDataList = data;
27 | }
28 |
29 |
30 | @Override
31 | public int getCount() {
32 | return mDataList.size();
33 | }
34 |
35 | @Override
36 | public Object getItem(int position) {
37 | return mDataList.get(position);
38 | }
39 |
40 | @Override
41 | public long getItemId(int position) {
42 | return position;
43 | }
44 |
45 | @Override
46 | public View getView(int position, View convertView, ViewGroup parent) {
47 | ViewHolder holder;
48 | if (convertView == null) {
49 | convertView = LayoutInflater.from(mContext).inflate(R.layout.material_dialog_list_item_layout, null);
50 | holder = new ViewHolder(convertView);
51 | convertView.setTag(holder);
52 | } else {
53 | holder = (ViewHolder) convertView.getTag();
54 | }
55 | holder.mTextView.setText(mDataList.get(position));
56 | return convertView;
57 | }
58 |
59 | class ViewHolder {
60 | TextView mTextView;
61 |
62 | public ViewHolder(View view) {
63 | mTextView = (TextView) view.findViewById(R.id.text);
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/MaterialDialog/src/main/java/com/common/design/MaterialDialog.java:
--------------------------------------------------------------------------------
1 | package com.common.design;
2 |
3 | import android.app.Dialog;
4 | import android.content.Context;
5 | import android.content.DialogInterface;
6 | import android.graphics.Color;
7 | import android.graphics.drawable.ColorDrawable;
8 | import android.graphics.drawable.Drawable;
9 | import android.os.Build;
10 | import android.text.TextUtils;
11 | import android.view.LayoutInflater;
12 | import android.view.View;
13 | import android.view.ViewGroup;
14 | import android.view.Window;
15 | import android.view.WindowManager;
16 | import android.widget.AdapterView;
17 | import android.widget.Button;
18 | import android.widget.LinearLayout;
19 | import android.widget.ListAdapter;
20 | import android.widget.ListView;
21 | import android.widget.TextView;
22 |
23 | import com.common.design.entity.OptionWrapper;
24 |
25 | import java.util.Arrays;
26 | import java.util.List;
27 |
28 | /**
29 | * @author liujingxing on 2016/04/20
30 | */
31 | public class MaterialDialog extends Dialog {
32 |
33 | public MaterialDialog(Context context) {
34 | this(context, R.style.MaterialDialogStyle);
35 | }
36 |
37 | public MaterialDialog(Context context, int theme) {
38 | super(context, theme);
39 | }
40 |
41 |
42 | interface BaseListener {
43 | }
44 |
45 | /**
46 | * 可用于ListView点击item的监听,以及mPositiveButton,mNegativeButton,mNeutralButton3个按钮的监听
47 | */
48 | public interface OnClickListener extends BaseListener {
49 | /**
50 | * @param dialog MaterialDialog接口对象
51 | * @param which 作为ListView中item的监听方法时,代表单击item的位置,即position
52 | * 作为mPositiveButton,mNegativeButton,mNeutralButton3个按钮的监听时,代表按钮的类型,即代表哪一个按钮
53 | * @return true 代表拦截后续的操作,即Dialog不会消失;反之,Dialog消失
54 | */
55 | boolean onClick(DialogInterface dialog, int which);
56 | }
57 |
58 | /**
59 | * 单选框最后选择结果监听器
60 | */
61 | public interface OnSCResultListener extends BaseListener {
62 | /**
63 | * 单选框最后选择结果监听方法
64 | *
65 | * @param dialog MaterialDialog接口对象
66 | * @param checkItem 单选框为true的位置,即选中的item的position
67 | * @return true 代表自己拦截后续的操作,即Dialog不会消失,反之,Dialog消失
68 | */
69 | boolean onClick(DialogInterface dialog, int checkItem);
70 | }
71 |
72 | /**
73 | * 复选框最后选择结果监听器
74 | */
75 | public interface OnMCResultListener extends BaseListener {
76 | /**
77 | * 复选框最后选择结果监听方法
78 | *
79 | * @param dialog MaterialDialog接口对象
80 | * @param checkItems 所有为true的复选框的位置的集合
81 | * @return true 代表自己拦截后续的操作,即Dialog不会消失,反之,Dialog消失
82 | */
83 | boolean onClick(DialogInterface dialog, List checkItems);
84 | }
85 |
86 | /**
87 | * 复选框单击item时的监听器
88 | */
89 | public interface OnMultiChoiceClickListener extends BaseListener {
90 | /**
91 | * 复选框单击item时的监听方法
92 | *
93 | * @param dialog MaterialDialog接口对象
94 | * @param position 单击item的位置
95 | * @param isChecked 单击item后复选框的状态
96 | */
97 | void onClick(DialogInterface dialog, int position, boolean isChecked);
98 | }
99 |
100 | public static class Builder {
101 | private MaterialParams P;
102 |
103 | private MaterialDialog mMaterialDialog;
104 |
105 | private View mContentView;
106 |
107 | private LinearLayout mMaterialLayout;
108 | private TextView mTitleView;
109 |
110 | private LinearLayout mBottomLayout;
111 | private Button mPositiveButton;
112 | private Button mNegativeButton;
113 | private Button mNeutralButton;
114 |
115 | private TextView mMessageView;
116 | private LinearLayout mContentLayout;
117 |
118 |
119 | public Builder(Context context) {
120 | P = new MaterialParams(context);
121 |
122 | mContentView = LayoutInflater.from(context).inflate(R.layout.material_dialog_layout, null);
123 |
124 | mMaterialDialog = new MaterialDialog(context);
125 | mMaterialDialog.setContentView(mContentView);
126 |
127 |
128 | mMaterialLayout = (LinearLayout) mContentView.findViewById(R.id.ll_material_layout);
129 | mTitleView = (TextView) mContentView.findViewById(R.id.tv_title);
130 |
131 | mContentLayout = (LinearLayout) mContentView.findViewById(R.id.ll_content_layout);
132 | mMessageView = (TextView) mContentLayout.findViewById(R.id.tv_message);
133 |
134 | mBottomLayout = (LinearLayout) mContentView.findViewById(R.id.ll_bottom_layout);
135 | mPositiveButton = (Button) mBottomLayout.findViewById(R.id.btn_positive);
136 | mNegativeButton = (Button) mBottomLayout.findViewById(R.id.btn_negative);
137 | mNeutralButton = (Button) mBottomLayout.findViewById(R.id.btn_neutral);
138 | }
139 |
140 |
141 | public Builder setTitle(int resId) {
142 | P.setTitle(resId);
143 | return this;
144 | }
145 |
146 | public Builder setTitle(CharSequence title) {
147 | P.setTitle(title);
148 | return this;
149 | }
150 |
151 | public Builder setMessage(int resId) {
152 | P.setMessage(resId);
153 | return this;
154 | }
155 |
156 | public Builder setMessage(CharSequence message) {
157 | P.setMessage(message);
158 | return this;
159 | }
160 |
161 | public Builder setPositiveButton(OnClickListener listener) {
162 | return setPositiveButton(R.string.confirm, listener);
163 | }
164 |
165 | /**
166 | * 如果想知道多选框最后的选择结果,调用本方法传入一个监听器即可,实际上是一个变相的PositiveButton,只是传的监听器不一样
167 | *
168 | * @param listener 多选框最后结果监听器
169 | */
170 | public Builder setMCResultButton(OnMCResultListener listener) {
171 | P.setPositive(R.string.confirm);
172 | P.setPositiveListener(listener);
173 | return this;
174 | }
175 |
176 | /**
177 | * 如果想知道单选框最后的选择结果,调用本方法传入一个监听器即可,实际上是一个变相的PositiveButton,只是传的监听器不一样
178 | *
179 | * @param listener 单选框最后结果监听器
180 | */
181 | public Builder setSCResultButton(OnSCResultListener listener) {
182 | P.setPositive(R.string.confirm);
183 | P.setPositiveListener(listener);
184 | return this;
185 | }
186 |
187 | public Builder setPositiveButton(int resId, OnClickListener listener) {
188 | P.setPositive(resId);
189 | P.setPositiveListener(listener);
190 | return this;
191 | }
192 |
193 | public Builder setPositiveButton(CharSequence text, OnClickListener listener) {
194 | P.setPositive(text);
195 | P.setPositiveListener(listener);
196 | return this;
197 | }
198 |
199 | public Builder setNegativeButton(final OnClickListener listener) {
200 | return setNegativeButton(R.string.cancel, listener);
201 | }
202 |
203 | public Builder setNegativeButton(int resId, final OnClickListener listener) {
204 | P.setNegative(resId);
205 | P.mNegativeListener = listener;
206 | return this;
207 | }
208 |
209 | public Builder setNegativeButton(CharSequence text, final OnClickListener listener) {
210 | P.setNegative(text);
211 | P.mNegativeListener = listener;
212 | return this;
213 | }
214 |
215 | public Builder setNeutralButton(int resId, final OnClickListener listener) {
216 | P.setNeutral(resId);
217 | P.mNeutralListener = listener;
218 | return this;
219 | }
220 |
221 | public Builder setNeutralButton(CharSequence text, final OnClickListener listener) {
222 | P.setNeutral(text);
223 | P.mNeutralListener = listener;
224 | return this;
225 | }
226 |
227 | public Builder setItems(int itemsId, OnClickListener listener) {
228 | return setItems(P.getContext().getResources().getStringArray(itemsId), listener);
229 | }
230 |
231 | public Builder setItems(CharSequence[] items, final OnClickListener listener) {
232 | return setItems(Arrays.asList(items), listener);
233 | }
234 |
235 | public Builder setItems(List extends CharSequence> items, final OnClickListener listener) {
236 | ListItemAdapter adapter = new ListItemAdapter(P.getContext(), items);
237 | return setAdapter(adapter, listener);
238 | }
239 |
240 |
241 | public Builder setSingleChoiceItems(int itemsId, OnClickListener listener) {
242 | return setSingleChoiceItems(itemsId, 0, listener);
243 | }
244 |
245 | public Builder setSingleChoiceItems(int itemsId, int checkItem, OnClickListener listener) {
246 | return setSingleChoiceItems(P.getContext().getResources().getStringArray(itemsId), checkItem, listener);
247 | }
248 |
249 | public Builder setSingleChoiceItems(CharSequence[] items, OnClickListener listener) {
250 | return setSingleChoiceItems(items, 0, listener);
251 | }
252 |
253 | public Builder setSingleChoiceItems(CharSequence[] items, int checkItem, OnClickListener listener) {
254 | return setSingleChoiceItems(Arrays.asList(items), checkItem, listener);
255 | }
256 |
257 | public Builder setSingleChoiceItems(List extends CharSequence> items, OnClickListener listener) {
258 | return setSingleChoiceItems(items, 0, listener);
259 | }
260 |
261 | /**
262 | * 以上重载方法最终都会调用本方法实现单选框
263 | *
264 | * @param items 选项集合
265 | * @param checkItem 默认选中的item的position
266 | * @param listener 监听器
267 | */
268 | public Builder setSingleChoiceItems(List extends CharSequence> items, int checkItem, final OnClickListener listener) {
269 | OptionWrapper optionWrapper = new OptionWrapper(true);
270 | optionWrapper.setOptions(items);
271 | optionWrapper.setChecked(checkItem);
272 | CheckGroup checkGroup = new CheckGroup(P.getContext());
273 | checkGroup.setLeftPadding(P.getContext().getResources().getDimensionPixelOffset(R.dimen.content_title_paddingLeft));
274 | checkGroup.setOptionWrapper(optionWrapper);
275 | checkGroup.setOnChangeListener(new CheckGroup.OnChangeListener() {
276 | @Override
277 | public void onChange(AdapterView> parent, View view, int position) {
278 | if (listener == null) return;
279 | listener.onClick(mMaterialDialog, position);
280 | }
281 | });
282 | setContentView(checkGroup, false);
283 | return this;
284 | }
285 |
286 | public Builder setMultiChoiceItems(int itemsId, OnMultiChoiceClickListener listener) {
287 | return setMultiChoiceItems(itemsId, null, listener);
288 | }
289 |
290 | public Builder setMultiChoiceItems(int itemsId, int[] checkedItems, OnMultiChoiceClickListener listener) {
291 | return setMultiChoiceItems(P.getContext().getResources().getStringArray(itemsId), checkedItems, listener);
292 | }
293 |
294 | public Builder setMultiChoiceItems(CharSequence[] items, OnMultiChoiceClickListener listener) {
295 | return setMultiChoiceItems(items, null, listener);
296 | }
297 |
298 | public Builder setMultiChoiceItems(CharSequence[] items, int[] checkedItems, OnMultiChoiceClickListener listener) {
299 | return setMultiChoiceItems(Arrays.asList(items), checkedItems, listener);
300 | }
301 |
302 | public Builder setMultiChoiceItems(List extends CharSequence> items, OnMultiChoiceClickListener listener) {
303 | return setMultiChoiceItems(items, null, listener);
304 | }
305 |
306 | /**
307 | * 以上重载方法最终都会调用本方法实现多选框功能
308 | *
309 | * @param items 选项集合
310 | * @param checkedItems 默认选中的item的position集合
311 | * @param listener 监听器
312 | */
313 | public Builder setMultiChoiceItems(List extends CharSequence> items, int[] checkedItems, final OnMultiChoiceClickListener listener) {
314 | OptionWrapper optionWrapper = new OptionWrapper();
315 | optionWrapper.setOptions(items);
316 | optionWrapper.setChecked(Utils.getArray(checkedItems));
317 | CheckGroup checkGroup = new CheckGroup(P.getContext());
318 | checkGroup.setLeftPadding(P.getContext().getResources().getDimensionPixelOffset(R.dimen.content_title_paddingLeft));
319 | checkGroup.setOptionWrapper(optionWrapper);
320 | checkGroup.setShape(CheckGroup.SQUARE);
321 | checkGroup.setOnChangeListener(new CheckGroup.OnChangeListener() {
322 | @Override
323 | public void onChange(AdapterView> parent, View view, int position) {
324 | if (listener == null) return;
325 | CheckBox checkBox = (CheckBox) view;
326 | listener.onClick(mMaterialDialog, position, checkBox.isChecked());
327 | }
328 | });
329 | setContentView(checkGroup, false);
330 | return this;
331 | }
332 |
333 | private Builder setAdapter(ListAdapter listAdapter, final OnClickListener listener) {
334 | ListView listView = (ListView) LayoutInflater.from(P.getContext()).inflate(R.layout.material_dialog_listview_layout, null);
335 | listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
336 | @Override
337 | public void onItemClick(AdapterView> parent, View view, int position, long id) {
338 | if (listener == null || !listener.onClick(mMaterialDialog, position)) {
339 | mMaterialDialog.dismiss();
340 | }
341 | }
342 | });
343 | listView.setAdapter(listAdapter);
344 | setContentView(listView, false);
345 | return this;
346 | }
347 |
348 | public Builder setContentView(View contentView, boolean needSpace) {
349 | ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(
350 | ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
351 | contentView.setLayoutParams(layoutParams);
352 | if (!needSpace) {
353 | mContentLayout.setPadding(0, 0, 0, 0);
354 | }
355 | if (mContentLayout != null) {
356 | mContentLayout.removeAllViews();
357 | mContentLayout.addView(contentView);
358 | }
359 | return this;
360 | }
361 |
362 | public Builder setContentView(View contentView) {
363 | return setContentView(contentView, true);
364 | }
365 |
366 | public Builder setContentView(int layoutResId) {
367 | setContentView(LayoutInflater.from(P.getContext()).inflate(layoutResId, null));
368 | return this;
369 | }
370 |
371 | public Builder setBackground(Drawable drawable) {
372 | mMaterialLayout.setBackgroundDrawable(drawable);
373 | return this;
374 | }
375 |
376 | public Builder setBackground(int resId) {
377 | mMaterialLayout.setBackgroundResource(resId);
378 | return this;
379 | }
380 |
381 | public Builder setLayout(int width, int height) {
382 | P.width = width;
383 | P.height = height;
384 | return this;
385 | }
386 |
387 | /**
388 | * 通过比例设置Dialog的宽高
389 | *
390 | * @param widthPercent 0~1之间
391 | * @param heightPercent 0~1之间
392 | */
393 | public Builder setLayout(float widthPercent, float heightPercent) {
394 | P.width = (int) (P.getScreenWidth() * widthPercent);
395 | P.height = (int) (P.getScreenHeight() * heightPercent);
396 | return this;
397 | }
398 |
399 | public Builder setWidth(int width) {
400 | P.width = width;
401 | return this;
402 | }
403 |
404 | /**
405 | * 通过比例设置Dialog的宽度
406 | *
407 | * @param percent 0~1之间
408 | */
409 | public Builder setWidth(float percent) {
410 | P.width = (int) (P.getScreenWidth() * percent);
411 | return this;
412 | }
413 |
414 | public Builder setHeight(int height) {
415 | P.height = height;
416 | return this;
417 | }
418 |
419 | /**
420 | * 通过比例设置Dialog的高度
421 | *
422 | * @param percent 0~1之间
423 | */
424 | public Builder setHeight(float percent) {
425 | P.height = (int) (P.getScreenHeight() * percent);
426 | return this;
427 | }
428 |
429 | public Builder setCanceledOnTouchOutside(boolean canceledOnTouchOutside) {
430 | mMaterialDialog.setCanceledOnTouchOutside(canceledOnTouchOutside);
431 | return this;
432 | }
433 |
434 | public Builder setCancelable(boolean cancelable) {
435 | mMaterialDialog.setCancelable(cancelable);
436 | return this;
437 | }
438 |
439 | public Builder setOnDismissListener(OnDismissListener listener) {
440 | mMaterialDialog.setOnDismissListener(listener);
441 | return this;
442 | }
443 |
444 | public MaterialDialog create() {
445 | setAttributes(mMaterialDialog.getWindow());
446 |
447 | setText(P.getTitle(), mTitleView);
448 | setText(P.getMessage(), mMessageView);
449 | setText(P.getPositiveText(), mPositiveButton, P.getPositiveListener());
450 | setText(P.getNegativeText(), mNegativeButton, P.mNegativeListener);
451 | setText(P.getNeutralText(), mNeutralButton, P.mNeutralListener);
452 |
453 | if (!P.haveButton()) {
454 | mBottomLayout.setVisibility(View.GONE);
455 | }
456 |
457 | return mMaterialDialog;
458 | }
459 |
460 | private void setAttributes(Window window) {
461 | window.clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
462 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
463 | window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_MASK_STATE);
464 | window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
465 | window.setLayout(P.width, P.height);
466 | if (Build.VERSION.SDK_INT >= 14) {
467 | window.setDimAmount(0.6f);
468 | } else {
469 | WindowManager.LayoutParams attributes = window.getAttributes();
470 | attributes.dimAmount = 0.6f;
471 | window.setAttributes(attributes);
472 | }
473 | }
474 |
475 | public void show() {
476 | create().show();
477 | }
478 |
479 | private void setText(CharSequence text, TextView textView) {
480 | setText(text, textView, null);
481 | }
482 |
483 | private void setText(CharSequence text, TextView textView, final BaseListener listener) {
484 | if (TextUtils.isEmpty(text)) {
485 | textView.setVisibility(View.GONE);
486 | return;
487 | }
488 | textView.setText(text);
489 | if (!(textView instanceof Button)) return;
490 | textView.setOnClickListener(new View.OnClickListener() {
491 | @Override
492 | public void onClick(View v) {
493 | int which;
494 | if (v == mPositiveButton) {
495 | which = DialogInterface.BUTTON_POSITIVE;
496 | } else if (v == mNegativeButton) {
497 | which = DialogInterface.BUTTON_NEGATIVE;
498 | } else {
499 | which = DialogInterface.BUTTON_NEUTRAL;
500 | }
501 | if (listener == null) {
502 | mMaterialDialog.dismiss();
503 | return;
504 | }
505 | boolean isIntercept = false;
506 | if (listener instanceof OnClickListener) {
507 | isIntercept = ((OnClickListener) listener).onClick(mMaterialDialog, which);
508 | } else {
509 | View childAt = mContentLayout.getChildAt(0);
510 | if (childAt instanceof CheckGroup) {
511 | CheckGroup checkGroup = (CheckGroup) childAt;
512 | if (listener instanceof OnSCResultListener) {
513 | isIntercept = ((OnSCResultListener) listener).onClick(mMaterialDialog, checkGroup.getCheckedIndex().get(0));
514 | } else if (listener instanceof OnMCResultListener) {
515 | isIntercept = ((OnMCResultListener) listener).onClick(mMaterialDialog, checkGroup.getCheckedIndex());
516 | }
517 | }
518 | }
519 | if (!isIntercept) {
520 | mMaterialDialog.dismiss();
521 | }
522 | }
523 | });
524 | }
525 | }
526 | }
527 |
528 |
--------------------------------------------------------------------------------
/MaterialDialog/src/main/java/com/common/design/MaterialParams.java:
--------------------------------------------------------------------------------
1 | package com.common.design;
2 |
3 | import android.content.Context;
4 | import android.view.WindowManager;
5 |
6 | /**
7 | * 设置对话框的一些参数
8 | *
9 | * @author liujingxing on 16/4/20.
10 | */
11 | class MaterialParams {
12 |
13 | Context mContext;
14 | int mTitleResId = -1;//标题资源id
15 | CharSequence mTitle;//标题
16 | int mMessageResId = -1;//内容资源id
17 | CharSequence mMessage;//内容
18 |
19 | int mPositiveResId = -1;//确定按钮文本资源id
20 | CharSequence mPositiveText;//确定按钮文本
21 | int mNegativeResId = -1;//取消按钮文本资源id
22 | CharSequence mNegativeText;//取消按钮文本
23 | int mNeutralResId = -1;//中间按钮文本资源id
24 | CharSequence mNeutralText;//中间按钮文本
25 |
26 | int width;//对话框宽度
27 | int height;//对话框高度
28 |
29 | //确定、取消、中间按钮单击监听器
30 | MaterialDialog.OnClickListener mPositiveListener, mNegativeListener, mNeutralListener;
31 | MaterialDialog.OnSCResultListener mOnSCResultListener;//单选对话框确定按钮监听器,会返回最终的选择结果
32 | MaterialDialog.OnMCResultListener mOnMCResultListener;//多选对话框确定按钮监听器,会返回最终的选择结果
33 |
34 | MaterialParams(Context context) {
35 | mContext = context;
36 | width = (int) (getScreenWidth() * 0.85f);
37 | height = WindowManager.LayoutParams.WRAP_CONTENT;
38 | }
39 |
40 | CharSequence getTitle() {
41 | return mTitleResId != -1 ? getString(mTitleResId) : mTitle;
42 | }
43 |
44 | void setTitle(int titleResId) {
45 | mTitleResId = titleResId;
46 | mTitle = null;
47 | }
48 |
49 | void setTitle(CharSequence title) {
50 | mTitle = title;
51 | mTitleResId = -1;
52 | }
53 |
54 | CharSequence getMessage() {
55 | return mMessageResId != -1 ? getString(mMessageResId) : mMessage;
56 | }
57 |
58 | void setMessage(int messageResId) {
59 | mMessageResId = messageResId;
60 | mMessage = null;
61 | }
62 |
63 | void setMessage(CharSequence message) {
64 | mMessage = message;
65 | mMessageResId = -1;
66 | }
67 |
68 | CharSequence getNegativeText() {
69 | return mNegativeResId != -1 ? getString(mNegativeResId) : mNegativeText;
70 | }
71 |
72 | boolean haveButton() {
73 | return getPositiveText() != null || getNegativeText() != null || getNeutralText() != null;
74 | }
75 |
76 | void setNegative(int negativeResId) {
77 | mNegativeResId = negativeResId;
78 | mNegativeText = null;
79 | }
80 |
81 |
82 | void setNegative(CharSequence negativeText) {
83 | mNegativeText = negativeText;
84 | mNegativeResId = -1;
85 | }
86 |
87 | CharSequence getPositiveText() {
88 | return mPositiveResId != -1 ? getString(mPositiveResId) : mPositiveText;
89 | }
90 |
91 |
92 | void setPositive(int positiveResId) {
93 | mPositiveResId = positiveResId;
94 | mPositiveText = null;
95 | }
96 |
97 |
98 | void setPositive(CharSequence positiveText) {
99 | mPositiveText = positiveText;
100 | mPositiveResId = -1;
101 | }
102 |
103 | MaterialDialog.BaseListener getPositiveListener() {
104 | if (mOnSCResultListener != null) return mOnSCResultListener;
105 | if (mOnMCResultListener != null) return mOnMCResultListener;
106 | return mPositiveListener;
107 | }
108 |
109 | void setPositiveListener(MaterialDialog.BaseListener listener) {
110 | if (listener instanceof MaterialDialog.OnSCResultListener) {
111 | mOnSCResultListener = (MaterialDialog.OnSCResultListener) listener;
112 | } else if (listener instanceof MaterialDialog.OnMCResultListener) {
113 | mOnMCResultListener = (MaterialDialog.OnMCResultListener) listener;
114 | } else {
115 | mPositiveListener = (MaterialDialog.OnClickListener) listener;
116 | }
117 | }
118 |
119 | CharSequence getNeutralText() {
120 | return mNeutralResId != -1 ? getString(mNeutralResId) : mNeutralText;
121 | }
122 |
123 |
124 | void setNeutral(int neutralResId) {
125 | mNeutralResId = neutralResId;
126 | }
127 |
128 |
129 | void setNeutral(CharSequence neutralText) {
130 | mNeutralText = neutralText;
131 | }
132 |
133 | Context getContext() {
134 | return mContext;
135 | }
136 |
137 | String getString(int resId) {
138 | return mContext.getString(resId);
139 | }
140 |
141 | public int getScreenWidth() {
142 | return mContext.getResources().getDisplayMetrics().widthPixels;
143 | }
144 |
145 | public int getScreenHeight() {
146 | return mContext.getResources().getDisplayMetrics().heightPixels;
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/MaterialDialog/src/main/java/com/common/design/Utils.java:
--------------------------------------------------------------------------------
1 | package com.common.design;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | /**
7 | * @author liujingxing on 16/8/9.
8 | */
9 | class Utils {
10 | static List getArray(int[] array) {
11 | if (array == null || array.length == 0) return null;
12 | List list = new ArrayList<>();
13 | for (int i : array) {
14 | list.add(i);
15 | }
16 | return list;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/MaterialDialog/src/main/java/com/common/design/entity/Option.java:
--------------------------------------------------------------------------------
1 | package com.common.design.entity;
2 |
3 | /**
4 | * 选项实体类
5 | *
6 | * @author liujingxing on 16/7/24.
7 | */
8 | public class Option {
9 | private CharSequence title;
10 | private boolean isCheck;
11 |
12 | private boolean enabled = true;
13 |
14 | public Option() {
15 | }
16 |
17 | public Option(CharSequence title) {
18 | this.title = title;
19 | }
20 |
21 | public Option(CharSequence title, boolean isCheck) {
22 | this.title = title;
23 | this.isCheck = isCheck;
24 | }
25 |
26 | public Option(boolean enabled, boolean isCheck, CharSequence title) {
27 | this.enabled = enabled;
28 | this.isCheck = isCheck;
29 | this.title = title;
30 | }
31 |
32 | public boolean isCheck() {
33 | return isCheck;
34 | }
35 |
36 | public void setCheck(boolean check) {
37 | isCheck = check;
38 | }
39 |
40 | public void toggle() {
41 | isCheck = !isCheck;
42 | }
43 |
44 | public boolean isEnabled() {
45 | return enabled;
46 | }
47 |
48 | public void setEnabled(boolean enabled) {
49 | this.enabled = enabled;
50 | }
51 |
52 | public CharSequence getTitle() {
53 | return title;
54 | }
55 |
56 | public void setTitle(CharSequence title) {
57 | this.title = title;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/MaterialDialog/src/main/java/com/common/design/entity/OptionWrapper.java:
--------------------------------------------------------------------------------
1 | package com.common.design.entity;
2 |
3 | import android.text.TextUtils;
4 |
5 | import java.util.ArrayList;
6 | import java.util.Arrays;
7 | import java.util.List;
8 |
9 | /**
10 | * 选项集合的封装类,默认多选
11 | *
12 | * @author liujingxing on 16/7/24.
13 | */
14 | public class OptionWrapper {
15 | /**
16 | * 选项集合
17 | */
18 | private List mOptions = new ArrayList<>();
19 |
20 | private boolean enabled = true;
21 |
22 | /**
23 | * 是否为单选
24 | */
25 | private boolean isSingleChoice;
26 |
27 |
28 | public OptionWrapper() {
29 | }
30 |
31 | public OptionWrapper(boolean isSingleChoice) {
32 | this.isSingleChoice = isSingleChoice;
33 | }
34 |
35 | public void set(OptionWrapper wrapper) {
36 | mOptions.clear();
37 | mOptions.addAll(wrapper.getOptions());
38 | enabled = wrapper.isEnabled();
39 | isSingleChoice = wrapper.isSingleChoice;
40 | }
41 |
42 | /**
43 | * 设置选项和默认选中
44 | *
45 | * @param options 选项集合
46 | * @param positions 选中item的position集合
47 | */
48 | public void setOptionsAndChecked(List extends CharSequence> options, Integer... positions) {
49 | setOptions(options);
50 | setChecked(positions);
51 | }
52 |
53 | /**
54 | * 设置选项
55 | *
56 | * @param options 选项集合
57 | */
58 | public void setOptions(CharSequence... options) {
59 | if (options == null || options.length == 0) return;
60 | setOptions(Arrays.asList(options));
61 | }
62 |
63 | /**
64 | * 设置选项
65 | *
66 | * @param options 选项集合
67 | */
68 | public void setOptions(List extends CharSequence> options) {
69 | if (options == null || options.size() == 0) return;
70 | Option option;
71 | for (CharSequence title : options) {
72 | if (TextUtils.isEmpty(title)) continue;
73 | option = new Option(title);
74 | mOptions.add(option);
75 | }
76 | }
77 |
78 | /**
79 | * 设置默认选中的item
80 | * 注:此方法一定要在setOptions之后调用才会有效
81 | * 单选时,默认取第一个有效值做为默认的选中
82 | *
83 | * @param positions 选中item的position集合
84 | */
85 | public void setChecked(Integer... positions) {
86 | if (positions == null || positions.length == 0) return;
87 | setChecked(Arrays.asList(positions));
88 | }
89 |
90 | /**
91 | * 设置默认选中的item
92 | * 注:此方法一定要在setOptions之后调用才会有效
93 | * 单选时,默认取第一个有效值做为默认的选中
94 | *
95 | * @param positions 选中item的position集合
96 | */
97 | public void setChecked(List positions) {
98 | if (positions == null || positions.size() == 0) return;
99 | for (int position : positions) {
100 | //当用户传过来的position大于等于集合的长度时,认为是无效值
101 | if (position >= mOptions.size()) continue;
102 | mOptions.get(position).setCheck(true);
103 | if (isSingleChoice) break;
104 | }
105 | }
106 |
107 | /**
108 | * @return 所有选项
109 | */
110 | public List getOptions() {
111 | return mOptions;
112 | }
113 |
114 | /**
115 | * 获取指定position的选项
116 | *
117 | * @param position 位置
118 | * @return position对应的选项
119 | */
120 | public Option getOptionAt(int position) {
121 | return mOptions.get(position);
122 | }
123 |
124 | /**
125 | * @return 选中item的集合
126 | */
127 | public List getChecked() {
128 | List options = new ArrayList<>();
129 | for (Option option : mOptions) {
130 | if (option == null || !option.isCheck()) continue;
131 | options.add(option);
132 | }
133 | return options;
134 | }
135 |
136 | /**
137 | * @return 选中item的文本集合
138 | */
139 | public List getCheckedText() {
140 | List titles = new ArrayList<>();
141 | for (Option option : mOptions) {
142 | if (option == null || !option.isCheck()) continue;
143 | titles.add(option.getTitle());
144 | }
145 | return titles;
146 | }
147 |
148 | /**
149 | * @return 选中item的position集合
150 | */
151 | public List getCheckedIndex() {
152 | List positions = new ArrayList<>();
153 | for (int i = 0; i < mOptions.size(); i++) {
154 | Option option = mOptions.get(i);
155 | if (option == null || !option.isCheck()) continue;
156 | positions.add(i);
157 | }
158 | return positions;
159 | }
160 |
161 |
162 | public void setEnabled(boolean enabled, int index) {
163 | mOptions.get(index).setEnabled(enabled);
164 | }
165 |
166 | public void setEnabled(boolean enabled) {
167 | this.enabled = enabled;
168 | }
169 |
170 | public boolean isEnabled() {
171 | return enabled;
172 | }
173 |
174 | public boolean isSingleChoice() {
175 | return isSingleChoice;
176 | }
177 | }
178 |
--------------------------------------------------------------------------------
/MaterialDialog/src/main/res/anim/material_dialog_in_anim.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/MaterialDialog/src/main/res/anim/material_dialog_out_anim.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
13 |
14 |
18 |
19 |
--------------------------------------------------------------------------------
/MaterialDialog/src/main/res/drawable-v21/button.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/MaterialDialog/src/main/res/drawable/bg_button_normal.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/MaterialDialog/src/main/res/drawable/bg_button_pressed.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/MaterialDialog/src/main/res/drawable/button.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
7 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/MaterialDialog/src/main/res/drawable/material_card.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | -
6 |
7 |
8 |
9 |
10 |
11 |
12 | -
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/MaterialDialog/src/main/res/layout/checkbox.xml:
--------------------------------------------------------------------------------
1 |
2 |
14 |
15 |
--------------------------------------------------------------------------------
/MaterialDialog/src/main/res/layout/material_dialog_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
38 |
39 |
47 |
48 |
49 |
50 |
51 |
52 |
60 |
61 |
67 |
68 |
75 |
76 |
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/MaterialDialog/src/main/res/layout/material_dialog_list_item_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
--------------------------------------------------------------------------------
/MaterialDialog/src/main/res/layout/material_dialog_listview_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
--------------------------------------------------------------------------------
/MaterialDialog/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 |
--------------------------------------------------------------------------------
/MaterialDialog/src/main/res/values/color.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #49BA52
4 |
5 | #10000000
6 | #DE000000
7 |
--------------------------------------------------------------------------------
/MaterialDialog/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 32dp
4 | 14sp
5 | 56dp
6 | 4dp
7 |
8 | 17dp
9 |
10 |
--------------------------------------------------------------------------------
/MaterialDialog/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | MaterialDialog-master
3 | 确定 >
4 | 取消 >
5 |
6 |
--------------------------------------------------------------------------------
/MaterialDialog/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
15 |
16 |
20 |
21 |
30 |
31 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MaterialDialog
2 | 仿Android原生的AlertDialog样式的对话框,目的在于解决原生的在Android 5.0以下手机样式丑陋问题。
3 | 初次开源项目,如有不足之处,请各位大神多多海涵,多多指导指导
4 |
5 | 效果图
6 |
7 | 
8 |
9 | Gradle引用方法
10 |
11 | dependencies {
12 | compile 'com.android.design:MaterialDialog:1.1.5'
13 | }
14 |
15 |
16 |
17 |
18 | 1.显示一个确认对话框
19 |
20 | new MaterialDialog.Builder(this)
21 | .setTitle("提示")
22 | .setMessage("仿原生AlertDialog样式的对话框,目的在于解决原生的在Android 5.0下样式丑陋问题")
23 | .setPositiveButton(null)
24 | .setNeutralButton("不再提示", null)
25 | .setNegativeButton(new MaterialDialog.OnClickListener() {
26 | @Override
27 | public boolean onClick(DialogInterface dialog, int which) {
28 | Toast.makeText(MainActivity.this, items[which], Toast.LENGTH_SHORT).show();
29 | return false;//默认返回false,返回true Dialog不消失,返回false Dialog消失
30 | }
31 | }).show();
32 |
33 | 2.显示一个列表对话框
34 |
35 | final String[] items = {"2016/01", "2016/02", "2016/03", "2016/04", "2016/05", "2016/06", "2016/07"};
36 | new MaterialDialog.Builder(this)
37 | .setItems(items, new MaterialDialog.OnClickListener() {
38 | @Override
39 | public boolean onClick(DialogInterface dialog, int which) {
40 | Toast.makeText(MainActivity.this, items[which], Toast.LENGTH_SHORT).show();
41 | return false;//默认返回false,返回true Dialog不消失,返回false Dialog消失
42 | }
43 | }).create().show();
44 |
45 | 3.显示一个单选对话框
46 |
47 | final String[] item2 = {"2016/01", "2016/02", "2016/03", "2016/04", "2016/05", "2016/06", "2016/07"};
48 | new MaterialDialog.Builder(this)
49 | .setTitle("单选框")
50 | .setSingleChoiceItems(item2, 2, new MaterialDialog.OnClickListener() {
51 | @Override
52 | public boolean onClick(DialogInterface dialog, int which) {
53 | Toast.makeText(MainActivity.this, item2[which], Toast.LENGTH_SHORT).show();
54 | return true;//默认返回false,返回true Dialog不消失,返回false Dialog消失
55 | }
56 | }).setPositiveButton("确定", null)
57 | .setNegativeButton("取消", null)
58 | .setNeutralButton("不在提示", null).show();
59 |
60 | 4.显示一个多选对话框
61 |
62 | new MaterialDialog.Builder(this)
63 | .setTitle("多选框")
64 | .setMultiChoiceItems(item1, new int[]{1, 2, 3}, new MaterialDialog.OnMultiChoiceClickListener() {
65 | @Override
66 | public void onClick(DialogInterface dialog, int which, boolean isChecked) {
67 | Toast.makeText(MainActivity.this, which + "--" + isChecked, Toast.LENGTH_SHORT).show();
68 | }
69 | }).setPositiveButton("确定", null)
70 | .setNegativeButton("取消", null)
71 | .setNeutralButton("不在提示", null).show();
72 |
73 | 5.自定义对话框显示的view
74 |
75 | new MaterialDialog.Builder(this).setTitle("自定义View")
76 | .setContentView(view)
77 | .setLayout(0.8f,0.8f)
78 | .show();
79 |
80 | 6.特殊方法介绍
81 |
82 | setLayout(float widthPercent, float heightPercent)
83 | 通过百分比传一个0~1之间的浮点数设置Dialog的宽高,例如:setLayout(0.8f,0.9f)表示宽为屏幕宽的80%,高为屏幕高90%
84 |
85 | setLayout(int width, int height)
86 | 同样设置Dialog的宽高,却别是传入准确的像素值,单位:px 例如setLayout(500,600)表示宽500个像素,高600个像素
87 | 同样可以调用setWidth和setHeight单独设置宽高,同样支持百分比和像素值
88 |
89 | setAdapter(ListAdapter adapter, OnClickListener listener)
90 | 当需要自定义ListView的item时,调用此方法传了一个自己实现的Adapter即可,如还需要监听item的单击事件,传一个OnClickListener即可。
91 |
92 | setSingleChoiceItems(List extends CharSequence> items, int checkItem, OnClickListener listener)
93 | 设置单选框列表时,有一系列重载方法,最终都是调用此方法
94 | items:表示单选列表的集合
95 | checkItem:表示默认选中item的位置
96 | listener:单机item时的监听器
97 |
98 | setSCResultButton(OnSCResultListener listener)
99 | 如果不想监听单选对话框单击item的动作,只想获取单选框最后的选择结果,调用此方法传入一个最后结果的监听器,监听方法中会有最终的选择结果
100 |
101 | setMultiChoiceItems(List extends CharSequence> items, int[] checkedItems, OnMultiChoiceClickListener listener)
102 | 设置复选框列表时,也有一系列重载方法,最终都是调用此方法
103 | items:表示复选列表的集合
104 | checkedItems:默认选择item的位置的集合
105 | listener:单机item时的监听器
106 |
107 | setMCResultButton(OnMCResultListener listener)
108 | 如果不想监听复选对话框单击item的动作,只想获取复选框最后的选择结果,调用此方法传入一个最后结果的监听器,监听方法中会返回选择的列表集合
109 |
110 |
111 |
112 | 部分灵感来源:https://github.com/drakeet/MaterialDialog
113 |
114 | 单选/复选框引用:https://github.com/andyxialm/SmoothCheckBox 并加入了自己的修改
115 |
116 |
117 | # Licenses
118 | ```
119 | Copyright 2016 liujingxing
120 |
121 | Licensed under the Apache License, Version 2.0 (the "License");
122 | you may not use this file except in compliance with the License.
123 | You may obtain a copy of the License at
124 |
125 | http://www.apache.org/licenses/LICENSE-2.0
126 |
127 | Unless required by applicable law or agreed to in writing, software
128 | distributed under the License is distributed on an "AS IS" BASIS,
129 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130 | See the License for the specific language governing permissions and
131 | limitations under the License.
132 | ```
133 |
134 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 28
5 |
6 | defaultConfig {
7 | applicationId "com.example.app"
8 | minSdkVersion 14
9 | targetSdkVersion 28
10 | versionCode 1
11 | versionName "1.0"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 |
20 | repositories {
21 | flatDir {
22 | dirs 'libs' //this way we can find the .aar file in libs folder
23 | }
24 | }
25 | }
26 |
27 | dependencies {
28 | implementation fileTree(dir: 'libs', include: ['*.jar'])
29 | testImplementation 'junit:junit:4.12'
30 | implementation 'com.android.support:appcompat-v7:28.0.0'
31 | // implementation 'com.android.design:MaterialDialog:1.1.5'
32 | implementation project(':MaterialDialog')
33 | // implementation (name:'MaterialDialog-release', ext:'aar')
34 | }
35 |
--------------------------------------------------------------------------------
/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 /Users/liujingxing/Documents/software/android-sdk_r24.0.2/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/example/app/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.example.app;
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/example/app/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.app;
2 |
3 | import android.content.DialogInterface;
4 | import android.os.Bundle;
5 | import android.support.v7.app.AppCompatActivity;
6 | import android.view.View;
7 | import android.widget.TextView;
8 | import android.widget.Toast;
9 |
10 | import com.common.design.CheckGroup;
11 | import com.common.design.MaterialDialog;
12 | import com.common.design.entity.Option;
13 | import com.common.design.entity.OptionWrapper;
14 |
15 | import java.util.List;
16 |
17 | public class MainActivity extends AppCompatActivity {
18 | CheckGroup mCheckGroup;
19 |
20 | @Override
21 | protected void onCreate(Bundle savedInstanceState) {
22 | super.onCreate(savedInstanceState);
23 | setContentView(R.layout.activity_main);
24 |
25 | mCheckGroup = (CheckGroup) findViewById(R.id.checkGroup);
26 | OptionWrapper optionWrapper = new OptionWrapper(true);//Option的封装类
27 | optionWrapper.setOptions("数学", "语文", "英语", "物理", "化学");
28 | optionWrapper.setChecked(1, 2, 4);//默认选中position为1 2 4的选项
29 | mCheckGroup.setShape(CheckGroup.SQUARE);//画方形,圆形传:CheckGroup.CIRCLE
30 | mCheckGroup.setOptionWrapper(optionWrapper);
31 | }
32 |
33 | public void onClick(View v) {
34 | switch (v.getId()) {
35 | case R.id.look:
36 | List checked = mCheckGroup.getChecked();
37 | List checkedText = mCheckGroup.getCheckedText();
38 | StringBuilder builder = new StringBuilder();
39 | for (CharSequence charSequence : checkedText) {
40 | builder.append(charSequence).append("、");
41 | }
42 | if (builder.length() > 0)
43 | builder.deleteCharAt(builder.length() - 1);
44 | ((TextView) findViewById(R.id.result)).setText(builder);
45 | break;
46 |
47 | case R.id.hit:
48 | new MaterialDialog.Builder(this)
49 | .setTitle("提示")
50 | .setMessage("仿原生AlertDialog样式的对话框,目的在于解决原生的在Android 5.0下样式丑陋问题")
51 | .setPositiveButton(new MaterialDialog.OnClickListener() {
52 | @Override
53 | public boolean onClick(DialogInterface dialog, int which) {
54 | return false;
55 | }
56 | })
57 | .setNeutralButton("不再提示", null)
58 | .setNegativeButton(null).show();
59 | break;
60 | case R.id.list:
61 | final String[] items = {"2016/01", "2016/02", "2016/03", "2016/04", "2016/05", "2016/06", "2016/07"};
62 | new MaterialDialog.Builder(this)
63 | .setItems(items, new MaterialDialog.OnClickListener() {
64 | @Override
65 | public boolean onClick(DialogInterface dialog, int which) {
66 | Toast.makeText(MainActivity.this, items[which], Toast.LENGTH_SHORT).show();
67 | return false;
68 | }
69 | }).create().show();
70 | break;
71 | case R.id.radio:
72 | final String[] item2 = {"2016/01", "2016/02", "2016/03", "2016/04", "2016/05", "2016/06", "2016/07"};
73 | new MaterialDialog.Builder(this)
74 | .setTitle("单选框")
75 | .setSingleChoiceItems(item2, 2, new MaterialDialog.OnClickListener() {
76 | @Override
77 | public boolean onClick(DialogInterface dialog, int which) {
78 | Toast.makeText(MainActivity.this, item2[which], Toast.LENGTH_SHORT).show();
79 | return true;
80 | }
81 | }).setPositiveButton("确定", null)
82 | .setNegativeButton("取消", null)
83 | .setNeutralButton("不在提示", null).show();
84 | break;
85 | case R.id.check:
86 | final String[] item1 = {"2016/01", "2016/02", "2016/03", "2016/04", "2016/05", "2016/06", "2016/07"};
87 | new MaterialDialog.Builder(this)
88 | .setTitle("多选框")
89 | .setMultiChoiceItems(item1, new int[]{1, 2, 3}, new MaterialDialog.OnMultiChoiceClickListener() {
90 | @Override
91 | public void onClick(DialogInterface dialog, int which, boolean isChecked) {
92 | Toast.makeText(MainActivity.this, which + "--" + isChecked, Toast.LENGTH_SHORT).show();
93 | }
94 | })
95 | .setMCResultButton(new MaterialDialog.OnMCResultListener() {
96 | @Override
97 | public boolean onClick(DialogInterface dialog, List checkItems) {
98 | return false;
99 | }
100 | })
101 | .setNegativeButton("取消", null)
102 | .setNeutralButton("不在提示", null).show();
103 | break;
104 |
105 | }
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
15 |
16 |
22 |
23 |
29 |
30 |
36 |
37 |
38 |
43 |
44 |
48 |
49 |
55 |
56 |
61 |
62 |
63 |
64 |
65 |
70 |
71 |
76 |
77 |
88 |
89 |
90 |
91 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liujingxing/MaterialDialogApplication/7eda1cf3b6fb0b37e50eee41e8df2e6e50a31db8/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liujingxing/MaterialDialogApplication/7eda1cf3b6fb0b37e50eee41e8df2e6e50a31db8/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liujingxing/MaterialDialogApplication/7eda1cf3b6fb0b37e50eee41e8df2e6e50a31db8/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liujingxing/MaterialDialogApplication/7eda1cf3b6fb0b37e50eee41e8df2e6e50a31db8/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liujingxing/MaterialDialogApplication/7eda1cf3b6fb0b37e50eee41e8df2e6e50a31db8/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/example/app/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.example.app;
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 | google()
7 | }
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:3.3.0'
10 | //自动化maven打包插件
11 | classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5'
12 | //自动上传至Bintray平台插件
13 | classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7"
14 | }
15 |
16 | }
17 |
18 | allprojects {
19 | repositories {
20 | jcenter()
21 | google()
22 | }
23 | }
24 |
25 | task clean(type: Delete) {
26 | delete rootProject.buildDir
27 | }
28 |
--------------------------------------------------------------------------------
/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/liujingxing/MaterialDialogApplication/7eda1cf3b6fb0b37e50eee41e8df2e6e50a31db8/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sun Feb 26 20:47:05 CST 2017
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-4.10.1-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 |
--------------------------------------------------------------------------------
/screenRecord/screen.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liujingxing/MaterialDialogApplication/7eda1cf3b6fb0b37e50eee41e8df2e6e50a31db8/screenRecord/screen.gif
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app',
2 | ':MaterialDialog'
3 |
--------------------------------------------------------------------------------