├── .gitignore
├── .idea
├── .name
├── compiler.xml
├── copyright
│ └── profiles_settings.xml
├── encodings.xml
├── gradle.xml
├── misc.xml
├── modules.xml
├── scopes
│ └── scope_settings.xml
└── vcs.xml
├── MaterialLibrary.iml
├── Readme.md
├── app
├── .gitignore
├── app.iml
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── micnubinub
│ │ └── materiallibrary
│ │ └── ApplicationTest.java
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── micnubinub
│ │ └── materiallibrary
│ │ ├── MainActivity.java
│ │ ├── MaterialButton.java
│ │ ├── MaterialCheckBox.java
│ │ ├── MaterialRadioButton.java
│ │ ├── MaterialRadioGroup.java
│ │ ├── MaterialSeekBar.java
│ │ ├── MaterialSingleLineTextAvatar.java
│ │ ├── MaterialSingleLineTextAvatarWithIcon.java
│ │ ├── MaterialSingleLineTextIcon.java
│ │ ├── MaterialSwitch.java
│ │ ├── MaterialThreeLineText.java
│ │ ├── MaterialThreeLineTextAvatar.java
│ │ ├── MaterialThreeLineTextAvatarWithIcon.java
│ │ ├── MaterialThreeLineTextIcon.java
│ │ ├── MaterialTwoLineText.java
│ │ ├── MaterialTwoLineTextAvatar.java
│ │ ├── MaterialTwoLineTextAvatarWithIcon.java
│ │ └── MaterialTwoLineTextIcon.java
│ └── res
│ ├── anim
│ └── zoom.xml
│ ├── drawable-hdpi
│ ├── block.png
│ ├── ic_launcher.png
│ ├── search.png
│ ├── test.jpg
│ └── white_background.xml
│ ├── drawable-mdpi
│ └── ic_launcher.png
│ ├── drawable-xhdpi
│ └── ic_launcher.png
│ ├── drawable-xxhdpi
│ └── ic_launcher.png
│ ├── layout
│ └── activity_main.xml
│ ├── menu
│ └── main.xml
│ ├── values-w820dp
│ └── dimens.xml
│ └── values
│ ├── attrs.xml
│ ├── colors.xml
│ ├── dimens.xml
│ ├── strings.xml
│ └── styles.xml
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── pic1.png
├── pic2.png
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 | /local.properties
3 | /.idea/workspace.xml
4 | /.idea/libraries
5 | .DS_Store
6 | /build
7 |
--------------------------------------------------------------------------------
/.idea/.name:
--------------------------------------------------------------------------------
1 | Material Library
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | Android
15 |
16 |
17 | Android Lint
18 |
19 |
20 | Java language level migration aids
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | Android API 19 Platform
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.idea/scopes/scope_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/MaterialLibrary.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/Readme.md:
--------------------------------------------------------------------------------
1 | *Old library, please use the official material library from google now
2 |
3 | **Credit : Lindelwe Michael Ncube (micnubinub : https://github.com/Micnubinub/)**
4 |
5 | **Credit : Robin Chutaux (traex : https://github.com/traex) > ripple effect library**
6 |
7 | **This library is made with most of the design guidelines by google in mind : http://www.google.com/design/spec/components/lists.html#lists-behavior**
8 |
9 | *Sample app link : https://play.google.com/store/apps/details?id=com.micnubinub.materiallibrary*
10 | 
11 |
12 | 
13 |
14 | **How to use:**
15 |
16 | **Note that the recommended layout params are in the main activity**
17 |
18 | **Material Switch:**
19 |
20 | **In XML:**
21 | ```xml
22 |
27 | ```
28 | **in Java:**
29 | ```java
30 | MaterialSwitch materialSwitch = (MaterialSwitch) findViewById(R.id.material_switch);
31 | materialSwitch.setOnCheckedChangeListener(new MaterialSwitch.OnCheckedChangedListener() {
32 | @Override
33 | public void onCheckedChange(MaterialSwitch materialSwitch, boolean isChecked) {
34 | //Do your stuff here
35 | }
36 | });
37 | ```
38 |
39 | **Material RadioGroup:**
40 |
41 | **in XML:**
42 | ```xml
43 |
47 |
48 |
52 |
53 |
57 |
58 |
62 |
63 | ```
64 |
65 | **in Java:**
66 | ```java
67 | MaterialRadioGroup materialRadioGroup = (MaterialRadioGroup) findViewById(R.id.material_radio_group);
68 | materialRadioGroup.setOnSelectionChanged(new MaterialRadioGroup.OnSelectionChangedListener() {
69 | @Override
70 | public void onSelectionChanged(MaterialRadioButton radioButton, int selectedChild) {
71 | //Do your stuff here
72 | }
73 | });
74 | ```
75 |
76 | **Material Single Line Text View with Icon/Avatar:**
77 |
78 | **In XML:**
79 | ```xml
80 |
84 | ```
85 | **in Java:**
86 | ```java
87 | MaterialSingleLineTextAvatar materialSingleLineTextAvatar = (MaterialSingleLineTextAvatar) findViewById(R.id.material_single_line_avatar);
88 | materialSingleLineTextAvatar.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dpToPixels(56)));
89 | materialSingleLineTextAvatar.setText("Material Single line text with avatar");
90 | materialSingleLineTextAvatar.setIcon(getResources().getDrawable(R.drawable.icon));
91 | ```
92 |
93 | **Material Two/Three Line Text View with Icon/Avatar/AvatarWithIcon:**
94 |
95 | **In XML:**
96 | ```xml
97 |
101 | ```
102 | **in Java:**
103 | ```java
104 | MaterialThreeLineTextAvatarWithIcon materialThreeLineTextAvatarWithIcon = (MaterialThreeLineTextAvatarWithIcon) findViewById(R.id.material_avatar_icon);
105 | materialThreeLineTextAvatarWithIcon.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dpToPixels(88)));
106 | materialThreeLineTextAvatarWithIcon.setPrimaryText("Primary text");
107 | materialThreeLineTextAvatarWithIcon.setSecondaryText("Material Three line text with Avatar and Icon test, making sure it spans over two lines so i can show case the 3 lines in the three line text");
108 | materialThreeLineTextAvatarWithIcon.setLeftIcon(getResources().getDrawable(R.drawable.avatar));
109 | materialThreeLineTextAvatarWithIcon.setRightIcon(getResources().getDrawable(R.drawable.icon));
110 | ```
111 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/app.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 20
5 | buildToolsVersion "20.0.0"
6 |
7 | defaultConfig {
8 | applicationId "com.micnubinub.materiallibrary"
9 | minSdkVersion 15
10 | targetSdkVersion 21
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | runProguard false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(dir: 'libs', include: ['*.jar'])
24 | }
25 |
--------------------------------------------------------------------------------
/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 /media/mike/Dev/android-sdk-linux/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/micnubinub/materiallibrary/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.micnubinub.materiallibrary;
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 |
6 |
11 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/java/com/micnubinub/materiallibrary/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.micnubinub.materiallibrary;
2 |
3 | import android.app.Activity;
4 | import android.os.Bundle;
5 | import android.util.TypedValue;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 | import android.widget.LinearLayout;
9 | import android.widget.Toast;
10 |
11 |
12 | public class MainActivity extends Activity {
13 |
14 | @Override
15 | protected void onCreate(Bundle savedInstanceState) {
16 | super.onCreate(savedInstanceState);
17 | setContentView(R.layout.activity_main);
18 | final LinearLayout ll = (LinearLayout) findViewById(R.id.ll);
19 | ll.addView(materialButton());
20 | ll.addView(materialCheckBox());
21 | ll.addView(materialSwitch());
22 | ll.addView(materialSeekBar());
23 | ll.addView(materialRadioGroup());
24 | ll.addView(materialSingleLineTextIcon());
25 | ll.addView(materialSingleLineTextAvatar());
26 | ll.addView(materialSingleLineTextAvatarWithIcon());
27 | ll.addView(materialTwoLineText());
28 | ll.addView(materialTwoLineTextIcon());
29 | ll.addView(materialTwoLineTextAvatar());
30 | ll.addView(materialTwoLineTextAvatarWithIcon());
31 | ll.addView(materialThreeLineText());
32 | ll.addView(materialThreeLineTextIcon());
33 | ll.addView(materialThreeLineTextAvatar());
34 | ll.addView(materialThreeLineTextAvatarWithIcon());
35 |
36 | }
37 |
38 | public int dpToPixels(int dp) {
39 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
40 | }
41 |
42 | private final View materialButton() {
43 | final MaterialButton button = new MaterialButton(this);
44 | button.setText("Material Button");
45 | button.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, dpToPixels(50)));
46 | return button;
47 | }
48 |
49 |
50 | private final View materialCheckBox() {
51 | final MaterialCheckBox materialCheckBox = new MaterialCheckBox(this);
52 | materialCheckBox.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dpToPixels(56)));
53 | materialCheckBox.setText("Material Check Box");
54 | materialCheckBox.setOnCheckedChangeListener(new MaterialCheckBox.OnCheckedChangedListener() {
55 | @Override
56 | public void onCheckedChange(MaterialCheckBox materialCheckBox, boolean isChecked) {
57 | Toast.makeText(getApplicationContext(), String.format("Checkbox : %s",
58 | isChecked ? "checked" : "not checked"), Toast.LENGTH_SHORT).show();
59 | }
60 | });
61 |
62 | return materialCheckBox;
63 | }
64 |
65 | private final View materialRadioGroup() {
66 | final MaterialRadioGroup materialRadioGroup = new MaterialRadioGroup(this);
67 | materialRadioGroup.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
68 |
69 | final ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dpToPixels(56));
70 |
71 | final MaterialRadioButton materialRadioButton1 = new MaterialRadioButton(this);
72 | materialRadioButton1.setLayoutParams(params);
73 | materialRadioButton1.setText("Radio Button 1");
74 |
75 | final MaterialRadioButton materialRadioButton2 = new MaterialRadioButton(this);
76 | materialRadioButton2.setLayoutParams(params);
77 | materialRadioButton2.setText("Radio Button 2");
78 |
79 | final MaterialRadioButton materialRadioButton3 = new MaterialRadioButton(this);
80 | materialRadioButton3.setLayoutParams(params);
81 | materialRadioButton3.setText("Radio Button 3");
82 |
83 | materialRadioGroup.addView(materialRadioButton1);
84 | materialRadioGroup.addView(materialRadioButton2);
85 | materialRadioGroup.addView(materialRadioButton3);
86 |
87 | return materialRadioGroup;
88 | }
89 |
90 | private final View materialSeekBar() {
91 | final MaterialSeekBar materialSeekBar = new MaterialSeekBar(this);
92 | materialSeekBar.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dpToPixels(25)));
93 | materialSeekBar.setMax(20);
94 | materialSeekBar.setOnProgressChangedListener(new MaterialSeekBar.OnProgressChangedListener() {
95 | @Override
96 | public void onProgressChanged(int max, int progress) {
97 | Toast.makeText(getApplicationContext(), String.format("Progress : %d of %d",
98 | progress, max), Toast.LENGTH_SHORT).show();
99 | }
100 | });
101 |
102 | return materialSeekBar;
103 | }
104 |
105 | private final View materialSingleLineTextAvatar() {
106 | final MaterialSingleLineTextAvatar materialSingleLineTextAvatar = new MaterialSingleLineTextAvatar(this);
107 | materialSingleLineTextAvatar.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dpToPixels(56)));
108 | materialSingleLineTextAvatar.setText("Material Single line text with avatar");
109 | materialSingleLineTextAvatar.setIcon(getResources().getDrawable(R.drawable.test));
110 |
111 | return materialSingleLineTextAvatar;
112 | }
113 |
114 | private final View materialSingleLineTextIcon() {
115 | final MaterialSingleLineTextIcon materialSingleLineTextIcon = new MaterialSingleLineTextIcon(this);
116 | materialSingleLineTextIcon.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dpToPixels(56)));
117 | materialSingleLineTextIcon.setText("Material Single line text with Icon");
118 | materialSingleLineTextIcon.setIcon(getResources().getDrawable(R.drawable.test));
119 |
120 | return materialSingleLineTextIcon;
121 | }
122 |
123 | private final View materialSingleLineTextAvatarWithIcon() {
124 | final MaterialSingleLineTextAvatarWithIcon materialSingleLineTextAvatarWithIcon = new MaterialSingleLineTextAvatarWithIcon(this);
125 | materialSingleLineTextAvatarWithIcon.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dpToPixels(56)));
126 | materialSingleLineTextAvatarWithIcon.setText("Material Single line text with avatar");
127 | materialSingleLineTextAvatarWithIcon.setLeftIcon(getResources().getDrawable(R.drawable.test));
128 | materialSingleLineTextAvatarWithIcon.setRightIcon(getResources().getDrawable(R.drawable.block));
129 |
130 | return materialSingleLineTextAvatarWithIcon;
131 | }
132 |
133 | private final View materialTwoLineText() {
134 | final MaterialTwoLineText materialTwoLineText = new MaterialTwoLineText(this);
135 | materialTwoLineText.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dpToPixels(72)));
136 | materialTwoLineText.setPrimaryText("Primary Text");
137 | materialTwoLineText.setSecondaryText("Material Two line text with no icon ");
138 |
139 | return materialTwoLineText;
140 | }
141 |
142 |
143 | private final View materialTwoLineTextIcon() {
144 | final MaterialTwoLineTextIcon materialTwoLineTextIcon = new MaterialTwoLineTextIcon(this);
145 | materialTwoLineTextIcon.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dpToPixels(72)));
146 | materialTwoLineTextIcon.setPrimaryText("Primary Text");
147 | materialTwoLineTextIcon.setSecondaryText("Material Two line text with Icon");
148 | materialTwoLineTextIcon.setIcon(getResources().getDrawable(R.drawable.test));
149 |
150 | return materialTwoLineTextIcon;
151 | }
152 |
153 | private final View materialTwoLineTextAvatar() {
154 | final MaterialTwoLineTextAvatar materialTwoLineTextAvatar = new MaterialTwoLineTextAvatar(this);
155 | materialTwoLineTextAvatar.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dpToPixels(72)));
156 | materialTwoLineTextAvatar.setPrimaryText("Primary text");
157 | materialTwoLineTextAvatar.setSecondaryText("Material Two line text with avatar");
158 | materialTwoLineTextAvatar.setIcon(getResources().getDrawable(R.drawable.test));
159 |
160 | return materialTwoLineTextAvatar;
161 | }
162 |
163 | private final View materialTwoLineTextAvatarWithIcon() {
164 | final MaterialTwoLineTextAvatarWithIcon materialTwoLineTextAvatarWithIcon = new MaterialTwoLineTextAvatarWithIcon(this);
165 | materialTwoLineTextAvatarWithIcon.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dpToPixels(72)));
166 | materialTwoLineTextAvatarWithIcon.setPrimaryText("Primary text");
167 | materialTwoLineTextAvatarWithIcon.setSecondaryText("Material Two line text with avatar");
168 | materialTwoLineTextAvatarWithIcon.setLeftIcon(getResources().getDrawable(R.drawable.test));
169 | materialTwoLineTextAvatarWithIcon.setRightIcon(getResources().getDrawable(R.drawable.block));
170 |
171 | return materialTwoLineTextAvatarWithIcon;
172 | }
173 |
174 | private final View materialThreeLineTextIcon() {
175 | final MaterialThreeLineTextIcon materialThreeLineTextIcon = new MaterialThreeLineTextIcon(this);
176 | materialThreeLineTextIcon.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dpToPixels(88)));
177 | materialThreeLineTextIcon.setPrimaryText("Primary Text");
178 | materialThreeLineTextIcon.setSecondaryText("Material Three line text with Icon test, making sure it spans over two lines so i can show case the 3 lines in the three line text'");
179 | materialThreeLineTextIcon.setIcon(getResources().getDrawable(R.drawable.test));
180 |
181 | return materialThreeLineTextIcon;
182 | }
183 |
184 | private final View materialThreeLineTextAvatar() {
185 | final MaterialThreeLineTextAvatar materialThreeLineTextAvatar = new MaterialThreeLineTextAvatar(this);
186 | materialThreeLineTextAvatar.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dpToPixels(88)));
187 | materialThreeLineTextAvatar.setPrimaryText("Primary text");
188 | materialThreeLineTextAvatar.setSecondaryText("Material Three line text with Avatar test, making sure it spans over two lines so i can show case the 3 lines in the three line text");
189 | materialThreeLineTextAvatar.setIcon(getResources().getDrawable(R.drawable.test));
190 |
191 | return materialThreeLineTextAvatar;
192 | }
193 |
194 | private final View materialThreeLineTextAvatarWithIcon() {
195 | final MaterialThreeLineTextAvatarWithIcon materialThreeLineTextAvatarWithIcon = new MaterialThreeLineTextAvatarWithIcon(this);
196 | materialThreeLineTextAvatarWithIcon.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dpToPixels(88)));
197 | materialThreeLineTextAvatarWithIcon.setPrimaryText("Primary text");
198 | materialThreeLineTextAvatarWithIcon.setSecondaryText("Material Three line text with Avatar and Icon test, making sure it spans over two lines so i can show case the 3 lines in the three line text");
199 | materialThreeLineTextAvatarWithIcon.setLeftIcon(getResources().getDrawable(R.drawable.test));
200 | materialThreeLineTextAvatarWithIcon.setRightIcon(getResources().getDrawable(R.drawable.block));
201 |
202 | return materialThreeLineTextAvatarWithIcon;
203 | }
204 |
205 | private final View materialThreeLineText() {
206 | final MaterialThreeLineText materialThreeLineText = new MaterialThreeLineText(this);
207 | materialThreeLineText.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dpToPixels(88)));
208 | materialThreeLineText.setPrimaryText("Primary Text");
209 | materialThreeLineText.setSecondaryText("Material Three line text with no icon test, making sure it spans over two lines so i can show case the 3 lines in the three line text");
210 | return materialThreeLineText;
211 | }
212 |
213 | private final View materialSwitch() {
214 | final MaterialSwitch materialSwitch = new MaterialSwitch(this);
215 | materialSwitch.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dpToPixels(55)));
216 | materialSwitch.setText("Material Check Box");
217 | materialSwitch.setOnCheckedChangeListener(new MaterialSwitch.OnCheckedChangedListener() {
218 | @Override
219 | public void onCheckedChange(MaterialSwitch materialSwitch, boolean isChecked) {
220 | Toast.makeText(getApplicationContext(), String.format("Switch : %s",
221 | isChecked ? "checked" : "not checked"), Toast.LENGTH_SHORT).show();
222 | }
223 | });
224 |
225 | return materialSwitch;
226 | }
227 |
228 |
229 | }
230 |
--------------------------------------------------------------------------------
/app/src/main/java/com/micnubinub/materiallibrary/MaterialButton.java:
--------------------------------------------------------------------------------
1 | package com.micnubinub.materiallibrary;
2 |
3 | import android.animation.Animator;
4 | import android.animation.ValueAnimator;
5 | import android.content.Context;
6 | import android.graphics.Canvas;
7 | import android.graphics.ColorFilter;
8 | import android.graphics.Paint;
9 | import android.graphics.RectF;
10 | import android.graphics.drawable.Drawable;
11 | import android.util.AttributeSet;
12 | import android.util.TypedValue;
13 | import android.view.MotionEvent;
14 | import android.view.animation.AccelerateInterpolator;
15 | import android.widget.Button;
16 |
17 | import java.util.Timer;
18 | import java.util.TimerTask;
19 |
20 | /**
21 | * Created by root on 17/10/14.
22 | */
23 | public class MaterialButton extends Button {
24 |
25 | private static final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
26 | private static final AccelerateInterpolator interpolator = new AccelerateInterpolator();
27 | private static int duration = 750;
28 | private final ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
29 | private final int rippleColor = 0x25000000;
30 | private int width;
31 | private int height;
32 | private float animated_value = 0;
33 | private float scaleTo = 1.065f;
34 | private int clickedX, clickedY;
35 | private boolean touchDown = false, animateRipple;
36 | private float ripple_animated_value = 0;
37 | private final ValueAnimator.AnimatorUpdateListener animatorUpdateListener = new ValueAnimator.AnimatorUpdateListener() {
38 | @Override
39 | public void onAnimationUpdate(ValueAnimator animation) {
40 | animated_value = (Float) (animation.getAnimatedValue());
41 | ripple_animated_value = animated_value;
42 | invalidatePoster();
43 | }
44 | };
45 | private final ValueAnimator.AnimatorListener animatorListener = new Animator.AnimatorListener() {
46 | @Override
47 | public void onAnimationStart(Animator animator) {
48 |
49 | }
50 |
51 | @Override
52 | public void onAnimationEnd(Animator animator) {
53 | if (!touchDown)
54 | ripple_animated_value = 0;
55 |
56 | animateRipple = false;
57 | invalidatePoster();
58 | }
59 |
60 | @Override
61 | public void onAnimationCancel(Animator animator) {
62 |
63 |
64 | }
65 |
66 | @Override
67 | public void onAnimationRepeat(Animator animator) {
68 |
69 | }
70 | };
71 | private int rippleR;
72 | private RectF backgroundRect = null;
73 |
74 | public MaterialButton(Context context) {
75 | super(context);
76 | init();
77 | }
78 |
79 | public MaterialButton(Context context, AttributeSet attrs) {
80 | super(context, attrs);
81 | init();
82 | }
83 |
84 | public MaterialButton(Context context, AttributeSet attrs, int defStyle) {
85 | super(context, attrs, defStyle);
86 | init();
87 | }
88 |
89 | public int dpToPixels(int dp) {
90 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
91 | }
92 |
93 | private void postAnimatedValueReset(int delay) {
94 | final Timer timer = new Timer();
95 | timer.schedule(new TimerTask() {
96 | @Override
97 | public void run() {
98 | if (!touchDown)
99 | animated_value = 0;
100 | invalidatePoster();
101 | }
102 | }, delay);
103 | }
104 |
105 | private void scale(final float scale) {
106 | post(new Runnable() {
107 | @Override
108 | public void run() {
109 | MaterialButton.this.setScaleX(scale);
110 | MaterialButton.this.setScaleY(scale);
111 | invalidatePoster();
112 | }
113 | });
114 |
115 | }
116 |
117 | private void scaleLater() {
118 | final Timer timer = new Timer();
119 | timer.schedule(new TimerTask() {
120 | @Override
121 | public void run() {
122 | if (touchDown)
123 | scale(scaleTo);
124 | else
125 | scale(1);
126 | }
127 | }, 175);
128 | }
129 |
130 | public void setRippleColor(int color) {
131 | paint.setColor(color);
132 | }
133 |
134 | public void setRippleAlpha(int alpha) {
135 | paint.setAlpha(alpha);
136 | }
137 |
138 | private void init() {
139 | setWillNotDraw(false);
140 | animator.setInterpolator(interpolator);
141 | animator.addUpdateListener(animatorUpdateListener);
142 | animator.addListener(animatorListener);
143 | animator.setDuration(duration);
144 | try {
145 | setBackground(new Drg());
146 | } catch (Exception e) {
147 | //noinspection deprecation
148 | setBackgroundDrawable(new Drg());
149 | }
150 |
151 | }
152 |
153 |
154 | public void setDuration(int duration) {
155 | MaterialButton.duration = duration;
156 | animator.setDuration(duration);
157 | }
158 |
159 | public void setScaleTo(float scaleTo) {
160 | this.scaleTo = scaleTo;
161 | }
162 |
163 | private void invalidatePoster() {
164 | this.post(new Runnable() {
165 | @Override
166 | public void run() {
167 | invalidate();
168 | }
169 | });
170 | }
171 |
172 | @Override
173 | public boolean onTouchEvent(MotionEvent event) {
174 | switch (event.getAction()) {
175 | case MotionEvent.ACTION_DOWN:
176 | clickedX = (int) event.getX();
177 | clickedY = (int) event.getY();
178 | rippleR = (int) (Math.sqrt(Math.pow(Math.max(width - clickedX, clickedX), 2) + Math.pow(Math.max(height - clickedY, clickedY), 2)) * 1.15);
179 |
180 | animator.start();
181 |
182 | touchDown = true;
183 | animateRipple = true;
184 | break;
185 | case MotionEvent.ACTION_UP:
186 | case MotionEvent.ACTION_CANCEL:
187 | touchDown = false;
188 |
189 | if (!animator.isRunning()) {
190 | ripple_animated_value = 0;
191 | invalidatePoster();
192 | }
193 | break;
194 | }
195 | return true;
196 | }
197 |
198 |
199 | @Override
200 | protected void onSizeChanged(final int w, final int h, int oldw, int oldh) {
201 | super.onSizeChanged(w, h, oldw, oldh);
202 | width = w;
203 | height = h;
204 | this.setPivotX(w / 2);
205 | this.setPivotY(h / 2);
206 | backgroundRect = new RectF(0, 0, w, h);
207 | }
208 |
209 | @Override
210 | protected void dispatchDraw(Canvas canvas) {
211 | super.dispatchDraw(canvas);
212 | if (animateRipple) {
213 | paint.setColor(rippleColor);
214 | canvas.drawCircle(clickedX, clickedY, rippleR * ripple_animated_value, paint);
215 | }
216 | }
217 |
218 | class Drg extends Drawable {
219 |
220 | @Override
221 | public void draw(Canvas canvas) {
222 | paint.setColor(getResources().getColor(R.color.white));
223 | canvas.drawRoundRect(backgroundRect, dpToPixels(5), dpToPixels(5), paint);
224 | }
225 |
226 | @Override
227 | public void setAlpha(int i) {
228 |
229 | }
230 |
231 | @Override
232 | public void setColorFilter(ColorFilter colorFilter) {
233 |
234 | }
235 |
236 | @Override
237 | public int getOpacity() {
238 | return 0;
239 | }
240 |
241 | }
242 |
243 | }
244 |
--------------------------------------------------------------------------------
/app/src/main/java/com/micnubinub/materiallibrary/MaterialCheckBox.java:
--------------------------------------------------------------------------------
1 | package com.micnubinub.materiallibrary;
2 |
3 | import android.animation.Animator;
4 | import android.animation.ValueAnimator;
5 | import android.content.Context;
6 | import android.content.res.TypedArray;
7 | import android.graphics.Canvas;
8 | import android.graphics.Paint;
9 | import android.graphics.RectF;
10 | import android.util.AttributeSet;
11 | import android.util.TypedValue;
12 | import android.view.MotionEvent;
13 | import android.view.View;
14 | import android.view.ViewGroup;
15 | import android.view.animation.AccelerateInterpolator;
16 | import android.widget.TextView;
17 |
18 |
19 | /**
20 | * Created by root on 30/09/14.
21 | */
22 | public class MaterialCheckBox extends ViewGroup {
23 |
24 | private static final AccelerateInterpolator interpolator = new AccelerateInterpolator();
25 | private static final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
26 | private static int PADDING = 2;
27 | private static int duration = 650;
28 | private final ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
29 | private int height;
30 | private int rippleR;
31 | private float ripple_animated_value = 0;
32 | private int clickedX, clickedY;
33 | private boolean touchDown = false, animateRipple;
34 | private final ValueAnimator.AnimatorListener animatorListener = new Animator.AnimatorListener() {
35 | @Override
36 | public void onAnimationStart(Animator animator) {
37 |
38 | }
39 |
40 | @Override
41 | public void onAnimationEnd(Animator animator) {
42 | if (!touchDown)
43 | ripple_animated_value = 0;
44 |
45 | animateRipple = false;
46 | invalidatePoster();
47 | }
48 |
49 | @Override
50 | public void onAnimationCancel(Animator animator) {
51 |
52 |
53 | }
54 |
55 | @Override
56 | public void onAnimationRepeat(Animator animator) {
57 |
58 | }
59 | };
60 | private int textSize;
61 | private String text = "";
62 | private CheckBox materialCheckBox;
63 | private int width;
64 | private boolean checked = false;
65 | private float animated_value = 0;
66 | private final ValueAnimator.AnimatorUpdateListener updateListener = new ValueAnimator.AnimatorUpdateListener() {
67 | @Override
68 | public void onAnimationUpdate(ValueAnimator animation) {
69 | animated_value = (Float) (animation.getAnimatedValue());
70 | ripple_animated_value = animated_value;
71 | invalidatePoster();
72 | }
73 | };
74 | private OnCheckedChangedListener listener;
75 | private TextView textView;
76 | private int rippleColor = 0x25000000;
77 |
78 | public MaterialCheckBox(Context context) {
79 | super(context);
80 | init();
81 | }
82 |
83 | public MaterialCheckBox(Context context, AttributeSet attrs) {
84 | super(context, attrs);
85 | TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MaterialRadioButton, 0, 0);
86 | setChecked(a.getBoolean(R.styleable.MaterialRadioButton_checked, false));
87 | text = a.getString(R.styleable.MaterialRadioButton_text);
88 | textSize = a.getInt(R.styleable.MaterialRadioButton_textSize, 20);
89 | a.recycle();
90 | textSize = textSize < 20 ? 20 : textSize;
91 | init();
92 | }
93 |
94 | public MaterialCheckBox(Context context, AttributeSet attrs, int defStyle) {
95 | super(context, attrs, defStyle);
96 | TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MaterialRadioButton, 0, 0);
97 | setChecked(a.getBoolean(R.styleable.MaterialRadioButton_checked, false));
98 | text = a.getString(R.styleable.MaterialRadioButton_text);
99 | textSize = a.getInt(R.styleable.MaterialRadioButton_textSize, 20);
100 | a.recycle();
101 | textSize = textSize < 20 ? 20 : textSize;
102 | init();
103 | }
104 |
105 | private int dpToPixels(int dp) {
106 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
107 | }
108 |
109 | @Override
110 | protected void onLayout(boolean b, int i, int i2, int i3, int i4) {
111 | final int checkBoxButtonPaddingTop = ((getMeasuredHeight() - materialCheckBox.getMeasuredHeight()) / 2);
112 | materialCheckBox.layout(
113 | getPaddingLeft(),
114 | checkBoxButtonPaddingTop,
115 | getPaddingLeft() + materialCheckBox.getMeasuredWidth(),
116 | getMeasuredHeight() - checkBoxButtonPaddingTop
117 | );
118 |
119 | final int textViewPaddingTop = ((getMeasuredHeight() - textView.getMeasuredHeight()) / 2);
120 | textView.layout(
121 | getPaddingLeft() + materialCheckBox.getMeasuredWidth() + PADDING,
122 | textViewPaddingTop,
123 | getMeasuredWidth() - getPaddingRight(),
124 | getMeasuredHeight() - textViewPaddingTop);
125 | checkViewParams(textView);
126 |
127 | }
128 |
129 | @Override
130 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
131 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
132 | int measuredHeight = 0;
133 | int measuredWidth = 0;
134 |
135 | for (int i = 0; i < getChildCount(); i++) {
136 | final View child = getChildAt(i);
137 | measureChild(child, widthMeasureSpec, heightMeasureSpec);
138 | measuredHeight = Math.max(measuredHeight, child.getMeasuredHeight());
139 | measuredWidth += child.getMeasuredWidth();
140 | }
141 |
142 | setMeasuredDimension(resolveSizeAndState(measuredWidth, widthMeasureSpec, 0),
143 | resolveSizeAndState(measuredHeight, heightMeasureSpec, 0));
144 | }
145 |
146 | private void checkViewParams(final View view, final int layoutWidth, final int layoutHeight) {
147 | final int width = view.getMeasuredWidth();
148 | final int height = view.getMeasuredHeight();
149 | if ((width > layoutWidth) || (height > layoutHeight)) {
150 | view.setLayoutParams(new LayoutParams(layoutWidth, layoutHeight));
151 | measureChild(view, MeasureSpec.AT_MOST, MeasureSpec.AT_MOST);
152 | view.requestLayout();
153 | view.invalidate();
154 | requestLayout();
155 |
156 | }
157 | }
158 |
159 | private void checkViewParams(final View view) {
160 | final int layoutWidth = view.getRight() - view.getLeft();
161 | final int layoutHeight = view.getBottom() - view.getTop();
162 |
163 | checkViewParams(view, layoutWidth, layoutHeight);
164 |
165 | }
166 |
167 | public boolean isChecked() {
168 | return checked;
169 | }
170 |
171 | public void setChecked(boolean checked) {
172 | this.checked = checked;
173 | animateSwitch();
174 | notifyListener();
175 | }
176 |
177 | public void toggle() {
178 | setChecked(!isChecked());
179 | }
180 |
181 | private void notifyListener() {
182 | if (listener != null)
183 | listener.onCheckedChange(this, isChecked());
184 | }
185 |
186 | private void setPaintColor(int color) {
187 | try {
188 | paint.setColor(color);
189 | } catch (Exception ignored) {
190 | }
191 | }
192 |
193 | public void setAnimationDuration(int duration) {
194 | MaterialCheckBox.duration = duration;
195 | animator.setDuration(duration);
196 | }
197 |
198 | public void setText(String text) {
199 | if (textView != null)
200 | textView.setText(text);
201 | invalidate();
202 | }
203 |
204 | private void init() {
205 | setWillNotDraw(false);
206 |
207 | width = dpToPixels(28);
208 | PADDING = dpToPixels(4);
209 |
210 | materialCheckBox = new CheckBox(getContext());
211 | materialCheckBox.setLayoutParams(new LayoutParams(width, width));
212 | materialCheckBox.setPadding(PADDING, PADDING, PADDING, PADDING);
213 |
214 | textView = new TextView(getContext());
215 | PADDING = dpToPixels(5);
216 | textView.setPadding(PADDING, PADDING, PADDING, PADDING);
217 | textView.setTextColor(getResources().getColor(R.color.dark_grey_text));
218 | textView.setTextSize(18);
219 | textView.setMaxLines(2);
220 | textView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
221 |
222 | addView(textView);
223 | addView(materialCheckBox);
224 |
225 | setText(text);
226 |
227 | paint.setStyle(Paint.Style.FILL);
228 |
229 | animator.setInterpolator(interpolator);
230 | animator.setDuration(duration);
231 | animator.addListener(animatorListener);
232 | animator.addUpdateListener(updateListener);
233 | }
234 |
235 | private void animateSwitch() {
236 | if (animator.isRunning() || animator.isStarted())
237 | animator.cancel();
238 | animator.start();
239 | }
240 |
241 | public void setOnCheckedChangeListener(OnCheckedChangedListener listener) {
242 | this.listener = listener;
243 | }
244 |
245 | @Override
246 | public boolean onInterceptTouchEvent(MotionEvent event) {
247 | return false;
248 | }
249 |
250 | @Override
251 | public boolean onTouchEvent(MotionEvent event) {
252 | switch (event.getAction()) {
253 | case MotionEvent.ACTION_DOWN:
254 | clickedX = (int) event.getX();
255 | clickedY = (int) event.getY();
256 | rippleR = (int) (Math.sqrt(Math.pow(Math.max(width - clickedX, clickedX), 2) + Math.pow(Math.max(height - clickedY, clickedY), 2)) * 1.15);
257 |
258 | toggle();
259 |
260 | touchDown = true;
261 | animateRipple = true;
262 | break;
263 | case MotionEvent.ACTION_UP:
264 | case MotionEvent.ACTION_CANCEL:
265 | touchDown = false;
266 |
267 | if (!animator.isRunning()) {
268 | ripple_animated_value = 0;
269 | invalidatePoster();
270 | }
271 | break;
272 | }
273 | return true;
274 | }
275 |
276 | public void setDuration(int duration) {
277 | MaterialCheckBox.duration = duration;
278 | animator.setDuration(duration);
279 | }
280 |
281 | private void invalidatePoster() {
282 | final Runnable runnable = new Runnable() {
283 | @Override
284 | public void run() {
285 | invalidate();
286 | }
287 | };
288 | this.post(runnable);
289 | if (materialCheckBox != null) {
290 | materialCheckBox.invalidate();
291 | }
292 | }
293 |
294 | public void setRippleColor(int color) {
295 | rippleColor = color;
296 | }
297 |
298 | @Override
299 | protected void dispatchDraw(Canvas canvas) {
300 | super.dispatchDraw(canvas);
301 | if (animateRipple) {
302 | paint.setColor(rippleColor);
303 | canvas.drawCircle(clickedX, clickedY, rippleR * ripple_animated_value, paint);
304 | }
305 | }
306 |
307 |
308 | @Override
309 | protected void onSizeChanged(final int w, final int h, int oldw, int oldh) {
310 | super.onSizeChanged(w, h, oldw, oldh);
311 | width = w;
312 | height = h;
313 | }
314 |
315 | public interface OnCheckedChangedListener {
316 | public void onCheckedChange(MaterialCheckBox materialCheckBox, boolean isChecked);
317 | }
318 |
319 | private class CheckBox extends View {
320 |
321 | private final RectF rectF = new RectF(0, 0, 100, 100);
322 | private int segments;
323 | private float leftX, leftY, midX, midY, rightX, rightY;
324 | private int inR, cx, cy, outR;
325 |
326 | public CheckBox(Context context) {
327 | super(context);
328 | invalidate();
329 | }
330 |
331 |
332 | @Override
333 | protected void onDraw(Canvas canvas) {
334 | super.onDraw(canvas);
335 | final int paintColor = isChecked() ? getResources().getColor(R.color.material_green) : getResources().getColor(R.color.material_red);
336 |
337 | paint.setColor(paintColor);
338 | final int sweepAngle = (int) ((animated_value < 0.75f ? animated_value / 0.75f : 1) * 360);
339 | canvas.drawArc(rectF, -90, sweepAngle, true, paint);
340 |
341 | paint.setColor(getResources().getColor(R.color.white));
342 | canvas.drawCircle(cx, cy, inR, paint);
343 |
344 | paint.setColor(paintColor);
345 | drawLines(canvas);
346 |
347 | }
348 |
349 | private void drawLines(Canvas canvas) {
350 | final float lineValue = isChecked() ? animated_value : 1f - animated_value;
351 | if (lineValue > 0.25f) {
352 |
353 | final float leftProg = ((lineValue > 0.5f ? 0.5f : lineValue) - 0.25f) / 0.25f;
354 | canvas.drawLine(
355 | leftX,
356 | leftY,
357 | leftX + ((midX - leftX) * leftProg),
358 | leftY + ((midY - leftY) * leftProg),
359 | paint
360 | );
361 | if (lineValue > 0.5) {
362 | final float rightProg = (lineValue - 0.5f) / 0.5f;
363 |
364 | canvas.drawLine(
365 | midX - (paint.getStrokeWidth() / 4),
366 | midY + (paint.getStrokeWidth() / 4),
367 | midX + ((rightX - midX) * rightProg),
368 | midY + ((rightY - midY) * rightProg),
369 | paint
370 | );
371 | }
372 | }
373 | }
374 |
375 | @Override
376 | protected void onSizeChanged(int w, int h, int oldw, int oldh) {
377 | super.onSizeChanged(w, h, oldw, oldh);
378 | cx = w / 2;
379 | cy = h / 2;
380 | outR = Math.min(w - getPaddingLeft() - getPaddingRight(), h - getPaddingTop() - getPaddingBottom()) / 2;
381 | inR = (int) (0.875f * outR);
382 | rectF.set(cx - outR, cy - outR, cx + outR, cy + outR);
383 | paint.setStrokeWidth(0.125f * outR);
384 |
385 | segments = ((int) (rectF.right - rectF.left) / 19);
386 | leftX = rectF.left + (4 * segments);
387 | leftY = rectF.top + (10 * segments);
388 |
389 | midX = rectF.left + (8 * segments);
390 | midY = rectF.top + (14 * segments);
391 |
392 | rightX = rectF.left + (15 * segments);
393 | rightY = rectF.top + (6 * segments);
394 |
395 | }
396 |
397 | @Override
398 | protected void onAttachedToWindow() {
399 | super.onAttachedToWindow();
400 | animated_value = 1;
401 | }
402 | }
403 |
404 |
405 | }
406 |
--------------------------------------------------------------------------------
/app/src/main/java/com/micnubinub/materiallibrary/MaterialRadioButton.java:
--------------------------------------------------------------------------------
1 | package com.micnubinub.materiallibrary;
2 |
3 | import android.animation.Animator;
4 | import android.animation.ValueAnimator;
5 | import android.content.Context;
6 | import android.content.res.TypedArray;
7 | import android.graphics.Canvas;
8 | import android.graphics.Paint;
9 | import android.util.AttributeSet;
10 | import android.util.TypedValue;
11 | import android.view.MotionEvent;
12 | import android.view.View;
13 | import android.view.ViewGroup;
14 | import android.view.animation.DecelerateInterpolator;
15 | import android.widget.TextView;
16 |
17 |
18 | /**
19 | * Created by root on 30/09/14.
20 | */
21 | public class MaterialRadioButton extends ViewGroup {
22 |
23 | private static final DecelerateInterpolator interpolator = new DecelerateInterpolator();
24 | private static final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
25 | private static int PADDING = 2;
26 | private static int duration = 600;
27 | private final ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
28 | private int height;
29 | private int clickedX, clickedY;
30 | private boolean touchDown = false, animateRipple;
31 | private float ripple_animated_value = 0;
32 | private final ValueAnimator.AnimatorListener animatorListener = new Animator.AnimatorListener() {
33 | @Override
34 | public void onAnimationStart(Animator animator) {
35 |
36 | }
37 |
38 | @Override
39 | public void onAnimationEnd(Animator animator) {
40 | if (!touchDown)
41 | ripple_animated_value = 0;
42 |
43 | animateRipple = false;
44 | invalidatePoster();
45 | }
46 |
47 | @Override
48 | public void onAnimationCancel(Animator animator) {
49 |
50 |
51 | }
52 |
53 | @Override
54 | public void onAnimationRepeat(Animator animator) {
55 |
56 | }
57 | };
58 | private int rippleR;
59 | private int textSize;
60 | private String text = "";
61 | private RadioButton radioButton;
62 | private int cx, cy, r, width, color_on, color_off, hole_r, inner_hole_r, color_hole;
63 | private boolean checked = false;
64 | private float animated_value = 0;
65 | private final ValueAnimator.AnimatorUpdateListener updateListener = new ValueAnimator.AnimatorUpdateListener() {
66 | @Override
67 | public void onAnimationUpdate(ValueAnimator animation) {
68 | animated_value = (Float) (animation.getAnimatedValue());
69 | ripple_animated_value = animated_value;
70 | invalidatePoster();
71 | }
72 | };
73 | private OnCheckedChangedListener listener;
74 | private TextView textView;
75 | private int rippleColor = 0x25000000;
76 |
77 | public MaterialRadioButton(Context context) {
78 | super(context);
79 | init();
80 | }
81 |
82 | public MaterialRadioButton(Context context, AttributeSet attrs) {
83 | super(context, attrs);
84 | TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MaterialRadioButton, 0, 0);
85 | setChecked(a.getBoolean(R.styleable.MaterialRadioButton_checked, false));
86 | text = a.getString(R.styleable.MaterialRadioButton_text);
87 | textSize = a.getInt(R.styleable.MaterialRadioButton_textSize, 20);
88 | a.recycle();
89 | textSize = textSize < 20 ? 20 : textSize;
90 | init();
91 | }
92 |
93 | public MaterialRadioButton(Context context, AttributeSet attrs, int defStyle) {
94 | super(context, attrs, defStyle);
95 | TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MaterialRadioButton, 0, 0);
96 | setChecked(a.getBoolean(R.styleable.MaterialRadioButton_checked, false));
97 | text = a.getString(R.styleable.MaterialRadioButton_text);
98 | textSize = a.getInt(R.styleable.MaterialRadioButton_textSize, 20);
99 | a.recycle();
100 | textSize = textSize < 20 ? 20 : textSize;
101 | init();
102 | }
103 |
104 | @Override
105 | public boolean onTouchEvent(MotionEvent event) {
106 | switch (event.getAction()) {
107 | case MotionEvent.ACTION_DOWN:
108 | clickedX = (int) event.getX();
109 | clickedY = (int) event.getY();
110 | rippleR = (int) (Math.sqrt(Math.pow(Math.max(width - clickedX, clickedX), 2) + Math.pow(Math.max(height - clickedY, clickedY), 2)) * 1.15);
111 |
112 | toggle();
113 |
114 | touchDown = true;
115 | animateRipple = true;
116 | break;
117 | case MotionEvent.ACTION_UP:
118 | case MotionEvent.ACTION_CANCEL:
119 | touchDown = false;
120 |
121 | if (!animator.isRunning()) {
122 | ripple_animated_value = 0;
123 | invalidatePoster();
124 | }
125 | break;
126 | }
127 | return true;
128 | }
129 |
130 | private int dpToPixels(int dp) {
131 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
132 | }
133 |
134 | @Override
135 | protected void onLayout(boolean b, int i, int i2, int i3, int i4) {
136 | final int radioButtonPaddingTop = ((getMeasuredHeight() - radioButton.getMeasuredHeight()) / 2);
137 | radioButton.layout(
138 | getPaddingLeft(),
139 | radioButtonPaddingTop,
140 | getPaddingLeft() + radioButton.getMeasuredWidth(),
141 | getMeasuredHeight() - radioButtonPaddingTop
142 | );
143 |
144 | final int textViewPaddingTop = ((getMeasuredHeight() - textView.getMeasuredHeight()) / 2);
145 | textView.layout(
146 | getPaddingLeft() + radioButton.getMeasuredWidth() + PADDING,
147 | textViewPaddingTop,
148 | getMeasuredWidth() - getPaddingRight(),
149 | getMeasuredHeight() - textViewPaddingTop);
150 | checkViewParams(textView);
151 |
152 | }
153 |
154 | @Override
155 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
156 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
157 | int measuredHeight = 0;
158 | int measuredWidth = 0;
159 |
160 | for (int i = 0; i < getChildCount(); i++) {
161 | final View child = getChildAt(i);
162 | measureChild(child, widthMeasureSpec, heightMeasureSpec);
163 | measuredHeight = Math.max(measuredHeight, child.getMeasuredHeight());
164 | measuredWidth += child.getMeasuredWidth();
165 | }
166 |
167 | setMeasuredDimension(resolveSizeAndState(measuredWidth, widthMeasureSpec, 0),
168 | resolveSizeAndState(measuredHeight, heightMeasureSpec, 0));
169 | }
170 |
171 | private void checkViewParams(final View view, final int layoutWidth, final int layoutHeight) {
172 | final int width = view.getMeasuredWidth();
173 | final int height = view.getMeasuredHeight();
174 | if ((width > layoutWidth) || (height > layoutHeight)) {
175 | view.setLayoutParams(new LayoutParams(layoutWidth, layoutHeight));
176 | measureChild(view, MeasureSpec.AT_MOST, MeasureSpec.AT_MOST);
177 | view.requestLayout();
178 | view.invalidate();
179 | requestLayout();
180 |
181 | }
182 | }
183 |
184 | private void checkViewParams(final View view) {
185 | final int layoutWidth = view.getRight() - view.getLeft();
186 | final int layoutHeight = view.getBottom() - view.getTop();
187 |
188 | checkViewParams(view, layoutWidth, layoutHeight);
189 |
190 | }
191 |
192 | public boolean isChecked() {
193 | return checked;
194 | }
195 |
196 | public void setChecked(boolean checked) {
197 | this.checked = checked;
198 | animateSwitch();
199 | notifyListener();
200 | }
201 |
202 | public void toggle() {
203 | setChecked(!isChecked());
204 | }
205 |
206 | private void notifyListener() {
207 | if (listener != null)
208 | listener.onCheckedChange(this, isChecked());
209 | }
210 |
211 | public void setOffColor(int color_off) {
212 | this.color_off = color_off;
213 | }
214 |
215 | public void setOnColor(int color_on) {
216 | this.color_on = color_on;
217 | }
218 |
219 | public void setHoleColor(int hole_color) {
220 | this.color_hole = hole_color;
221 | }
222 |
223 | public void setAnimationDuration(int duration) {
224 | MaterialRadioButton.duration = duration;
225 | animator.setDuration(duration);
226 | }
227 |
228 | public void setText(String text) {
229 | if (textView != null)
230 | textView.setText(text);
231 | invalidate();
232 | }
233 |
234 | private void init() {
235 | setWillNotDraw(false);
236 |
237 | color_off = 0xff0c0c0c;
238 | color_on = 0xff42bd41;
239 | color_hole = 0xffffffff;
240 |
241 | width = dpToPixels(28);
242 | PADDING = dpToPixels(4);
243 |
244 | radioButton = new RadioButton(getContext());
245 | radioButton.setLayoutParams(new LayoutParams(width, width));
246 | radioButton.setPadding(PADDING, PADDING, PADDING, PADDING);
247 |
248 | textView = new TextView(getContext());
249 | PADDING = dpToPixels(5);
250 | textView.setPadding(PADDING, PADDING, PADDING, PADDING);
251 | textView.setTextColor(getResources().getColor(R.color.dark_grey_text));
252 | textView.setTextSize(18);
253 | textView.setMaxLines(2);
254 | textView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
255 |
256 | addView(textView);
257 | addView(radioButton);
258 |
259 | setText(text);
260 |
261 |
262 | paint.setStyle(Paint.Style.FILL);
263 | paint.setColor(color_off);
264 |
265 | animator.setInterpolator(interpolator);
266 | animator.setDuration(duration);
267 | animator.addListener(animatorListener);
268 | animator.addUpdateListener(updateListener);
269 | }
270 |
271 | private void animateSwitch() {
272 | if (animator.isRunning() || animator.isStarted())
273 | animator.cancel();
274 | animator.start();
275 | }
276 |
277 | public void setOnCheckedChangeListener(OnCheckedChangedListener listener) {
278 | this.listener = listener;
279 | }
280 |
281 | @Override
282 | public boolean onInterceptTouchEvent(MotionEvent event) {
283 | return false;
284 | }
285 |
286 | public void setDuration(int duration) {
287 | MaterialRadioButton.duration = duration;
288 | animator.setDuration(duration);
289 | }
290 |
291 | private void invalidatePoster() {
292 | final Runnable runnable = new Runnable() {
293 | @Override
294 | public void run() {
295 | invalidate();
296 | }
297 | };
298 | this.post(runnable);
299 | if (radioButton != null) {
300 | radioButton.invalidate();
301 | }
302 | }
303 |
304 | public void setRippleColor(int color) {
305 | rippleColor = color;
306 | }
307 |
308 | @Override
309 | protected void dispatchDraw(Canvas canvas) {
310 | super.dispatchDraw(canvas);
311 | if (animateRipple) {
312 | paint.setColor(rippleColor);
313 | canvas.drawCircle(clickedX, clickedY, rippleR * ripple_animated_value, paint);
314 | }
315 | }
316 |
317 |
318 | @Override
319 | protected void onSizeChanged(final int w, final int h, int oldw, int oldh) {
320 | super.onSizeChanged(w, h, oldw, oldh);
321 | width = w;
322 | height = h;
323 | }
324 |
325 | public interface OnCheckedChangedListener {
326 | public void onCheckedChange(MaterialRadioButton materialRadioButton, boolean isChecked);
327 | }
328 |
329 | private final class RadioButton extends View {
330 | public RadioButton(Context context) {
331 | super(context);
332 | invalidate();
333 | }
334 |
335 | @Override
336 | protected void onDraw(Canvas canvas) {
337 | if (isChecked())
338 | animateOn(canvas);
339 | else
340 | animateOff(canvas);
341 | }
342 |
343 |
344 | private void animateOff(Canvas canvas) {
345 | paint.setColor(color_hole);
346 | if (animator.isRunning()) {
347 | canvas.drawCircle(cx, cy, hole_r, paint);
348 | paint.setColor(color_on);
349 |
350 | float circleAnimatedValue = (animated_value / 0.85f);
351 | circleAnimatedValue = circleAnimatedValue > 1 ? 1 : circleAnimatedValue;
352 |
353 | canvas.drawCircle(cx, cy, inner_hole_r * (1 - circleAnimatedValue), paint);
354 | } else {
355 | canvas.drawCircle(cx, cy, hole_r, paint);
356 | }
357 | }
358 |
359 | private void animateOn(Canvas canvas) {
360 | paint.setColor(color_hole);
361 | if (animator.isRunning()) {
362 | canvas.drawCircle(cx, cy, hole_r, paint);
363 | paint.setColor(color_on);
364 |
365 | float circleAnimatedValue = (animated_value / 0.85f);
366 | circleAnimatedValue = circleAnimatedValue > 1 ? 1 : circleAnimatedValue;
367 |
368 | canvas.drawCircle(cx, cy, inner_hole_r * circleAnimatedValue, paint);
369 | } else {
370 | canvas.drawCircle(cx, cy, hole_r, paint);
371 | paint.setColor(color_on);
372 | canvas.drawCircle(cx, cy, inner_hole_r, paint);
373 | }
374 | }
375 |
376 |
377 | @Override
378 | protected void onSizeChanged(int w, int h, int oldw, int oldh) {
379 | super.onSizeChanged(w, h, oldw, oldh);
380 | r = Math.min(w - getPaddingLeft() - getPaddingRight(), h - getPaddingTop() - getPaddingBottom()) / 2;
381 | cx = w / 2;
382 | cy = h / 2;
383 | hole_r = (int) (r * 0.9f);
384 | inner_hole_r = (int) (r * 0.75f);
385 | }
386 |
387 | @Override
388 | protected void onAttachedToWindow() {
389 | super.onAttachedToWindow();
390 | if (isChecked())
391 | animated_value = 1;
392 | }
393 |
394 | }
395 |
396 |
397 | }
398 |
--------------------------------------------------------------------------------
/app/src/main/java/com/micnubinub/materiallibrary/MaterialRadioGroup.java:
--------------------------------------------------------------------------------
1 | package com.micnubinub.materiallibrary;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 |
8 | /**
9 | * Created by root on 18/09/14.
10 | */
11 | public class MaterialRadioGroup extends ViewGroup {
12 | private int selectedRadioButton = -1;
13 | private OnSelectionChangedListener selectionChanged;
14 | private final MaterialRadioButton.OnCheckedChangedListener listener = new MaterialRadioButton.OnCheckedChangedListener() {
15 | @Override
16 | public void onCheckedChange(MaterialRadioButton materialCheckBox, boolean isChecked) {
17 | final int indexOfChild = indexOfChild(materialCheckBox);
18 | if (isChecked && !(selectedRadioButton == indexOfChild)) {
19 | if (selectedRadioButton >= 0) {
20 | MaterialRadioButton materialRadioButton = (MaterialRadioButton) getChildAt(selectedRadioButton);
21 | materialRadioButton.setChecked(false);
22 | materialRadioButton.invalidate();
23 | }
24 | }
25 | if (selectedRadioButton == indexOfChild) {
26 | selectedRadioButton = -1;
27 | } else {
28 | selectedRadioButton = indexOfChild;
29 | }
30 |
31 | if (selectionChanged != null)
32 | selectionChanged.onSelectionChanged((MaterialRadioButton) getChildAt(selectedRadioButton), selectedRadioButton);
33 | }
34 | };
35 |
36 | public MaterialRadioGroup(Context context) {
37 | super(context);
38 | }
39 |
40 | public MaterialRadioGroup(Context context, AttributeSet attrs) {
41 | super(context, attrs);
42 |
43 | }
44 |
45 | public MaterialRadioGroup(Context context, AttributeSet attrs, int defStyleAttr) {
46 | super(context, attrs, defStyleAttr);
47 | }
48 |
49 | @Override
50 | protected void onLayout(boolean b, int i, int i2, int i3, int i4) {
51 |
52 | int currentChildRight;
53 | int currentChildBottom;
54 | int currentChildTop = 0;
55 | final int currentChildLeft = getPaddingLeft();
56 |
57 | for (int j = 0; j < getChildCount(); j++) {
58 | final View child = getChildAt(j);
59 |
60 | if (j > 0) {
61 | currentChildTop += getChildAt(j - 1).getHeight();
62 | currentChildBottom = currentChildTop + child.getMeasuredHeight();
63 | } else {
64 | currentChildTop = getPaddingTop();
65 | currentChildBottom = child.getMeasuredHeight() - getPaddingBottom();
66 | }
67 | currentChildRight = child.getMeasuredWidth() - getPaddingRight();
68 | child.layout(currentChildLeft, currentChildTop, currentChildRight, currentChildBottom);
69 | }
70 | }
71 |
72 | @Override
73 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
74 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
75 |
76 | //Todo setMeasuredDimension();
77 | //Todo measureChildWithMargins()
78 | //Todo xmlns:custom="http://schemas.android.com/apk/res/com.packa..."
79 |
80 |
81 | int measuredHeight = 0;
82 | int measuredWidth = 0;
83 |
84 | for (int i = 0; i < getChildCount(); i++) {
85 | final View child = getChildAt(i);
86 | if (child.getVisibility() != GONE) {
87 | measureChild(child, widthMeasureSpec, heightMeasureSpec);
88 | measuredHeight += child.getMeasuredHeight();
89 | measuredWidth = Math.max(measuredWidth, child.getMeasuredWidth());
90 | }
91 | }
92 | setMeasuredDimension(resolveSizeAndState(measuredWidth, widthMeasureSpec, 0),
93 | resolveSizeAndState(measuredHeight, heightMeasureSpec, 0));
94 |
95 | }
96 | //Todo check if everything works fine, cause you removed all the other addView(...)s
97 |
98 | @Override
99 | public void addView(View child, int index, LayoutParams params) {
100 | addListener((MaterialRadioButton) child);
101 | super.addView(child, index, params);
102 | }
103 |
104 | private void addListener(MaterialRadioButton materialCheckBox) {
105 | try {
106 | materialCheckBox.setOnCheckedChangeListener(listener);
107 | materialCheckBox.setChecked(false);
108 | } catch (Exception ignored) {
109 | }
110 | }
111 |
112 | public void setOnSelectionChanged(OnSelectionChangedListener selectionChanged) {
113 | this.selectionChanged = selectionChanged;
114 | }
115 |
116 | public interface OnSelectionChangedListener {
117 | public void onSelectionChanged(MaterialRadioButton radioButton, int selectedChild);
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/app/src/main/java/com/micnubinub/materiallibrary/MaterialSeekBar.java:
--------------------------------------------------------------------------------
1 | package com.micnubinub.materiallibrary;
2 |
3 |
4 | import android.content.Context;
5 | import android.graphics.Canvas;
6 | import android.graphics.Paint;
7 | import android.util.AttributeSet;
8 | import android.view.MotionEvent;
9 | import android.view.View;
10 |
11 |
12 | /**
13 | * Created by root on 24/08/14.
14 | */
15 | public class MaterialSeekBar extends View {
16 | private final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
17 | private int lineRight;
18 | private float line_pos, scaleTo = 1.22f;
19 | private int r, rDown, rUp, width, scrubberColor, progressColor, progressBackgroundColor;
20 | private int max;
21 | private float progress, scrubberPosition;
22 | private OnProgressChangedListener listener;
23 |
24 | public MaterialSeekBar(Context context) {
25 | super(context);
26 | init();
27 | }
28 |
29 | public MaterialSeekBar(Context context, AttributeSet attrs) {
30 | super(context, attrs);
31 | init();
32 | }
33 |
34 | public MaterialSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
35 | super(context, attrs, defStyleAttr);
36 | init();
37 | }
38 |
39 | public int getMax() {
40 | return max;
41 | }
42 |
43 | public void setMax(int max) {
44 | this.max = max;
45 | }
46 |
47 | private void init() {
48 | paint.setStyle(Paint.Style.FILL);
49 | paint.setStrokeCap(Paint.Cap.ROUND);
50 | //setLayerType(View.LAYER_TYPE_SOFTWARE, null);
51 | setMax(100);
52 | setScrubberColor(getResources().getColor(R.color.material_green_light));
53 | setProgressColor(getResources().getColor(R.color.material_green_light));
54 | //setShadowColor(res.getColor(R.color.black));
55 | setProgressBackgroundColor(getResources().getColor(R.color.lite_grey));
56 | setOnTouchListener(new OnTouchListener() {
57 | @Override
58 | public boolean onTouch(View v, MotionEvent event) {
59 | //boolean drawShadow_tmp = drawShadow;
60 | switch (event.getAction()) {
61 |
62 | case MotionEvent.ACTION_DOWN:
63 | case MotionEvent.ACTION_MOVE:
64 | final int touch = (int) (event.getX());
65 | if (touch < lineRight && touch > rUp)
66 | setProgress(max * ((event.getX() - rUp) / (float) (width - 2 * rUp)));
67 |
68 | r = rUp;
69 | break;
70 | case MotionEvent.ACTION_UP:
71 | case MotionEvent.ACTION_CANCEL:
72 | case MotionEvent.ACTION_OUTSIDE:
73 | r = rDown;
74 | break;
75 |
76 | }
77 | invalidate();
78 | return true;
79 | }
80 | });
81 |
82 | }
83 |
84 | @Override
85 | protected void onDraw(Canvas canvas) {
86 | super.onDraw(canvas);
87 |
88 | scrubberPosition = ((width - getPaddingRight() - getPaddingLeft()) * progress / (float) max);
89 | scrubberPosition = scrubberPosition < rUp ? rUp : scrubberPosition;
90 | scrubberPosition = scrubberPosition > lineRight ? lineRight : scrubberPosition;
91 |
92 | setPaintColor(progressBackgroundColor);
93 | canvas.drawLine(scrubberPosition, line_pos, lineRight, line_pos, paint);
94 |
95 | setPaintColor(progressColor);
96 | canvas.drawLine(rUp, line_pos, scrubberPosition, line_pos, paint);
97 |
98 | setPaintColor(scrubberColor);
99 | /*
100 | if (drawShadow) {
101 | paint.setShadowLayer(shadowRadius, 0, 0, shadowColor);
102 | canvas.drawCircle(scrubberPosition, line_pos, r, paint);
103 | paint.setShadowLayer(0, 0, 0, 0);
104 | } else*/
105 | canvas.drawCircle(scrubberPosition, line_pos, r, paint);
106 | }
107 |
108 | @Override
109 | protected void onSizeChanged(int w, int h, int oldw, int oldh) {
110 | super.onSizeChanged(w, h, oldw, oldh);
111 |
112 | line_pos = h / 2;
113 | rDown = ((int) (Math.min((w - getPaddingLeft() - getPaddingRight()), (h - getPaddingBottom() - getPaddingTop())) / scaleTo)) / 2;
114 | rUp = Math.min((w - getPaddingLeft() - getPaddingRight()), (h - getPaddingBottom() - getPaddingTop())) / 2;
115 |
116 | lineRight = w - rUp;
117 | r = rDown;
118 | paint.setStrokeWidth(rDown / 2.3f);
119 | width = w;
120 |
121 | }
122 |
123 | private void notifyListener() {
124 | if (listener != null)
125 | listener.onProgressChanged(getMax(), getProgress());
126 | }
127 |
128 | private void setPaintColor(int color) {
129 | try {
130 | this.paint.setColor(color);
131 | } catch (Exception ignored) {
132 | }
133 | }
134 |
135 | public void setOnProgressChangedListener(OnProgressChangedListener listener) {
136 | this.listener = listener;
137 | }
138 |
139 | public int getProgress() {
140 | return Math.round(progress);
141 | }
142 |
143 | public void setProgress(float progress) {
144 | progress = progress > max ? max : progress;
145 | progress = progress < 0 ? 0 : progress;
146 | this.progress = progress;
147 | notifyListener();
148 | }
149 |
150 | public void setProgress(int progress) {
151 | this.progress = progress;
152 | notifyListener();
153 | }
154 |
155 | public void setScrubberRadius(int r) {
156 | this.rDown = r;
157 | }
158 |
159 | public void setScrubberColor(int scrubberColor) {
160 | this.scrubberColor = scrubberColor;
161 | }
162 |
163 | public void setProgressColor(int progressColor) {
164 | this.progressColor = progressColor;
165 | }
166 |
167 | public void setProgressBackgroundColor(int progressBackgroundColor) {
168 | this.progressBackgroundColor = progressBackgroundColor;
169 | }
170 |
171 | public interface OnProgressChangedListener {
172 | public void onProgressChanged(int max, int progress);
173 | }
174 | }
175 |
--------------------------------------------------------------------------------
/app/src/main/java/com/micnubinub/materiallibrary/MaterialSingleLineTextAvatar.java:
--------------------------------------------------------------------------------
1 | package com.micnubinub.materiallibrary;
2 |
3 | import android.animation.Animator;
4 | import android.animation.ValueAnimator;
5 | import android.content.Context;
6 | import android.content.res.TypedArray;
7 | import android.graphics.Bitmap;
8 | import android.graphics.BitmapFactory;
9 | import android.graphics.Canvas;
10 | import android.graphics.Paint;
11 | import android.graphics.PorterDuff;
12 | import android.graphics.PorterDuffXfermode;
13 | import android.graphics.Rect;
14 | import android.graphics.drawable.BitmapDrawable;
15 | import android.graphics.drawable.Drawable;
16 | import android.text.TextUtils;
17 | import android.util.AttributeSet;
18 | import android.util.TypedValue;
19 | import android.view.MotionEvent;
20 | import android.view.View;
21 | import android.view.ViewGroup;
22 | import android.view.animation.AccelerateInterpolator;
23 | import android.widget.ImageView;
24 | import android.widget.TextView;
25 |
26 | import java.util.Timer;
27 | import java.util.TimerTask;
28 |
29 | /**
30 | * Created by root on 21/10/14.
31 | */
32 | public class MaterialSingleLineTextAvatar extends ViewGroup {
33 | private static final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
34 | private static final AccelerateInterpolator interpolator = new AccelerateInterpolator();
35 | private static int duration = 600;
36 | private final ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
37 | private TextView textView;
38 | private ImageView imageView;
39 | private int width;
40 | private int height;
41 | private float animated_value = 0;
42 | private float scaleTo = 1.065f;
43 | private int clickedX, clickedY;
44 | private boolean touchDown = false, animateRipple;
45 | private float ripple_animated_value = 0;
46 | private final ValueAnimator.AnimatorUpdateListener animatorUpdateListener = new ValueAnimator.AnimatorUpdateListener() {
47 | @Override
48 | public void onAnimationUpdate(ValueAnimator animation) {
49 | animated_value = (Float) (animation.getAnimatedValue());
50 | ripple_animated_value = animated_value;
51 | invalidatePoster();
52 | }
53 | };
54 | private final ValueAnimator.AnimatorListener animatorListener = new Animator.AnimatorListener() {
55 | @Override
56 | public void onAnimationStart(Animator animator) {
57 |
58 | }
59 |
60 | @Override
61 | public void onAnimationEnd(Animator animator) {
62 | if (!touchDown)
63 | ripple_animated_value = 0;
64 |
65 | animateRipple = false;
66 | invalidatePoster();
67 | }
68 |
69 | @Override
70 | public void onAnimationCancel(Animator animator) {
71 |
72 |
73 | }
74 |
75 | @Override
76 | public void onAnimationRepeat(Animator animator) {
77 |
78 | }
79 | };
80 | private int rippleR;
81 | private int rippleColor = 0x25000000;
82 |
83 | public MaterialSingleLineTextAvatar(Context context) {
84 | super(context);
85 | init();
86 | }
87 |
88 | public MaterialSingleLineTextAvatar(Context context, AttributeSet attrs) {
89 | super(context, attrs);
90 |
91 | try {
92 | final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MaterialTwoLineText, 0, 0);
93 | setTextColor(a.getInteger(R.attr.primaryTextColor, getResources().getColor(R.color.dark_dark_grey)));
94 | setTextSize(a.getInteger(R.attr.primaryTextSize, 18));
95 | a.recycle();
96 | } catch (Exception ignored) {
97 | }
98 | init();
99 |
100 |
101 | }
102 |
103 |
104 | public MaterialSingleLineTextAvatar(Context context, AttributeSet attrs, int defStyle) {
105 | super(context, attrs, defStyle);
106 | try {
107 | final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MaterialTwoLineText, 0, 0);
108 | setTextColor(a.getInteger(R.attr.primaryTextColor, getResources().getColor(R.color.dark_dark_grey)));
109 | setTextSize(a.getInteger(R.attr.primaryTextSize, 16));
110 | a.recycle();
111 | } catch (Exception ignored) {
112 | }
113 |
114 |
115 | init();
116 |
117 |
118 | }
119 |
120 | @Override
121 | public boolean onTouchEvent(MotionEvent event) {
122 | switch (event.getAction()) {
123 | case MotionEvent.ACTION_DOWN:
124 | clickedX = (int) event.getX();
125 | clickedY = (int) event.getY();
126 | rippleR = (int) (Math.sqrt(Math.pow(Math.max(width - clickedX, clickedX), 2) + Math.pow(Math.max(height - clickedY, clickedY), 2)) * 1.15);
127 |
128 | animator.start();
129 |
130 | touchDown = true;
131 | animateRipple = true;
132 | break;
133 | case MotionEvent.ACTION_UP:
134 | case MotionEvent.ACTION_CANCEL:
135 | touchDown = false;
136 |
137 | if (!animator.isRunning()) {
138 | ripple_animated_value = 0;
139 | invalidatePoster();
140 | }
141 | break;
142 | }
143 | return true;
144 | }
145 |
146 | public void setText(String text) {
147 | textView.setText(text);
148 | invalidatePoster();
149 | }
150 |
151 | public int dpToPixels(int dp) {
152 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
153 | }
154 |
155 | private void init() {
156 | final int padding = dpToPixels(16);
157 | final int imageWidth = dpToPixels(72);
158 |
159 | textView = new TextView(getContext());
160 | textView.setTextColor(getResources().getColor(R.color.dark_dark_grey));
161 | textView.setTextSize(18);
162 | textView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
163 | textView.setMaxLines(1);
164 | textView.setEllipsize(TextUtils.TruncateAt.END);
165 | textView.setPadding(padding, padding / 2, padding, padding / 2);
166 |
167 | imageView = new ImageView(getContext());
168 | imageView.setLayoutParams(new LayoutParams(imageWidth, imageWidth));
169 | imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
170 | imageView.setPadding(padding, padding, padding, padding);
171 |
172 | setWillNotDraw(false);
173 | animator.setInterpolator(interpolator);
174 | animator.addUpdateListener(animatorUpdateListener);
175 | animator.addListener(animatorListener);
176 | animator.setDuration(duration);
177 | paint.setColor(0x25000000);
178 |
179 | addView(textView);
180 | addView(imageView);
181 | }
182 |
183 | public void setIcon(Drawable icon) {
184 | imageView.setImageBitmap(getCircleBitmap(icon, dpToPixels(40)));
185 | }
186 |
187 | public void setIcon(Bitmap icon) {
188 | imageView.setImageBitmap(getCircleBitmap(icon, dpToPixels(40)));
189 | }
190 |
191 | public void setTextSize(int sp) {
192 | textView.setTextSize(sp);
193 | }
194 |
195 | public void setTextColor(int color) {
196 | textView.setTextColor(color);
197 | }
198 |
199 | private void scale(final float scale) {
200 | post(new Runnable() {
201 | @Override
202 | public void run() {
203 | MaterialSingleLineTextAvatar.this.setScaleX(scale);
204 | MaterialSingleLineTextAvatar.this.setScaleY(scale);
205 | invalidatePoster();
206 | }
207 | });
208 |
209 | }
210 |
211 | private void scaleLater() {
212 | final Timer timer = new Timer();
213 | timer.schedule(new TimerTask() {
214 | @Override
215 | public void run() {
216 | if (touchDown)
217 | scale(scaleTo);
218 | else
219 | scale(1);
220 | }
221 | }, 175);
222 | }
223 |
224 | @Override
225 | public boolean onInterceptTouchEvent(MotionEvent event) {
226 |
227 | return false;
228 |
229 | }
230 |
231 | public void setDuration(int duration) {
232 | MaterialSingleLineTextAvatar.duration = duration;
233 | animator.setDuration(duration);
234 | }
235 |
236 | public void setScaleTo(float scaleTo) {
237 | this.scaleTo = scaleTo;
238 | }
239 |
240 |
241 | private void invalidatePoster() {
242 | this.post(new Runnable() {
243 | @Override
244 | public void run() {
245 | invalidate();
246 | }
247 | });
248 | }
249 |
250 | public void setRippleColor(int color) {
251 | rippleColor = color;
252 | }
253 |
254 | @Override
255 | protected void dispatchDraw(Canvas canvas) {
256 | super.dispatchDraw(canvas);
257 | if (animateRipple) {
258 | paint.setColor(rippleColor);
259 | canvas.drawCircle(clickedX, clickedY, rippleR * ripple_animated_value, paint);
260 | }
261 | }
262 |
263 | @Override
264 | public void addView(View child, int index, LayoutParams params) {
265 | if (getChildCount() >= 2)
266 | return;
267 | super.addView(child, index, params);
268 | }
269 |
270 |
271 | @Override
272 | protected void onSizeChanged(final int w, final int h, int oldw, int oldh) {
273 | super.onSizeChanged(w, h, oldw, oldh);
274 | width = w;
275 | height = h;
276 | }
277 |
278 | @Override
279 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
280 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
281 | int measuredHeight = 0;
282 | int measuredWidth = 0;
283 |
284 | for (int i = 0; i < getChildCount(); i++) {
285 | final View child = getChildAt(i);
286 | measureChild(child, widthMeasureSpec, heightMeasureSpec);
287 | measuredHeight = Math.max(child.getMeasuredHeight(), measuredHeight);
288 | measuredWidth = Math.max(child.getMeasuredWidth(), measuredWidth);
289 | }
290 |
291 | setMeasuredDimension(resolveSizeAndState(measuredWidth, widthMeasureSpec, 0),
292 | resolveSizeAndState(measuredHeight, heightMeasureSpec, 0));
293 | }
294 |
295 | @Override
296 | protected void onLayout(boolean b, int i, int i2, int i3, int i4) {
297 | final int imageViewPaddingTop = (getMeasuredHeight() - imageView.getMeasuredHeight()) / 2;
298 | imageView.layout(getPaddingLeft(),
299 | imageViewPaddingTop,
300 | getPaddingLeft() + imageView.getMeasuredWidth(),
301 | getMeasuredHeight() - imageViewPaddingTop
302 | );
303 |
304 | final int textViewPaddingTop = (getMeasuredHeight() - textView.getMeasuredHeight()) / 2;
305 | textView.layout(getPaddingLeft() + imageView.getMeasuredWidth(), textViewPaddingTop,
306 | getMeasuredWidth() - getPaddingRight(),
307 | getMeasuredHeight() - textViewPaddingTop);
308 |
309 | checkViewParams(textView);
310 | }
311 |
312 | private void checkViewParams(final View view, final int layoutWidth, final int layoutHeight) {
313 | final int width = view.getMeasuredWidth();
314 | final int height = view.getMeasuredHeight();
315 | if ((width > layoutWidth) || (height > layoutHeight)) {
316 | view.setLayoutParams(new LayoutParams(layoutWidth, layoutHeight));
317 | measureChild(view, MeasureSpec.AT_MOST, MeasureSpec.AT_MOST);
318 | view.requestLayout();
319 | view.invalidate();
320 | requestLayout();
321 |
322 | }
323 | }
324 |
325 | private void checkViewParams(final View view) {
326 | final int layoutWidth = view.getRight() - view.getLeft();
327 | final int layoutHeight = view.getBottom() - view.getTop();
328 |
329 | checkViewParams(view, layoutWidth, layoutHeight);
330 |
331 | }
332 |
333 | public Bitmap drawableToBitmap(Drawable drawable) {
334 | if (drawable == null) // Don't do anything without a proper drawable
335 | return null;
336 | else if (drawable instanceof BitmapDrawable) // Use the getBitmap() method instead if BitmapDrawable
337 | return ((BitmapDrawable) drawable).getBitmap();
338 | // Create Bitmap object out of the drawable
339 | Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
340 | Canvas canvas = new Canvas(bitmap);
341 | drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
342 | drawable.draw(canvas);
343 | return bitmap;
344 | }
345 |
346 | public Bitmap getCircleBitmap(final Drawable drawable, final int width) {
347 | BitmapFactory.Options options = new BitmapFactory.Options();
348 | options.inMutable = true;
349 | options.inPreferredConfig = Bitmap.Config.ARGB_8888;
350 | Bitmap bitmap = drawableToBitmap(drawable);
351 |
352 | return getCircleBitmap(bitmap, width);
353 | }
354 |
355 | public Bitmap getCircleBitmap(Bitmap bitmap, final int width) {
356 | bitmap.setHasAlpha(true);
357 | bitmap = Bitmap.createScaledBitmap(bitmap, width, width, true);
358 | Bitmap output = Bitmap.createBitmap(width,
359 | width, Bitmap.Config.ARGB_8888);
360 | final Rect rect = new Rect(0, 0, width,
361 | width);
362 | Canvas canvas = new Canvas(output);
363 | Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
364 | paint.setColor(0xff000000);
365 | canvas.drawCircle(width / 2, width / 2, width / 2, paint);
366 | paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
367 | canvas.drawBitmap(bitmap, rect, rect, paint);
368 | bitmap.recycle();
369 | return output;
370 | }
371 |
372 |
373 | }
374 |
--------------------------------------------------------------------------------
/app/src/main/java/com/micnubinub/materiallibrary/MaterialSingleLineTextAvatarWithIcon.java:
--------------------------------------------------------------------------------
1 | package com.micnubinub.materiallibrary;
2 |
3 | import android.animation.Animator;
4 | import android.animation.ValueAnimator;
5 | import android.content.Context;
6 | import android.content.res.TypedArray;
7 | import android.graphics.Bitmap;
8 | import android.graphics.BitmapFactory;
9 | import android.graphics.Canvas;
10 | import android.graphics.Paint;
11 | import android.graphics.PorterDuff;
12 | import android.graphics.PorterDuffXfermode;
13 | import android.graphics.Rect;
14 | import android.graphics.drawable.BitmapDrawable;
15 | import android.graphics.drawable.Drawable;
16 | import android.text.TextUtils;
17 | import android.util.AttributeSet;
18 | import android.util.TypedValue;
19 | import android.view.MotionEvent;
20 | import android.view.View;
21 | import android.view.ViewGroup;
22 | import android.view.animation.AccelerateInterpolator;
23 | import android.widget.ImageView;
24 | import android.widget.TextView;
25 |
26 | import java.util.Timer;
27 | import java.util.TimerTask;
28 |
29 | /**
30 | * Created by root on 21/10/14.
31 | */
32 | public class MaterialSingleLineTextAvatarWithIcon extends ViewGroup {
33 | private static final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
34 | private static final AccelerateInterpolator interpolator = new AccelerateInterpolator();
35 | private static int duration = 600;
36 | private final ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
37 | private TextView textView;
38 | private ImageView avatar, icon;
39 | private int width;
40 | private int height;
41 | private float animated_value = 0;
42 | private float scaleTo = 1.065f;
43 | private int clickedX, clickedY;
44 | private boolean touchDown = false, animateRipple;
45 | private float ripple_animated_value = 0;
46 | private final ValueAnimator.AnimatorUpdateListener animatorUpdateListener = new ValueAnimator.AnimatorUpdateListener() {
47 | @Override
48 | public void onAnimationUpdate(ValueAnimator animation) {
49 | animated_value = (Float) (animation.getAnimatedValue());
50 | ripple_animated_value = animated_value;
51 | invalidatePoster();
52 | }
53 | };
54 | private final ValueAnimator.AnimatorListener animatorListener = new Animator.AnimatorListener() {
55 | @Override
56 | public void onAnimationStart(Animator animator) {
57 |
58 | }
59 |
60 | @Override
61 | public void onAnimationEnd(Animator animator) {
62 | if (!touchDown)
63 | ripple_animated_value = 0;
64 |
65 | animateRipple = false;
66 | invalidatePoster();
67 | }
68 |
69 | @Override
70 | public void onAnimationCancel(Animator animator) {
71 |
72 |
73 | }
74 |
75 | @Override
76 | public void onAnimationRepeat(Animator animator) {
77 |
78 | }
79 | };
80 | private int rippleR;
81 | private int rippleColor = 0x25000000;
82 |
83 | public MaterialSingleLineTextAvatarWithIcon(Context context) {
84 | super(context);
85 | init();
86 | }
87 |
88 | public MaterialSingleLineTextAvatarWithIcon(Context context, AttributeSet attrs) {
89 | super(context, attrs);
90 |
91 | try {
92 | final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MaterialTwoLineText, 0, 0);
93 | setTextColor(a.getInteger(R.attr.textColor, getResources().getColor(R.color.dark_grey)));
94 | setTextSize(a.getInteger(R.attr.primaryTextSize, 16));
95 | setTextMaxLines(a.getInteger(R.attr.secondaryTextMaxLines, 1));
96 | a.recycle();
97 | } catch (Exception ignored) {
98 | }
99 |
100 | init();
101 |
102 | }
103 |
104 |
105 | public MaterialSingleLineTextAvatarWithIcon(Context context, AttributeSet attrs, int defStyle) {
106 | super(context, attrs, defStyle);
107 | try {
108 | final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MaterialTwoLineText, 0, 0);
109 | setTextColor(a.getInteger(R.attr.secondaryTextColor, getResources().getColor(R.color.dark_grey)));
110 | setTextSize(a.getInteger(R.attr.primaryTextSize, 16));
111 | setTextMaxLines(a.getInteger(R.attr.secondaryTextMaxLines, 1));
112 | a.recycle();
113 | } catch (Exception ignored) {
114 | }
115 |
116 | init();
117 |
118 | }
119 |
120 | @Override
121 | public boolean onTouchEvent(MotionEvent event) {
122 | switch (event.getAction()) {
123 | case MotionEvent.ACTION_DOWN:
124 | clickedX = (int) event.getX();
125 | clickedY = (int) event.getY();
126 | rippleR = (int) (Math.sqrt(Math.pow(Math.max(width - clickedX, clickedX), 2) + Math.pow(Math.max(height - clickedY, clickedY), 2)) * 1.15);
127 |
128 | animator.start();
129 |
130 | touchDown = true;
131 | animateRipple = true;
132 | break;
133 | case MotionEvent.ACTION_UP:
134 | case MotionEvent.ACTION_CANCEL:
135 | touchDown = false;
136 |
137 | if (!animator.isRunning()) {
138 | ripple_animated_value = 0;
139 | invalidatePoster();
140 | }
141 | break;
142 | }
143 | return true;
144 | }
145 |
146 |
147 | public void setText(String text) {
148 | textView.setText(text);
149 | invalidatePoster();
150 | }
151 |
152 | public int dpToPixels(int dp) {
153 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
154 | }
155 |
156 | private void init() {
157 | setWillNotDraw(false);
158 | final int padding = dpToPixels(16);
159 | final int imageWidth = dpToPixels(72);
160 |
161 | textView = new TextView(getContext());
162 | textView.setTextColor(getResources().getColor(R.color.dark_grey));
163 | textView.setTextSize(18);
164 | textView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
165 | textView.setMaxLines(1);
166 | textView.setEllipsize(TextUtils.TruncateAt.END);
167 | textView.setPadding(padding, padding, padding, padding);
168 |
169 | avatar = new ImageView(getContext());
170 | avatar.setLayoutParams(new LayoutParams(imageWidth, imageWidth));
171 | avatar.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
172 | avatar.setPadding(padding, padding, padding, padding);
173 |
174 | final int iconPadding = dpToPixels(4);
175 | final int iconWidth = dpToPixels(48);
176 | icon = new ImageView(getContext());
177 | icon.setLayoutParams(new LayoutParams(iconWidth, iconWidth));
178 | icon.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
179 | icon.setPadding(iconPadding, iconPadding, iconPadding, iconPadding);
180 |
181 |
182 | animator.setInterpolator(interpolator);
183 | animator.addUpdateListener(animatorUpdateListener);
184 | animator.addListener(animatorListener);
185 | animator.setDuration(duration);
186 | paint.setColor(0x25000000);
187 |
188 |
189 | addView(textView);
190 | addView(avatar);
191 | addView(icon);
192 | }
193 |
194 | public void setLeftIcon(Drawable leftIcon) {
195 | if (avatar != null)
196 | avatar.setImageBitmap(getCircleBitmap(leftIcon, dpToPixels(40)));
197 | }
198 |
199 | public void setLeftIcon(Bitmap leftIcon) {
200 | if (avatar != null)
201 | avatar.setImageBitmap(getCircleBitmap(leftIcon, dpToPixels(40)));
202 | }
203 |
204 | public void setRightIcon(Drawable rightIcon) {
205 | if (icon != null)
206 | icon.setImageDrawable(rightIcon);
207 | }
208 |
209 | public void setRightIcon(Bitmap icon) {
210 | if (this.icon != null)
211 | this.icon.setImageBitmap(icon);
212 | }
213 |
214 | public void setTextColor(int color) {
215 | textView.setTextColor(color);
216 | }
217 |
218 | public void setTextMaxLines(int maxLines) {
219 | textView.setMaxLines(maxLines);
220 | }
221 |
222 | public void setTextSize(int sp) {
223 | textView.setTextSize(sp);
224 | }
225 |
226 | private void scale(final float scale) {
227 | post(new Runnable() {
228 | @Override
229 | public void run() {
230 | MaterialSingleLineTextAvatarWithIcon.this.setScaleX(scale);
231 | MaterialSingleLineTextAvatarWithIcon.this.setScaleY(scale);
232 | invalidatePoster();
233 | }
234 | });
235 |
236 | }
237 |
238 | private void scaleLater() {
239 | final Timer timer = new Timer();
240 | timer.schedule(new TimerTask() {
241 | @Override
242 | public void run() {
243 | if (touchDown)
244 | scale(scaleTo);
245 | else
246 | scale(1);
247 | }
248 | }, 175);
249 | }
250 |
251 | @Override
252 | public boolean onInterceptTouchEvent(MotionEvent event) {
253 |
254 | return false;
255 |
256 | }
257 |
258 | public void setDuration(int duration) {
259 | MaterialSingleLineTextAvatarWithIcon.duration = duration;
260 | animator.setDuration(duration);
261 | }
262 |
263 | public void setScaleTo(float scaleTo) {
264 | this.scaleTo = scaleTo;
265 | }
266 |
267 | private void invalidatePoster() {
268 | this.post(new Runnable() {
269 | @Override
270 | public void run() {
271 | invalidate();
272 | }
273 | });
274 | }
275 |
276 | public void setRippleColor(int color) {
277 | rippleColor = color;
278 | }
279 |
280 | @Override
281 | protected void dispatchDraw(Canvas canvas) {
282 | super.dispatchDraw(canvas);
283 | if (animateRipple) {
284 | paint.setColor(rippleColor);
285 | canvas.drawCircle(clickedX, clickedY, rippleR * ripple_animated_value, paint);
286 | }
287 | }
288 |
289 | @Override
290 | public void addView(View child, int index, LayoutParams params) {
291 | if (getChildCount() >= 4)
292 | return;
293 | super.addView(child, index, params);
294 | }
295 |
296 |
297 | @Override
298 | protected void onSizeChanged(final int w, final int h, int oldw, int oldh) {
299 | super.onSizeChanged(w, h, oldw, oldh);
300 | width = w;
301 | height = h;
302 | }
303 |
304 | @Override
305 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
306 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
307 | int measuredHeight = 0;
308 | int measuredWidth = 0;
309 |
310 | for (int i = 0; i < getChildCount(); i++) {
311 |
312 | final View child = getChildAt(i);
313 | measureChild(child, widthMeasureSpec, heightMeasureSpec);
314 | measuredHeight += child.getMeasuredHeight();
315 | measuredWidth = Math.max(child.getMeasuredWidth(), measuredWidth);
316 | }
317 |
318 | setMeasuredDimension(resolveSizeAndState(measuredWidth, widthMeasureSpec, 0),
319 | resolveSizeAndState(measuredHeight, heightMeasureSpec, 0));
320 |
321 |
322 | }
323 |
324 | @Override
325 | protected void onLayout(boolean b, int i, int i2, int i3, int i4) {
326 | final int avatarPaddingTop = (getMeasuredHeight() - avatar.getMeasuredHeight()) / 2;
327 | avatar.layout(avatarPaddingTop,
328 | getPaddingTop(),
329 | getPaddingLeft() + avatar.getMeasuredWidth(),
330 | getMeasuredHeight() - avatarPaddingTop
331 | );
332 |
333 | final int textViewPaddingTop = (getMeasuredHeight() - textView.getMeasuredHeight()) / 2;
334 | textView.layout(getPaddingLeft() + avatar.getMeasuredWidth(),
335 | textViewPaddingTop,
336 | getMeasuredWidth() - getPaddingRight() - icon.getMeasuredWidth(),
337 | getMeasuredHeight() - textViewPaddingTop
338 | );
339 |
340 | checkViewParams(textView);
341 |
342 | icon.layout(getMeasuredWidth() - icon.getMeasuredWidth() - getPaddingRight(),
343 | getPaddingTop(),
344 | getMeasuredWidth() - getPaddingRight(),
345 | getMeasuredHeight() - getPaddingBottom());
346 |
347 |
348 | }
349 |
350 | private void checkViewParams(final View view, final int layoutWidth, final int layoutHeight) {
351 | final int width = view.getMeasuredWidth();
352 | final int height = view.getMeasuredHeight();
353 | if ((width > layoutWidth) || (height > layoutHeight)) {
354 | view.setLayoutParams(new LayoutParams(layoutWidth, layoutHeight));
355 | measureChild(view, MeasureSpec.AT_MOST, MeasureSpec.AT_MOST);
356 | view.requestLayout();
357 | view.invalidate();
358 | requestLayout();
359 |
360 | }
361 | }
362 |
363 | private void checkViewParams(final View view) {
364 | final int layoutWidth = view.getRight() - view.getLeft();
365 | final int layoutHeight = view.getBottom() - view.getTop();
366 |
367 | checkViewParams(view, layoutWidth, layoutHeight);
368 |
369 | }
370 |
371 | public Bitmap drawableToBitmap(Drawable drawable) {
372 | if (drawable == null) // Don't do anything without a proper drawable
373 | return null;
374 | else if (drawable instanceof BitmapDrawable) // Use the getBitmap() method instead if BitmapDrawable
375 | return ((BitmapDrawable) drawable).getBitmap();
376 | // Create Bitmap object out of the drawable
377 | Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
378 | Canvas canvas = new Canvas(bitmap);
379 | drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
380 | drawable.draw(canvas);
381 | return bitmap;
382 | }
383 |
384 | public Bitmap getCircleBitmap(final Drawable drawable, final int width) {
385 | BitmapFactory.Options options = new BitmapFactory.Options();
386 | options.inMutable = true;
387 | options.inPreferredConfig = Bitmap.Config.ARGB_8888;
388 | Bitmap bitmap = drawableToBitmap(drawable);
389 |
390 | return getCircleBitmap(bitmap, width);
391 | }
392 |
393 | public Bitmap getCircleBitmap(Bitmap bitmap, final int width) {
394 | bitmap.setHasAlpha(true);
395 | bitmap = Bitmap.createScaledBitmap(bitmap, width, width, true);
396 | Bitmap output = Bitmap.createBitmap(width,
397 | width, Bitmap.Config.ARGB_8888);
398 | final Rect rect = new Rect(0, 0, width,
399 | width);
400 | Canvas canvas = new Canvas(output);
401 | Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
402 | paint.setColor(0xff000000);
403 | canvas.drawCircle(width / 2, width / 2, width / 2, paint);
404 | paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
405 | canvas.drawBitmap(bitmap, rect, rect, paint);
406 | bitmap.recycle();
407 | return output;
408 | }
409 | }
410 |
--------------------------------------------------------------------------------
/app/src/main/java/com/micnubinub/materiallibrary/MaterialSingleLineTextIcon.java:
--------------------------------------------------------------------------------
1 | package com.micnubinub.materiallibrary;
2 |
3 | import android.animation.Animator;
4 | import android.animation.ValueAnimator;
5 | import android.content.Context;
6 | import android.content.res.TypedArray;
7 | import android.graphics.Bitmap;
8 | import android.graphics.Canvas;
9 | import android.graphics.Paint;
10 | import android.graphics.drawable.Drawable;
11 | import android.text.TextUtils;
12 | import android.util.AttributeSet;
13 | import android.util.TypedValue;
14 | import android.view.MotionEvent;
15 | import android.view.View;
16 | import android.view.ViewGroup;
17 | import android.view.animation.AccelerateInterpolator;
18 | import android.widget.ImageView;
19 | import android.widget.TextView;
20 |
21 | import java.util.Timer;
22 | import java.util.TimerTask;
23 |
24 | /**
25 | * Created by root on 20/10/14.
26 | */
27 | public class MaterialSingleLineTextIcon extends ViewGroup {
28 | private static final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
29 | private static final AccelerateInterpolator interpolator = new AccelerateInterpolator();
30 | private static int duration = 600;
31 | private final ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
32 | private TextView textView;
33 | private ImageView imageView;
34 | private int width;
35 | private int height;
36 | private float animated_value = 0;
37 | private float scaleTo = 1.065f;
38 | private int clickedX, clickedY;
39 | private boolean touchDown = false, animateRipple;
40 | private float ripple_animated_value = 0;
41 | private final ValueAnimator.AnimatorUpdateListener animatorUpdateListener = new ValueAnimator.AnimatorUpdateListener() {
42 | @Override
43 | public void onAnimationUpdate(ValueAnimator animation) {
44 | animated_value = (Float) (animation.getAnimatedValue());
45 | ripple_animated_value = animated_value;
46 | invalidatePoster();
47 | }
48 | };
49 | private final ValueAnimator.AnimatorListener animatorListener = new Animator.AnimatorListener() {
50 | @Override
51 | public void onAnimationStart(Animator animator) {
52 |
53 | }
54 |
55 | @Override
56 | public void onAnimationEnd(Animator animator) {
57 | if (!touchDown)
58 | ripple_animated_value = 0;
59 |
60 | animateRipple = false;
61 | invalidatePoster();
62 | }
63 |
64 | @Override
65 | public void onAnimationCancel(Animator animator) {
66 |
67 |
68 | }
69 |
70 | @Override
71 | public void onAnimationRepeat(Animator animator) {
72 |
73 | }
74 | };
75 | private int rippleR;
76 | private int rippleColor = 0x25000000;
77 |
78 | public MaterialSingleLineTextIcon(Context context) {
79 | super(context);
80 | init();
81 | }
82 |
83 | public MaterialSingleLineTextIcon(Context context, AttributeSet attrs) {
84 | super(context, attrs);
85 | try {
86 | final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MaterialTwoLineText, 0, 0);
87 | setPrimaryTextColor(a.getInteger(R.attr.primaryTextColor, getResources().getColor(R.color.dark_dark_grey)));
88 | setPrimaryTextSize(a.getInteger(R.attr.primaryTextSize, 18));
89 | a.recycle();
90 | } catch (Exception ignored) {
91 | }
92 |
93 |
94 | init();
95 |
96 | }
97 |
98 |
99 | public MaterialSingleLineTextIcon(Context context, AttributeSet attrs, int defStyle) {
100 | super(context, attrs, defStyle);
101 | try {
102 | final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MaterialTwoLineText, 0, 0);
103 | setPrimaryTextColor(a.getInteger(R.attr.primaryTextColor, getResources().getColor(R.color.dark_dark_grey)));
104 | setPrimaryTextSize(a.getInteger(R.attr.primaryTextSize, 18));
105 | a.recycle();
106 | } catch (Exception ignored) {
107 | }
108 |
109 | init();
110 |
111 | }
112 |
113 | @Override
114 | public boolean onTouchEvent(MotionEvent event) {
115 | switch (event.getAction()) {
116 | case MotionEvent.ACTION_DOWN:
117 | clickedX = (int) event.getX();
118 | clickedY = (int) event.getY();
119 | rippleR = (int) (Math.sqrt(Math.pow(Math.max(width - clickedX, clickedX), 2) + Math.pow(Math.max(height - clickedY, clickedY), 2)) * 1.15);
120 |
121 | animator.start();
122 |
123 | touchDown = true;
124 | animateRipple = true;
125 | break;
126 | case MotionEvent.ACTION_UP:
127 | case MotionEvent.ACTION_CANCEL:
128 | touchDown = false;
129 |
130 | if (!animator.isRunning()) {
131 | ripple_animated_value = 0;
132 | invalidatePoster();
133 | }
134 | break;
135 | }
136 | return true;
137 | }
138 |
139 |
140 | public void setText(String text) {
141 | textView.setText(text);
142 | invalidatePoster();
143 | }
144 |
145 | public int dpToPixels(int dp) {
146 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
147 | }
148 |
149 | private void init() {
150 | //Todo consider 16 and 14 (in the guidelines)
151 | final int padding = dpToPixels(16);
152 | final int imageWidth = dpToPixels(72);
153 |
154 | textView = new TextView(getContext());
155 | textView.setTextColor(getResources().getColor(R.color.dark_dark_grey));
156 | textView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
157 | textView.setTextSize(18);
158 | textView.setMaxLines(1);
159 | textView.setEllipsize(TextUtils.TruncateAt.END);
160 | textView.setPadding(padding, padding, padding, padding);
161 |
162 | imageView = new ImageView(getContext());
163 | imageView.setLayoutParams(new LayoutParams(imageWidth, imageWidth));
164 | imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
165 | imageView.setPadding(padding, padding, padding, padding);
166 |
167 | setWillNotDraw(false);
168 | animator.setInterpolator(interpolator);
169 | animator.addUpdateListener(animatorUpdateListener);
170 | animator.addListener(animatorListener);
171 | animator.setDuration(duration);
172 | paint.setColor(0x25000000);
173 |
174 |
175 | addView(textView);
176 | addView(imageView);
177 | }
178 |
179 | public void setIcon(Drawable icon) {
180 | if (imageView != null)
181 | imageView.setImageDrawable(icon);
182 | }
183 |
184 | public void setIcon(Bitmap icon) {
185 | if (imageView != null)
186 | imageView.setImageBitmap(icon);
187 | }
188 |
189 | public void setPrimaryTextSize(int sp) {
190 | textView.setTextSize(sp);
191 | }
192 |
193 | public void setPrimaryTextColor(int color) {
194 | textView.setTextColor(color);
195 | }
196 |
197 | private void scale(final float scale) {
198 | post(new Runnable() {
199 | @Override
200 | public void run() {
201 | MaterialSingleLineTextIcon.this.setScaleX(scale);
202 | MaterialSingleLineTextIcon.this.setScaleY(scale);
203 | invalidatePoster();
204 | }
205 | });
206 |
207 | }
208 |
209 | private void scaleLater() {
210 | final Timer timer = new Timer();
211 | timer.schedule(new TimerTask() {
212 | @Override
213 | public void run() {
214 | if (touchDown)
215 | scale(scaleTo);
216 | else
217 | scale(1);
218 | }
219 | }, 175);
220 | }
221 |
222 | @Override
223 | public boolean onInterceptTouchEvent(MotionEvent event) {
224 |
225 | return false;
226 |
227 | }
228 |
229 | public void setDuration(int duration) {
230 | MaterialSingleLineTextIcon.duration = duration;
231 | animator.setDuration(duration);
232 | }
233 |
234 | public void setScaleTo(float scaleTo) {
235 | this.scaleTo = scaleTo;
236 | }
237 |
238 | private void invalidatePoster() {
239 | this.post(new Runnable() {
240 | @Override
241 | public void run() {
242 | invalidate();
243 | }
244 | });
245 | }
246 |
247 | public void setRippleColor(int color) {
248 | rippleColor = color;
249 | }
250 |
251 | @Override
252 | protected void dispatchDraw(Canvas canvas) {
253 | super.dispatchDraw(canvas);
254 | if (animateRipple) {
255 | paint.setColor(rippleColor);
256 | canvas.drawCircle(clickedX, clickedY, rippleR * ripple_animated_value, paint);
257 | }
258 | }
259 |
260 |
261 | @Override
262 | public void addView(View child, int index, LayoutParams params) {
263 | if (getChildCount() >= 3)
264 | return;
265 | super.addView(child, index, params);
266 | }
267 |
268 |
269 | @Override
270 | protected void onSizeChanged(final int w, final int h, int oldw, int oldh) {
271 | super.onSizeChanged(w, h, oldw, oldh);
272 | width = w;
273 | height = h;
274 | }
275 |
276 | @Override
277 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
278 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
279 | int measuredHeight = 0;
280 | int measuredWidth = 0;
281 |
282 | for (int i = 0; i < getChildCount(); i++) {
283 |
284 | final View child = getChildAt(i);
285 | measureChild(child, widthMeasureSpec, heightMeasureSpec);
286 | measuredHeight += child.getMeasuredHeight();
287 | measuredWidth = Math.max(child.getMeasuredWidth(), measuredWidth);
288 | }
289 |
290 | setMeasuredDimension(resolveSizeAndState(measuredWidth, widthMeasureSpec, 0),
291 | resolveSizeAndState(measuredHeight, heightMeasureSpec, 0));
292 |
293 |
294 | }
295 |
296 | @Override
297 | protected void onLayout(boolean b, int i, int i2, int i3, int i4) {
298 | final int imageViewPadding = (getMeasuredHeight() - imageView.getMeasuredHeight()) / 2;
299 | imageView.layout(imageViewPadding,
300 | getPaddingTop(),
301 | getPaddingLeft() + imageView.getMeasuredWidth(),
302 | getMeasuredHeight() - imageViewPadding
303 | );
304 |
305 | final int textViewPadding = (getMeasuredHeight() - textView.getMeasuredHeight()) / 2;
306 | textView.layout(getPaddingLeft() + imageView.getMeasuredWidth(), textViewPadding,
307 | getMeasuredWidth() - getPaddingRight(),
308 | getMeasuredHeight() - textViewPadding);
309 |
310 | checkViewParams(textView);
311 | }
312 |
313 | private void checkViewParams(final View view, final int layoutWidth, final int layoutHeight) {
314 | final int width = view.getMeasuredWidth();
315 | final int height = view.getMeasuredHeight();
316 | if ((width > layoutWidth) || (height > layoutHeight)) {
317 | view.setLayoutParams(new LayoutParams(layoutWidth, layoutHeight));
318 | measureChild(view, MeasureSpec.AT_MOST, MeasureSpec.AT_MOST);
319 | view.requestLayout();
320 | view.invalidate();
321 | requestLayout();
322 |
323 | }
324 | }
325 |
326 | private void checkViewParams(final View view) {
327 | final int layoutWidth = view.getRight() - view.getLeft();
328 | final int layoutHeight = view.getBottom() - view.getTop();
329 |
330 | checkViewParams(view, layoutWidth, layoutHeight);
331 |
332 | }
333 | /*
334 | public Bitmap drawableToBitmap(Drawable drawable) {
335 | if (drawable == null) // Don't do anything without a proper drawable
336 | return null;
337 | else if (drawable instanceof BitmapDrawable) // Use the getBitmap() method instead if BitmapDrawable
338 | return ((BitmapDrawable) drawable).getBitmap();
339 | // Create Bitmap object out of the drawable
340 | Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
341 | Canvas canvas = new Canvas(bitmap);
342 | drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
343 | drawable.draw(canvas);
344 | // Return the created Bitmap
345 | return bitmap;
346 | }
347 |
348 |
349 | public static Bitmap getCircleBitmap(Resources res, int sourceResId, int width) {
350 | BitmapFactory.Options options = new BitmapFactory.Options();
351 | options.inMutable = true;
352 | options.inPreferredConfig = Bitmap.Config.ARGB_8888;
353 | Bitmap bitmap = BitmapFactory.decodeResource(res, sourceResId, options);
354 | bitmap.setHasAlpha(true);
355 | bitmap = Bitmap.createScaledBitmap(bitmap, width, width, true);
356 | Bitmap output = Bitmap.createBitmap(width,
357 | width, Bitmap.Config.ARGB_8888);
358 | final Rect rect = new Rect(0, 0, width,
359 | width);
360 | Canvas canvas = new Canvas(output);
361 | Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
362 | paint.setColor(0xff000000);
363 | canvas.drawCircle(width / 2, width / 2, width / 2, paint);
364 | paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
365 | canvas.drawBitmap(bitmap, rect, rect, paint);
366 | bitmap.recycle();
367 | return output;
368 | }
369 | */
370 | }
371 |
--------------------------------------------------------------------------------
/app/src/main/java/com/micnubinub/materiallibrary/MaterialSwitch.java:
--------------------------------------------------------------------------------
1 | package com.micnubinub.materiallibrary;
2 |
3 | import android.animation.Animator;
4 | import android.animation.ValueAnimator;
5 | import android.content.Context;
6 | import android.content.res.TypedArray;
7 | import android.graphics.Canvas;
8 | import android.graphics.Paint;
9 | import android.util.AttributeSet;
10 | import android.util.TypedValue;
11 | import android.view.MotionEvent;
12 | import android.view.View;
13 | import android.view.ViewGroup;
14 | import android.view.animation.DecelerateInterpolator;
15 | import android.widget.TextView;
16 |
17 |
18 | /**
19 | * Created by root on 30/09/14.
20 | */
21 | @SuppressWarnings("ALL")
22 | public class MaterialSwitch extends ViewGroup {
23 |
24 | private static final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
25 | private static int PADDING = 2;
26 | private static int duration = 600;
27 | private final DecelerateInterpolator interpolator = new DecelerateInterpolator();
28 | private final ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
29 | private int height;
30 | private int rippleR;
31 | private float ripple_animated_value = 0;
32 | private int clickedX, clickedY;
33 | private boolean touchDown = false, animateRipple;
34 | private ValueAnimator.AnimatorListener animatorListener = new Animator.AnimatorListener() {
35 | @Override
36 | public void onAnimationStart(Animator animator) {
37 |
38 | }
39 |
40 | @Override
41 | public void onAnimationEnd(Animator animator) {
42 | if (!touchDown)
43 | ripple_animated_value = 0;
44 |
45 | animateRipple = false;
46 | invalidatePoster();
47 | }
48 |
49 | @Override
50 | public void onAnimationCancel(Animator animator) {
51 |
52 |
53 | }
54 |
55 | @Override
56 | public void onAnimationRepeat(Animator animator) {
57 |
58 | }
59 | };
60 | private int textSize;
61 | private String text = "";
62 | private Switch materialSwitch;
63 |
64 | private float line_pos;
65 | private int r, color_on, color_off, hole_r, color_hole;
66 | private boolean updating = false;
67 | private boolean checked = false;
68 | private float animated_value = 0;
69 | private final ValueAnimator.AnimatorUpdateListener updateListener = new ValueAnimator.AnimatorUpdateListener() {
70 | @Override
71 | public void onAnimationUpdate(ValueAnimator animation) {
72 | animated_value = (Float) (animation.getAnimatedValue());
73 | ripple_animated_value = animated_value;
74 | invalidatePoster();
75 | }
76 | };
77 | private OnCheckedChangedListener listener;
78 | private TextView textView;
79 | private int width;
80 | private int rippleColor = 0x25000000;
81 |
82 | public MaterialSwitch(Context context) {
83 | super(context);
84 | init();
85 | }
86 |
87 | public MaterialSwitch(Context context, AttributeSet attrs) {
88 | super(context, attrs);
89 | TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MaterialRadioButton, 0, 0);
90 | setChecked(a.getBoolean(R.styleable.MaterialRadioButton_checked, false));
91 | text = a.getString(R.styleable.MaterialRadioButton_text);
92 | textSize = a.getInt(R.styleable.MaterialRadioButton_textSize, 20);
93 | a.recycle();
94 | textSize = textSize < 20 ? 20 : textSize;
95 | init();
96 | }
97 |
98 | public MaterialSwitch(Context context, AttributeSet attrs, int defStyle) {
99 | super(context, attrs, defStyle);
100 | TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MaterialRadioButton, 0, 0);
101 | setChecked(a.getBoolean(R.styleable.MaterialRadioButton_checked, false));
102 | text = a.getString(R.styleable.MaterialRadioButton_text);
103 | textSize = a.getInt(R.styleable.MaterialRadioButton_textSize, 20);
104 | a.recycle();
105 | textSize = textSize < 20 ? 20 : textSize;
106 | init();
107 | }
108 |
109 | private int dpToPixels(int dp) {
110 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
111 | }
112 |
113 | @Override
114 | protected void onLayout(boolean b, int i, int i2, int i3, int i4) {
115 | final int textViewPaddingTop = ((getMeasuredHeight() - textView.getMeasuredHeight()) / 2);
116 | textView.layout(
117 | getPaddingLeft(),
118 | textViewPaddingTop,
119 | getMeasuredWidth() - getPaddingRight() - materialSwitch.getMeasuredWidth() - PADDING,
120 | getMeasuredHeight() - textViewPaddingTop);
121 |
122 | checkViewParams(textView);
123 |
124 | final int radioButtonPaddingTop = ((getMeasuredHeight() - materialSwitch.getMeasuredHeight()) / 2);
125 | materialSwitch.layout(
126 | getMeasuredWidth() - getPaddingRight() - materialSwitch.getMeasuredWidth(),
127 | radioButtonPaddingTop,
128 | getMeasuredWidth() - getPaddingRight(),
129 | getMeasuredHeight() - radioButtonPaddingTop
130 | );
131 |
132 |
133 | }
134 |
135 | @Override
136 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
137 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
138 |
139 | //Todo setMeasuredDimension();
140 | //Todo measureChildWithMargins()
141 | //Todo xmlns:custom="http://schemas.android.com/apk/res/com.packa..."
142 | // measureChildren(widthMeasureSpec, heightMeasureSpec);
143 |
144 | int measuredHeight = 0;
145 | int measuredWidth = 0;
146 |
147 | try {
148 | for (int i = 0; i < getChildCount(); i++) {
149 | final View child = getChildAt(i);
150 | measureChild(child, widthMeasureSpec, heightMeasureSpec);
151 |
152 | measuredHeight = Math.max(measuredHeight, child.getMeasuredHeight());
153 | measuredWidth += child.getMeasuredWidth();
154 | }
155 | } catch (Exception ignored) {
156 | }
157 |
158 | setMeasuredDimension(resolveSizeAndState(measuredWidth, widthMeasureSpec, 0),
159 | resolveSizeAndState(measuredHeight, heightMeasureSpec, 0));
160 |
161 | }
162 |
163 | private void checkViewParams(final View view, final int layoutWidth, final int layoutHeight) {
164 | final int width = view.getMeasuredWidth();
165 | final int height = view.getMeasuredHeight();
166 | if ((width > layoutWidth) || (height > layoutHeight)) {
167 | view.setLayoutParams(new LayoutParams(layoutWidth, layoutHeight));
168 | measureChild(view, MeasureSpec.AT_MOST, MeasureSpec.AT_MOST);
169 | view.requestLayout();
170 | view.invalidate();
171 | requestLayout();
172 |
173 | }
174 | }
175 |
176 | private void checkViewParams(final View view) {
177 | final int layoutWidth = view.getRight() - view.getLeft();
178 | final int layoutHeight = view.getBottom() - view.getTop();
179 |
180 | checkViewParams(view, layoutWidth, layoutHeight);
181 |
182 | }
183 |
184 | public boolean isChecked() {
185 | return checked;
186 | }
187 |
188 | public void setChecked(boolean checked) {
189 | this.checked = checked;
190 | animateSwitch();
191 | notifyListener();
192 | }
193 |
194 | public void toggle() {
195 | setChecked(!isChecked());
196 | }
197 |
198 | private void notifyListener() {
199 | if (listener != null)
200 | listener.onCheckedChange(this, isChecked());
201 | }
202 |
203 | private void setPaintColor(int color) {
204 | try {
205 | paint.setColor(color);
206 | } catch (Exception ignored) {
207 | }
208 | }
209 |
210 | public void setOffColor(int color_off) {
211 | this.color_off = color_off;
212 | }
213 |
214 | public void setOnColor(int color_on) {
215 | this.color_on = color_on;
216 | }
217 |
218 | public void setHoleColor(int hole_color) {
219 | this.color_hole = hole_color;
220 | }
221 |
222 | public void setUpdating(boolean updating) {
223 | this.updating = updating;
224 | }
225 |
226 | public void setAnimationDuration(int duration) {
227 | MaterialSwitch.duration = duration;
228 | animator.setDuration(duration);
229 | }
230 |
231 | public void setText(String text) {
232 | if (textView != null)
233 | textView.setText(text);
234 | invalidate();
235 | }
236 |
237 | private void init() {
238 | setWillNotDraw(false);
239 |
240 | setOffColor(getResources().getColor(R.color.lite_grey));
241 | setOnColor(getResources().getColor(R.color.material_green_light));
242 | setHoleColor(getResources().getColor(R.color.white));
243 | paint.setStyle(Paint.Style.FILL);
244 | paint.setStrokeCap(Paint.Cap.ROUND);
245 | paint.setColor(color_off);
246 |
247 | PADDING = dpToPixels(4);
248 |
249 | materialSwitch = new Switch(getContext());
250 |
251 | materialSwitch.setLayoutParams(new LayoutParams(dpToPixels(35), dpToPixels(20)));
252 | setPadding(PADDING, PADDING, PADDING, PADDING);
253 |
254 | textView = new TextView(getContext());
255 | PADDING = dpToPixels(5);
256 | textView.setPadding(PADDING, PADDING, PADDING, PADDING);
257 | textView.setTextColor(getResources().getColor(R.color.dark_grey_text));
258 | textView.setTextSize(18);
259 | textView.setMaxLines(2);
260 | textView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
261 |
262 |
263 | setText(text);
264 | addView(textView);
265 | addView(materialSwitch);
266 | materialSwitch.invalidate();
267 |
268 | setText(text);
269 |
270 | animator.setInterpolator(interpolator);
271 | animator.setDuration(duration);
272 | animator.addListener(animatorListener);
273 | animator.addUpdateListener(updateListener);
274 | }
275 |
276 | private void animateSwitch() {
277 | if (animator.isRunning() || animator.isStarted())
278 | animator.cancel();
279 | animator.start();
280 | }
281 |
282 | public void setOnCheckedChangeListener(OnCheckedChangedListener listener) {
283 | this.listener = listener;
284 | }
285 |
286 | @Override
287 | public boolean onInterceptTouchEvent(MotionEvent event) {
288 | return false;
289 | }
290 |
291 | @Override
292 | public boolean onTouchEvent(MotionEvent event) {
293 | switch (event.getAction()) {
294 | case MotionEvent.ACTION_DOWN:
295 | clickedX = (int) event.getX();
296 | clickedY = (int) event.getY();
297 | rippleR = (int) (Math.sqrt(Math.pow(Math.max(width - clickedX, clickedX), 2) + Math.pow(Math.max(height - clickedY, clickedY), 2)) * 1.15);
298 |
299 | toggle();
300 |
301 | touchDown = true;
302 | animateRipple = true;
303 | break;
304 | case MotionEvent.ACTION_UP:
305 | case MotionEvent.ACTION_CANCEL:
306 | touchDown = false;
307 |
308 | if (!animator.isRunning()) {
309 | ripple_animated_value = 0;
310 | invalidatePoster();
311 | }
312 | break;
313 | }
314 | return true;
315 | }
316 |
317 | public void setRippleColor(int color) {
318 | rippleColor = color;
319 | }
320 |
321 | public void setDuration(int duration) {
322 | MaterialSwitch.duration = duration;
323 | animator.setDuration(duration);
324 | }
325 |
326 | private void invalidatePoster() {
327 | final Runnable runnable = new Runnable() {
328 | @Override
329 | public void run() {
330 | invalidate();
331 | }
332 | };
333 | this.post(runnable);
334 | if (materialSwitch != null) {
335 | materialSwitch.invalidate();
336 | }
337 | }
338 |
339 | @Override
340 | protected void dispatchDraw(Canvas canvas) {
341 | super.dispatchDraw(canvas);
342 | if (animateRipple) {
343 | paint.setColor(rippleColor);
344 | canvas.drawCircle(clickedX, clickedY, rippleR * ripple_animated_value, paint);
345 | }
346 | }
347 |
348 | @Override
349 | protected void onSizeChanged(final int w, final int h, int oldw, int oldh) {
350 | super.onSizeChanged(w, h, oldw, oldh);
351 | height = h;
352 | width = w;
353 | }
354 |
355 | public interface OnCheckedChangedListener {
356 | public void onCheckedChange(MaterialSwitch materialSwitch, boolean isChecked);
357 | }
358 |
359 | private class Switch extends View {
360 | private int switchWidth;
361 |
362 | public Switch(Context context) {
363 | super(context);
364 | invalidate();
365 | }
366 |
367 | @Override
368 | protected void onDraw(Canvas canvas) {
369 | super.onDraw(canvas);
370 |
371 | if (isChecked())
372 | animateOn(canvas);
373 | else
374 | animateOff(canvas);
375 |
376 | if (updating)
377 | invalidate();
378 |
379 | }
380 |
381 |
382 | private void animateOn(Canvas canvas) {
383 |
384 | setPaintColor(color_on);
385 | canvas.drawLine(getPaddingLeft(), line_pos, (float) (switchWidth - getPaddingRight()), line_pos, paint);
386 | canvas.drawCircle((r + (animated_value * (switchWidth - r - r))), line_pos, r, paint);
387 |
388 | setPaintColor(color_hole);
389 | if (updating)
390 | canvas.drawCircle((r + (animated_value * (switchWidth - r - r))), line_pos, hole_r * (1 - animated_value), paint);
391 |
392 |
393 | }
394 |
395 | private void animateOff(Canvas canvas) {
396 | setPaintColor(color_off);
397 | canvas.drawLine(getPaddingLeft(), line_pos, (float) (switchWidth - getPaddingRight()), line_pos, paint);
398 | canvas.drawCircle((r + ((1 - animated_value) * (switchWidth - r - r))), line_pos, r, paint);
399 |
400 | setPaintColor(color_hole);
401 |
402 | if (updating)
403 | canvas.drawCircle((r + ((1 - animated_value) * (switchWidth - r - r))), line_pos, hole_r * animated_value, paint);
404 | else
405 | canvas.drawCircle((r + ((1 - animated_value) * (switchWidth - r - r))), line_pos, hole_r, paint);
406 | }
407 |
408 | @Override
409 | protected void onSizeChanged(int w, int h, int oldw, int oldh) {
410 | super.onSizeChanged(w, h, oldw, oldh);
411 | paint.setStrokeWidth(0.15f * Math.min(w, h));
412 | line_pos = h / 2;
413 | r = Math.min((w - getPaddingLeft() - getPaddingRight()), (h - getPaddingBottom() - getPaddingTop())) / 2;
414 | hole_r = (int) (r * 0.85f);
415 | switchWidth = w;
416 | }
417 |
418 | @Override
419 | protected void onAttachedToWindow() {
420 | super.onAttachedToWindow();
421 | if (isChecked())
422 | animated_value = 1;
423 | }
424 |
425 | }
426 |
427 |
428 | }
429 |
--------------------------------------------------------------------------------
/app/src/main/java/com/micnubinub/materiallibrary/MaterialThreeLineText.java:
--------------------------------------------------------------------------------
1 | package com.micnubinub.materiallibrary;
2 |
3 | import android.animation.Animator;
4 | import android.animation.ValueAnimator;
5 | import android.content.Context;
6 | import android.content.res.TypedArray;
7 | import android.graphics.Canvas;
8 | import android.graphics.Paint;
9 | import android.graphics.Typeface;
10 | import android.text.TextUtils;
11 | import android.util.AttributeSet;
12 | import android.util.TypedValue;
13 | import android.view.MotionEvent;
14 | import android.view.View;
15 | import android.view.ViewGroup;
16 | import android.view.animation.AccelerateInterpolator;
17 | import android.widget.TextView;
18 |
19 | import java.util.Timer;
20 | import java.util.TimerTask;
21 |
22 | /**
23 | * Created by root on 20/10/14.
24 | */
25 | public class MaterialThreeLineText extends ViewGroup {
26 | private static final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
27 | private static final AccelerateInterpolator interpolator = new AccelerateInterpolator();
28 | private static int duration = 600;
29 | private final ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
30 | private TextView primaryTextView, secondaryTextView;
31 | private String primaryText, secondaryText;
32 | private int width;
33 | private int height;
34 | private float animated_value = 0;
35 | private float scaleTo = 1.065f;
36 | private int clickedX, clickedY;
37 | private boolean touchDown = false, animateRipple;
38 | private float ripple_animated_value = 0;
39 | private final ValueAnimator.AnimatorUpdateListener animatorUpdateListener = new ValueAnimator.AnimatorUpdateListener() {
40 | @Override
41 | public void onAnimationUpdate(ValueAnimator animation) {
42 | animated_value = (Float) (animation.getAnimatedValue());
43 | ripple_animated_value = animated_value;
44 | invalidatePoster();
45 | }
46 | };
47 | private final ValueAnimator.AnimatorListener animatorListener = new Animator.AnimatorListener() {
48 | @Override
49 | public void onAnimationStart(Animator animator) {
50 |
51 | }
52 |
53 | @Override
54 | public void onAnimationEnd(Animator animator) {
55 | if (!touchDown)
56 | ripple_animated_value = 0;
57 |
58 | animateRipple = false;
59 | invalidatePoster();
60 | }
61 |
62 | @Override
63 | public void onAnimationCancel(Animator animator) {
64 |
65 |
66 | }
67 |
68 | @Override
69 | public void onAnimationRepeat(Animator animator) {
70 |
71 | }
72 | };
73 | private int rippleR;
74 | private int rippleColor = 0x25000000;
75 |
76 | public MaterialThreeLineText(Context context) {
77 | super(context);
78 | init();
79 | }
80 |
81 | public MaterialThreeLineText(Context context, AttributeSet attrs) {
82 | super(context, attrs);
83 | try {
84 | final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MaterialTwoLineText, 0, 0);
85 | setPrimaryTextColor(a.getInteger(R.attr.primaryTextColor, getResources().getColor(R.color.dark_dark_grey)));
86 | setSecondaryTextColor(a.getInteger(R.attr.secondaryTextColor, getResources().getColor(R.color.dark_grey)));
87 | setPrimaryTextSize(a.getInteger(R.attr.primaryTextSize, 18));
88 | setSecondaryTextSize(a.getInteger(R.attr.primaryTextSize, 16));
89 | setSecondaryTextMaxLines(a.getInteger(R.attr.secondaryTextMaxLines, 1));
90 | secondaryText = a.getString(R.attr.secondaryText);
91 | primaryText = a.getString(R.attr.primaryText);
92 | a.recycle();
93 | } catch (Exception ignored) {
94 | }
95 |
96 | if (secondaryText == null)
97 | secondaryText = "";
98 |
99 | if (primaryText == null)
100 | primaryText = "";
101 |
102 | init();
103 |
104 | setPrimaryText(primaryText);
105 | setSecondaryText(secondaryText);
106 | }
107 |
108 |
109 | public MaterialThreeLineText(Context context, AttributeSet attrs, int defStyle) {
110 | super(context, attrs, defStyle);
111 | try {
112 | final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MaterialTwoLineText, 0, 0);
113 | setPrimaryTextColor(a.getInteger(R.attr.primaryTextColor, getResources().getColor(R.color.dark_dark_grey)));
114 | setSecondaryTextColor(a.getInteger(R.attr.secondaryTextColor, getResources().getColor(R.color.dark_grey)));
115 | setPrimaryTextSize(a.getInteger(R.attr.primaryTextSize, 18));
116 | setSecondaryTextSize(a.getInteger(R.attr.primaryTextSize, 16));
117 | setSecondaryTextMaxLines(a.getInteger(R.attr.secondaryTextMaxLines, 1));
118 | a.recycle();
119 | } catch (Exception ignored) {
120 | }
121 |
122 | if (secondaryText == null)
123 | secondaryText = "";
124 |
125 | if (primaryText == null)
126 | primaryText = "";
127 |
128 | init();
129 |
130 | setPrimaryText(primaryText);
131 | setSecondaryText(secondaryText);
132 | }
133 |
134 | @Override
135 | public boolean onTouchEvent(MotionEvent event) {
136 | switch (event.getAction()) {
137 | case MotionEvent.ACTION_DOWN:
138 | clickedX = (int) event.getX();
139 | clickedY = (int) event.getY();
140 | rippleR = (int) (Math.sqrt(Math.pow(Math.max(width - clickedX, clickedX), 2) + Math.pow(Math.max(height - clickedY, clickedY), 2)) * 1.15);
141 |
142 | animator.start();
143 |
144 | touchDown = true;
145 | animateRipple = true;
146 | break;
147 | case MotionEvent.ACTION_UP:
148 | case MotionEvent.ACTION_CANCEL:
149 | touchDown = false;
150 |
151 | if (!animator.isRunning()) {
152 | ripple_animated_value = 0;
153 | invalidatePoster();
154 | }
155 | break;
156 | }
157 | return true;
158 | }
159 |
160 | public void setPrimaryText(String text) {
161 | primaryText = text;
162 | primaryTextView.setText(text);
163 | invalidate();
164 | }
165 |
166 | public void setSecondaryText(String text) {
167 | secondaryText = text;
168 | secondaryTextView.setText(text);
169 | invalidate();
170 | }
171 |
172 | public int dpToPixels(int dp) {
173 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
174 | }
175 |
176 | private void init() {
177 | final int padding = dpToPixels(16);
178 | final LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
179 |
180 | primaryTextView = new TextView(getContext());
181 | primaryTextView.setTextColor(getResources().getColor(R.color.dark_dark_grey));
182 | primaryTextView.setTypeface(null, Typeface.BOLD);
183 | primaryTextView.setTextSize(18);
184 | primaryTextView.setMaxLines(1);
185 | primaryTextView.setLayoutParams(params);
186 | primaryTextView.setEllipsize(TextUtils.TruncateAt.END);
187 | primaryTextView.setPadding(padding, padding / 2, padding, padding / 2);
188 |
189 | secondaryTextView = new TextView(getContext());
190 | secondaryTextView.setTextColor(getResources().getColor(R.color.dark_grey));
191 | secondaryTextView.setTextSize(16);
192 | secondaryTextView.setMaxLines(2);
193 | secondaryTextView.setLayoutParams(params);
194 | secondaryTextView.setEllipsize(TextUtils.TruncateAt.END);
195 | secondaryTextView.setPadding(padding, padding / 2, padding, padding);
196 |
197 | primaryTextView.setText("Primary");
198 | secondaryTextView.setText("Secondary");
199 |
200 | setWillNotDraw(false);
201 | animator.setInterpolator(interpolator);
202 | animator.addUpdateListener(animatorUpdateListener);
203 | animator.addListener(animatorListener);
204 | animator.setDuration(duration);
205 | paint.setColor(0x25000000);
206 |
207 |
208 | addView(primaryTextView);
209 | addView(secondaryTextView);
210 | }
211 |
212 | public void setSecondaryTextColor(int color) {
213 | secondaryTextView.setTextColor(color);
214 | }
215 |
216 | public void setSecondaryTextMaxLines(int maxLines) {
217 | secondaryTextView.setMaxLines(maxLines);
218 | }
219 |
220 | public void setSecondaryTextSize(int sp) {
221 | secondaryTextView.setTextSize(sp);
222 | }
223 |
224 | public void setPrimaryTextSize(int sp) {
225 | primaryTextView.setTextSize(sp);
226 | }
227 |
228 | public void setPrimaryTextColor(int color) {
229 | primaryTextView.setTextColor(color);
230 | }
231 |
232 | @Override
233 | protected void onLayout(boolean b, int i, int i2, int i3, int i4) {
234 | final int textViewPadding = ((getMeasuredHeight() - primaryTextView.getMeasuredHeight() - secondaryTextView.getMeasuredHeight()) / 2);
235 | primaryTextView.layout(getPaddingLeft(), textViewPadding,
236 | getMeasuredWidth() - getPaddingRight(),
237 | primaryTextView.getMeasuredHeight() + textViewPadding);
238 |
239 | checkViewParams(primaryTextView);
240 |
241 | secondaryTextView.layout(getPaddingLeft(),
242 | getMeasuredHeight() - textViewPadding - secondaryTextView.getMeasuredHeight(),
243 | getMeasuredWidth() - getPaddingRight(),
244 | getMeasuredHeight() - textViewPadding);
245 |
246 | checkViewParams(secondaryTextView);
247 | }
248 |
249 | private void checkViewParams(final View view, final int layoutWidth, final int layoutHeight) {
250 | final int width = view.getMeasuredWidth();
251 | final int height = view.getMeasuredHeight();
252 | if ((width > layoutWidth) || (height > layoutHeight)) {
253 | view.setLayoutParams(new LayoutParams(layoutWidth, layoutHeight));
254 | measureChild(view, MeasureSpec.AT_MOST, MeasureSpec.AT_MOST);
255 | view.requestLayout();
256 | view.invalidate();
257 | requestLayout();
258 |
259 | }
260 | }
261 |
262 | private void checkViewParams(final View view) {
263 | final int layoutWidth = view.getRight() - view.getLeft();
264 | final int layoutHeight = view.getBottom() - view.getTop();
265 |
266 | checkViewParams(view, layoutWidth, layoutHeight);
267 |
268 | }
269 |
270 | private void scale(final float scale) {
271 | post(new Runnable() {
272 | @Override
273 | public void run() {
274 | MaterialThreeLineText.this.setScaleX(scale);
275 | MaterialThreeLineText.this.setScaleY(scale);
276 | invalidatePoster();
277 | }
278 | });
279 |
280 | }
281 |
282 | private void scaleLater() {
283 | final Timer timer = new Timer();
284 | timer.schedule(new TimerTask() {
285 | @Override
286 | public void run() {
287 | if (touchDown)
288 | scale(scaleTo);
289 | else
290 | scale(1);
291 | }
292 | }, 175);
293 | }
294 |
295 | @Override
296 | public boolean onInterceptTouchEvent(MotionEvent event) {
297 | return false;
298 | }
299 |
300 | public void setDuration(int duration) {
301 | MaterialThreeLineText.duration = duration;
302 | animator.setDuration(duration);
303 | }
304 |
305 | public void setScaleTo(float scaleTo) {
306 | this.scaleTo = scaleTo;
307 | }
308 |
309 | private void invalidatePoster() {
310 | this.post(new Runnable() {
311 | @Override
312 | public void run() {
313 | invalidate();
314 | }
315 | });
316 | }
317 |
318 | public void setRippleColor(int color) {
319 | rippleColor = color;
320 | }
321 |
322 | @Override
323 | protected void dispatchDraw(Canvas canvas) {
324 | super.dispatchDraw(canvas);
325 | if (animateRipple) {
326 | paint.setColor(rippleColor);
327 | canvas.drawCircle(clickedX, clickedY, rippleR * ripple_animated_value, paint);
328 | }
329 | }
330 |
331 |
332 | @Override
333 | public void addView(View child, int index, LayoutParams params) {
334 | if (getChildCount() >= 2)
335 | return;
336 | super.addView(child, index, params);
337 | }
338 |
339 |
340 | @Override
341 | protected void onSizeChanged(final int w, final int h, int oldw, int oldh) {
342 | super.onSizeChanged(w, h, oldw, oldh);
343 | width = w;
344 | height = h;
345 | }
346 |
347 | @Override
348 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
349 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
350 | int measuredHeight = 0;
351 | int measuredWidth = 0;
352 |
353 | for (int i = 0; i < getChildCount(); i++) {
354 |
355 | final View child = getChildAt(i);
356 | measureChild(child, widthMeasureSpec, heightMeasureSpec);
357 | measuredHeight += child.getMeasuredHeight();
358 | measuredWidth = Math.max(child.getMeasuredWidth(), measuredWidth);
359 | }
360 |
361 | setMeasuredDimension(resolveSizeAndState(measuredWidth, widthMeasureSpec, 0),
362 | resolveSizeAndState(measuredHeight, heightMeasureSpec, 0));
363 |
364 |
365 | }
366 | }
367 |
--------------------------------------------------------------------------------
/app/src/main/java/com/micnubinub/materiallibrary/MaterialThreeLineTextIcon.java:
--------------------------------------------------------------------------------
1 | package com.micnubinub.materiallibrary;
2 |
3 | import android.animation.Animator;
4 | import android.animation.ValueAnimator;
5 | import android.content.Context;
6 | import android.content.res.TypedArray;
7 | import android.graphics.Bitmap;
8 | import android.graphics.Canvas;
9 | import android.graphics.Paint;
10 | import android.graphics.Typeface;
11 | import android.graphics.drawable.Drawable;
12 | import android.text.TextUtils;
13 | import android.util.AttributeSet;
14 | import android.util.TypedValue;
15 | import android.view.MotionEvent;
16 | import android.view.View;
17 | import android.view.ViewGroup;
18 | import android.view.animation.AccelerateInterpolator;
19 | import android.widget.ImageView;
20 | import android.widget.TextView;
21 |
22 | import java.util.Timer;
23 | import java.util.TimerTask;
24 |
25 | /**
26 | * Created by root on 20/10/14.
27 | */
28 | @SuppressWarnings("ALL")
29 | public class MaterialThreeLineTextIcon extends ViewGroup {
30 | private static final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
31 | private static final AccelerateInterpolator interpolator = new AccelerateInterpolator();
32 | private static int duration = 600;
33 | private final ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
34 | private TextView primaryTextView, secondaryTextView;
35 | private ImageView imageView;
36 | private String primaryText, secondaryText;
37 |
38 | private int width;
39 | private int height;
40 | private float animated_value = 0;
41 | private float scaleTo = 1.065f;
42 | private int clickedX, clickedY;
43 | private boolean touchDown = false, animateRipple;
44 | private float ripple_animated_value = 0;
45 | private final ValueAnimator.AnimatorUpdateListener animatorUpdateListener = new ValueAnimator.AnimatorUpdateListener() {
46 | @Override
47 | public void onAnimationUpdate(ValueAnimator animation) {
48 | animated_value = (Float) (animation.getAnimatedValue());
49 | ripple_animated_value = animated_value;
50 | invalidatePoster();
51 | }
52 | };
53 | private ValueAnimator.AnimatorListener animatorListener = new Animator.AnimatorListener() {
54 | @Override
55 | public void onAnimationStart(Animator animator) {
56 |
57 | }
58 |
59 | @Override
60 | public void onAnimationEnd(Animator animator) {
61 | if (!touchDown)
62 | ripple_animated_value = 0;
63 |
64 | animateRipple = false;
65 | invalidatePoster();
66 | }
67 |
68 | @Override
69 | public void onAnimationCancel(Animator animator) {
70 |
71 |
72 | }
73 |
74 | @Override
75 | public void onAnimationRepeat(Animator animator) {
76 |
77 | }
78 | };
79 | private int rippleR;
80 | private int rippleColor = 0x25000000;
81 |
82 | public MaterialThreeLineTextIcon(Context context) {
83 | super(context);
84 | init();
85 | }
86 |
87 | public MaterialThreeLineTextIcon(Context context, AttributeSet attrs) {
88 | super(context, attrs);
89 |
90 | try {
91 | final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MaterialTwoLineText, 0, 0);
92 | setPrimaryTextColor(a.getInteger(R.attr.primaryTextColor, getResources().getColor(R.color.dark_dark_grey)));
93 | setSecondaryTextColor(a.getInteger(R.attr.secondaryTextColor, getResources().getColor(R.color.dark_grey)));
94 | setPrimaryTextSize(a.getInteger(R.attr.primaryTextSize, 18));
95 | setSecondaryTextSize(a.getInteger(R.attr.primaryTextSize, 16));
96 | setSecondaryTextMaxLines(a.getInteger(R.attr.secondaryTextMaxLines, 1));
97 | secondaryText = a.getString(R.attr.secondaryText);
98 | primaryText = a.getString(R.attr.primaryText);
99 | a.recycle();
100 | } catch (Exception ignored) {
101 | }
102 |
103 | if (secondaryText == null)
104 | secondaryText = "";
105 |
106 | if (primaryText == null)
107 | primaryText = "";
108 |
109 | init();
110 |
111 | setPrimaryText(primaryText);
112 | setSecondaryText(secondaryText);
113 | }
114 |
115 |
116 | public MaterialThreeLineTextIcon(Context context, AttributeSet attrs, int defStyle) {
117 | super(context, attrs, defStyle);
118 | try {
119 | final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MaterialTwoLineText, 0, 0);
120 | setPrimaryTextColor(a.getInteger(R.attr.primaryTextColor, getResources().getColor(R.color.dark_dark_grey)));
121 | setSecondaryTextColor(a.getInteger(R.attr.secondaryTextColor, getResources().getColor(R.color.dark_grey)));
122 | setPrimaryTextSize(a.getInteger(R.attr.primaryTextSize, 18));
123 | setSecondaryTextSize(a.getInteger(R.attr.primaryTextSize, 16));
124 | setSecondaryTextMaxLines(a.getInteger(R.attr.secondaryTextMaxLines, 1));
125 |
126 | a.recycle();
127 | } catch (Exception ignored) {
128 | }
129 |
130 | if (secondaryText == null)
131 | secondaryText = "empty";
132 |
133 | if (primaryText == null)
134 | primaryText = "empty";
135 |
136 | init();
137 |
138 | setPrimaryText(primaryText);
139 | setSecondaryText(secondaryText);
140 | }
141 |
142 | @Override
143 | public boolean onTouchEvent(MotionEvent event) {
144 | switch (event.getAction()) {
145 | case MotionEvent.ACTION_DOWN:
146 | clickedX = (int) event.getX();
147 | clickedY = (int) event.getY();
148 | rippleR = (int) (Math.sqrt(Math.pow(Math.max(width - clickedX, clickedX), 2) + Math.pow(Math.max(height - clickedY, clickedY), 2)) * 1.15);
149 |
150 | animator.start();
151 |
152 | touchDown = true;
153 | animateRipple = true;
154 | break;
155 | case MotionEvent.ACTION_UP:
156 | case MotionEvent.ACTION_CANCEL:
157 | touchDown = false;
158 |
159 | if (!animator.isRunning()) {
160 | ripple_animated_value = 0;
161 | invalidatePoster();
162 | }
163 | break;
164 | }
165 | return true;
166 | }
167 |
168 |
169 | public void setPrimaryText(String text) {
170 | primaryText = text;
171 | primaryTextView.setText(text);
172 | }
173 |
174 | public void setSecondaryText(String text) {
175 | secondaryText = text;
176 | secondaryTextView.setText(text);
177 | }
178 |
179 | public int dpToPixels(int dp) {
180 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
181 | }
182 |
183 | private void init() {
184 | //Todo consider 16 and 14 (in the guidelines)
185 | final int padding = dpToPixels(16);
186 | final int imageWidth = dpToPixels(72);
187 | final LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
188 |
189 | primaryTextView = new TextView(getContext());
190 | primaryTextView.setTextColor(getResources().getColor(R.color.dark_dark_grey));
191 | primaryTextView.setTypeface(null, Typeface.BOLD);
192 | primaryTextView.setTextSize(18);
193 | primaryTextView.setMaxLines(1);
194 | primaryTextView.setLayoutParams(params);
195 | primaryTextView.setEllipsize(TextUtils.TruncateAt.END);
196 | primaryTextView.setPadding(padding, padding, padding, padding / 2);
197 |
198 | secondaryTextView = new TextView(getContext());
199 | secondaryTextView.setTextColor(getResources().getColor(R.color.dark_grey));
200 | secondaryTextView.setTextSize(16);
201 | secondaryTextView.setMaxLines(2);
202 | secondaryTextView.setLayoutParams(params);
203 | secondaryTextView.setEllipsize(TextUtils.TruncateAt.END);
204 | secondaryTextView.setPadding(padding, padding / 2, padding, padding);
205 |
206 | imageView = new ImageView(getContext());
207 | imageView.setLayoutParams(new LayoutParams(imageWidth, imageWidth));
208 | imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
209 | imageView.setPadding(padding, padding, padding, padding);
210 |
211 |
212 | setWillNotDraw(false);
213 | animator.setInterpolator(interpolator);
214 | animator.addUpdateListener(animatorUpdateListener);
215 | animator.addListener(animatorListener);
216 | animator.setDuration(duration);
217 | paint.setColor(0x25000000);
218 |
219 |
220 | addView(primaryTextView);
221 | addView(secondaryTextView);
222 | addView(imageView);
223 | }
224 |
225 | public void setIcon(Drawable icon) {
226 | if (imageView != null)
227 | imageView.setImageDrawable(icon);
228 | }
229 |
230 | public void setIcon(Bitmap icon) {
231 | if (imageView != null)
232 | imageView.setImageBitmap(icon);
233 | }
234 |
235 | public void setSecondaryTextColor(int color) {
236 | secondaryTextView.setTextColor(color);
237 | }
238 |
239 | public void setSecondaryTextMaxLines(int maxLines) {
240 | secondaryTextView.setMaxLines(maxLines);
241 | }
242 |
243 | public void setSecondaryTextSize(int sp) {
244 | secondaryTextView.setTextSize(sp);
245 | }
246 |
247 | public void setPrimaryTextSize(int sp) {
248 | primaryTextView.setTextSize(sp);
249 | }
250 |
251 | public void setPrimaryTextColor(int color) {
252 | primaryTextView.setTextColor(color);
253 | }
254 |
255 | private void scale(final float scale) {
256 | post(new Runnable() {
257 | @Override
258 | public void run() {
259 | MaterialThreeLineTextIcon.this.setScaleX(scale);
260 | MaterialThreeLineTextIcon.this.setScaleY(scale);
261 | invalidatePoster();
262 | }
263 | });
264 |
265 | }
266 |
267 | private void scaleLater() {
268 | final Timer timer = new Timer();
269 | timer.schedule(new TimerTask() {
270 | @Override
271 | public void run() {
272 | if (touchDown)
273 | scale(scaleTo);
274 | else
275 | scale(1);
276 | }
277 | }, 175);
278 | }
279 |
280 | @Override
281 | public boolean onInterceptTouchEvent(MotionEvent event) {
282 |
283 | return false;
284 |
285 | }
286 |
287 | public void setDuration(int duration) {
288 | MaterialThreeLineTextIcon.duration = duration;
289 | animator.setDuration(duration);
290 | }
291 |
292 | public void setScaleTo(float scaleTo) {
293 | this.scaleTo = scaleTo;
294 | }
295 |
296 | private void invalidatePoster() {
297 | this.post(new Runnable() {
298 | @Override
299 | public void run() {
300 | invalidate();
301 | }
302 | });
303 | }
304 |
305 | public void setRippleColor(int color) {
306 | rippleColor = color;
307 | }
308 |
309 | @Override
310 | protected void dispatchDraw(Canvas canvas) {
311 | super.dispatchDraw(canvas);
312 | if (animateRipple) {
313 | paint.setColor(rippleColor);
314 | canvas.drawCircle(clickedX, clickedY, rippleR * ripple_animated_value, paint);
315 | }
316 | }
317 |
318 |
319 | @Override
320 | public void addView(View child, int index, LayoutParams params) {
321 | if (getChildCount() >= 3)
322 | return;
323 | super.addView(child, index, params);
324 | }
325 |
326 |
327 | @Override
328 | protected void onSizeChanged(final int w, final int h, int oldw, int oldh) {
329 | super.onSizeChanged(w, h, oldw, oldh);
330 | width = w;
331 | height = h;
332 | }
333 |
334 | @Override
335 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
336 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
337 | int measuredWidth = 0;
338 |
339 | for (int i = 0; i < getChildCount(); i++) {
340 |
341 | final View child = getChildAt(i);
342 | measureChild(child, widthMeasureSpec, heightMeasureSpec);
343 | measuredWidth = Math.max(child.getMeasuredWidth(), measuredWidth);
344 | }
345 |
346 | final int measuredHeight = Math.max(primaryTextView.getMeasuredHeight() + secondaryTextView.getMeasuredHeight(), imageView.getMeasuredHeight());
347 |
348 | setMeasuredDimension(resolveSizeAndState(measuredWidth, widthMeasureSpec, 0),
349 | resolveSizeAndState(measuredHeight, heightMeasureSpec, 0));
350 |
351 |
352 | }
353 |
354 | @Override
355 | protected void onLayout(boolean b, int i, int i2, int i3, int i4) {
356 | final int imageViewPaddingTop = getPaddingTop();
357 | imageView.layout(getPaddingLeft(),
358 | imageViewPaddingTop,
359 | getPaddingLeft() + imageView.getMeasuredWidth(),
360 | getMeasuredHeight() - imageViewPaddingTop
361 | );
362 |
363 | final int textViewPadding = (getMeasuredHeight() - (primaryTextView.getMeasuredHeight() + secondaryTextView.getMeasuredHeight())) / 2;
364 | primaryTextView.layout(getPaddingLeft() + imageView.getMeasuredWidth(),
365 | textViewPadding,
366 | getMeasuredWidth() - getPaddingRight(),
367 | textViewPadding + primaryTextView.getMeasuredHeight());
368 |
369 | checkViewParams(primaryTextView);
370 |
371 | secondaryTextView.layout(getPaddingLeft() + imageView.getMeasuredWidth(),
372 | getMeasuredHeight() - secondaryTextView.getMeasuredHeight() - textViewPadding,
373 | getMeasuredWidth() - getPaddingRight(),
374 | getMeasuredHeight() - textViewPadding
375 | );
376 |
377 | checkViewParams(secondaryTextView);
378 | }
379 |
380 | private void checkViewParams(final View view, final int layoutWidth, final int layoutHeight) {
381 | final int width = view.getMeasuredWidth();
382 | final int height = view.getMeasuredHeight();
383 | if ((width > layoutWidth) || (height > layoutHeight)) {
384 | view.setLayoutParams(new LayoutParams(layoutWidth, layoutHeight));
385 | measureChild(view, MeasureSpec.AT_MOST, MeasureSpec.AT_MOST);
386 | view.requestLayout();
387 | view.invalidate();
388 | requestLayout();
389 |
390 | }
391 | }
392 |
393 | private void checkViewParams(final View view) {
394 | final int layoutWidth = view.getRight() - view.getLeft();
395 | final int layoutHeight = view.getBottom() - view.getTop();
396 |
397 | checkViewParams(view, layoutWidth, layoutHeight);
398 |
399 | }
400 | /*
401 | public Bitmap drawableToBitmap(Drawable drawable) {
402 | if (drawable == null) // Don't do anything without a proper drawable
403 | return null;
404 | else if (drawable instanceof BitmapDrawable) // Use the getBitmap() method instead if BitmapDrawable
405 | return ((BitmapDrawable) drawable).getBitmap();
406 | // Create Bitmap object out of the drawable
407 | Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
408 | Canvas canvas = new Canvas(bitmap);
409 | drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
410 | drawable.draw(canvas);
411 | // Return the created Bitmap
412 | return bitmap;
413 | }
414 |
415 |
416 | public static Bitmap getCircleBitmap(Resources res, int sourceResId, int width) {
417 | BitmapFactory.Options options = new BitmapFactory.Options();
418 | options.inMutable = true;
419 | options.inPreferredConfig = Bitmap.Config.ARGB_8888;
420 | Bitmap bitmap = BitmapFactory.decodeResource(res, sourceResId, options);
421 | bitmap.setHasAlpha(true);
422 | bitmap = Bitmap.createScaledBitmap(bitmap, width, width, true);
423 | Bitmap output = Bitmap.createBitmap(width,
424 | width, Bitmap.Config.ARGB_8888);
425 | final Rect rect = new Rect(0, 0, width,
426 | width);
427 | Canvas canvas = new Canvas(output);
428 | Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
429 | paint.setColor(0xff000000);
430 | canvas.drawCircle(width / 2, width / 2, width / 2, paint);
431 | paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
432 | canvas.drawBitmap(bitmap, rect, rect, paint);
433 | bitmap.recycle();
434 | return output;
435 | }
436 | */
437 | }
438 |
--------------------------------------------------------------------------------
/app/src/main/java/com/micnubinub/materiallibrary/MaterialTwoLineText.java:
--------------------------------------------------------------------------------
1 | package com.micnubinub.materiallibrary;
2 |
3 | import android.animation.Animator;
4 | import android.animation.ValueAnimator;
5 | import android.content.Context;
6 | import android.content.res.TypedArray;
7 | import android.graphics.Canvas;
8 | import android.graphics.Paint;
9 | import android.graphics.Typeface;
10 | import android.text.TextUtils;
11 | import android.util.AttributeSet;
12 | import android.util.Log;
13 | import android.util.TypedValue;
14 | import android.view.MotionEvent;
15 | import android.view.View;
16 | import android.view.ViewGroup;
17 | import android.view.animation.AccelerateInterpolator;
18 | import android.widget.TextView;
19 |
20 | import java.util.Timer;
21 | import java.util.TimerTask;
22 |
23 | /**
24 | * Created by root on 20/10/14.
25 | */
26 | public class MaterialTwoLineText extends ViewGroup {
27 | private static final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
28 | private static final AccelerateInterpolator interpolator = new AccelerateInterpolator();
29 | private static int duration = 600;
30 | private final ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
31 | private TextView primaryTextView, secondaryTextView;
32 | private String primaryText, secondaryText;
33 | private int width;
34 | private int height;
35 | private float animated_value = 0;
36 | private float scaleTo = 1.065f;
37 | private int clickedX, clickedY;
38 | private boolean scaleOnTouch = true;
39 | private boolean touchDown = false, animateRipple;
40 | private float ripple_animated_value = 0;
41 | private final ValueAnimator.AnimatorUpdateListener animatorUpdateListener = new ValueAnimator.AnimatorUpdateListener() {
42 | @Override
43 | public void onAnimationUpdate(ValueAnimator animation) {
44 | animated_value = (Float) (animation.getAnimatedValue());
45 | ripple_animated_value = animated_value;
46 | Log.e("ripple val", String.format("%f", ripple_animated_value));
47 | invalidatePoster();
48 | }
49 | };
50 | private final ValueAnimator.AnimatorListener animatorListener = new Animator.AnimatorListener() {
51 | @Override
52 | public void onAnimationStart(Animator animator) {
53 |
54 | }
55 |
56 | @Override
57 | public void onAnimationEnd(Animator animator) {
58 | if (!touchDown)
59 | ripple_animated_value = 0;
60 |
61 | animateRipple = false;
62 | invalidatePoster();
63 | }
64 |
65 | @Override
66 | public void onAnimationCancel(Animator animator) {
67 |
68 |
69 | }
70 |
71 | @Override
72 | public void onAnimationRepeat(Animator animator) {
73 |
74 | }
75 | };
76 | private int rippleR;
77 | private int rippleColor = 0x25000000;
78 |
79 | public MaterialTwoLineText(Context context) {
80 | super(context);
81 | init();
82 | }
83 |
84 | public MaterialTwoLineText(Context context, AttributeSet attrs) {
85 | super(context, attrs);
86 |
87 | try {
88 | final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MaterialTwoLineText, 0, 0);
89 | setPrimaryTextColor(a.getInteger(R.attr.primaryTextColor, getResources().getColor(R.color.dark_dark_grey)));
90 | setSecondaryTextColor(a.getInteger(R.attr.secondaryTextColor, getResources().getColor(R.color.dark_grey)));
91 | setPrimaryTextSize(a.getInteger(R.attr.primaryTextSize, 18));
92 | setSecondaryTextSize(a.getInteger(R.attr.primaryTextSize, 16));
93 | setSecondaryTextMaxLines(a.getInteger(R.attr.secondaryTextMaxLines, 1));
94 | secondaryText = a.getString(R.attr.secondaryText);
95 | primaryText = a.getString(R.attr.primaryText);
96 | a.recycle();
97 | } catch (Exception ignored) {
98 | }
99 |
100 | if (secondaryText == null)
101 | secondaryText = "";
102 |
103 | if (primaryText == null)
104 | primaryText = "";
105 |
106 | init();
107 |
108 | setPrimaryText(primaryText);
109 | setSecondaryText(secondaryText);
110 | }
111 |
112 |
113 | public MaterialTwoLineText(Context context, AttributeSet attrs, int defStyle) {
114 | super(context, attrs, defStyle);
115 | try {
116 | final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MaterialTwoLineText, 0, 0);
117 | setPrimaryTextColor(a.getInteger(R.attr.primaryTextColor, getResources().getColor(R.color.dark_dark_grey)));
118 | setSecondaryTextColor(a.getInteger(R.attr.secondaryTextColor, getResources().getColor(R.color.dark_grey)));
119 | setPrimaryTextSize(a.getInteger(R.attr.primaryTextSize, 18));
120 | setSecondaryTextSize(a.getInteger(R.attr.primaryTextSize, 16));
121 | setSecondaryTextMaxLines(a.getInteger(R.attr.secondaryTextMaxLines, 1));
122 |
123 | a.recycle();
124 | } catch (Exception ignored) {
125 | }
126 |
127 | if (secondaryText == null)
128 | secondaryText = "";
129 |
130 | if (primaryText == null)
131 | primaryText = "";
132 |
133 | init();
134 |
135 | setPrimaryText(primaryText);
136 | setSecondaryText(secondaryText);
137 | }
138 |
139 | @Override
140 | public boolean onTouchEvent(MotionEvent event) {
141 | switch (event.getAction()) {
142 | case MotionEvent.ACTION_DOWN:
143 | clickedX = (int) event.getX();
144 | clickedY = (int) event.getY();
145 | rippleR = (int) (Math.sqrt(Math.pow(Math.max(width - clickedX, clickedX), 2) + Math.pow(Math.max(height - clickedY, clickedY), 2)) * 1.15);
146 |
147 | animator.start();
148 |
149 | touchDown = true;
150 | animateRipple = true;
151 | break;
152 | case MotionEvent.ACTION_UP:
153 | case MotionEvent.ACTION_CANCEL:
154 | touchDown = false;
155 |
156 | if (!animator.isRunning()) {
157 | ripple_animated_value = 0;
158 | invalidatePoster();
159 | }
160 | break;
161 | }
162 | return true;
163 | }
164 |
165 | public void setPrimaryText(String text) {
166 | primaryText = text;
167 | primaryTextView.setText(text);
168 | invalidatePoster();
169 | }
170 |
171 | public void setSecondaryText(String text) {
172 | secondaryText = text;
173 | secondaryTextView.setText(text);
174 | invalidatePoster();
175 | }
176 |
177 | public int dpToPixels(int dp) {
178 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
179 | }
180 |
181 | private void init() {
182 | //Todo consider 16 and 14 (in the guidelines)
183 | final int padding = dpToPixels(16);
184 | final LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
185 |
186 | primaryTextView = new TextView(getContext());
187 | primaryTextView.setTextColor(getResources().getColor(R.color.dark_dark_grey));
188 | primaryTextView.setTypeface(null, Typeface.BOLD);
189 | primaryTextView.setTextSize(18);
190 | primaryTextView.setMaxLines(1);
191 | primaryTextView.setLayoutParams(params);
192 | primaryTextView.setEllipsize(TextUtils.TruncateAt.END);
193 | primaryTextView.setPadding(padding, padding, padding, padding / 2);
194 |
195 | secondaryTextView = new TextView(getContext());
196 | secondaryTextView.setTextColor(getResources().getColor(R.color.dark_grey));
197 | secondaryTextView.setTextSize(16);
198 | secondaryTextView.setMaxLines(1);
199 | secondaryTextView.setLayoutParams(params);
200 | secondaryTextView.setEllipsize(TextUtils.TruncateAt.END);
201 | secondaryTextView.setPadding(padding, padding / 2, padding, padding);
202 |
203 | primaryTextView.setText("Primary");
204 | secondaryTextView.setText("Secondary text dkjsgjkab sjkdg bka sjb gas sdg sj dgjsgjs gj sgdjj jsdgj sdg");
205 |
206 | setWillNotDraw(false);
207 | animator.setInterpolator(interpolator);
208 | animator.addUpdateListener(animatorUpdateListener);
209 | animator.addListener(animatorListener);
210 | animator.setDuration(duration);
211 | paint.setColor(0x25000000);
212 |
213 |
214 | addView(primaryTextView);
215 | addView(secondaryTextView);
216 | }
217 |
218 | public void setSecondaryTextColor(int color) {
219 | secondaryTextView.setTextColor(color);
220 | }
221 |
222 | public void setSecondaryTextMaxLines(int maxLines) {
223 | secondaryTextView.setMaxLines(maxLines);
224 | }
225 |
226 | public void setSecondaryTextSize(int sp) {
227 | secondaryTextView.setTextSize(sp);
228 | }
229 |
230 | public void setPrimaryTextSize(int sp) {
231 | primaryTextView.setTextSize(sp);
232 | }
233 |
234 | public void setPrimaryTextColor(int color) {
235 | primaryTextView.setTextColor(color);
236 | }
237 |
238 | @Override
239 | protected void onLayout(boolean b, int i, int i2, int i3, int i4) {
240 | final int textViewPadding = ((getMeasuredHeight() - primaryTextView.getMeasuredHeight() - secondaryTextView.getMeasuredHeight()) / 2);
241 | primaryTextView.layout(getPaddingLeft(), textViewPadding,
242 | getMeasuredWidth() - getPaddingRight(),
243 | primaryTextView.getMeasuredHeight() + textViewPadding);
244 |
245 | checkViewParams(primaryTextView);
246 |
247 | secondaryTextView.layout(getPaddingLeft(),
248 | getMeasuredHeight() - textViewPadding - secondaryTextView.getMeasuredHeight(),
249 | getMeasuredWidth() - getPaddingRight(),
250 | getMeasuredHeight() - textViewPadding
251 | );
252 |
253 | checkViewParams(secondaryTextView);
254 | }
255 |
256 | private void checkViewParams(final View view, final int layoutWidth, final int layoutHeight) {
257 | final int width = view.getMeasuredWidth();
258 | final int height = view.getMeasuredHeight();
259 | if ((width > layoutWidth) || (height > layoutHeight)) {
260 | view.setLayoutParams(new LayoutParams(layoutWidth, layoutHeight));
261 | measureChild(view, MeasureSpec.AT_MOST, MeasureSpec.AT_MOST);
262 | view.requestLayout();
263 | view.invalidate();
264 | requestLayout();
265 |
266 | }
267 | }
268 |
269 | private void checkViewParams(final View view) {
270 | final int layoutWidth = view.getRight() - view.getLeft();
271 | final int layoutHeight = view.getBottom() - view.getTop();
272 |
273 | checkViewParams(view, layoutWidth, layoutHeight);
274 |
275 | }
276 |
277 | private void scale(final float scale) {
278 | post(new Runnable() {
279 | @Override
280 | public void run() {
281 | MaterialTwoLineText.this.setScaleX(scale);
282 | MaterialTwoLineText.this.setScaleY(scale);
283 | invalidatePoster();
284 | }
285 | });
286 |
287 | }
288 |
289 | private void scaleLater() {
290 | final Timer timer = new Timer();
291 | timer.schedule(new TimerTask() {
292 | @Override
293 | public void run() {
294 | if (touchDown)
295 | scale(scaleTo);
296 | else
297 | scale(1);
298 | }
299 | }, 175);
300 | }
301 |
302 | @Override
303 | public boolean onInterceptTouchEvent(MotionEvent event) {
304 |
305 | return false;
306 |
307 | }
308 |
309 | public void setDuration(int duration) {
310 | MaterialTwoLineText.duration = duration;
311 | animator.setDuration(duration);
312 | }
313 |
314 | public void setScaleTo(float scaleTo) {
315 | this.scaleTo = scaleTo;
316 | }
317 |
318 | public void setScaleOnTouch(boolean scaleOnTouch) {
319 | this.scaleOnTouch = scaleOnTouch;
320 | }
321 |
322 | private void invalidatePoster() {
323 | this.post(new Runnable() {
324 | @Override
325 | public void run() {
326 | invalidate();
327 | }
328 | });
329 | }
330 |
331 | public void setRippleColor(int color) {
332 | rippleColor = color;
333 | }
334 |
335 | @Override
336 | protected void dispatchDraw(Canvas canvas) {
337 | super.dispatchDraw(canvas);
338 | if (animateRipple) {
339 | paint.setColor(rippleColor);
340 | canvas.drawCircle(clickedX, clickedY, rippleR * ripple_animated_value, paint);
341 | }
342 | }
343 |
344 |
345 | @Override
346 | public void addView(View child, int index, LayoutParams params) {
347 | if (getChildCount() >= 2)
348 | return;
349 | super.addView(child, index, params);
350 | }
351 |
352 |
353 | @Override
354 | protected void onSizeChanged(final int w, final int h, int oldw, int oldh) {
355 | super.onSizeChanged(w, h, oldw, oldh);
356 | width = w;
357 | height = h;
358 | }
359 |
360 | @Override
361 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
362 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
363 | int measuredHeight = 0;
364 | int measuredWidth = 0;
365 |
366 | for (int i = 0; i < getChildCount(); i++) {
367 |
368 | final View child = getChildAt(i);
369 | measureChild(child, widthMeasureSpec, heightMeasureSpec);
370 | measuredHeight += child.getMeasuredHeight();
371 | measuredWidth = Math.max(child.getMeasuredWidth(), measuredWidth);
372 | }
373 |
374 | setMeasuredDimension(resolveSizeAndState(measuredWidth, widthMeasureSpec, 0),
375 | resolveSizeAndState(measuredHeight, heightMeasureSpec, 0));
376 |
377 |
378 | }
379 | }
380 |
--------------------------------------------------------------------------------
/app/src/main/java/com/micnubinub/materiallibrary/MaterialTwoLineTextIcon.java:
--------------------------------------------------------------------------------
1 | package com.micnubinub.materiallibrary;
2 |
3 | import android.animation.Animator;
4 | import android.animation.ValueAnimator;
5 | import android.content.Context;
6 | import android.content.res.TypedArray;
7 | import android.graphics.Bitmap;
8 | import android.graphics.Canvas;
9 | import android.graphics.Paint;
10 | import android.graphics.Typeface;
11 | import android.graphics.drawable.Drawable;
12 | import android.text.TextUtils;
13 | import android.util.AttributeSet;
14 | import android.util.TypedValue;
15 | import android.view.MotionEvent;
16 | import android.view.View;
17 | import android.view.ViewGroup;
18 | import android.view.animation.AccelerateInterpolator;
19 | import android.widget.ImageView;
20 | import android.widget.TextView;
21 |
22 | import java.util.Timer;
23 | import java.util.TimerTask;
24 |
25 | /**
26 | * Created by root on 20/10/14.
27 | */
28 | public class MaterialTwoLineTextIcon extends ViewGroup {
29 | private static final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
30 | private static final AccelerateInterpolator interpolator = new AccelerateInterpolator();
31 | private static int duration = 600;
32 | private final ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
33 | private TextView primaryTextView, secondaryTextView;
34 | private ImageView imageView;
35 | private String primaryText, secondaryText;
36 | private int width;
37 | private int height;
38 | private float animated_value = 0;
39 | private float scaleTo = 1.065f;
40 | private int clickedX, clickedY;
41 | private boolean touchDown = false, animateRipple;
42 | private float ripple_animated_value = 0;
43 | private final ValueAnimator.AnimatorUpdateListener animatorUpdateListener = new ValueAnimator.AnimatorUpdateListener() {
44 | @Override
45 | public void onAnimationUpdate(ValueAnimator animation) {
46 | animated_value = (Float) (animation.getAnimatedValue());
47 | ripple_animated_value = animated_value;
48 | invalidatePoster();
49 | }
50 | };
51 | private final ValueAnimator.AnimatorListener animatorListener = new Animator.AnimatorListener() {
52 | @Override
53 | public void onAnimationStart(Animator animator) {
54 |
55 | }
56 |
57 | @Override
58 | public void onAnimationEnd(Animator animator) {
59 | if (!touchDown)
60 | ripple_animated_value = 0;
61 |
62 | animateRipple = false;
63 | invalidatePoster();
64 | }
65 |
66 | @Override
67 | public void onAnimationCancel(Animator animator) {
68 |
69 |
70 | }
71 |
72 | @Override
73 | public void onAnimationRepeat(Animator animator) {
74 |
75 | }
76 | };
77 | private int rippleR;
78 | private int rippleColor = 0x25000000;
79 |
80 | public MaterialTwoLineTextIcon(Context context) {
81 | super(context);
82 | init();
83 | }
84 |
85 | public MaterialTwoLineTextIcon(Context context, AttributeSet attrs) {
86 | super(context, attrs);
87 |
88 | try {
89 | final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MaterialTwoLineText, 0, 0);
90 | setPrimaryTextColor(a.getInteger(R.attr.primaryTextColor, getResources().getColor(R.color.dark_dark_grey)));
91 | setSecondaryTextColor(a.getInteger(R.attr.secondaryTextColor, getResources().getColor(R.color.dark_grey)));
92 | setPrimaryTextSize(a.getInteger(R.attr.primaryTextSize, 18));
93 | setSecondaryTextSize(a.getInteger(R.attr.primaryTextSize, 16));
94 | setSecondaryTextMaxLines(a.getInteger(R.attr.secondaryTextMaxLines, 1));
95 | secondaryText = a.getString(R.attr.secondaryText);
96 | primaryText = a.getString(R.attr.primaryText);
97 | a.recycle();
98 | } catch (Exception ignored) {
99 | }
100 |
101 | if (secondaryText == null)
102 | secondaryText = "";
103 |
104 | if (primaryText == null)
105 | primaryText = "";
106 |
107 | init();
108 |
109 | setPrimaryText(primaryText);
110 | setSecondaryText(secondaryText);
111 | }
112 |
113 |
114 | public MaterialTwoLineTextIcon(Context context, AttributeSet attrs, int defStyle) {
115 | super(context, attrs, defStyle);
116 | try {
117 | final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MaterialTwoLineText, 0, 0);
118 | setPrimaryTextColor(a.getInteger(R.attr.primaryTextColor, getResources().getColor(R.color.dark_dark_grey)));
119 | setSecondaryTextColor(a.getInteger(R.attr.secondaryTextColor, getResources().getColor(R.color.dark_grey)));
120 | setPrimaryTextSize(a.getInteger(R.attr.primaryTextSize, 18));
121 | setSecondaryTextSize(a.getInteger(R.attr.primaryTextSize, 16));
122 | setSecondaryTextMaxLines(a.getInteger(R.attr.secondaryTextMaxLines, 1));
123 |
124 | a.recycle();
125 | } catch (Exception ignored) {
126 | }
127 |
128 | if (secondaryText == null)
129 | secondaryText = "empty";
130 |
131 | if (primaryText == null)
132 | primaryText = "empty";
133 |
134 | init();
135 |
136 | setPrimaryText(primaryText);
137 | setSecondaryText(secondaryText);
138 | }
139 |
140 |
141 |
142 |
143 | public void setPrimaryText(String text) {
144 | primaryText = text;
145 | primaryTextView.setText(text);
146 | }
147 |
148 | public void setSecondaryText(String text) {
149 | secondaryText = text;
150 | secondaryTextView.setText(text);
151 | }
152 |
153 | public int dpToPixels(int dp) {
154 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
155 | }
156 |
157 | private void init() {
158 | //Todo consider 16 and 14 (in the guidelines)
159 | final int padding = dpToPixels(16);
160 | final int imageWidth = dpToPixels(72);
161 | final ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
162 |
163 | primaryTextView = new TextView(getContext());
164 | primaryTextView.setTextColor(getResources().getColor(R.color.dark_dark_grey));
165 | primaryTextView.setTypeface(null, Typeface.BOLD);
166 | primaryTextView.setTextSize(18);
167 | primaryTextView.setMaxLines(1);
168 | primaryTextView.setLayoutParams(params);
169 | primaryTextView.setEllipsize(TextUtils.TruncateAt.END);
170 | primaryTextView.setPadding(padding, padding / 2, padding, padding / 2);
171 |
172 | secondaryTextView = new TextView(getContext());
173 | secondaryTextView.setTextColor(getResources().getColor(R.color.dark_grey));
174 | secondaryTextView.setTextSize(16);
175 | secondaryTextView.setMaxLines(1);
176 | secondaryTextView.setLayoutParams(params);
177 | secondaryTextView.setEllipsize(TextUtils.TruncateAt.END);
178 | secondaryTextView.setPadding(padding, padding / 2, padding, padding);
179 |
180 | imageView = new ImageView(getContext());
181 | imageView.setLayoutParams(new LayoutParams(imageWidth, imageWidth));
182 | imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
183 | imageView.setPadding(padding, padding, padding, padding);
184 |
185 | setWillNotDraw(false);
186 | animator.setInterpolator(interpolator);
187 | animator.addUpdateListener(animatorUpdateListener);
188 | animator.addListener(animatorListener);
189 | animator.setDuration(duration);
190 | paint.setColor(0x25000000);
191 |
192 |
193 | addView(primaryTextView);
194 | addView(secondaryTextView);
195 | addView(imageView);
196 | }
197 |
198 | public void setIcon(Drawable icon) {
199 | if (imageView != null)
200 | imageView.setImageDrawable(icon);
201 | }
202 |
203 | public void setIcon(Bitmap icon) {
204 | if (imageView != null)
205 | imageView.setImageBitmap(icon);
206 | }
207 |
208 | public void setSecondaryTextColor(int color) {
209 | secondaryTextView.setTextColor(color);
210 | }
211 |
212 | public void setSecondaryTextMaxLines(int maxLines) {
213 | secondaryTextView.setMaxLines(maxLines);
214 | }
215 |
216 | public void setSecondaryTextSize(int sp) {
217 | secondaryTextView.setTextSize(sp);
218 | }
219 |
220 | public void setPrimaryTextSize(int sp) {
221 | primaryTextView.setTextSize(sp);
222 | }
223 |
224 | public void setPrimaryTextColor(int color) {
225 | primaryTextView.setTextColor(color);
226 | }
227 |
228 | private void scale(final float scale) {
229 | post(new Runnable() {
230 | @Override
231 | public void run() {
232 | MaterialTwoLineTextIcon.this.setScaleX(scale);
233 | MaterialTwoLineTextIcon.this.setScaleY(scale);
234 | invalidatePoster();
235 | }
236 | });
237 |
238 | }
239 |
240 | private void scaleLater() {
241 | final Timer timer = new Timer();
242 | timer.schedule(new TimerTask() {
243 | @Override
244 | public void run() {
245 | if (touchDown)
246 | scale(scaleTo);
247 | else
248 | scale(1);
249 | }
250 | }, 175);
251 | }
252 |
253 | @Override
254 | public boolean onInterceptTouchEvent(MotionEvent event) {
255 | return false;
256 | }
257 |
258 | @Override
259 | public boolean onTouchEvent(MotionEvent event) {
260 | switch (event.getAction()) {
261 | case MotionEvent.ACTION_DOWN:
262 | clickedX = (int) event.getX();
263 | clickedY = (int) event.getY();
264 | rippleR = (int) (Math.sqrt(Math.pow(Math.max(width - clickedX, clickedX), 2) + Math.pow(Math.max(height - clickedY, clickedY), 2)) * 1.15);
265 |
266 | animator.start();
267 |
268 | touchDown = true;
269 | animateRipple = true;
270 | break;
271 | case MotionEvent.ACTION_UP:
272 | case MotionEvent.ACTION_CANCEL:
273 | touchDown = false;
274 |
275 | if (!animator.isRunning()) {
276 | ripple_animated_value = 0;
277 | invalidatePoster();
278 | }
279 | break;
280 | }
281 | return true;
282 | }
283 |
284 | public void setDuration(int duration) {
285 | MaterialTwoLineTextIcon.duration = duration;
286 | animator.setDuration(duration);
287 | }
288 |
289 | public void setScaleTo(float scaleTo) {
290 | this.scaleTo = scaleTo;
291 | }
292 |
293 | private void invalidatePoster() {
294 | this.post(new Runnable() {
295 | @Override
296 | public void run() {
297 | invalidate();
298 | }
299 | });
300 | }
301 |
302 | public void setRippleColor(int color) {
303 | rippleColor = color;
304 | }
305 |
306 | @Override
307 | protected void dispatchDraw(Canvas canvas) {
308 | super.dispatchDraw(canvas);
309 | if (animateRipple) {
310 | paint.setColor(rippleColor);
311 | canvas.drawCircle(clickedX, clickedY, rippleR * ripple_animated_value, paint);
312 | }
313 | }
314 |
315 |
316 | @Override
317 | public void addView(View child, int index, ViewGroup.LayoutParams params) {
318 | if (getChildCount() >= 3)
319 | return;
320 | super.addView(child, index, params);
321 | }
322 |
323 |
324 | @Override
325 | protected void onSizeChanged(final int w, final int h, int oldw, int oldh) {
326 | super.onSizeChanged(w, h, oldw, oldh);
327 | width = w;
328 | height = h;
329 | }
330 |
331 | @Override
332 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
333 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
334 | int measuredWidth = 0;
335 |
336 | for (int i = 0; i < getChildCount(); i++) {
337 |
338 | final View child = getChildAt(i);
339 | measureChild(child, widthMeasureSpec, heightMeasureSpec);
340 | measuredWidth = Math.max(child.getMeasuredWidth(), measuredWidth);
341 | }
342 |
343 | final int measuredHeight = Math.max(primaryTextView.getMeasuredHeight() + secondaryTextView.getMeasuredHeight(), imageView.getMeasuredHeight());
344 |
345 |
346 | setMeasuredDimension(resolveSizeAndState(measuredWidth, widthMeasureSpec, 0),
347 | resolveSizeAndState(measuredHeight, heightMeasureSpec, 0));
348 |
349 |
350 | }
351 |
352 |
353 | @Override
354 | protected void onLayout(boolean b, int i, int i2, int i3, int i4) {
355 | imageView.layout(getPaddingLeft(),
356 | getPaddingTop(),
357 | getPaddingLeft() + imageView.getMeasuredWidth(),
358 | getMeasuredHeight() - getPaddingBottom()
359 | );
360 |
361 | primaryTextView.layout(getPaddingLeft() + imageView.getMeasuredWidth(), getPaddingTop(),
362 | getMeasuredWidth() - getPaddingRight(),
363 | primaryTextView.getMeasuredHeight() + getPaddingTop());
364 |
365 | checkViewParams(primaryTextView);
366 |
367 | secondaryTextView.layout(getPaddingLeft() + imageView.getMeasuredWidth(),
368 | getMeasuredHeight() - getPaddingTop() - secondaryTextView.getMeasuredHeight(),
369 | getMeasuredWidth() - getPaddingRight(),
370 | getMeasuredHeight() - getPaddingBottom()
371 | );
372 |
373 | checkViewParams(secondaryTextView);
374 | }
375 |
376 | private void checkViewParams(final View view, final int layoutWidth, final int layoutHeight) {
377 | final int width = view.getMeasuredWidth();
378 | final int height = view.getMeasuredHeight();
379 | if ((width > layoutWidth) || (height > layoutHeight)) {
380 | view.setLayoutParams(new LayoutParams(layoutWidth, layoutHeight));
381 | measureChild(view, MeasureSpec.AT_MOST, MeasureSpec.AT_MOST);
382 | view.requestLayout();
383 | view.invalidate();
384 | requestLayout();
385 |
386 | }
387 | }
388 |
389 | private void checkViewParams(final View view) {
390 | final int layoutWidth = view.getRight() - view.getLeft();
391 | final int layoutHeight = view.getBottom() - view.getTop();
392 |
393 | checkViewParams(view, layoutWidth, layoutHeight);
394 |
395 | }
396 | /*
397 | public Bitmap drawableToBitmap(Drawable drawable) {
398 | if (drawable == null) // Don't do anything without a proper drawable
399 | return null;
400 | else if (drawable instanceof BitmapDrawable) // Use the getBitmap() method instead if BitmapDrawable
401 | return ((BitmapDrawable) drawable).getBitmap();
402 | // Create Bitmap object out of the drawable
403 | Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
404 | Canvas canvas = new Canvas(bitmap);
405 | drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
406 | drawable.draw(canvas);
407 | // Return the created Bitmap
408 | return bitmap;
409 | }
410 |
411 |
412 | public static Bitmap getCircleBitmap(Resources res, int sourceResId, int width) {
413 | BitmapFactory.Options options = new BitmapFactory.Options();
414 | options.inMutable = true;
415 | options.inPreferredConfig = Bitmap.Config.ARGB_8888;
416 | Bitmap bitmap = BitmapFactory.decodeResource(res, sourceResId, options);
417 | bitmap.setHasAlpha(true);
418 | bitmap = Bitmap.createScaledBitmap(bitmap, width, width, true);
419 | Bitmap output = Bitmap.createBitmap(width,
420 | width, Bitmap.Config.ARGB_8888);
421 | final Rect rect = new Rect(0, 0, width,
422 | width);
423 | Canvas canvas = new Canvas(output);
424 | Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
425 | paint.setColor(0xff000000);
426 | canvas.drawCircle(width / 2, width / 2, width / 2, paint);
427 | paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
428 | canvas.drawBitmap(bitmap, rect, rect, paint);
429 | bitmap.recycle();
430 | return output;
431 | }
432 | */
433 | }
434 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/zoom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/block.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Micnubinub/MaterialLibrary/feebb0841af432a6f7de9c377dcdd3a33cb9e0dd/app/src/main/res/drawable-hdpi/block.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Micnubinub/MaterialLibrary/feebb0841af432a6f7de9c377dcdd3a33cb9e0dd/app/src/main/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Micnubinub/MaterialLibrary/feebb0841af432a6f7de9c377dcdd3a33cb9e0dd/app/src/main/res/drawable-hdpi/search.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/test.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Micnubinub/MaterialLibrary/feebb0841af432a6f7de9c377dcdd3a33cb9e0dd/app/src/main/res/drawable-hdpi/test.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/white_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Micnubinub/MaterialLibrary/feebb0841af432a6f7de9c377dcdd3a33cb9e0dd/app/src/main/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Micnubinub/MaterialLibrary/feebb0841af432a6f7de9c377dcdd3a33cb9e0dd/app/src/main/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Micnubinub/MaterialLibrary/feebb0841af432a6f7de9c377dcdd3a33cb9e0dd/app/src/main/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/main.xml:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #00000000
4 | #19000000
5 | #ffdc862a
6 | #ffaa22
7 | #1a1a1a
8 | #ffcc00
9 | #ffd2de0f
10 | #bbff00
11 | #00dd00
12 | #4ac925
13 | #ff16ba0d
14 | #00bbff
15 | #2089ee
16 | #ff0213c4
17 | #ff9819d2
18 | #ffe7069f
19 | #ff1111
20 | #ff3022
21 | #fff
22 | #efefef
23 | #dcdcdc
24 | #ababab
25 | #606060
26 | #888888
27 | #989898
28 | #454545
29 | #272727
30 | #222222
31 | #000000
32 | #aaffffff
33 | #311b92
34 | #5c6bc0
35 | #3f51b5
36 | #303f9f
37 | #e51c23
38 | #e84e40
39 | #d01716
40 | #f06292
41 | #e91e63
42 | #c2185b
43 | #ab47bc
44 | #9c27b0
45 | #7b1fa2
46 | #738ffe
47 | #5677fc
48 | #455ede
49 | #42bd41
50 | #259b24
51 | #0a7e07
52 | #fff176
53 | #ffeb3b
54 | #fdd835
55 | #ffa726
56 | #fb8c00
57 | #e65100
58 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Material Library
5 | Hello world!
6 | Settings
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
13 |
14 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:0.12.2'
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Settings specified in this file will override any Gradle settings
5 | # configured through the IDE.
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/Micnubinub/MaterialLibrary/feebb0841af432a6f7de9c377dcdd3a33cb9e0dd/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Apr 10 15:27:10 PDT 2013
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=http\://services.gradle.org/distributions/gradle-1.12-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 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/pic1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Micnubinub/MaterialLibrary/feebb0841af432a6f7de9c377dcdd3a33cb9e0dd/pic1.png
--------------------------------------------------------------------------------
/pic2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Micnubinub/MaterialLibrary/feebb0841af432a6f7de9c377dcdd3a33cb9e0dd/pic2.png
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------