├── .gitignore
├── .idea
├── codeStyleSettings.xml
├── compiler.xml
├── copyright
│ └── profiles_settings.xml
├── encodings.xml
├── gradle.xml
├── misc.xml
├── modules.xml
├── runConfigurations.xml
└── vcs.xml
├── LICENSE
├── Material.iml
├── README.md
├── app
├── .gitignore
├── app.iml
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── assets
│ └── FreeSans.ttf
│ ├── java
│ └── com
│ │ └── rey
│ │ └── material
│ │ ├── app
│ │ ├── ContactEditText.java
│ │ ├── ContactView.java
│ │ ├── Recipient.java
│ │ ├── Recurring.java
│ │ ├── RecurringPickerDialog.java
│ │ └── WeekView.java
│ │ └── demo
│ │ ├── ButtonFragment.java
│ │ ├── CustomViewPager.java
│ │ ├── DemoApplication.java
│ │ ├── DialogsFragment.java
│ │ ├── FabFragment.java
│ │ ├── MainActivity.java
│ │ ├── ProgressFragment.java
│ │ ├── SliderFragment.java
│ │ ├── SnackbarFragment.java
│ │ ├── SpinnersFragment.java
│ │ ├── SwitchesFragment.java
│ │ └── TextfieldFragment.java
│ └── res
│ ├── anim
│ ├── anim_scale_in.xml
│ └── anim_scale_out.xml
│ ├── drawable-xhdpi
│ ├── bg_bt_raise.9.png
│ ├── bg_bt_raise_color.9.png
│ ├── bg_bt_raise_dark.9.png
│ ├── bg_toolbar_dark.xml
│ ├── bg_toolbar_light.xml
│ ├── ic_autorenew_white_24dp.png
│ ├── ic_cancel_white_24dp.png
│ ├── ic_done_all_white_24dp.png
│ ├── ic_done_white_24dp.png
│ ├── ic_launcher.png
│ ├── ic_user.png
│ ├── ic_visibility_white_24dp.png
│ └── popup_background_dark.9.png
│ ├── drawable
│ ├── bg_window_dark.xml
│ ├── bg_window_light.xml
│ ├── color_divider_dark.xml
│ ├── color_divider_light.xml
│ ├── color_label_dark.xml
│ ├── color_label_light.xml
│ ├── color_switch_dark.xml
│ ├── color_thumb_dark.xml
│ ├── color_thumb_light.xml
│ ├── color_tpi_dark.xml
│ ├── color_tpi_light.xml
│ ├── color_track_dark.xml
│ ├── color_track_light.xml
│ └── color_wv_text.xml
│ ├── layout
│ ├── activity_main.xml
│ ├── dialog_recurring.xml
│ ├── fragment_button.xml
│ ├── fragment_dialog.xml
│ ├── fragment_fab.xml
│ ├── fragment_progress.xml
│ ├── fragment_slider.xml
│ ├── fragment_snackbar.xml
│ ├── fragment_spinner.xml
│ ├── fragment_switches.xml
│ ├── fragment_textfield.xml
│ ├── layout_dialog_custom.xml
│ ├── rd_item_dropdown_end.xml
│ ├── rd_item_dropdown_mode.xml
│ ├── rd_item_end.xml
│ ├── rd_item_mode.xml
│ ├── row_contact_replace.xml
│ ├── row_contact_selected.xml
│ ├── row_drawer.xml
│ ├── row_spn.xml
│ ├── row_spn_dropdown.xml
│ └── view_bottomsheet.xml
│ ├── menu
│ └── menu_main.xml
│ ├── values
│ ├── attrs.xml
│ ├── colors.xml
│ ├── dimens.xml
│ ├── strings.xml
│ ├── styles.xml
│ ├── styles_dark.xml
│ ├── styles_light.xml
│ └── themes.xml
│ └── xml
│ └── fab_icon_states.xml
├── build.gradle
├── gradle.properties
├── gradle
├── local.properties
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── image
├── bottomsheet.gif
├── button_flat_touch.gif
├── button_flat_wave.gif
├── button_raise_touch.gif
├── button_raise_wave.gif
├── cb.gif
├── dialog_1.png
├── dialog_2.png
├── dialog_3.png
├── dialog_4.png
├── fab_image.gif
├── fab_line.gif
├── progress_circular_determinate.gif
├── progress_circular_indeterminate.gif
├── progress_linear_buffer.gif
├── progress_linear_determinate.gif
├── progress_linear_indeterminate.gif
├── progress_linear_query.gif
├── rb.gif
├── slider_continuous.gif
├── slider_discrete.gif
├── snackbar.png
├── spn.gif
├── switch.gif
├── textfield.gif
├── theme.gif
└── tpi.gif
├── material
├── .gitignore
├── bintray.gradle
├── build.gradle
├── install.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ ├── androidx
│ │ └── appcompat
│ │ │ └── widget
│ │ │ └── ListViewCompat.java
│ └── com
│ │ └── rey
│ │ └── material
│ │ ├── app
│ │ ├── BottomSheetDialog.java
│ │ ├── DatePickerDialog.java
│ │ ├── Dialog.java
│ │ ├── DialogFragment.java
│ │ ├── SimpleDialog.java
│ │ ├── ThemeManager.java
│ │ ├── TimePickerDialog.java
│ │ └── ToolbarManager.java
│ │ ├── drawable
│ │ ├── ArrowDrawable.java
│ │ ├── BlankDrawable.java
│ │ ├── CheckBoxDrawable.java
│ │ ├── CircleDrawable.java
│ │ ├── CircularProgressDrawable.java
│ │ ├── ContactChipDrawable.java
│ │ ├── DividerDrawable.java
│ │ ├── LineMorphingDrawable.java
│ │ ├── LinearProgressDrawable.java
│ │ ├── NavigationDrawerDrawable.java
│ │ ├── OvalShadowDrawable.java
│ │ ├── PaddingDrawable.java
│ │ ├── RadioButtonDrawable.java
│ │ ├── RevealDrawable.java
│ │ ├── RippleDrawable.java
│ │ ├── ThemeDrawable.java
│ │ └── ToolbarRippleDrawable.java
│ │ ├── text
│ │ └── style
│ │ │ └── ContactChipSpan.java
│ │ ├── util
│ │ ├── ColorUtil.java
│ │ ├── ThemeUtil.java
│ │ ├── TypefaceUtil.java
│ │ └── ViewUtil.java
│ │ └── widget
│ │ ├── Button.java
│ │ ├── CheckBox.java
│ │ ├── CheckedImageView.java
│ │ ├── CheckedTextView.java
│ │ ├── CircleCheckedTextView.java
│ │ ├── CompoundButton.java
│ │ ├── DatePicker.java
│ │ ├── EditText.java
│ │ ├── FloatingActionButton.java
│ │ ├── FrameLayout.java
│ │ ├── ImageButton.java
│ │ ├── ImageView.java
│ │ ├── LinearLayout.java
│ │ ├── ListPopupWindow.java
│ │ ├── ListView.java
│ │ ├── PopupWindow.java
│ │ ├── ProgressView.java
│ │ ├── RadioButton.java
│ │ ├── RelativeLayout.java
│ │ ├── RippleManager.java
│ │ ├── Slider.java
│ │ ├── SnackBar.java
│ │ ├── Spinner.java
│ │ ├── Switch.java
│ │ ├── TabIndicatorView.java
│ │ ├── TabPageIndicator.java
│ │ ├── TextView.java
│ │ ├── TimePicker.java
│ │ └── YearPicker.java
│ └── res
│ ├── values
│ ├── attrs.xml
│ └── styles.xml
│ └── xml
│ └── nav_states.xml
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/caches
5 | /.idea/libraries
6 | /.idea/modules.xml
7 | /.idea/workspace.xml
8 | /.idea/navEditor.xml
9 | /.idea/assetWizardSettings.xml
10 | .DS_Store
11 | /build
12 | /captures
13 | .externalNativeBuild
14 | .cxx
15 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
22 |
23 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/Material.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/caches
5 | /.idea/libraries
6 | /.idea/modules.xml
7 | /.idea/workspace.xml
8 | /.idea/navEditor.xml
9 | /.idea/assetWizardSettings.xml
10 | .DS_Store
11 | /build
12 | /captures
13 | .externalNativeBuild
14 | .cxx
15 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 28
5 | buildToolsVersion "28.0.3"
6 |
7 | defaultConfig {
8 | applicationId "com.rey.material.demo"
9 | minSdkVersion 14
10 | targetSdkVersion 28
11 | versionCode 7
12 | versionName "0.0.7"
13 | }
14 |
15 | buildTypes {
16 | release {
17 | minifyEnabled false
18 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
19 | }
20 | }
21 |
22 | if(project.hasProperty('MATERIAL_KEYSTORE_FILE')) {
23 | android.signingConfigs {
24 | release {
25 | storeFile file(MATERIAL_KEYSTORE_FILE)
26 | storePassword MATERIAL_KEYSTORE_PASSWORD
27 | keyAlias MATERIAL_KEYSTORE_ALIAS
28 | keyPassword MATERIAL_KEYSTORE_PASSWORD
29 | }
30 | }
31 |
32 | android.buildTypes.release.signingConfig signingConfigs.release
33 | }
34 | }
35 |
36 | ext{
37 | androidXVersion = '1.0.0'
38 | }
39 |
40 | dependencies {
41 | implementation fileTree(dir: 'libs', include: ['*.jar'])
42 | implementation "androidx.appcompat:appcompat:${androidXVersion}"
43 | implementation "androidx.cardview:cardview:${androidXVersion}"
44 | implementation "androidx.recyclerview:recyclerview:${androidXVersion}"
45 | implementation 'com.squareup.picasso:picasso:2.5.0'
46 | implementation 'com.squareup.leakcanary:leakcanary-android:1.3.1'
47 | implementation project(':material')
48 | }
49 |
--------------------------------------------------------------------------------
/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 D:\vietph\android\adt-bundle-windows-x86_64-20140702\sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
12 |
13 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/assets/FreeSans.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rey5137/material/b06373bf1dca194811c6e5374f5380cf04cfc859/app/src/main/assets/FreeSans.ttf
--------------------------------------------------------------------------------
/app/src/main/java/com/rey/material/app/Recipient.java:
--------------------------------------------------------------------------------
1 | package com.rey.material.app;
2 |
3 | import android.os.Parcel;
4 | import android.os.Parcelable;
5 |
6 | /**
7 | * Created by Rey on 3/2/2015.
8 | */
9 | public class Recipient implements Parcelable{
10 | String name;
11 | String number;
12 | String lookupKey;
13 |
14 | public Recipient() {
15 | }
16 |
17 | private Recipient(Parcel in) {
18 | this.name = in.readString();
19 | this.number = in.readString();
20 | this.lookupKey = in.readString();
21 | }
22 |
23 | @Override
24 | public String toString(){
25 | return Recipient.class.getSimpleName() + "[name = " + name + ", number = " + number + ", key = " + lookupKey + "]";
26 | }
27 |
28 |
29 | @Override
30 | public int describeContents() {
31 | return 0;
32 | }
33 |
34 | @Override
35 | public void writeToParcel(Parcel dest, int flags) {
36 | dest.writeString(this.name);
37 | dest.writeString(this.number);
38 | dest.writeString(this.lookupKey);
39 | }
40 |
41 | public static final Creator CREATOR = new Creator() {
42 | public Recipient createFromParcel(Parcel source) {
43 | return new Recipient(source);
44 | }
45 |
46 | public Recipient[] newArray(int size) {
47 | return new Recipient[size];
48 | }
49 | };
50 | }
51 |
--------------------------------------------------------------------------------
/app/src/main/java/com/rey/material/demo/ButtonFragment.java:
--------------------------------------------------------------------------------
1 | package com.rey.material.demo;
2 |
3 | import android.annotation.TargetApi;
4 | import android.os.Build;
5 | import android.os.Bundle;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 |
10 | import androidx.fragment.app.Fragment;
11 |
12 | import com.rey.material.widget.Button;
13 | import com.rey.material.widget.FloatingActionButton;
14 |
15 | public class ButtonFragment extends Fragment {
16 |
17 | public static ButtonFragment newInstance(){
18 | ButtonFragment fragment = new ButtonFragment();
19 |
20 | return fragment;
21 | }
22 |
23 | @TargetApi(Build.VERSION_CODES.HONEYCOMB)
24 | @Override
25 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
26 | View v = inflater.inflate(R.layout.fragment_button, container, false);
27 |
28 | Button bt_flat = (Button)v.findViewById(R.id.button_bt_flat);
29 | Button bt_flat_color = (Button)v.findViewById(R.id.button_bt_flat_color);
30 | Button bt_flat_wave = (Button)v.findViewById(R.id.button_bt_flat_wave);
31 | Button bt_flat_wave_color = (Button)v.findViewById(R.id.button_bt_flat_wave_color);
32 | Button bt_raise = (Button)v.findViewById(R.id.button_bt_raise);
33 | Button bt_raise_color = (Button)v.findViewById(R.id.button_bt_raise_color);
34 | Button bt_raise_wave = (Button)v.findViewById(R.id.button_bt_raise_wave);
35 | Button bt_raise_wave_color = (Button)v.findViewById(R.id.button_bt_raise_wave_color);
36 | FloatingActionButton bt_float = (FloatingActionButton)v.findViewById(R.id.button_bt_float);
37 | FloatingActionButton bt_float_color = (FloatingActionButton)v.findViewById(R.id.button_bt_float_color);
38 | FloatingActionButton bt_float_wave = (FloatingActionButton)v.findViewById(R.id.button_bt_float_wave);
39 | FloatingActionButton bt_float_wave_color = (FloatingActionButton)v.findViewById(R.id.button_bt_float_wave_color);
40 |
41 | View.OnClickListener listener = new View.OnClickListener() {
42 |
43 | @Override
44 | public void onClick(View v) {
45 | if(v instanceof FloatingActionButton){
46 | FloatingActionButton bt = (FloatingActionButton)v;
47 | bt.setLineMorphingState((bt.getLineMorphingState() + 1) % 2, true);
48 | }
49 |
50 | // System.out.println(v + " " + ((RippleDrawable)v.getBackground()).getDelayClickType());
51 | }
52 | };
53 |
54 | View.OnClickListener listener_delay = new View.OnClickListener() {
55 |
56 | @Override
57 | public void onClick(View v) {
58 | if(v instanceof FloatingActionButton){
59 | FloatingActionButton bt = (FloatingActionButton)v;
60 | bt.setLineMorphingState((bt.getLineMorphingState() + 1) % 2, true);
61 | }
62 |
63 | // System.out.println(v + " " + ((RippleDrawable)v.getBackground()).getDelayClickType());
64 | }
65 | };
66 |
67 | bt_flat.setOnClickListener(listener);
68 | bt_flat_wave.setOnClickListener(listener);
69 | bt_raise.setOnClickListener(listener);
70 | bt_raise_wave.setOnClickListener(listener);
71 | bt_float.setOnClickListener(listener);
72 | bt_float_wave.setOnClickListener(listener);
73 |
74 | bt_flat_color.setOnClickListener(listener_delay);
75 | bt_flat_wave_color.setOnClickListener(listener_delay);
76 | bt_raise_color.setOnClickListener(listener_delay);
77 | bt_raise_wave_color.setOnClickListener(listener_delay);
78 | bt_float_color.setOnClickListener(listener_delay);
79 | bt_float_wave_color.setOnClickListener(listener_delay);
80 |
81 | // bt_flat.setOnClickListener(new View.OnClickListener(){
82 | // @Override
83 | // public void onClick(View v) {
84 | // RecurringPickerDialog.Builder builder = new RecurringPickerDialog.Builder(R.style.Material_App_Dialog_Light){
85 | // @Override
86 | // public void onPositiveActionClicked(DialogFragment fragment) {
87 | // RecurringPickerDialog dialog = (RecurringPickerDialog)fragment.getDialog();
88 | // Toast.makeText(fragment.getActivity(), dialog.getRecurring().toString(), Toast.LENGTH_LONG).show();
89 | // fragment.dismiss();
90 | // }
91 | //
92 | // @Override
93 | // public void onNegativeActionClicked(DialogFragment fragment) {
94 | // Toast.makeText(fragment.getActivity(), "Cancelled", Toast.LENGTH_SHORT).show();
95 | // fragment.dismiss();
96 | // }
97 | // };
98 | // Recurring recurring = new Recurring();
99 | // recurring.setStartTime(System.currentTimeMillis());
100 | // recurring.setRepeatMode(Recurring.REPEAT_WEEKLY);
101 | // recurring.setEnabledWeekday(Calendar.SUNDAY, true);
102 | // recurring.setEnabledWeekday(Calendar.TUESDAY, true);
103 | // builder.recurring(recurring)
104 | // .datePickerLayoutStyle(R.style.Material_App_Dialog_DatePicker_Light)
105 | // .positiveAction("OK")
106 | // .negativeAction("CANCEL");
107 | //
108 | // DialogFragment fragment = DialogFragment.newInstance(builder);
109 | // fragment.show(getFragmentManager(), null);
110 | // }
111 | // });
112 |
113 | return v;
114 | }
115 |
116 | @Override
117 | public void onPause() {
118 | super.onPause();
119 | }
120 |
121 | @Override
122 | public void onResume() {
123 | super.onResume();
124 | }
125 |
126 | }
127 |
--------------------------------------------------------------------------------
/app/src/main/java/com/rey/material/demo/CustomViewPager.java:
--------------------------------------------------------------------------------
1 | package com.rey.material.demo;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.view.View;
6 |
7 | import androidx.viewpager.widget.ViewPager;
8 |
9 | import com.rey.material.widget.Slider;
10 | import com.rey.material.widget.Switch;
11 |
12 | /**
13 | * Created by Rey on 3/18/2015.
14 | */
15 | public class CustomViewPager extends ViewPager {
16 |
17 | public CustomViewPager(Context context, AttributeSet attrs) {
18 | super(context, attrs);
19 | }
20 |
21 | public CustomViewPager(Context context) {
22 | super(context);
23 | }
24 |
25 | protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
26 | return super.canScroll(v, checkV, dx, x, y) || (checkV && customCanScroll(v));
27 | }
28 |
29 | protected boolean customCanScroll(View v) {
30 | if (v instanceof Slider || v instanceof Switch)
31 | return true;
32 | return false;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/app/src/main/java/com/rey/material/demo/DemoApplication.java:
--------------------------------------------------------------------------------
1 | package com.rey.material.demo;
2 |
3 | import android.app.Application;
4 | import android.content.Context;
5 |
6 | import com.rey.material.app.ThemeManager;
7 | import com.squareup.leakcanary.RefWatcher;
8 |
9 | /**
10 | * Created by Rey on 5/22/2015.
11 | */
12 | public class DemoApplication extends Application{
13 |
14 | public static RefWatcher getRefWatcher(Context context) {
15 | DemoApplication application = (DemoApplication) context.getApplicationContext();
16 | return application.refWatcher;
17 | }
18 |
19 | private RefWatcher refWatcher;
20 |
21 | @Override public void onCreate() {
22 | super.onCreate();
23 | ThemeManager.init(this, 2, 0, null);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/app/src/main/java/com/rey/material/demo/FabFragment.java:
--------------------------------------------------------------------------------
1 | package com.rey.material.demo;
2 |
3 | import android.annotation.TargetApi;
4 | import android.graphics.drawable.Drawable;
5 | import android.os.Build;
6 | import android.os.Bundle;
7 | import androidx.fragment.app.Fragment;
8 | import android.view.LayoutInflater;
9 | import android.view.View;
10 | import android.view.ViewGroup;
11 |
12 | import com.rey.material.widget.FloatingActionButton;
13 |
14 | public class FabFragment extends Fragment{
15 |
16 |
17 | public static FabFragment newInstance(){
18 | FabFragment fragment = new FabFragment();
19 |
20 | return fragment;
21 | }
22 |
23 | private Drawable[] mDrawables = new Drawable[2];
24 | private int index = 0;
25 |
26 | @TargetApi(Build.VERSION_CODES.HONEYCOMB)
27 | @Override
28 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
29 | View v = inflater.inflate(R.layout.fragment_fab, container, false);
30 |
31 | final FloatingActionButton fab_line = (FloatingActionButton)v.findViewById(R.id.fab_line);
32 | fab_line.setOnClickListener(new View.OnClickListener() {
33 | @Override
34 | public void onClick(View v) {
35 | fab_line.setLineMorphingState((fab_line.getLineMorphingState() + 1) % 2, true);
36 | }
37 | });
38 |
39 | final FloatingActionButton fab_image = (FloatingActionButton)v.findViewById(R.id.fab_image);
40 | mDrawables[0] = v.getResources().getDrawable(R.drawable.ic_autorenew_white_24dp);
41 | mDrawables[1] = v.getResources().getDrawable(R.drawable.ic_done_white_24dp);
42 | fab_image.setIcon(mDrawables[index], false);
43 | fab_image.setOnClickListener(new View.OnClickListener() {
44 | @Override
45 | public void onClick(View v) {
46 | index = (index + 1) % 2;
47 | fab_image.setIcon(mDrawables[index], true);
48 | }
49 | });
50 |
51 | return v;
52 | }
53 |
54 | @Override
55 | public void onPause() {
56 | super.onPause();
57 | }
58 |
59 | @Override
60 | public void onResume() {
61 | super.onResume();
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/app/src/main/java/com/rey/material/demo/ProgressFragment.java:
--------------------------------------------------------------------------------
1 | package com.rey.material.demo;
2 |
3 | import android.os.Bundle;
4 | import android.os.Handler;
5 | import android.os.Handler.Callback;
6 | import android.os.Message;
7 | import androidx.fragment.app.Fragment;
8 | import android.view.LayoutInflater;
9 | import android.view.View;
10 | import android.view.ViewGroup;
11 |
12 | import com.rey.material.widget.ProgressView;
13 |
14 | public class ProgressFragment extends Fragment implements Callback{
15 |
16 | private ProgressView pv_circular;
17 | private ProgressView pv_circular_colors;
18 | private ProgressView pv_circular_inout;
19 | private ProgressView pv_circular_inout_colors;
20 | private ProgressView pv_circular_determinate_in_out;
21 | private ProgressView pv_circular_determinate;
22 | private ProgressView pv_linear;
23 | private ProgressView pv_linear_colors;
24 | private ProgressView pv_linear_determinate;
25 | private ProgressView pv_linear_query;
26 | private ProgressView pv_linear_buffer;
27 |
28 | private Handler mHandler;
29 |
30 | private static final int MSG_START_PROGRESS = 1000;
31 | private static final int MSG_STOP_PROGRESS = 1001;
32 | private static final int MSG_UPDATE_PROGRESS = 1002;
33 | private static final int MSG_UPDATE_QUERY_PROGRESS = 1003;
34 | private static final int MSG_UPDATE_BUFFER_PROGRESS = 1004;
35 |
36 | private static final long PROGRESS_INTERVAL = 7000;
37 | private static final long START_DELAY = 2000;
38 | private static final long PROGRESS_UPDATE_INTERVAL = PROGRESS_INTERVAL / 100;
39 | private static final long START_QUERY_DELAY = PROGRESS_INTERVAL / 2;
40 | private static final long QUERY_PROGRESS_UPDATE_INTERVAL = (PROGRESS_INTERVAL - START_QUERY_DELAY) / 100;
41 | private static final long BUFFER_PROGRESS_UPDATE_INTERVAL = (PROGRESS_INTERVAL - START_QUERY_DELAY) / 100;
42 |
43 | public static ProgressFragment newInstance(){
44 | ProgressFragment fragment = new ProgressFragment();
45 | return fragment;
46 | }
47 |
48 | @Override
49 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
50 | View v = inflater.inflate(R.layout.fragment_progress, container, false);
51 |
52 | pv_circular = (ProgressView)v.findViewById(R.id.progress_pv_circular);
53 | pv_circular_colors = (ProgressView)v.findViewById(R.id.progress_pv_circular_colors);
54 | pv_circular_inout = (ProgressView)v.findViewById(R.id.progress_pv_circular_inout);
55 | pv_circular_inout_colors = (ProgressView)v.findViewById(R.id.progress_pv_circular_inout_colors);
56 | pv_circular_determinate_in_out = (ProgressView)v.findViewById(R.id.progress_pv_circular_determinate_in_out);
57 | pv_circular_determinate = (ProgressView)v.findViewById(R.id.progress_pv_circular_determinate);
58 | pv_linear = (ProgressView)v.findViewById(R.id.progress_pv_linear);
59 | pv_linear_colors = (ProgressView)v.findViewById(R.id.progress_pv_linear_colors);
60 | pv_linear_determinate = (ProgressView)v.findViewById(R.id.progress_pv_linear_determinate);
61 | pv_linear_query = (ProgressView)v.findViewById(R.id.progress_pv_linear_query);
62 | pv_linear_buffer = (ProgressView)v.findViewById(R.id.progress_pv_linear_buffer);
63 |
64 | mHandler = new Handler(this);
65 |
66 | return v;
67 | }
68 |
69 | @Override
70 | public void onPause() {
71 | super.onPause();
72 |
73 | mHandler.removeCallbacksAndMessages(null);
74 | pv_circular_determinate_in_out.setVisibility(View.GONE);
75 | }
76 |
77 | @Override
78 | public void onResume() {
79 | super.onResume();
80 | mHandler.sendEmptyMessageDelayed(MSG_START_PROGRESS, START_DELAY);
81 | }
82 |
83 | @Override
84 | public boolean handleMessage(Message msg) {
85 | switch (msg.what) {
86 | case MSG_START_PROGRESS:
87 | pv_circular.start();
88 | pv_circular_colors.start();
89 | pv_circular_inout.start();
90 | pv_circular_inout_colors.start();
91 | pv_circular_determinate_in_out.setProgress(0f);
92 | pv_circular_determinate_in_out.start();
93 | pv_circular_determinate.setProgress(0f);
94 | pv_circular_determinate.start();
95 | pv_linear.start();
96 | pv_linear_colors.start();
97 | pv_linear_determinate.setProgress(0f);
98 | pv_linear_determinate.start();
99 | pv_linear_query.setProgress(0f);
100 | pv_linear_query.start();
101 | pv_linear_buffer.setProgress(0f);
102 | pv_linear_buffer.setSecondaryProgress(0f);
103 | pv_linear_buffer.start();
104 | mHandler.sendEmptyMessageDelayed(MSG_STOP_PROGRESS, PROGRESS_INTERVAL);
105 | mHandler.sendEmptyMessageDelayed(MSG_UPDATE_PROGRESS, PROGRESS_UPDATE_INTERVAL);
106 | mHandler.sendEmptyMessageDelayed(MSG_UPDATE_QUERY_PROGRESS, START_QUERY_DELAY);
107 | mHandler.sendEmptyMessageDelayed(MSG_UPDATE_BUFFER_PROGRESS, BUFFER_PROGRESS_UPDATE_INTERVAL);
108 | break;
109 | case MSG_UPDATE_QUERY_PROGRESS:
110 | pv_linear_query.setProgress(pv_linear_query.getProgress() + 0.01f);
111 |
112 | if(pv_linear_query.getProgress() < 1f)
113 | mHandler.sendEmptyMessageDelayed(MSG_UPDATE_QUERY_PROGRESS, QUERY_PROGRESS_UPDATE_INTERVAL);
114 | else
115 | pv_linear_query.stop();
116 | break;
117 | case MSG_UPDATE_BUFFER_PROGRESS:
118 | pv_linear_buffer.setSecondaryProgress(pv_linear_buffer.getSecondaryProgress() + 0.01f);
119 |
120 | if(pv_linear_buffer.getSecondaryProgress() < 1f)
121 | mHandler.sendEmptyMessageDelayed(MSG_UPDATE_BUFFER_PROGRESS, BUFFER_PROGRESS_UPDATE_INTERVAL);
122 | break;
123 | case MSG_UPDATE_PROGRESS:
124 | pv_circular_determinate_in_out.setProgress(pv_circular_determinate_in_out.getProgress() + 0.01f);
125 | pv_circular_determinate.setProgress(pv_circular_determinate.getProgress() + 0.01f);
126 |
127 | pv_linear_determinate.setProgress(pv_linear_determinate.getProgress() + 0.01f);
128 | pv_linear_buffer.setProgress(pv_linear_buffer.getProgress() + 0.01f);
129 | if(pv_circular_determinate_in_out.getProgress() < 1f)
130 | mHandler.sendEmptyMessageDelayed(MSG_UPDATE_PROGRESS, PROGRESS_UPDATE_INTERVAL);
131 | else{
132 | pv_circular_determinate_in_out.stop();
133 | pv_circular_determinate.stop();
134 | pv_linear_determinate.stop();
135 | pv_linear_buffer.stop();
136 | }
137 | break;
138 | case MSG_STOP_PROGRESS:
139 | pv_circular.stop();
140 | pv_circular_colors.stop();
141 | pv_circular_inout.stop();
142 | pv_circular_inout_colors.stop();
143 | pv_linear.stop();
144 | pv_linear_colors.stop();
145 | mHandler.sendEmptyMessageDelayed(MSG_START_PROGRESS, START_DELAY);
146 | break;
147 | }
148 | return false;
149 | }
150 |
151 | }
152 |
--------------------------------------------------------------------------------
/app/src/main/java/com/rey/material/demo/SliderFragment.java:
--------------------------------------------------------------------------------
1 | package com.rey.material.demo;
2 |
3 | import android.annotation.TargetApi;
4 | import android.os.Build;
5 | import android.os.Bundle;
6 | import androidx.fragment.app.Fragment;
7 | import android.view.LayoutInflater;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 | import android.widget.TextView;
11 |
12 | import com.rey.material.widget.Slider;
13 |
14 | public class SliderFragment extends Fragment{
15 |
16 |
17 | public static SliderFragment newInstance(){
18 | SliderFragment fragment = new SliderFragment();
19 |
20 | return fragment;
21 | }
22 |
23 | @TargetApi(Build.VERSION_CODES.HONEYCOMB)
24 | @Override
25 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
26 | View v = inflater.inflate(R.layout.fragment_slider, container, false);
27 |
28 | Slider sl_continuous = (Slider)v.findViewById(R.id.slider_sl_continuous);
29 | final TextView tv_continuous = (TextView)v.findViewById(R.id.slider_tv_continuous);
30 | tv_continuous.setText(String.format("pos=%.1f value=%d", sl_continuous.getPosition(), sl_continuous.getValue()));
31 | sl_continuous.setOnPositionChangeListener(new Slider.OnPositionChangeListener() {
32 | @Override
33 | public void onPositionChanged(Slider view, boolean fromUser, float oldPos, float newPos, int oldValue, int newValue) {
34 | tv_continuous.setText(String.format("pos=%.1f value=%d", newPos, newValue));
35 | }
36 | });
37 |
38 | Slider sl_discrete = (Slider)v.findViewById(R.id.slider_sl_discrete);
39 | final TextView tv_discrete = (TextView)v.findViewById(R.id.slider_tv_discrete);
40 | tv_discrete.setText(String.format("pos=%.1f value=%d", sl_discrete.getPosition(), sl_discrete.getValue()));
41 | sl_discrete.setOnPositionChangeListener(new Slider.OnPositionChangeListener() {
42 | @Override
43 | public void onPositionChanged(Slider view, boolean fromUser, float oldPos, float newPos, int oldValue, int newValue) {
44 | tv_discrete.setText(String.format("pos=%.1f value=%d", newPos, newValue));
45 | }
46 | });
47 |
48 | return v;
49 | }
50 |
51 | @Override
52 | public void onPause() {
53 | super.onPause();
54 | }
55 |
56 | @Override
57 | public void onResume() {
58 | super.onResume();
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/app/src/main/java/com/rey/material/demo/SnackbarFragment.java:
--------------------------------------------------------------------------------
1 | package com.rey.material.demo;
2 |
3 | import android.annotation.TargetApi;
4 | import android.os.Build;
5 | import android.os.Bundle;
6 | import androidx.fragment.app.Fragment;
7 | import android.view.LayoutInflater;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 |
11 | import com.rey.material.widget.Button;
12 | import com.rey.material.widget.SnackBar;
13 |
14 | public class SnackbarFragment extends Fragment{
15 |
16 | SnackBar mSnackBar;
17 |
18 | public static SnackbarFragment newInstance(){
19 | SnackbarFragment fragment = new SnackbarFragment();
20 |
21 | return fragment;
22 | }
23 |
24 | @TargetApi(Build.VERSION_CODES.HONEYCOMB)
25 | @Override
26 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
27 | View v = inflater.inflate(R.layout.fragment_snackbar, container, false);
28 |
29 | Button bt_mobile_single = (Button)v.findViewById(R.id.snackbar_bt_mobile_single);
30 | Button bt_mobile_multi = (Button)v.findViewById(R.id.snackbar_bt_mobile_multi);
31 | Button bt_tablet_single = (Button)v.findViewById(R.id.snackbar_bt_tablet_single);
32 | Button bt_tablet_multi = (Button)v.findViewById(R.id.snackbar_bt_tablet_multi);
33 |
34 | View.OnClickListener listener = new View.OnClickListener() {
35 |
36 | @Override
37 | public void onClick(View v) {
38 | if(mSnackBar.getState() == SnackBar.STATE_SHOWN)
39 | mSnackBar.dismiss();
40 | else{
41 | switch (v.getId()) {
42 | case R.id.snackbar_bt_mobile_single:
43 | mSnackBar.applyStyle(R.style.SnackBarSingleLine);
44 | mSnackBar.show();
45 | break;
46 | case R.id.snackbar_bt_mobile_multi:
47 | mSnackBar.applyStyle(R.style.SnackBarMultiLine);
48 | mSnackBar.show();
49 | break;
50 | case R.id.snackbar_bt_tablet_single:
51 | mSnackBar.applyStyle(R.style.Material_Widget_SnackBar_Tablet);
52 | mSnackBar.text("This is single-line snackbar.")
53 | .actionText("CLOSE")
54 | .duration(0)
55 | .show();
56 | break;
57 | case R.id.snackbar_bt_tablet_multi:
58 | mSnackBar.applyStyle(R.style.Material_Widget_SnackBar_Tablet_MultiLine);
59 | mSnackBar.text("This is multi-line snackbar.\nIt will auto-close after 5s.")
60 | .actionText(null)
61 | .duration(5000)
62 | .show();
63 | break;
64 | }
65 | }
66 | }
67 | };
68 |
69 |
70 | bt_mobile_single.setOnClickListener(listener);
71 | bt_mobile_multi.setOnClickListener(listener);
72 | bt_tablet_single.setOnClickListener(listener);
73 | bt_tablet_multi.setOnClickListener(listener);
74 |
75 | mSnackBar = ((MainActivity)getActivity()).getSnackBar();
76 |
77 | return v;
78 | }
79 |
80 | @Override
81 | public void onPause() {
82 | super.onPause();
83 | }
84 |
85 | @Override
86 | public void onResume() {
87 | super.onResume();
88 | }
89 |
90 | }
91 |
--------------------------------------------------------------------------------
/app/src/main/java/com/rey/material/demo/SpinnersFragment.java:
--------------------------------------------------------------------------------
1 | package com.rey.material.demo;
2 |
3 | import android.annotation.TargetApi;
4 | import android.graphics.drawable.Drawable;
5 | import android.os.Build;
6 | import android.os.Bundle;
7 | import androidx.fragment.app.Fragment;
8 | import android.view.LayoutInflater;
9 | import android.view.View;
10 | import android.view.ViewGroup;
11 | import android.widget.ArrayAdapter;
12 |
13 | import com.rey.material.widget.FloatingActionButton;
14 | import com.rey.material.widget.Spinner;
15 |
16 | public class SpinnersFragment extends Fragment{
17 |
18 |
19 | public static SpinnersFragment newInstance(){
20 | SpinnersFragment fragment = new SpinnersFragment();
21 |
22 | return fragment;
23 | }
24 |
25 | private Drawable[] mDrawables = new Drawable[2];
26 | private int index = 0;
27 |
28 | @TargetApi(Build.VERSION_CODES.HONEYCOMB)
29 | @Override
30 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
31 | View v = inflater.inflate(R.layout.fragment_spinner, container, false);
32 |
33 | Spinner spn_label = (Spinner)v.findViewById(R.id.spinner_label);
34 | Spinner spn_no_arrow = (Spinner)v.findViewById(R.id.spinner_no_arrow);
35 | String[] items = new String[20];
36 | for(int i = 0; i < items.length; i++)
37 | items[i] = "Item " + String.valueOf(i + 1);
38 | ArrayAdapter adapter = new ArrayAdapter<>(getActivity(), R.layout.row_spn, items);
39 | adapter.setDropDownViewResource(R.layout.row_spn_dropdown);
40 | spn_label.setAdapter(adapter);
41 | spn_no_arrow.setAdapter(adapter);
42 |
43 | return v;
44 | }
45 |
46 | @Override
47 | public void onPause() {
48 | super.onPause();
49 | }
50 |
51 | @Override
52 | public void onResume() {
53 | super.onResume();
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/app/src/main/java/com/rey/material/demo/SwitchesFragment.java:
--------------------------------------------------------------------------------
1 | package com.rey.material.demo;
2 |
3 | import android.annotation.TargetApi;
4 | import android.os.Build;
5 | import android.os.Bundle;
6 | import androidx.fragment.app.Fragment;
7 | import android.view.LayoutInflater;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 | import android.widget.CompoundButton;
11 |
12 | import com.rey.material.widget.RadioButton;
13 |
14 | public class SwitchesFragment extends Fragment{
15 |
16 | RadioButton rb1;
17 | RadioButton rb2;
18 | RadioButton rb3;
19 |
20 | public static SwitchesFragment newInstance(){
21 | SwitchesFragment fragment = new SwitchesFragment();
22 |
23 | return fragment;
24 | }
25 |
26 | @TargetApi(Build.VERSION_CODES.HONEYCOMB)
27 | @Override
28 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
29 | View v = inflater.inflate(R.layout.fragment_switches, container, false);
30 |
31 | rb1 = (RadioButton)v.findViewById(R.id.switches_rb1);
32 | rb2 = (RadioButton)v.findViewById(R.id.switches_rb2);
33 | rb3 = (RadioButton)v.findViewById(R.id.switches_rb3);
34 |
35 | CompoundButton.OnCheckedChangeListener listener = new CompoundButton.OnCheckedChangeListener() {
36 |
37 | @Override
38 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
39 | if(isChecked){
40 | rb1.setChecked(rb1 == buttonView);
41 | rb2.setChecked(rb2 == buttonView);
42 | rb3.setChecked(rb3 == buttonView);
43 | }
44 |
45 | }
46 |
47 | };
48 |
49 | rb1.setOnCheckedChangeListener(listener);
50 | rb2.setOnCheckedChangeListener(listener);
51 | rb3.setOnCheckedChangeListener(listener);
52 |
53 | return v;
54 | }
55 |
56 | @Override
57 | public void onPause() {
58 | super.onPause();
59 | }
60 |
61 | @Override
62 | public void onResume() {
63 | super.onResume();
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/app/src/main/java/com/rey/material/demo/TextfieldFragment.java:
--------------------------------------------------------------------------------
1 | package com.rey.material.demo;
2 |
3 | import com.rey.material.app.ContactEditText;
4 | import com.rey.material.drawable.ContactChipDrawable;
5 | import com.rey.material.text.style.ContactChipSpan;
6 | import com.rey.material.util.ThemeUtil;
7 | import com.rey.material.widget.EditText;
8 |
9 | import android.content.Context;
10 | import android.database.Cursor;
11 | import android.graphics.Bitmap;
12 | import android.graphics.BitmapFactory;
13 | import android.graphics.Typeface;
14 | import android.os.Build;
15 | import android.os.Bundle;
16 | import android.provider.ContactsContract;
17 | import androidx.fragment.app.Fragment;
18 | import android.text.SpannableStringBuilder;
19 | import android.text.Spanned;
20 | import android.view.KeyEvent;
21 | import android.view.LayoutInflater;
22 | import android.view.View;
23 | import android.view.ViewGroup;
24 | import android.widget.BaseAdapter;
25 | import android.widget.Filter;
26 | import android.widget.Filterable;
27 | import android.widget.TextView;
28 |
29 | import java.util.ArrayList;
30 |
31 | import static android.provider.ContactsContract.CommonDataKinds.Phone;
32 |
33 | public class TextfieldFragment extends Fragment{
34 |
35 | public static TextfieldFragment newInstance(){
36 | TextfieldFragment fragment = new TextfieldFragment();
37 |
38 | return fragment;
39 | }
40 |
41 | @Override
42 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
43 | View v = inflater.inflate(R.layout.fragment_textfield, container, false);
44 |
45 | final EditText et_helper = (EditText)v.findViewById(R.id.textfield_et_helper);
46 |
47 | et_helper.setOnKeyListener(new View.OnKeyListener() {
48 |
49 | @Override
50 | public boolean onKey(View v, int keyCode, KeyEvent event) {
51 | if(keyCode == KeyEvent.KEYCODE_ENTER && event.getAction() == KeyEvent.ACTION_UP)
52 | et_helper.setError("Password is incorrect.");
53 |
54 | return false;
55 | }
56 |
57 | });
58 |
59 | et_helper.setOnFocusChangeListener(new View.OnFocusChangeListener() {
60 |
61 | @Override
62 | public void onFocusChange(View v, boolean hasFocus) {
63 | if(hasFocus)
64 | et_helper.setError(null);
65 | }
66 |
67 | });
68 |
69 | final EditText et_helper_error = (EditText)v.findViewById(R.id.textfield_et_helper_error);
70 |
71 | et_helper_error.setOnKeyListener(new View.OnKeyListener() {
72 |
73 | @Override
74 | public boolean onKey(View v, int keyCode, KeyEvent event) {
75 | if(keyCode == KeyEvent.KEYCODE_ENTER && event.getAction() == KeyEvent.ACTION_UP)
76 | et_helper_error.setError("Password is incorrect.");
77 |
78 | return false;
79 | }
80 |
81 | });
82 |
83 | et_helper_error.setOnFocusChangeListener(new View.OnFocusChangeListener() {
84 |
85 | @Override
86 | public void onFocusChange(View v, boolean hasFocus) {
87 | if(hasFocus)
88 | et_helper_error.setError(null);
89 | }
90 |
91 | });
92 |
93 | ContactEditText a = (ContactEditText) v.findViewById(R.id.textfield_tv);
94 |
95 | return v;
96 | }
97 |
98 | @Override
99 | public void onPause() {
100 | super.onPause();
101 | }
102 |
103 | @Override
104 | public void onResume() {
105 | super.onResume();
106 | }
107 |
108 |
109 | }
110 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/anim_scale_in.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/anim_scale_out.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/bg_bt_raise.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rey5137/material/b06373bf1dca194811c6e5374f5380cf04cfc859/app/src/main/res/drawable-xhdpi/bg_bt_raise.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/bg_bt_raise_color.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rey5137/material/b06373bf1dca194811c6e5374f5380cf04cfc859/app/src/main/res/drawable-xhdpi/bg_bt_raise_color.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/bg_bt_raise_dark.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rey5137/material/b06373bf1dca194811c6e5374f5380cf04cfc859/app/src/main/res/drawable-xhdpi/bg_bt_raise_dark.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/bg_toolbar_dark.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/bg_toolbar_light.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_autorenew_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rey5137/material/b06373bf1dca194811c6e5374f5380cf04cfc859/app/src/main/res/drawable-xhdpi/ic_autorenew_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_cancel_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rey5137/material/b06373bf1dca194811c6e5374f5380cf04cfc859/app/src/main/res/drawable-xhdpi/ic_cancel_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_done_all_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rey5137/material/b06373bf1dca194811c6e5374f5380cf04cfc859/app/src/main/res/drawable-xhdpi/ic_done_all_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_done_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rey5137/material/b06373bf1dca194811c6e5374f5380cf04cfc859/app/src/main/res/drawable-xhdpi/ic_done_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rey5137/material/b06373bf1dca194811c6e5374f5380cf04cfc859/app/src/main/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_user.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rey5137/material/b06373bf1dca194811c6e5374f5380cf04cfc859/app/src/main/res/drawable-xhdpi/ic_user.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_visibility_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rey5137/material/b06373bf1dca194811c6e5374f5380cf04cfc859/app/src/main/res/drawable-xhdpi/ic_visibility_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/popup_background_dark.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rey5137/material/b06373bf1dca194811c6e5374f5380cf04cfc859/app/src/main/res/drawable-xhdpi/popup_background_dark.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_window_dark.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_window_light.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/color_divider_dark.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/color_divider_light.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/color_label_dark.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/color_label_light.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/color_switch_dark.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/color_thumb_dark.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/color_thumb_light.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/color_tpi_dark.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/color_tpi_light.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/color_track_dark.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/color_track_light.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/color_wv_text.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
12 |
13 |
17 |
18 |
24 |
25 |
32 |
33 |
37 |
38 |
39 |
40 |
46 |
47 |
48 |
49 |
55 |
56 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_fab.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
15 |
16 |
21 |
22 |
28 |
29 |
34 |
35 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_slider.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
15 |
16 |
21 |
22 |
30 |
31 |
37 |
38 |
46 |
47 |
52 |
53 |
61 |
62 |
68 |
69 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_snackbar.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
15 |
16 |
21 |
22 |
31 |
32 |
42 |
43 |
48 |
49 |
58 |
59 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_spinner.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
15 |
16 |
25 |
26 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_switches.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
15 |
16 |
21 |
22 |
30 |
31 |
39 |
40 |
48 |
49 |
54 |
55 |
63 |
64 |
72 |
73 |
81 |
82 |
87 |
88 |
96 |
97 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_textfield.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
14 |
15 |
29 |
30 |
39 |
40 |
51 |
52 |
63 |
64 |
75 |
76 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_dialog_custom.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
18 |
19 |
29 |
30 |
40 |
41 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/rd_item_dropdown_end.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/rd_item_dropdown_mode.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/rd_item_end.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/rd_item_mode.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/row_contact_replace.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/row_contact_selected.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/row_drawer.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/row_spn.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/row_spn_dropdown.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_bottomsheet.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
22 |
23 |
31 |
32 |
36 |
37 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
41 |
--------------------------------------------------------------------------------
/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 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | #FF03A9F4
5 | #ff0171c9
6 | #FF00E5FF
7 | #FF78909C
8 | #FF03A9F4
9 | #FF78909C
10 |
11 | #3303A9F4
12 | #9003A9F4
13 | #9078909C
14 | #9003A9F4
15 | #3300E5FF
16 | #9000E5FF
17 |
18 |
19 | - #FF03A9F4
20 | - #FFD8433C
21 | - #FFF2AF3A
22 | - #FF279B5E
23 |
24 |
25 |
26 | - #FF00E5FF
27 | - #ffd81d5a
28 | - #fff27512
29 | - #ff63bc34
30 |
31 |
32 |
33 | - #4B03A9F4
34 | - #3303A9F4
35 | - #1903A9F4
36 |
37 |
38 |
39 | - #4B00E5FF
40 | - #3300E5FF
41 | - #1900E5FF
42 |
43 |
44 | #FFFFFFFF
45 | #99FFFFFF
46 |
47 | @color/colorControlActivated
48 | #FF6D6D6D
49 | #FFC1C1C1
50 |
51 |
52 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 240dp
4 | 20sp
5 | 16sp
6 |
7 | 36dp
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | MaterialDemo
4 |
5 | Repeat
6 | Daily
7 | Weekly
8 | Monthly
9 | Yearly
10 | None
11 | Every
12 | day
13 | days
14 | week
15 | weeks
16 | month
17 | months
18 | year
19 | years
20 | Forever
21 | Until
22 | Until a date
23 | For
24 | For a number of events
25 | on the same day each month
26 | on every last %s
27 | on every first %s
28 | on every second %s
29 | on every third %s
30 | on every fourth %s
31 | event
32 | events
33 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
11 |
12 |
15 |
16 |
17 |
18 |
22 |
23 |
27 |
28 |
32 |
33 |
34 |
35 |
40 |
41 |
46 |
47 |
51 |
52 |
56 |
57 |
58 |
68 |
69 |
82 |
83 |
98 |
99 |
109 |
110 |
111 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/fab_icon_states.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | - 0.5
7 | - 0
8 | - 0.5
9 | - 1
10 |
11 | - 0
12 | - 0.5
13 | - 1
14 | - 0.5
15 |
16 |
17 |
18 |
19 |
20 | - 0.633
21 | - 0.161
22 | - 0
23 | - 0.793
24 |
25 | - 0.633
26 | - 0.161
27 | - 1
28 | - 0.527
29 |
30 |
31 |
32 | - 0
33 | - 1
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/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 | google()
6 | jcenter()
7 | maven {
8 | url 'https://maven.google.com'
9 | }
10 | }
11 | dependencies {
12 | classpath 'com.android.tools.build:gradle:3.4.1'
13 | classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4'
14 | classpath 'com.github.dcendents:android-maven-gradle-plugin:1.4.1'
15 | // NOTE: Do not place your application dependencies here; they belong
16 | // in the individual module build.gradle files
17 | }
18 | }
19 |
20 | allprojects {
21 | repositories {
22 | google()
23 | jcenter()
24 | }
25 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 |
20 |
--------------------------------------------------------------------------------
/gradle/local.properties:
--------------------------------------------------------------------------------
1 | ## This file is automatically generated by Android Studio.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must *NOT* be checked into Version Control Systems,
5 | # as it contains information specific to your local configuration.
6 | #
7 | # Location of the SDK. This is only used by Gradle.
8 | # For customization when using a Version Control System, please read the
9 | # header note.
10 | #Tue Dec 09 22:34:29 ICT 2014
11 | sdk.dir=C\:\\ADT\\sdk
12 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rey5137/material/b06373bf1dca194811c6e5374f5380cf04cfc859/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Jun 12 11:01:23 ICT 2019
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # 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 |
--------------------------------------------------------------------------------
/image/bottomsheet.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rey5137/material/b06373bf1dca194811c6e5374f5380cf04cfc859/image/bottomsheet.gif
--------------------------------------------------------------------------------
/image/button_flat_touch.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rey5137/material/b06373bf1dca194811c6e5374f5380cf04cfc859/image/button_flat_touch.gif
--------------------------------------------------------------------------------
/image/button_flat_wave.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rey5137/material/b06373bf1dca194811c6e5374f5380cf04cfc859/image/button_flat_wave.gif
--------------------------------------------------------------------------------
/image/button_raise_touch.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rey5137/material/b06373bf1dca194811c6e5374f5380cf04cfc859/image/button_raise_touch.gif
--------------------------------------------------------------------------------
/image/button_raise_wave.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rey5137/material/b06373bf1dca194811c6e5374f5380cf04cfc859/image/button_raise_wave.gif
--------------------------------------------------------------------------------
/image/cb.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rey5137/material/b06373bf1dca194811c6e5374f5380cf04cfc859/image/cb.gif
--------------------------------------------------------------------------------
/image/dialog_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rey5137/material/b06373bf1dca194811c6e5374f5380cf04cfc859/image/dialog_1.png
--------------------------------------------------------------------------------
/image/dialog_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rey5137/material/b06373bf1dca194811c6e5374f5380cf04cfc859/image/dialog_2.png
--------------------------------------------------------------------------------
/image/dialog_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rey5137/material/b06373bf1dca194811c6e5374f5380cf04cfc859/image/dialog_3.png
--------------------------------------------------------------------------------
/image/dialog_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rey5137/material/b06373bf1dca194811c6e5374f5380cf04cfc859/image/dialog_4.png
--------------------------------------------------------------------------------
/image/fab_image.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rey5137/material/b06373bf1dca194811c6e5374f5380cf04cfc859/image/fab_image.gif
--------------------------------------------------------------------------------
/image/fab_line.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rey5137/material/b06373bf1dca194811c6e5374f5380cf04cfc859/image/fab_line.gif
--------------------------------------------------------------------------------
/image/progress_circular_determinate.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rey5137/material/b06373bf1dca194811c6e5374f5380cf04cfc859/image/progress_circular_determinate.gif
--------------------------------------------------------------------------------
/image/progress_circular_indeterminate.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rey5137/material/b06373bf1dca194811c6e5374f5380cf04cfc859/image/progress_circular_indeterminate.gif
--------------------------------------------------------------------------------
/image/progress_linear_buffer.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rey5137/material/b06373bf1dca194811c6e5374f5380cf04cfc859/image/progress_linear_buffer.gif
--------------------------------------------------------------------------------
/image/progress_linear_determinate.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rey5137/material/b06373bf1dca194811c6e5374f5380cf04cfc859/image/progress_linear_determinate.gif
--------------------------------------------------------------------------------
/image/progress_linear_indeterminate.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rey5137/material/b06373bf1dca194811c6e5374f5380cf04cfc859/image/progress_linear_indeterminate.gif
--------------------------------------------------------------------------------
/image/progress_linear_query.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rey5137/material/b06373bf1dca194811c6e5374f5380cf04cfc859/image/progress_linear_query.gif
--------------------------------------------------------------------------------
/image/rb.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rey5137/material/b06373bf1dca194811c6e5374f5380cf04cfc859/image/rb.gif
--------------------------------------------------------------------------------
/image/slider_continuous.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rey5137/material/b06373bf1dca194811c6e5374f5380cf04cfc859/image/slider_continuous.gif
--------------------------------------------------------------------------------
/image/slider_discrete.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rey5137/material/b06373bf1dca194811c6e5374f5380cf04cfc859/image/slider_discrete.gif
--------------------------------------------------------------------------------
/image/snackbar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rey5137/material/b06373bf1dca194811c6e5374f5380cf04cfc859/image/snackbar.png
--------------------------------------------------------------------------------
/image/spn.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rey5137/material/b06373bf1dca194811c6e5374f5380cf04cfc859/image/spn.gif
--------------------------------------------------------------------------------
/image/switch.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rey5137/material/b06373bf1dca194811c6e5374f5380cf04cfc859/image/switch.gif
--------------------------------------------------------------------------------
/image/textfield.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rey5137/material/b06373bf1dca194811c6e5374f5380cf04cfc859/image/textfield.gif
--------------------------------------------------------------------------------
/image/theme.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rey5137/material/b06373bf1dca194811c6e5374f5380cf04cfc859/image/theme.gif
--------------------------------------------------------------------------------
/image/tpi.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rey5137/material/b06373bf1dca194811c6e5374f5380cf04cfc859/image/tpi.gif
--------------------------------------------------------------------------------
/material/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/caches
5 | /.idea/libraries
6 | /.idea/modules.xml
7 | /.idea/workspace.xml
8 | /.idea/navEditor.xml
9 | /.idea/assetWizardSettings.xml
10 | .DS_Store
11 | /build
12 | /captures
13 | .externalNativeBuild
14 | .cxx
15 |
--------------------------------------------------------------------------------
/material/bintray.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.jfrog.bintray'
2 |
3 | ext {
4 | bintrayUser = project.hasProperty('BINTRAY_USERNAME') ? BINTRAY_USERNAME : ""
5 | bintrayApiKey = project.hasProperty('BINTRAY_APIKEY') ? BINTRAY_APIKEY : ""
6 | bintrayGpgPassword = project.hasProperty('GPG_PASSWORD') ? GPG_PASSWORD : ""
7 |
8 | bintrayRepo = "maven"
9 | bintrayName = "material"
10 |
11 | libraryVersion = "1.3.1"
12 | libraryDescription = "An Android library to bring Material Design UI to pre-Lolipop Android."
13 |
14 | siteUrl = "https://github.com/rey5137/material"
15 | gitUrl = "https://github.com/rey5137/material.git"
16 |
17 | }
18 |
19 | version = libraryVersion
20 |
21 | task sourcesJar(type: Jar) {
22 | from android.sourceSets.main.java.srcDirs
23 | classifier = 'sources'
24 | }
25 |
26 | task javadoc(type: Javadoc) {
27 | source = android.sourceSets.main.java.srcDirs
28 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
29 | }
30 |
31 | task javadocJar(type: Jar, dependsOn: javadoc) {
32 | classifier = 'javadoc'
33 | from javadoc.destinationDir
34 | }
35 |
36 | artifacts {
37 | archives javadocJar
38 | archives sourcesJar
39 | }
40 |
41 | bintray {
42 | user = bintrayUser
43 | key = bintrayApiKey
44 |
45 | configurations = ['archives']
46 | pkg {
47 | repo = bintrayRepo
48 | name = bintrayName
49 | desc = libraryDescription
50 | websiteUrl = siteUrl
51 | vcsUrl = gitUrl
52 | licenses = ["Apache-2.0"]
53 | publish = true
54 | publicDownloadNumbers = true
55 | version {
56 | desc = libraryDescription
57 | gpg {
58 | sign = true //Determines whether to GPG sign the files. The default is false
59 | passphrase = bintrayGpgPassword
60 | //Optional. The passphrase for GPG signing'
61 | }
62 | }
63 | }
64 |
65 | }
--------------------------------------------------------------------------------
/material/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 28
5 | buildToolsVersion "28.0.3"
6 |
7 | defaultConfig {
8 | minSdkVersion 14
9 | targetSdkVersion 28
10 | versionCode 22
11 | versionName "1.3.1"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | }
20 |
21 | ext{
22 | androidXVersion = '1.0.0'
23 | }
24 |
25 | dependencies {
26 | implementation fileTree(dir: 'libs', include: ['*.jar'])
27 | testImplementation 'junit:junit:4.12'
28 | implementation "androidx.appcompat:appcompat:${androidXVersion}"
29 | implementation "androidx.cardview:cardview:${androidXVersion}"
30 | implementation "androidx.recyclerview:recyclerview:${androidXVersion}"
31 | }
32 |
33 | tasks.withType(Javadoc) {
34 | options.addStringOption('Xdoclint:none', '-quiet')
35 | options.addStringOption('encoding', 'UTF-8')
36 | options.addStringOption('charSet', 'UTF-8')
37 | }
38 |
39 | // Place it at the end of the file
40 | apply from: 'install.gradle'
41 | apply from: 'bintray.gradle'
42 |
--------------------------------------------------------------------------------
/material/install.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.github.dcendents.android-maven'
2 |
3 | ext {
4 | publishedGroupId = "com.github.rey5137"
5 |
6 | artifact = "material"
7 | libraryName = "Material Library"
8 | libraryDescription = "An Android library to bring Material Design UI to pre-Lolipop Android."
9 | siteUrl = "https://github.com/rey5137/material"
10 |
11 | developerId = "rey5137"
12 | developerName = "Rey Pham"
13 | developerEmail = "pea5137@gmail.com"
14 | }
15 |
16 | group = publishedGroupId
17 |
18 | install {
19 | repositories.mavenInstaller {
20 | pom {
21 | project {
22 | packaging 'aar'
23 | groupId publishedGroupId
24 | artifactId artifact
25 | name libraryName
26 | description libraryDescription
27 | url siteUrl
28 |
29 | licenses {
30 | license {
31 | name 'The Apache Software License, Version 2.0'
32 | url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
33 | }
34 | }
35 |
36 | developers {
37 | developer {
38 | id developerId
39 | name developerName
40 | email developerEmail
41 | }
42 | }
43 |
44 | scm {
45 | connection siteUrl
46 | developerConnection siteUrl
47 | url siteUrl
48 | }
49 | }
50 | }
51 | }
52 | }
--------------------------------------------------------------------------------
/material/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 D:\vietph\android\adt-bundle-windows-x86_64-20140702\sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/material/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/material/src/main/java/com/rey/material/app/DialogFragment.java:
--------------------------------------------------------------------------------
1 | package com.rey.material.app;
2 |
3 | import android.content.Context;
4 | import android.content.DialogInterface;
5 | import android.os.Bundle;
6 | import android.os.Parcelable;
7 | import androidx.annotation.NonNull;
8 | import android.view.View;
9 |
10 | /**
11 | * Created by Rey on 1/12/2015.
12 | */
13 | public class DialogFragment extends androidx.fragment.app.DialogFragment {
14 |
15 | /**
16 | * Interface definition for passing style data.
17 | */
18 | public interface Builder{
19 | /**
20 | * Get a Dialog instance used for this fragment.
21 | * @param context A Context instance.
22 | * @return The Dialog will be used for this fragment.
23 | */
24 | Dialog build(Context context);
25 |
26 | /**
27 | * Handle click event on Positive Action.
28 | */
29 | void onPositiveActionClicked(DialogFragment fragment);
30 |
31 | /**
32 | * Handle click event on Negative Action.
33 | */
34 | void onNegativeActionClicked(DialogFragment fragment);
35 |
36 | /**
37 | * Handle click event on Neutral Action.
38 | */
39 | void onNeutralActionClicked(DialogFragment fragment);
40 |
41 | /**
42 | * Handle OnCancel event of dialog.
43 | * @param dialog
44 | */
45 | void onCancel(DialogInterface dialog);
46 |
47 | /**
48 | * Handle OnDismiss event of dialog.
49 | * @param dialog
50 | */
51 | void onDismiss(DialogInterface dialog);
52 | }
53 |
54 | protected static final String ARG_BUILDER = "arg_builder";
55 |
56 | protected Builder mBuilder;
57 |
58 | private View.OnClickListener mActionListener = new View.OnClickListener() {
59 | @Override
60 | public void onClick(View v) {
61 | if(mBuilder == null)
62 | return;
63 |
64 | if(v.getId() == Dialog.ACTION_POSITIVE)
65 | mBuilder.onPositiveActionClicked(DialogFragment.this);
66 | else if(v.getId() == Dialog.ACTION_NEGATIVE)
67 | mBuilder.onNegativeActionClicked(DialogFragment.this);
68 | else if(v.getId() == Dialog.ACTION_NEUTRAL)
69 | mBuilder.onNeutralActionClicked(DialogFragment.this);
70 | }
71 | };
72 |
73 | public static DialogFragment newInstance(Builder builder){
74 | DialogFragment fragment = new DialogFragment();
75 | fragment.mBuilder = builder;
76 | return fragment;
77 | }
78 |
79 | @NonNull
80 | @Override
81 | public Dialog onCreateDialog(Bundle savedInstanceState) {
82 | Dialog dialog = mBuilder == null ? new Dialog(getActivity()) : mBuilder.build(getActivity());
83 | dialog.positiveActionClickListener(mActionListener)
84 | .negativeActionClickListener(mActionListener)
85 | .neutralActionClickListener(mActionListener);
86 | return dialog;
87 | }
88 |
89 | @Override
90 | public void onCreate(Bundle savedInstanceState) {
91 | super.onCreate(savedInstanceState);
92 | if(savedInstanceState != null && mBuilder == null)
93 | mBuilder = savedInstanceState.getParcelable(ARG_BUILDER);
94 | }
95 |
96 | @Override
97 | public void onSaveInstanceState(Bundle outState) {
98 | super.onSaveInstanceState(outState);
99 |
100 | if(mBuilder != null && mBuilder instanceof Parcelable)
101 | outState.putParcelable(ARG_BUILDER, (Parcelable)mBuilder);
102 | }
103 |
104 | @Override
105 | public void onDestroyView() {
106 | android.app.Dialog dialog = getDialog();
107 |
108 | if(dialog != null && dialog instanceof Dialog)
109 | ((Dialog)dialog).dismissImmediately();
110 |
111 | super.onDestroyView();
112 | }
113 |
114 | @Override
115 | public void onCancel(DialogInterface dialog) {
116 | super.onCancel(dialog);
117 | mBuilder.onCancel(dialog);
118 | }
119 |
120 | @Override
121 | public void onDismiss(DialogInterface dialog) {
122 | super.onDismiss(dialog);
123 | mBuilder.onDismiss(dialog);
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/material/src/main/java/com/rey/material/drawable/ArrowDrawable.java:
--------------------------------------------------------------------------------
1 | package com.rey.material.drawable;
2 |
3 | import android.content.res.ColorStateList;
4 | import android.graphics.Canvas;
5 | import android.graphics.ColorFilter;
6 | import android.graphics.Paint;
7 | import android.graphics.Path;
8 | import android.graphics.PixelFormat;
9 | import android.graphics.Rect;
10 | import android.graphics.drawable.Animatable;
11 | import android.graphics.drawable.Drawable;
12 | import android.os.SystemClock;
13 | import android.view.animation.DecelerateInterpolator;
14 | import android.view.animation.Interpolator;
15 |
16 | import com.rey.material.util.ViewUtil;
17 |
18 | public class ArrowDrawable extends Drawable implements Animatable{
19 |
20 | private boolean mRunning = false;
21 | private long mStartTime;
22 | private float mAnimProgress;
23 | private int mAnimDuration;
24 |
25 | private Paint mPaint;
26 | private ColorStateList mColorStateList;
27 | private int mSize;
28 | private int mCurColor;
29 | private int mMode;
30 | private Interpolator mInterpolator;
31 |
32 | private Path mPath;
33 |
34 | public static int MODE_DOWN = 0;
35 | public static int MODE_UP = 1;
36 |
37 | private boolean mClockwise = true;
38 |
39 | public ArrowDrawable(int mode, int size, ColorStateList colorStateList, int animDuration, Interpolator interpolator, boolean clockwise){
40 | mSize = size;
41 | mAnimDuration = animDuration;
42 | mMode = mode;
43 | mInterpolator = interpolator;
44 | if(mInterpolator == null)
45 | mInterpolator = new DecelerateInterpolator();
46 | mClockwise = clockwise;
47 |
48 | mPaint = new Paint();
49 | mPaint.setAntiAlias(true);
50 | mPaint.setStyle(Paint.Style.FILL);
51 |
52 | mPath = new Path();
53 |
54 | setColor(colorStateList);
55 | }
56 |
57 | public void setColor(ColorStateList colorStateList){
58 | mColorStateList = colorStateList;
59 | onStateChange(getState());
60 | }
61 |
62 | public void setAnimationDuration(int duration){
63 | mAnimDuration = duration;
64 | }
65 |
66 | public void setInterpolator(Interpolator interpolator){
67 | mInterpolator = interpolator;
68 | }
69 |
70 | public void setClockwise(boolean clockwise){
71 | mClockwise = clockwise;
72 | }
73 |
74 | public void setArrowSize(int size){
75 | if(mSize != size){
76 | mSize = size;
77 | invalidateSelf();
78 | }
79 | }
80 |
81 | public void setMode(int mode, boolean animation){
82 | if(mMode != mode){
83 | mMode = mode;
84 | if(animation && mAnimDuration > 0)
85 | start();
86 | else
87 | invalidateSelf();
88 | }
89 | }
90 |
91 | public int getMode(){
92 | return mMode;
93 | }
94 |
95 | @Override
96 | protected void onBoundsChange(Rect bounds) {
97 | float x = bounds.exactCenterX();
98 | float y = bounds.exactCenterY();
99 |
100 | mPath.reset();
101 | mPath.moveTo(x, y + mSize / 2f);
102 | mPath.lineTo(x - mSize, y - mSize / 2f);
103 | mPath.lineTo(x + mSize, y - mSize / 2f);
104 | mPath.close();
105 | }
106 |
107 | @Override
108 | public void draw(Canvas canvas) {
109 | int saveCount = canvas.save();
110 | Rect bounds = getBounds();
111 |
112 | if(!isRunning()){
113 | if(mMode == MODE_UP)
114 | canvas.rotate(180, bounds.exactCenterX(), bounds.exactCenterY());
115 | }
116 | else{
117 | float value = mInterpolator.getInterpolation(mAnimProgress);
118 | float degree;
119 |
120 | if(mClockwise){
121 | if(mMode == MODE_UP) // move down > up
122 | degree = 180 * value;
123 | else // move up > down
124 | degree = 180 * (1 + value);
125 | }
126 | else{
127 | if(mMode == MODE_UP) // move down > up
128 | degree = -180 * value;
129 | else // move up > down
130 | degree = -180 * (1 + value);
131 | }
132 |
133 | canvas.rotate(degree, bounds.exactCenterX(), bounds.exactCenterY());
134 | }
135 |
136 | mPaint.setColor(mCurColor);
137 | canvas.drawPath(mPath, mPaint);
138 |
139 | canvas.restoreToCount(saveCount);
140 | }
141 |
142 | @Override
143 | public void setAlpha(int alpha) {
144 | mPaint.setAlpha(alpha);
145 | }
146 |
147 | @Override
148 | public void setColorFilter(ColorFilter cf) {
149 | mPaint.setColorFilter(cf);
150 | }
151 |
152 | @Override
153 | public int getOpacity() {
154 | return PixelFormat.TRANSLUCENT;
155 | }
156 |
157 | @Override
158 | public boolean isStateful() {
159 | return true;
160 | }
161 |
162 | @Override
163 | protected boolean onStateChange(int[] state) {
164 | int color = mColorStateList.getColorForState(state, mCurColor);
165 |
166 | if(mCurColor != color){
167 | mCurColor = color;
168 | return true;
169 | }
170 |
171 | return false;
172 | }
173 |
174 | private void resetAnimation(){
175 | mStartTime = SystemClock.uptimeMillis();
176 | mAnimProgress = 0f;
177 | }
178 |
179 | @Override
180 | public void start() {
181 | resetAnimation();
182 | scheduleSelf(mUpdater, SystemClock.uptimeMillis() + ViewUtil.FRAME_DURATION);
183 | invalidateSelf();
184 | }
185 |
186 | @Override
187 | public void stop() {
188 | mRunning = false;
189 | unscheduleSelf(mUpdater);
190 | invalidateSelf();
191 | }
192 |
193 | @Override
194 | public boolean isRunning() {
195 | return mRunning;
196 | }
197 |
198 | @Override
199 | public void scheduleSelf(Runnable what, long when) {
200 | mRunning = true;
201 | super.scheduleSelf(what, when);
202 | }
203 |
204 | private final Runnable mUpdater = new Runnable() {
205 |
206 | @Override
207 | public void run() {
208 | update();
209 | }
210 |
211 | };
212 |
213 | private void update(){
214 | long curTime = SystemClock.uptimeMillis();
215 | mAnimProgress = Math.min(1f, (float)(curTime - mStartTime) / mAnimDuration);
216 |
217 | if(mAnimProgress == 1f)
218 | mRunning = false;
219 |
220 | if(isRunning())
221 | scheduleSelf(mUpdater, SystemClock.uptimeMillis() + ViewUtil.FRAME_DURATION);
222 |
223 | invalidateSelf();
224 | }
225 |
226 | }
227 |
--------------------------------------------------------------------------------
/material/src/main/java/com/rey/material/drawable/BlankDrawable.java:
--------------------------------------------------------------------------------
1 | package com.rey.material.drawable;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.ColorFilter;
5 | import android.graphics.PixelFormat;
6 | import android.graphics.drawable.Drawable;
7 |
8 | /**
9 | * A drawable that draw nothing.
10 | * @author Rey
11 | *
12 | */
13 | public class BlankDrawable extends Drawable {
14 |
15 | private static BlankDrawable mInstance;
16 |
17 | public static BlankDrawable getInstance(){
18 | if(mInstance == null)
19 | synchronized (BlankDrawable.class) {
20 | if(mInstance == null)
21 | mInstance = new BlankDrawable();
22 | }
23 |
24 | return mInstance;
25 | }
26 |
27 | @Override
28 | public void draw(Canvas canvas) {}
29 |
30 | @Override
31 | public void setAlpha(int alpha) {}
32 |
33 | @Override
34 | public void setColorFilter(ColorFilter cf) {}
35 |
36 | @Override
37 | public int getOpacity() {
38 | return PixelFormat.TRANSPARENT;
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/material/src/main/java/com/rey/material/drawable/CircleDrawable.java:
--------------------------------------------------------------------------------
1 | package com.rey.material.drawable;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.ColorFilter;
5 | import android.graphics.Paint;
6 | import android.graphics.PixelFormat;
7 | import android.graphics.Rect;
8 | import android.graphics.drawable.Animatable;
9 | import android.graphics.drawable.Drawable;
10 | import android.os.SystemClock;
11 | import android.view.animation.DecelerateInterpolator;
12 | import android.view.animation.Interpolator;
13 |
14 | import com.rey.material.util.ViewUtil;
15 |
16 | /**
17 | * Created by Rey on 12/26/2014.
18 | */
19 | public class CircleDrawable extends Drawable implements Animatable {
20 |
21 | private boolean mRunning = false;
22 | private long mStartTime;
23 | private float mAnimProgress;
24 | private int mAnimDuration = 1000;
25 | private Interpolator mInInterpolator = new DecelerateInterpolator();
26 | private Interpolator mOutInterpolator = new DecelerateInterpolator();
27 |
28 | private Paint mPaint;
29 |
30 | private float mX;
31 | private float mY;
32 | private float mRadius;
33 |
34 | private boolean mVisible;
35 | private boolean mInEditMode = false;
36 | private boolean mAnimEnable = true;
37 |
38 | public CircleDrawable() {
39 | mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
40 | mPaint.setStyle(Paint.Style.FILL);
41 | }
42 |
43 | public void setInEditMode(boolean b) {
44 | mInEditMode = b;
45 | }
46 |
47 | public void setAnimEnable(boolean b) {
48 | mAnimEnable = b;
49 | }
50 |
51 | public void setColor(int color) {
52 | mPaint.setColor(color);
53 | invalidateSelf();
54 | }
55 |
56 | public void setAnimDuration(int duration) {
57 | mAnimDuration = duration;
58 | }
59 |
60 | public void setInterpolator(Interpolator in, Interpolator out) {
61 | mInInterpolator = in;
62 | mOutInterpolator = out;
63 | }
64 |
65 | @Override
66 | public boolean isStateful() {
67 | return true;
68 | }
69 |
70 | @Override
71 | protected boolean onStateChange(int[] state) {
72 | boolean visible = ViewUtil.hasState(state, android.R.attr.state_checked) || ViewUtil.hasState(state, android.R.attr.state_pressed);
73 |
74 | if (mVisible != visible) {
75 | mVisible = visible;
76 | if (!mInEditMode && mAnimEnable)
77 | start();
78 | return true;
79 | }
80 |
81 | return false;
82 | }
83 |
84 | @Override
85 | protected void onBoundsChange(Rect bounds) {
86 | mX = bounds.exactCenterX();
87 | mY = bounds.exactCenterY();
88 | mRadius = Math.min(bounds.width(), bounds.height()) / 2f;
89 | }
90 |
91 | @Override
92 | public void draw(Canvas canvas) {
93 | if (!mRunning) {
94 | if (mVisible)
95 | canvas.drawCircle(mX, mY, mRadius, mPaint);
96 | } else {
97 | float radius = mVisible ? mInInterpolator.getInterpolation(mAnimProgress) * mRadius : (1f - mOutInterpolator.getInterpolation(mAnimProgress)) * mRadius;
98 | canvas.drawCircle(mX, mY, radius, mPaint);
99 | }
100 | }
101 |
102 | @Override
103 | public void setAlpha(int alpha) {
104 | mPaint.setAlpha(alpha);
105 | }
106 |
107 | @Override
108 | public void setColorFilter(ColorFilter cf) {
109 | mPaint.setColorFilter(cf);
110 | }
111 |
112 | @Override
113 | public int getOpacity() {
114 | return PixelFormat.TRANSLUCENT;
115 | }
116 |
117 | private void resetAnimation() {
118 | mStartTime = SystemClock.uptimeMillis();
119 | mAnimProgress = 0f;
120 | }
121 |
122 | @Override
123 | public void start() {
124 | resetAnimation();
125 | scheduleSelf(mUpdater, SystemClock.uptimeMillis() + ViewUtil.FRAME_DURATION);
126 | invalidateSelf();
127 | }
128 |
129 | @Override
130 | public void stop() {
131 | mRunning = false;
132 | unscheduleSelf(mUpdater);
133 | invalidateSelf();
134 | }
135 |
136 | @Override
137 | public boolean isRunning() {
138 | return mRunning;
139 | }
140 |
141 | @Override
142 | public void scheduleSelf(Runnable what, long when) {
143 | mRunning = true;
144 | super.scheduleSelf(what, when);
145 | }
146 |
147 | private final Runnable mUpdater = new Runnable() {
148 |
149 | @Override
150 | public void run() {
151 | update();
152 | }
153 |
154 | };
155 |
156 | private void update() {
157 | long curTime = SystemClock.uptimeMillis();
158 | mAnimProgress = Math.min(1f, (float) (curTime - mStartTime) / mAnimDuration);
159 |
160 | if (mAnimProgress == 1f)
161 | mRunning = false;
162 |
163 | if (isRunning())
164 | scheduleSelf(mUpdater, SystemClock.uptimeMillis() + ViewUtil.FRAME_DURATION);
165 |
166 | invalidateSelf();
167 | }
168 |
169 | }
170 |
--------------------------------------------------------------------------------
/material/src/main/java/com/rey/material/drawable/ContactChipDrawable.java:
--------------------------------------------------------------------------------
1 | package com.rey.material.drawable;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.BitmapShader;
5 | import android.graphics.Canvas;
6 | import android.graphics.ColorFilter;
7 | import android.graphics.Matrix;
8 | import android.graphics.Paint;
9 | import android.graphics.PixelFormat;
10 | import android.graphics.Rect;
11 | import android.graphics.RectF;
12 | import android.graphics.Shader;
13 | import android.graphics.Typeface;
14 | import android.graphics.drawable.Drawable;
15 | import android.text.BoringLayout;
16 | import android.text.Layout;
17 | import android.text.TextPaint;
18 | import android.text.TextUtils;
19 |
20 | /**
21 | * Created by Rey on 1/21/2015.
22 | */
23 | public class ContactChipDrawable extends Drawable{
24 |
25 | private Paint mPaint;
26 | private int mPaddingLeft;
27 | private int mPaddingRight;
28 | private int mBackgroundColor;
29 |
30 | private CharSequence mContactName;
31 | private BoringLayout mBoringLayout;
32 | private BoringLayout.Metrics mMetrics;
33 | private TextPaint mTextPaint;
34 | private RectF mRect;
35 |
36 | private BitmapShader mBitmapShader;
37 | private Bitmap mBitmap;
38 | private Matrix mMatrix;
39 |
40 | public ContactChipDrawable(int paddingLeft, int paddingRight, Typeface typeface, int textColor, int textSize, int backgroundColor) {
41 | mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
42 | mPaint.setStyle(Paint.Style.FILL);
43 | mPaint.setColor(textColor);
44 | mPaint.setTypeface(typeface);
45 | mPaint.setTextSize(textSize);
46 |
47 | mTextPaint = new TextPaint(mPaint);
48 | mMetrics = new BoringLayout.Metrics();
49 | Paint.FontMetricsInt temp = mTextPaint.getFontMetricsInt();
50 | mMetrics.ascent = temp.ascent;
51 | mMetrics.bottom = temp.bottom;
52 | mMetrics.descent = temp.descent;
53 | mMetrics.top = temp.top;
54 | mMetrics.leading = temp.leading;
55 |
56 | mRect = new RectF();
57 |
58 | mMatrix = new Matrix();
59 |
60 | mPaddingLeft = paddingLeft;
61 | mPaddingRight = paddingRight;
62 | mBackgroundColor = backgroundColor;
63 | }
64 |
65 | public void setContactName(CharSequence name){
66 | mContactName = name;
67 | updateLayout();
68 | invalidateSelf();
69 | }
70 |
71 | public void setImage(Bitmap bm){
72 | if(mBitmap != bm){
73 | mBitmap = bm;
74 | if(mBitmap != null) {
75 | mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
76 | updateMatrix();
77 | }
78 | invalidateSelf();
79 | }
80 | }
81 |
82 | private void updateLayout(){
83 | if(mContactName == null)
84 | return;
85 |
86 | Rect bounds = getBounds();
87 | if(bounds.width() == 0 || bounds.height() == 0)
88 | return;
89 |
90 | int outerWidth = Math.max(0, bounds.width() - bounds.height() - mPaddingLeft - mPaddingRight);
91 | mMetrics.width = Math.round(mTextPaint.measureText(mContactName, 0, mContactName.length()) + 0.5f);
92 |
93 | if(mBoringLayout == null)
94 | mBoringLayout = BoringLayout.make(mContactName, mTextPaint, outerWidth, Layout.Alignment.ALIGN_NORMAL, 1f, 1f, mMetrics, true, TextUtils.TruncateAt.END, outerWidth);
95 | else
96 | mBoringLayout = mBoringLayout.replaceOrMake(mContactName, mTextPaint, outerWidth, Layout.Alignment.ALIGN_NORMAL, 1f, 1f, mMetrics, true, TextUtils.TruncateAt.END, outerWidth);
97 | }
98 |
99 | private void updateMatrix(){
100 | if(mBitmap == null)
101 | return;
102 |
103 | Rect bounds = getBounds();
104 | if(bounds.width() == 0 || bounds.height() == 0)
105 | return;
106 |
107 | mMatrix.reset();
108 | float scale = bounds.height() / (float)Math.min(mBitmap.getWidth(), mBitmap.getHeight());
109 | mMatrix.setScale(scale, scale, 0, 0);
110 | mMatrix.postTranslate((bounds.height() - mBitmap.getWidth() * scale) / 2, (bounds.height() - mBitmap.getHeight() * scale) / 2);
111 |
112 | mBitmapShader.setLocalMatrix(mMatrix);
113 | }
114 |
115 | @Override
116 | protected void onBoundsChange(Rect bounds) {
117 | updateLayout();
118 | updateMatrix();
119 | }
120 |
121 | @Override
122 | public void draw(Canvas canvas) {
123 | int saveCount = canvas.save();
124 |
125 | Rect bounds = getBounds();
126 | float halfHeight = bounds.height() / 2f;
127 | mPaint.setShader(null);
128 | mPaint.setColor(mBackgroundColor);
129 | mRect.set(1, 0, bounds.height() + 1, bounds.height());
130 | canvas.drawArc(mRect, 90, 180, true, mPaint);
131 | mRect.set(bounds.width() - bounds.height(), 0, bounds.width(), bounds.height());
132 | canvas.drawArc(mRect, 270, 180, true, mPaint);
133 | mRect.set(halfHeight, 0, bounds.width() - halfHeight, bounds.height());
134 | canvas.drawRect(mRect, mPaint);
135 |
136 | if(mBitmap != null){
137 | mPaint.setShader(mBitmapShader);
138 | canvas.drawCircle(halfHeight, halfHeight, halfHeight, mPaint);
139 | }
140 |
141 | if(mContactName != null && mBoringLayout != null) {
142 | canvas.translate(bounds.height() + mPaddingLeft, (bounds.height() - mBoringLayout.getHeight()) / 2f);
143 | mBoringLayout.draw(canvas);
144 | }
145 |
146 | canvas.restoreToCount(saveCount);
147 | }
148 |
149 | @Override
150 | public void setAlpha(int alpha) {
151 | mPaint.setAlpha(alpha);
152 | }
153 |
154 | @Override
155 | public void setColorFilter(ColorFilter cf) {
156 | mPaint.setColorFilter(cf);
157 | }
158 |
159 | @Override
160 | public int getOpacity() {
161 | return PixelFormat.TRANSLUCENT;
162 | }
163 | }
164 |
--------------------------------------------------------------------------------
/material/src/main/java/com/rey/material/drawable/NavigationDrawerDrawable.java:
--------------------------------------------------------------------------------
1 | package com.rey.material.drawable;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.graphics.Canvas;
6 | import android.graphics.ColorFilter;
7 | import android.graphics.PixelFormat;
8 | import android.graphics.drawable.Drawable;
9 | import android.util.AttributeSet;
10 |
11 | import com.rey.material.R;
12 |
13 | public class NavigationDrawerDrawable extends Drawable implements Drawable.Callback{
14 |
15 | private ToolbarRippleDrawable mRippleDrawable;
16 | private LineMorphingDrawable mLineDrawable;
17 |
18 | public static final int STATE_DRAWER = 0;
19 | public static final int STATE_ARROW = 1;
20 |
21 | public NavigationDrawerDrawable(ToolbarRippleDrawable rippleDrawable, LineMorphingDrawable lineDrawable){
22 | mRippleDrawable = rippleDrawable;
23 | mLineDrawable = lineDrawable;
24 |
25 | mRippleDrawable.setCallback(this);
26 | mLineDrawable.setCallback(this);
27 | }
28 |
29 | public void switchIconState(int state, boolean animation){
30 | mLineDrawable.switchLineState(state, animation);
31 | }
32 |
33 | public int getIconState(){
34 | return mLineDrawable.getLineState();
35 | }
36 |
37 | public boolean setIconState(int state, float progress){
38 | return mLineDrawable.setLineState(state, progress);
39 | }
40 |
41 | public float getIconAnimProgress(){
42 | return mLineDrawable.getAnimProgress();
43 | }
44 |
45 | public void cancel(){
46 | if(mRippleDrawable != null)
47 | mRippleDrawable.cancel();
48 | if(mLineDrawable != null)
49 | mLineDrawable.cancel();
50 | }
51 |
52 | @Override
53 | public void draw(Canvas canvas) {
54 | mRippleDrawable.draw(canvas);
55 | mLineDrawable.draw(canvas);
56 | }
57 |
58 | @Override
59 | public void setAlpha(int alpha) {
60 | mRippleDrawable.setAlpha(alpha);
61 | mLineDrawable.setAlpha(alpha);
62 | }
63 |
64 | @Override
65 | public void setColorFilter(ColorFilter cf) {
66 | mRippleDrawable.setColorFilter(cf);
67 | mLineDrawable.setColorFilter(cf);
68 | }
69 |
70 | @Override
71 | public int getOpacity() {
72 | return PixelFormat.TRANSLUCENT;
73 | }
74 |
75 | @Override
76 | public void setBounds(int left, int top, int right, int bottom) {
77 | mRippleDrawable.setBounds(left, top, right, bottom);
78 | mLineDrawable.setBounds(left, top, right, bottom);
79 | }
80 |
81 | @Override
82 | public void setDither(boolean dither) {
83 | mRippleDrawable.setDither(dither);
84 | mLineDrawable.setDither(dither);
85 | }
86 |
87 | @Override
88 | public void invalidateDrawable(Drawable who) {
89 | invalidateSelf();
90 | }
91 |
92 | @Override
93 | public void scheduleDrawable(Drawable who, Runnable what, long when) {
94 | scheduleSelf(what, when);
95 | }
96 |
97 | @Override
98 | public void unscheduleDrawable(Drawable who, Runnable what) {
99 | unscheduleSelf(what);
100 | }
101 |
102 | @Override
103 | public boolean isStateful() {
104 | return true;
105 | }
106 |
107 | @Override
108 | protected boolean onStateChange(int[] state) {
109 | return mRippleDrawable.onStateChange(state);
110 | }
111 |
112 | public static class Builder{
113 | private ToolbarRippleDrawable mRippleDrawable;
114 | private LineMorphingDrawable mLineDrawable;
115 |
116 | public Builder(){}
117 |
118 | public Builder(Context context, int defStyleRes){
119 | this(context, null, 0, defStyleRes);
120 | }
121 |
122 | public Builder(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes){
123 | TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.NavigationDrawerDrawable, defStyleAttr, defStyleRes);
124 |
125 | if(a != null){
126 | int rippleId = a.getResourceId(R.styleable.NavigationDrawerDrawable_nd_ripple, 0);
127 | int lineId = a.getResourceId(R.styleable.NavigationDrawerDrawable_nd_icon, 0);
128 |
129 | if(rippleId > 0)
130 | ripple(new ToolbarRippleDrawable.Builder(context, rippleId).build());
131 |
132 | if(lineId > 0){
133 | LineMorphingDrawable.Builder builder = new LineMorphingDrawable.Builder(context, lineId);
134 | line(builder.build());
135 | }
136 |
137 | a.recycle();
138 | }
139 | }
140 |
141 | public NavigationDrawerDrawable build(){
142 | return new NavigationDrawerDrawable(mRippleDrawable, mLineDrawable);
143 | }
144 |
145 | public Builder ripple(ToolbarRippleDrawable drawable){
146 | mRippleDrawable = drawable;
147 |
148 | return this;
149 | }
150 |
151 | public Builder line(LineMorphingDrawable drawable){
152 | mLineDrawable = drawable;
153 |
154 | return this;
155 | }
156 |
157 | }
158 | }
159 |
--------------------------------------------------------------------------------
/material/src/main/java/com/rey/material/drawable/ThemeDrawable.java:
--------------------------------------------------------------------------------
1 | package com.rey.material.drawable;
2 |
3 | import android.graphics.drawable.Drawable;
4 | import android.graphics.drawable.LevelListDrawable;
5 |
6 | import com.rey.material.app.ThemeManager;
7 |
8 | /**
9 | * Created by Rey on 5/27/2015.
10 | */
11 | public class ThemeDrawable extends LevelListDrawable implements ThemeManager.OnThemeChangedListener {
12 | private int mStyleId;
13 |
14 | public ThemeDrawable(int styleId) {
15 | mStyleId = styleId;
16 |
17 | if(mStyleId != 0) {
18 | ThemeManager.getInstance().registerOnThemeChangedListener(this);
19 | initDrawables();
20 | }
21 | }
22 |
23 | private void initDrawables(){
24 | ThemeManager themeManager = ThemeManager.getInstance();
25 | int count = themeManager.getThemeCount();
26 |
27 | for(int i = 0; i < count; i++){
28 | Drawable drawable = themeManager.getContext().getResources().getDrawable(themeManager.getStyle(mStyleId, i));
29 | addLevel(i, i, drawable);
30 | }
31 |
32 | setLevel(themeManager.getCurrentTheme());
33 | }
34 |
35 | @Override
36 | public void onThemeChanged(ThemeManager.OnThemeChangedEvent event) {
37 | if(getLevel() != event.theme)
38 | setLevel(event.theme);
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/material/src/main/java/com/rey/material/text/style/ContactChipSpan.java:
--------------------------------------------------------------------------------
1 | package com.rey.material.text.style;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.BitmapShader;
5 | import android.graphics.Canvas;
6 | import android.graphics.Matrix;
7 | import android.graphics.Paint;
8 | import android.graphics.RectF;
9 | import android.graphics.Shader;
10 | import android.graphics.Typeface;
11 | import android.text.BoringLayout;
12 | import android.text.Layout;
13 | import android.text.TextPaint;
14 | import android.text.TextUtils;
15 | import android.text.style.ReplacementSpan;
16 |
17 | /**
18 | * Created by Rey on 1/21/2015.
19 | */
20 | public class ContactChipSpan extends ReplacementSpan {
21 |
22 | private Paint mPaint;
23 | private int mPaddingLeft;
24 | private int mPaddingRight;
25 | private int mBackgroundColor;
26 | private int mHeight;
27 | private int mWidth;
28 |
29 | private CharSequence mContactName;
30 | private BoringLayout mBoringLayout;
31 | private TextPaint mTextPaint;
32 | private RectF mRect;
33 |
34 | private BitmapShader mBitmapShader;
35 | private Bitmap mBitmap;
36 | private Matrix mMatrix;
37 |
38 | public ContactChipSpan(CharSequence name, int height, int maxWidth, int paddingLeft, int paddingRight, Typeface typeface, int textColor, int textSize, int backgroundColor) {
39 | mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
40 | mPaint.setStyle(Paint.Style.FILL);
41 | mPaint.setColor(textColor);
42 | mPaint.setTypeface(typeface);
43 | mPaint.setTextSize(textSize);
44 |
45 | mTextPaint = new TextPaint(mPaint);
46 |
47 |
48 | mRect = new RectF();
49 |
50 | mMatrix = new Matrix();
51 |
52 | mContactName = name;
53 | mPaddingLeft = paddingLeft;
54 | mPaddingRight = paddingRight;
55 | mBackgroundColor = backgroundColor;
56 | mHeight = height;
57 | mWidth = Math.round(Math.min(maxWidth, mPaint.measureText(name, 0, name.length()) + paddingLeft + paddingRight + height));
58 |
59 | int outerWidth = Math.max(0, mWidth - mPaddingLeft - mPaddingRight - mHeight);
60 | Paint.FontMetricsInt temp = mTextPaint.getFontMetricsInt();
61 | BoringLayout.Metrics mMetrics = new BoringLayout.Metrics();
62 | mMetrics.width = Math.round(mTextPaint.measureText(mContactName, 0, mContactName.length()) + 0.5f);
63 | mMetrics.ascent = temp.ascent;
64 | mMetrics.bottom = temp.bottom;
65 | mMetrics.descent = temp.descent;
66 | mMetrics.top = temp.top;
67 | mMetrics.leading = temp.leading;
68 | mBoringLayout = BoringLayout.make(mContactName, mTextPaint, outerWidth, Layout.Alignment.ALIGN_NORMAL, 1f, 1f, mMetrics, true, TextUtils.TruncateAt.END, outerWidth);
69 | }
70 |
71 | public void setImage(Bitmap bm){
72 | if(mBitmap != bm){
73 | mBitmap = bm;
74 | if(mBitmap != null) {
75 | mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
76 | mMatrix.reset();
77 | float scale = mHeight / (float)Math.min(mBitmap.getWidth(), mBitmap.getHeight());
78 | mMatrix.setScale(scale, scale, 0, 0);
79 | mMatrix.postTranslate((mHeight - mBitmap.getWidth() * scale) / 2, (mHeight - mBitmap.getHeight() * scale) / 2);
80 |
81 | mBitmapShader.setLocalMatrix(mMatrix);
82 | }
83 | }
84 | }
85 |
86 | @Override
87 | public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) {
88 | if (fm != null) {
89 | int cy = (fm.ascent + fm.descent) / 2;
90 | fm.ascent = Math.min(fm.ascent, cy - mHeight / 2);
91 | fm.descent = Math.max(fm.descent, cy + mHeight / 2);
92 | fm.top = Math.min(fm.top, fm.ascent);
93 | fm.bottom = Math.max(fm.bottom, fm.descent);
94 | }
95 |
96 | return mWidth;
97 | }
98 |
99 | @Override
100 | public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) {
101 | canvas.save();
102 |
103 | canvas.translate(x, top);
104 |
105 | float halfHeight = mHeight / 2f;
106 | mPaint.setShader(null);
107 | mPaint.setColor(mBackgroundColor);
108 | mRect.set(1, 0, mHeight + 1, mHeight);
109 | canvas.drawArc(mRect, 90, 180, true, mPaint);
110 | mRect.set(mWidth - mHeight, 0, mWidth, mHeight);
111 | canvas.drawArc(mRect, 270, 180, true, mPaint);
112 | mRect.set(halfHeight, 0, mWidth - halfHeight, mHeight);
113 | canvas.drawRect(mRect, mPaint);
114 |
115 | if(mBitmap != null){
116 | mPaint.setShader(mBitmapShader);
117 | canvas.drawCircle(halfHeight, halfHeight, halfHeight, mPaint);
118 | }
119 |
120 | if(mContactName != null && mBoringLayout != null) {
121 | canvas.translate(mHeight + mPaddingLeft, (mHeight - mBoringLayout.getHeight()) / 2f);
122 | mBoringLayout.draw(canvas);
123 | }
124 |
125 | canvas.restore();
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/material/src/main/java/com/rey/material/util/ColorUtil.java:
--------------------------------------------------------------------------------
1 | package com.rey.material.util;
2 |
3 | import android.graphics.Color;
4 |
5 | public class ColorUtil {
6 |
7 | private static int getMiddleValue(int prev, int next, float factor){
8 | return Math.round(prev + (next - prev) * factor);
9 | }
10 |
11 | public static int getMiddleColor(int prevColor, int curColor, float factor){
12 | if(prevColor == curColor)
13 | return curColor;
14 |
15 | if(factor == 0f)
16 | return prevColor;
17 | else if(factor == 1f)
18 | return curColor;
19 |
20 | int a = getMiddleValue(Color.alpha(prevColor), Color.alpha(curColor), factor);
21 | int r = getMiddleValue(Color.red(prevColor), Color.red(curColor), factor);
22 | int g = getMiddleValue(Color.green(prevColor), Color.green(curColor), factor);
23 | int b = getMiddleValue(Color.blue(prevColor), Color.blue(curColor), factor);
24 |
25 | return Color.argb(a, r, g, b);
26 | }
27 |
28 | public static int getColor(int baseColor, float alphaPercent){
29 | int alpha = Math.round(Color.alpha(baseColor) * alphaPercent);
30 |
31 | return (baseColor & 0x00FFFFFF) | (alpha << 24);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/material/src/main/java/com/rey/material/util/ThemeUtil.java:
--------------------------------------------------------------------------------
1 | package com.rey.material.util;
2 |
3 | import android.annotation.TargetApi;
4 | import android.content.Context;
5 | import android.content.res.Resources.Theme;
6 | import android.content.res.TypedArray;
7 | import android.os.Build;
8 | import android.util.TypedValue;
9 |
10 | import com.rey.material.R;
11 |
12 | public class ThemeUtil {
13 |
14 | private static TypedValue value;
15 |
16 | public static int dpToPx(Context context, int dp){
17 | return (int)(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.getResources().getDisplayMetrics()) + 0.5f);
18 | }
19 |
20 | public static int spToPx(Context context, int sp){
21 | return (int)(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, context.getResources().getDisplayMetrics()) + 0.5f);
22 | }
23 |
24 | private static int getColor(Context context, int id, int defaultValue){
25 | if(value == null)
26 | value = new TypedValue();
27 |
28 | try{
29 | Theme theme = context.getTheme();
30 | if(theme != null && theme.resolveAttribute(id, value, true)){
31 | if (value.type >= TypedValue.TYPE_FIRST_INT && value.type <= TypedValue.TYPE_LAST_INT)
32 | return value.data;
33 | else if (value.type == TypedValue.TYPE_STRING)
34 | return context.getResources().getColor(value.resourceId);
35 | }
36 | }
37 | catch(Exception ex){}
38 |
39 | return defaultValue;
40 | }
41 |
42 | public static int windowBackground(Context context, int defaultValue){
43 | return getColor(context, android.R.attr.windowBackground, defaultValue);
44 | }
45 |
46 | public static int textColorPrimary(Context context, int defaultValue){
47 | return getColor(context, android.R.attr.textColorPrimary, defaultValue);
48 | }
49 |
50 | public static int textColorSecondary(Context context, int defaultValue){
51 | return getColor(context, android.R.attr.textColorSecondary, defaultValue);
52 | }
53 |
54 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
55 | public static int colorPrimary(Context context, int defaultValue){
56 | if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
57 | return getColor(context, android.R.attr.colorPrimary, defaultValue);
58 |
59 | return getColor(context, R.attr.colorPrimary, defaultValue);
60 | }
61 |
62 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
63 | public static int colorPrimaryDark(Context context, int defaultValue){
64 | if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
65 | return getColor(context, android.R.attr.colorPrimaryDark, defaultValue);
66 |
67 | return getColor(context, R.attr.colorPrimaryDark, defaultValue);
68 | }
69 |
70 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
71 | public static int colorAccent(Context context, int defaultValue){
72 | if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
73 | return getColor(context, android.R.attr.colorAccent, defaultValue);
74 |
75 | return getColor(context, R.attr.colorAccent, defaultValue);
76 | }
77 |
78 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
79 | public static int colorControlNormal(Context context, int defaultValue){
80 | if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
81 | return getColor(context, android.R.attr.colorControlNormal, defaultValue);
82 |
83 | return getColor(context, R.attr.colorControlNormal, defaultValue);
84 | }
85 |
86 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
87 | public static int colorControlActivated(Context context, int defaultValue){
88 | if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
89 | return getColor(context, android.R.attr.colorControlActivated, defaultValue);
90 |
91 | return getColor(context, R.attr.colorControlActivated, defaultValue);
92 | }
93 |
94 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
95 | public static int colorControlHighlight(Context context, int defaultValue){
96 | if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
97 | return getColor(context, android.R.attr.colorControlHighlight, defaultValue);
98 |
99 | return getColor(context, R.attr.colorControlHighlight, defaultValue);
100 | }
101 |
102 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
103 | public static int colorButtonNormal(Context context, int defaultValue){
104 | if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
105 | return getColor(context, android.R.attr.colorButtonNormal, defaultValue);
106 |
107 | return getColor(context, R.attr.colorButtonNormal, defaultValue);
108 | }
109 |
110 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
111 | public static int colorSwitchThumbNormal(Context context, int defaultValue){
112 | return getColor(context, R.attr.colorSwitchThumbNormal, defaultValue);
113 | }
114 |
115 | public static int getType(TypedArray array, int index){
116 | if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
117 | return array.getType(index);
118 | else{
119 | TypedValue value = array.peekValue(index);
120 | return value == null ? TypedValue.TYPE_NULL : value.type;
121 | }
122 | }
123 |
124 | public static CharSequence getString(TypedArray array, int index, CharSequence defaultValue){
125 | String result = array.getString(index);
126 | return result == null ? defaultValue : result;
127 | }
128 |
129 | }
130 |
--------------------------------------------------------------------------------
/material/src/main/java/com/rey/material/util/TypefaceUtil.java:
--------------------------------------------------------------------------------
1 | package com.rey.material.util;
2 |
3 | import android.content.Context;
4 | import android.graphics.Typeface;
5 |
6 | import java.util.HashMap;
7 |
8 | /**
9 | * Created by Rey on 12/23/2014.
10 | */
11 | public class TypefaceUtil {
12 |
13 | private static final HashMap sCachedFonts = new HashMap();
14 | private static final String PREFIX_ASSET = "asset:";
15 |
16 | private TypefaceUtil() {
17 | }
18 |
19 | /**
20 | * @param familyName if start with 'asset:' prefix, then load font from asset folder.
21 | * @return
22 | */
23 | public static Typeface load(Context context, String familyName, int style) {
24 | if(familyName != null && familyName.startsWith(PREFIX_ASSET))
25 | synchronized (sCachedFonts) {
26 | try {
27 | if (!sCachedFonts.containsKey(familyName)) {
28 | final Typeface typeface = Typeface.createFromAsset(context.getAssets(), familyName.substring(PREFIX_ASSET.length()));
29 | sCachedFonts.put(familyName, typeface);
30 | return typeface;
31 | }
32 | } catch (Exception e) {
33 | return Typeface.DEFAULT;
34 | }
35 |
36 | return sCachedFonts.get(familyName);
37 | }
38 |
39 | return Typeface.create(familyName, style);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/material/src/main/java/com/rey/material/widget/Button.java:
--------------------------------------------------------------------------------
1 | package com.rey.material.widget;
2 |
3 | import android.content.Context;
4 | import android.graphics.drawable.Drawable;
5 | import androidx.annotation.NonNull;
6 | import androidx.appcompat.widget.AppCompatButton;
7 |
8 | import android.util.AttributeSet;
9 | import android.view.MotionEvent;
10 |
11 | import com.rey.material.app.ThemeManager;
12 | import com.rey.material.drawable.RippleDrawable;
13 | import com.rey.material.util.ViewUtil;
14 |
15 | public class Button extends AppCompatButton implements ThemeManager.OnThemeChangedListener{
16 |
17 | private RippleManager mRippleManager;
18 |
19 | protected int mStyleId;
20 | protected int mCurrentStyle = ThemeManager.THEME_UNDEFINED;
21 |
22 | public Button(Context context) {
23 | super(context);
24 |
25 | init(context, null, 0, 0);
26 | }
27 |
28 | public Button(Context context, AttributeSet attrs) {
29 | super(context, attrs);
30 |
31 | init(context, attrs, 0, 0);
32 | }
33 |
34 | public Button(Context context, AttributeSet attrs, int defStyleAttr) {
35 | super(context, attrs, defStyleAttr);
36 |
37 | init(context, attrs, defStyleAttr, 0);
38 | }
39 |
40 | protected void init(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes){
41 | ViewUtil.applyFont(this, attrs, defStyleAttr, defStyleRes);
42 | applyStyle(context, attrs, defStyleAttr, defStyleRes);
43 | if(!isInEditMode())
44 | mStyleId = ThemeManager.getStyleId(context, attrs, defStyleAttr, defStyleRes);
45 | }
46 |
47 | public void applyStyle(int resId){
48 | ViewUtil.applyStyle(this, resId);
49 | applyStyle(getContext(), null, 0, resId);
50 | }
51 |
52 | protected void applyStyle(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes){
53 | getRippleManager().onCreate(this, context, attrs, defStyleAttr, defStyleRes);
54 | }
55 |
56 | @Override
57 | public void setTextAppearance(int resId) {
58 | ViewUtil.applyTextAppearance(this, resId);
59 | }
60 |
61 | @Override
62 | public void setTextAppearance(Context context, int resId) {
63 | ViewUtil.applyTextAppearance(this, resId);
64 | }
65 |
66 | @Override
67 | public void onThemeChanged(ThemeManager.OnThemeChangedEvent event) {
68 | int style = ThemeManager.getInstance().getCurrentStyle(mStyleId);
69 | if(mCurrentStyle != style){
70 | mCurrentStyle = style;
71 | applyStyle(mCurrentStyle);
72 | }
73 | }
74 |
75 | @Override
76 | protected void onAttachedToWindow() {
77 | super.onAttachedToWindow();
78 | if(mStyleId != 0) {
79 | ThemeManager.getInstance().registerOnThemeChangedListener(this);
80 | onThemeChanged(null);
81 | }
82 | }
83 |
84 | @Override
85 | protected void onDetachedFromWindow() {
86 | super.onDetachedFromWindow();
87 | RippleManager.cancelRipple(this);
88 | if(mStyleId != 0)
89 | ThemeManager.getInstance().unregisterOnThemeChangedListener(this);
90 | }
91 |
92 | @Override
93 | public void setBackgroundDrawable(Drawable drawable) {
94 | Drawable background = getBackground();
95 | if(background instanceof RippleDrawable && !(drawable instanceof RippleDrawable))
96 | ((RippleDrawable) background).setBackgroundDrawable(drawable);
97 | else
98 | super.setBackgroundDrawable(drawable);
99 | }
100 |
101 | protected RippleManager getRippleManager(){
102 | if(mRippleManager == null){
103 | synchronized (RippleManager.class){
104 | if(mRippleManager == null)
105 | mRippleManager = new RippleManager();
106 | }
107 | }
108 |
109 | return mRippleManager;
110 | }
111 |
112 | @Override
113 | public void setOnClickListener(OnClickListener l) {
114 | RippleManager rippleManager = getRippleManager();
115 | if (l == rippleManager)
116 | super.setOnClickListener(l);
117 | else {
118 | rippleManager.setOnClickListener(l);
119 | setOnClickListener(rippleManager);
120 | }
121 | }
122 |
123 | @Override
124 | public boolean onTouchEvent(@NonNull MotionEvent event) {
125 | boolean result = super.onTouchEvent(event);
126 | return getRippleManager().onTouchEvent(this, event) || result;
127 | }
128 |
129 | }
130 |
--------------------------------------------------------------------------------
/material/src/main/java/com/rey/material/widget/CheckBox.java:
--------------------------------------------------------------------------------
1 | package com.rey.material.widget;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 |
6 | import com.rey.material.drawable.CheckBoxDrawable;
7 |
8 | public class CheckBox extends CompoundButton {
9 |
10 | public CheckBox(Context context) {
11 | super(context);
12 | }
13 |
14 | public CheckBox(Context context, AttributeSet attrs) {
15 | super(context, attrs);
16 | }
17 |
18 | public CheckBox(Context context, AttributeSet attrs, int defStyleAttr) {
19 | super(context, attrs, defStyleAttr);
20 | }
21 |
22 | @Override
23 | protected void applyStyle(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes){
24 | super.applyStyle(context, attrs, defStyleAttr, defStyleRes);
25 |
26 | CheckBoxDrawable drawable = new CheckBoxDrawable.Builder(context, attrs, defStyleAttr, defStyleRes).build();
27 | drawable.setInEditMode(isInEditMode());
28 | drawable.setAnimEnable(false);
29 | setButtonDrawable(drawable);
30 | drawable.setAnimEnable(true);
31 | }
32 |
33 | /**
34 | * Change the checked state of this button immediately without showing animation.
35 | * @param checked The checked state.
36 | */
37 | public void setCheckedImmediately(boolean checked){
38 | if(getButtonDrawable() instanceof CheckBoxDrawable){
39 | CheckBoxDrawable drawable = (CheckBoxDrawable)getButtonDrawable();
40 | drawable.setAnimEnable(false);
41 | setChecked(checked);
42 | drawable.setAnimEnable(true);
43 | }
44 | else
45 | setChecked(checked);
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/material/src/main/java/com/rey/material/widget/CheckedImageView.java:
--------------------------------------------------------------------------------
1 | package com.rey.material.widget;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.widget.Checkable;
6 |
7 | /**
8 | * Created by Rey on 9/16/2015.
9 | */
10 | public class CheckedImageView extends ImageView implements Checkable {
11 |
12 | private boolean mChecked = false;
13 |
14 | private static final int[] STATE_CHECKED = new int[]{
15 | android.R.attr.state_checked
16 | };
17 |
18 | public CheckedImageView(Context context) {
19 | super(context);
20 | }
21 |
22 | public CheckedImageView(Context context, AttributeSet attrs) {
23 | super(context, attrs);
24 | }
25 |
26 | public CheckedImageView(Context context, AttributeSet attrs, int defStyleAttr) {
27 | super(context, attrs, defStyleAttr);
28 | }
29 |
30 | @Override
31 | public void setChecked(boolean b) {
32 | if(mChecked != b){
33 | mChecked = b;
34 | refreshDrawableState();
35 | }
36 | }
37 |
38 | @Override
39 | public boolean isChecked() {
40 | return mChecked;
41 | }
42 |
43 | @Override
44 | public void toggle() {
45 | setChecked(!isChecked());
46 | }
47 |
48 | @Override
49 | public int[] onCreateDrawableState(int extraSpace) {
50 | final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
51 |
52 | int[] additionalStates = mChecked ? STATE_CHECKED : null;
53 | if (additionalStates != null)
54 | mergeDrawableStates(drawableState, additionalStates);
55 |
56 | return drawableState;
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/material/src/main/java/com/rey/material/widget/CheckedTextView.java:
--------------------------------------------------------------------------------
1 | package com.rey.material.widget;
2 |
3 | import android.content.Context;
4 | import android.graphics.drawable.Drawable;
5 | import androidx.annotation.NonNull;
6 | import androidx.appcompat.widget.AppCompatCheckedTextView;
7 |
8 | import android.util.AttributeSet;
9 | import android.view.MotionEvent;
10 |
11 | import com.rey.material.app.ThemeManager;
12 | import com.rey.material.drawable.RippleDrawable;
13 | import com.rey.material.util.ViewUtil;
14 |
15 | public class CheckedTextView extends AppCompatCheckedTextView implements ThemeManager.OnThemeChangedListener {
16 |
17 | private RippleManager mRippleManager;
18 | protected int mStyleId;
19 | protected int mCurrentStyle = ThemeManager.THEME_UNDEFINED;
20 |
21 | /**
22 | * Interface definition for a callback to be invoked when the checked state is changed.
23 | */
24 | public interface OnCheckedChangeListener{
25 | /**
26 | * Called when the checked state is changed.
27 | * @param view The CheckedTextView view.
28 | * @param checked The checked state.
29 | */
30 | void onCheckedChanged(CheckedTextView view, boolean checked);
31 | }
32 |
33 | private OnCheckedChangeListener mOnCheckedChangeListener;
34 |
35 | public CheckedTextView(Context context) {
36 | super(context);
37 |
38 | init(context, null, 0, 0);
39 | }
40 |
41 | public CheckedTextView(Context context, AttributeSet attrs) {
42 | super(context, attrs);
43 |
44 | init(context, attrs, 0, 0);
45 | }
46 |
47 | public CheckedTextView(Context context, AttributeSet attrs, int defStyleAttr) {
48 | super(context, attrs, defStyleAttr);
49 |
50 | init(context, attrs, defStyleAttr, 0);
51 | }
52 |
53 | protected void init(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes){
54 | ViewUtil.applyFont(this, attrs, defStyleAttr, defStyleRes);
55 | applyStyle(context, attrs, defStyleAttr, defStyleRes);
56 | if(!isInEditMode())
57 | mStyleId = ThemeManager.getStyleId(context, attrs, defStyleAttr, defStyleRes);
58 | }
59 |
60 | public void applyStyle(int resId){
61 | ViewUtil.applyStyle(this, resId);
62 | applyStyle(getContext(), null, 0, resId);
63 | }
64 |
65 | protected void applyStyle(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes){
66 | getRippleManager().onCreate(this, context, attrs, defStyleAttr, defStyleRes);
67 | }
68 |
69 | /**
70 | * Set a listener will be called when the checked state is changed.
71 | * @param listener The {@link OnCheckedChangeListener} will be called.
72 | */
73 | public void setOnCheckedChangeListener(OnCheckedChangeListener listener){
74 | mOnCheckedChangeListener = listener;
75 | }
76 |
77 | @Override
78 | public void setChecked(boolean checked) {
79 | boolean change = isChecked() != checked;
80 | super.setChecked(checked);
81 | if(change && mOnCheckedChangeListener != null)
82 | mOnCheckedChangeListener.onCheckedChanged(this, checked);
83 | }
84 |
85 | @Override
86 | public void setTextAppearance(int resId) {
87 | ViewUtil.applyTextAppearance(this, resId);
88 | }
89 |
90 | @Override
91 | public void setTextAppearance(Context context, int resId) {
92 | ViewUtil.applyTextAppearance(this, resId);
93 | }
94 |
95 | @Override
96 | public void onThemeChanged(ThemeManager.OnThemeChangedEvent event) {
97 | int style = ThemeManager.getInstance().getCurrentStyle(mStyleId);
98 | if(mCurrentStyle != style){
99 | mCurrentStyle = style;
100 | applyStyle(mCurrentStyle);
101 | }
102 | }
103 |
104 | @Override
105 | protected void onAttachedToWindow() {
106 | super.onAttachedToWindow();
107 | if(mStyleId != 0) {
108 | ThemeManager.getInstance().registerOnThemeChangedListener(this);
109 | onThemeChanged(null);
110 | }
111 | }
112 |
113 | @Override
114 | protected void onDetachedFromWindow() {
115 | super.onDetachedFromWindow();
116 | RippleManager.cancelRipple(this);
117 | if(mStyleId != 0)
118 | ThemeManager.getInstance().unregisterOnThemeChangedListener(this);
119 | }
120 |
121 | @Override
122 | public void setBackgroundDrawable(Drawable drawable) {
123 | Drawable background = getBackground();
124 | if(background instanceof RippleDrawable && !(drawable instanceof RippleDrawable))
125 | ((RippleDrawable) background).setBackgroundDrawable(drawable);
126 | else
127 | super.setBackgroundDrawable(drawable);
128 | }
129 |
130 | protected RippleManager getRippleManager(){
131 | if(mRippleManager == null){
132 | synchronized (RippleManager.class){
133 | if(mRippleManager == null)
134 | mRippleManager = new RippleManager();
135 | }
136 | }
137 |
138 | return mRippleManager;
139 | }
140 |
141 | @Override
142 | public void setOnClickListener(OnClickListener l) {
143 | RippleManager rippleManager = getRippleManager();
144 | if (l == rippleManager)
145 | super.setOnClickListener(l);
146 | else {
147 | rippleManager.setOnClickListener(l);
148 | setOnClickListener(rippleManager);
149 | }
150 | }
151 |
152 | @Override
153 | public boolean onTouchEvent(@NonNull MotionEvent event) {
154 | boolean result = super.onTouchEvent(event);
155 | return getRippleManager().onTouchEvent(this, event) || result;
156 | }
157 | }
158 |
--------------------------------------------------------------------------------
/material/src/main/java/com/rey/material/widget/CircleCheckedTextView.java:
--------------------------------------------------------------------------------
1 | package com.rey.material.widget;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.view.Gravity;
6 | import android.view.animation.Interpolator;
7 |
8 | import androidx.appcompat.widget.AppCompatCheckedTextView;
9 |
10 | import com.rey.material.drawable.CircleDrawable;
11 | import com.rey.material.util.ViewUtil;
12 |
13 | /**
14 | * Created by Rey on 2/5/2015.
15 | */
16 | public class CircleCheckedTextView extends AppCompatCheckedTextView {
17 |
18 | private CircleDrawable mBackground;
19 |
20 | public interface OnCheckedChangeListener{
21 | void onCheckedChanged(CircleCheckedTextView view, boolean checked);
22 | }
23 |
24 | private OnCheckedChangeListener mCheckedChangeListener;
25 |
26 | public CircleCheckedTextView(Context context) {
27 | super(context);
28 |
29 | init(context, null, 0, 0);
30 | }
31 |
32 | public CircleCheckedTextView(Context context, AttributeSet attrs) {
33 | super(context, attrs);
34 |
35 | init(context, attrs, 0, 0);
36 | }
37 |
38 | public CircleCheckedTextView(Context context, AttributeSet attrs, int defStyleAttr) {
39 | super(context, attrs, defStyleAttr);
40 |
41 | init(context, attrs, defStyleAttr, 0);
42 | }
43 |
44 | protected void init(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes){
45 | setGravity(Gravity.CENTER);
46 | setPadding(0, 0, 0, 0);
47 |
48 | mBackground = new CircleDrawable();
49 | mBackground.setInEditMode(isInEditMode());
50 | mBackground.setAnimEnable(false);
51 | ViewUtil.setBackground(this, mBackground);
52 | mBackground.setAnimEnable(true);
53 | }
54 |
55 | public void setOnCheckedChangeListener(OnCheckedChangeListener listener){
56 | mCheckedChangeListener = listener;
57 | }
58 |
59 | @Override
60 | public void setTextAppearance(int resId) {
61 | ViewUtil.applyTextAppearance(this, resId);
62 | }
63 |
64 | @Override
65 | public void setTextAppearance(Context context, int resId) {
66 | ViewUtil.applyTextAppearance(this, resId);
67 | }
68 |
69 | @Override
70 | public void setBackgroundColor(int color) {
71 | mBackground.setColor(color);
72 | }
73 |
74 | /**
75 | * Set the duration of background's animation.
76 | * @param duration The duration
77 | */
78 | public void setAnimDuration(int duration) {
79 | mBackground.setAnimDuration(duration);
80 | }
81 |
82 | public void setInterpolator(Interpolator in, Interpolator out) {
83 | mBackground.setInterpolator(in, out);
84 | }
85 |
86 | @Override
87 | public void setChecked(boolean checked) {
88 | boolean oldCheck = isChecked();
89 |
90 | if(oldCheck != checked) {
91 | super.setChecked(checked);
92 |
93 | if(mCheckedChangeListener != null)
94 | mCheckedChangeListener.onCheckedChanged(this, checked);
95 | }
96 | }
97 |
98 | public void setCheckedImmediately(boolean checked){
99 | mBackground.setAnimEnable(false);
100 | setChecked(checked);
101 | mBackground.setAnimEnable(true);
102 | }
103 |
104 | }
105 |
--------------------------------------------------------------------------------
/material/src/main/java/com/rey/material/widget/FrameLayout.java:
--------------------------------------------------------------------------------
1 | package com.rey.material.widget;
2 |
3 | import android.content.Context;
4 | import android.graphics.drawable.Drawable;
5 | import androidx.annotation.NonNull;
6 | import android.util.AttributeSet;
7 | import android.view.MotionEvent;
8 |
9 | import com.rey.material.app.ThemeManager;
10 | import com.rey.material.drawable.RippleDrawable;
11 | import com.rey.material.util.ViewUtil;
12 |
13 | public class FrameLayout extends android.widget.FrameLayout implements ThemeManager.OnThemeChangedListener{
14 |
15 | private RippleManager mRippleManager;
16 |
17 | protected int mStyleId;
18 | protected int mCurrentStyle = ThemeManager.THEME_UNDEFINED;
19 |
20 | public FrameLayout(Context context) {
21 | super(context);
22 |
23 | init(context, null, 0, 0);
24 | }
25 |
26 | public FrameLayout(Context context, AttributeSet attrs) {
27 | super(context, attrs);
28 |
29 | init(context, attrs, 0, 0);
30 | }
31 |
32 | public FrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
33 | super(context, attrs, defStyleAttr);
34 |
35 | init(context, attrs, defStyleAttr, 0);
36 | }
37 |
38 | protected void init(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes){
39 | applyStyle(context, attrs, defStyleAttr, defStyleRes);
40 | if(!isInEditMode())
41 | mStyleId = ThemeManager.getStyleId(context, attrs, defStyleAttr, defStyleRes);
42 | }
43 |
44 | public void applyStyle(int resId){
45 | ViewUtil.applyStyle(this, resId);
46 | applyStyle(getContext(), null, 0, resId);
47 | }
48 |
49 | protected void applyStyle(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes){
50 | getRippleManager().onCreate(this, context, attrs, defStyleAttr, defStyleRes);
51 | }
52 |
53 | @Override
54 | public void onThemeChanged(ThemeManager.OnThemeChangedEvent event) {
55 | int style = ThemeManager.getInstance().getCurrentStyle(mStyleId);
56 | if(mCurrentStyle != style){
57 | mCurrentStyle = style;
58 | applyStyle(mCurrentStyle);
59 | }
60 | }
61 |
62 | @Override
63 | protected void onAttachedToWindow() {
64 | super.onAttachedToWindow();
65 | if(mStyleId != 0) {
66 | ThemeManager.getInstance().registerOnThemeChangedListener(this);
67 | onThemeChanged(null);
68 | }
69 | }
70 |
71 | @Override
72 | protected void onDetachedFromWindow() {
73 | super.onDetachedFromWindow();
74 | RippleManager.cancelRipple(this);
75 | if(mStyleId != 0)
76 | ThemeManager.getInstance().unregisterOnThemeChangedListener(this);
77 | }
78 |
79 | @Override
80 | public void setBackgroundDrawable(Drawable drawable) {
81 | Drawable background = getBackground();
82 | if(background instanceof RippleDrawable && !(drawable instanceof RippleDrawable))
83 | ((RippleDrawable) background).setBackgroundDrawable(drawable);
84 | else
85 | super.setBackgroundDrawable(drawable);
86 | }
87 |
88 | protected RippleManager getRippleManager(){
89 | if(mRippleManager == null){
90 | synchronized (RippleManager.class){
91 | if(mRippleManager == null)
92 | mRippleManager = new RippleManager();
93 | }
94 | }
95 |
96 | return mRippleManager;
97 | }
98 |
99 | @Override
100 | public void setOnClickListener(OnClickListener l) {
101 | RippleManager rippleManager = getRippleManager();
102 | if (l == rippleManager)
103 | super.setOnClickListener(l);
104 | else {
105 | rippleManager.setOnClickListener(l);
106 | setOnClickListener(rippleManager);
107 | }
108 | }
109 |
110 | @Override
111 | public boolean onTouchEvent(@NonNull MotionEvent event) {
112 | boolean result = super.onTouchEvent(event);
113 | return getRippleManager().onTouchEvent(this, event) || result;
114 | }
115 |
116 | }
117 |
--------------------------------------------------------------------------------
/material/src/main/java/com/rey/material/widget/ImageButton.java:
--------------------------------------------------------------------------------
1 | package com.rey.material.widget;
2 |
3 | import android.content.Context;
4 | import android.graphics.drawable.Drawable;
5 | import androidx.annotation.NonNull;
6 | import androidx.appcompat.widget.AppCompatImageButton;
7 |
8 | import android.util.AttributeSet;
9 | import android.view.MotionEvent;
10 |
11 | import com.rey.material.app.ThemeManager;
12 | import com.rey.material.drawable.RippleDrawable;
13 | import com.rey.material.util.ViewUtil;
14 |
15 | public class ImageButton extends AppCompatImageButton implements ThemeManager.OnThemeChangedListener{
16 |
17 | private RippleManager mRippleManager;
18 | protected int mStyleId;
19 | protected int mCurrentStyle = ThemeManager.THEME_UNDEFINED;
20 |
21 | public ImageButton(Context context) {
22 | super(context);
23 |
24 | init(context, null, 0, 0);
25 | }
26 |
27 | public ImageButton(Context context, AttributeSet attrs) {
28 | super(context, attrs);
29 |
30 | init(context, attrs, 0, 0);
31 | }
32 |
33 | public ImageButton(Context context, AttributeSet attrs, int defStyleAttr) {
34 | super(context, attrs, defStyleAttr);
35 |
36 | init(context, attrs, defStyleAttr, 0);
37 | }
38 |
39 | protected void init(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes){
40 | applyStyle(context, attrs, defStyleAttr, defStyleRes);
41 | if(!isInEditMode())
42 | mStyleId = ThemeManager.getStyleId(context, attrs, defStyleAttr, defStyleRes);
43 | }
44 |
45 | public void applyStyle(int resId){
46 | ViewUtil.applyStyle(this, resId);
47 | applyStyle(getContext(), null, 0, resId);
48 | }
49 |
50 | protected void applyStyle(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes){
51 | getRippleManager().onCreate(this, context, attrs, defStyleAttr, defStyleRes);
52 | }
53 |
54 | @Override
55 | public void onThemeChanged(ThemeManager.OnThemeChangedEvent event) {
56 | int style = ThemeManager.getInstance().getCurrentStyle(mStyleId);
57 | if(mCurrentStyle != style){
58 | mCurrentStyle = style;
59 | applyStyle(mCurrentStyle);
60 | }
61 | }
62 |
63 | @Override
64 | protected void onAttachedToWindow() {
65 | super.onAttachedToWindow();
66 | if(mStyleId != 0) {
67 | ThemeManager.getInstance().registerOnThemeChangedListener(this);
68 | onThemeChanged(null);
69 | }
70 | }
71 |
72 | @Override
73 | protected void onDetachedFromWindow() {
74 | super.onDetachedFromWindow();
75 | RippleManager.cancelRipple(this);
76 | if(mStyleId != 0)
77 | ThemeManager.getInstance().unregisterOnThemeChangedListener(this);
78 | }
79 |
80 | @Override
81 | public void setBackgroundDrawable(Drawable drawable) {
82 | Drawable background = getBackground();
83 | if(background instanceof RippleDrawable && !(drawable instanceof RippleDrawable))
84 | ((RippleDrawable) background).setBackgroundDrawable(drawable);
85 | else
86 | super.setBackgroundDrawable(drawable);
87 | }
88 |
89 | protected RippleManager getRippleManager(){
90 | if(mRippleManager == null){
91 | synchronized (RippleManager.class){
92 | if(mRippleManager == null)
93 | mRippleManager = new RippleManager();
94 | }
95 | }
96 |
97 | return mRippleManager;
98 | }
99 |
100 | @Override
101 | public void setOnClickListener(OnClickListener l) {
102 | RippleManager rippleManager = getRippleManager();
103 | if (l == rippleManager)
104 | super.setOnClickListener(l);
105 | else {
106 | rippleManager.setOnClickListener(l);
107 | setOnClickListener(rippleManager);
108 | }
109 | }
110 |
111 | @Override
112 | public boolean onTouchEvent(@NonNull MotionEvent event) {
113 | boolean result = super.onTouchEvent(event);
114 | return getRippleManager().onTouchEvent(this, event) || result;
115 | }
116 |
117 | }
118 |
--------------------------------------------------------------------------------
/material/src/main/java/com/rey/material/widget/ImageView.java:
--------------------------------------------------------------------------------
1 | package com.rey.material.widget;
2 |
3 | import android.content.Context;
4 | import android.graphics.drawable.Drawable;
5 | import androidx.annotation.NonNull;
6 | import androidx.appcompat.widget.AppCompatImageView;
7 |
8 | import android.util.AttributeSet;
9 | import android.view.MotionEvent;
10 |
11 | import com.rey.material.app.ThemeManager;
12 | import com.rey.material.drawable.RippleDrawable;
13 | import com.rey.material.util.ViewUtil;
14 |
15 | /**
16 | * Created by Rey on 9/16/2015.
17 | */
18 | public class ImageView extends AppCompatImageView implements ThemeManager.OnThemeChangedListener {
19 |
20 | private RippleManager mRippleManager;
21 | protected int mStyleId;
22 | protected int mCurrentStyle = ThemeManager.THEME_UNDEFINED;
23 |
24 | public ImageView(Context context) {
25 | super(context);
26 |
27 | init(context, null, 0, 0);
28 | }
29 |
30 | public ImageView(Context context, AttributeSet attrs) {
31 | super(context, attrs);
32 |
33 | init(context, attrs, 0, 0);
34 | }
35 |
36 | public ImageView(Context context, AttributeSet attrs, int defStyleAttr) {
37 | super(context, attrs, defStyleAttr);
38 |
39 | init(context, attrs, defStyleAttr, 0);
40 | }
41 |
42 | protected void init(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes){
43 | applyStyle(context, attrs, defStyleAttr, defStyleRes);
44 | if(!isInEditMode())
45 | mStyleId = ThemeManager.getStyleId(context, attrs, defStyleAttr, defStyleRes);
46 | }
47 |
48 | public void applyStyle(int resId){
49 | ViewUtil.applyStyle(this, resId);
50 | applyStyle(getContext(), null, 0, resId);
51 | }
52 |
53 | protected void applyStyle(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes){
54 | getRippleManager().onCreate(this, context, attrs, defStyleAttr, defStyleRes);
55 | }
56 |
57 | @Override
58 | public void onThemeChanged(ThemeManager.OnThemeChangedEvent event) {
59 | int style = ThemeManager.getInstance().getCurrentStyle(mStyleId);
60 | if(mCurrentStyle != style){
61 | mCurrentStyle = style;
62 | applyStyle(mCurrentStyle);
63 | }
64 | }
65 |
66 | @Override
67 | protected void onAttachedToWindow() {
68 | super.onAttachedToWindow();
69 | if(mStyleId != 0) {
70 | ThemeManager.getInstance().registerOnThemeChangedListener(this);
71 | onThemeChanged(null);
72 | }
73 | }
74 |
75 | @Override
76 | protected void onDetachedFromWindow() {
77 | super.onDetachedFromWindow();
78 | RippleManager.cancelRipple(this);
79 | if(mStyleId != 0)
80 | ThemeManager.getInstance().unregisterOnThemeChangedListener(this);
81 | }
82 |
83 | @Override
84 | public void setBackgroundDrawable(Drawable drawable) {
85 | Drawable background = getBackground();
86 | if(background instanceof RippleDrawable && !(drawable instanceof RippleDrawable))
87 | ((RippleDrawable) background).setBackgroundDrawable(drawable);
88 | else
89 | super.setBackgroundDrawable(drawable);
90 | }
91 |
92 | protected RippleManager getRippleManager(){
93 | if(mRippleManager == null){
94 | synchronized (RippleManager.class){
95 | if(mRippleManager == null)
96 | mRippleManager = new RippleManager();
97 | }
98 | }
99 |
100 | return mRippleManager;
101 | }
102 |
103 | @Override
104 | public void setOnClickListener(OnClickListener l) {
105 | RippleManager rippleManager = getRippleManager();
106 | if (l == rippleManager)
107 | super.setOnClickListener(l);
108 | else {
109 | rippleManager.setOnClickListener(l);
110 | setOnClickListener(rippleManager);
111 | }
112 | }
113 |
114 | @Override
115 | public boolean onTouchEvent(@NonNull MotionEvent event) {
116 | boolean result = super.onTouchEvent(event);
117 | return getRippleManager().onTouchEvent(this, event) || result;
118 | }
119 |
120 | }
121 |
--------------------------------------------------------------------------------
/material/src/main/java/com/rey/material/widget/LinearLayout.java:
--------------------------------------------------------------------------------
1 | package com.rey.material.widget;
2 |
3 | import android.annotation.TargetApi;
4 | import android.content.Context;
5 | import android.graphics.drawable.Drawable;
6 | import android.os.Build;
7 | import androidx.annotation.NonNull;
8 | import android.util.AttributeSet;
9 | import android.view.MotionEvent;
10 |
11 | import com.rey.material.app.ThemeManager;
12 | import com.rey.material.drawable.RippleDrawable;
13 | import com.rey.material.util.ViewUtil;
14 |
15 | public class LinearLayout extends android.widget.LinearLayout implements ThemeManager.OnThemeChangedListener{
16 |
17 | private RippleManager mRippleManager;
18 |
19 | protected int mStyleId;
20 | protected int mCurrentStyle = ThemeManager.THEME_UNDEFINED;
21 |
22 | public LinearLayout(Context context) {
23 | super(context);
24 |
25 | init(context, null, 0, 0);
26 | }
27 |
28 | public LinearLayout(Context context, AttributeSet attrs) {
29 | super(context, attrs);
30 |
31 | init(context, attrs, 0, 0);
32 | }
33 |
34 | @TargetApi(Build.VERSION_CODES.HONEYCOMB)
35 | public LinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
36 | super(context, attrs, defStyleAttr);
37 |
38 | init(context, attrs, defStyleAttr, 0);
39 | }
40 |
41 | protected void init(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes){
42 | applyStyle(context, attrs, defStyleAttr, defStyleRes);
43 | if(!isInEditMode())
44 | mStyleId = ThemeManager.getStyleId(context, attrs, defStyleAttr, defStyleRes);
45 | }
46 |
47 | public void applyStyle(int resId){
48 | ViewUtil.applyStyle(this, resId);
49 | applyStyle(getContext(), null, 0, resId);
50 | }
51 |
52 | protected void applyStyle(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes){
53 | getRippleManager().onCreate(this, context, attrs, defStyleAttr, defStyleRes);
54 | }
55 |
56 | @Override
57 | public void onThemeChanged(ThemeManager.OnThemeChangedEvent event) {
58 | int style = ThemeManager.getInstance().getCurrentStyle(mStyleId);
59 | if(mCurrentStyle != style){
60 | mCurrentStyle = style;
61 | applyStyle(mCurrentStyle);
62 | }
63 | }
64 |
65 | @Override
66 | protected void onAttachedToWindow() {
67 | super.onAttachedToWindow();
68 | if(mStyleId != 0) {
69 | ThemeManager.getInstance().registerOnThemeChangedListener(this);
70 | onThemeChanged(null);
71 | }
72 | }
73 |
74 | @Override
75 | protected void onDetachedFromWindow() {
76 | super.onDetachedFromWindow();
77 | RippleManager.cancelRipple(this);
78 | if(mStyleId != 0)
79 | ThemeManager.getInstance().unregisterOnThemeChangedListener(this);
80 | }
81 |
82 | @Override
83 | public void setBackgroundDrawable(Drawable drawable) {
84 | Drawable background = getBackground();
85 | if(background instanceof RippleDrawable && !(drawable instanceof RippleDrawable))
86 | ((RippleDrawable) background).setBackgroundDrawable(drawable);
87 | else
88 | super.setBackgroundDrawable(drawable);
89 | }
90 |
91 | protected RippleManager getRippleManager(){
92 | if(mRippleManager == null){
93 | synchronized (RippleManager.class){
94 | if(mRippleManager == null)
95 | mRippleManager = new RippleManager();
96 | }
97 | }
98 |
99 | return mRippleManager;
100 | }
101 |
102 | @Override
103 | public void setOnClickListener(OnClickListener l) {
104 | RippleManager rippleManager = getRippleManager();
105 | if (l == rippleManager)
106 | super.setOnClickListener(l);
107 | else {
108 | rippleManager.setOnClickListener(l);
109 | setOnClickListener(rippleManager);
110 | }
111 | }
112 |
113 | @Override
114 | public boolean onTouchEvent(@NonNull MotionEvent event) {
115 | boolean result = super.onTouchEvent(event);
116 | return getRippleManager().onTouchEvent(this, event) || result;
117 | }
118 |
119 | }
120 |
--------------------------------------------------------------------------------
/material/src/main/java/com/rey/material/widget/ListView.java:
--------------------------------------------------------------------------------
1 | package com.rey.material.widget;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.view.View;
6 |
7 | import androidx.appcompat.widget.ListViewCompat;
8 |
9 | import com.rey.material.app.ThemeManager;
10 | import com.rey.material.util.ViewUtil;
11 |
12 | public class ListView extends ListViewCompat implements ThemeManager.OnThemeChangedListener{
13 |
14 | private RecyclerListener mRecyclerListener;
15 |
16 | protected int mStyleId;
17 | protected int mCurrentStyle = ThemeManager.THEME_UNDEFINED;
18 |
19 | public ListView(Context context) {
20 | super(context);
21 |
22 | init(context, null, 0, 0);
23 | }
24 |
25 | public ListView(Context context, AttributeSet attrs) {
26 | super(context, attrs);
27 |
28 | init(context, attrs, 0, 0);
29 | }
30 |
31 | public ListView(Context context, AttributeSet attrs, int defStyleAttr) {
32 | super(context, attrs, defStyleAttr);
33 |
34 | init(context, attrs, defStyleAttr, 0);
35 | }
36 |
37 | protected void init(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes){
38 |
39 | super.setRecyclerListener(new RecyclerListener() {
40 |
41 | @Override
42 | public void onMovedToScrapHeap(View view) {
43 | RippleManager.cancelRipple(view);
44 |
45 | if(mRecyclerListener != null)
46 | mRecyclerListener.onMovedToScrapHeap(view);
47 | }
48 |
49 | });
50 |
51 | if(!isInEditMode())
52 | mStyleId = ThemeManager.getStyleId(context, attrs, defStyleAttr, defStyleRes);
53 | }
54 |
55 | public void applyStyle(int resId){
56 | ViewUtil.applyStyle(this, resId);
57 | applyStyle(getContext(), null, 0, resId);
58 | }
59 |
60 | protected void applyStyle(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes){
61 | }
62 |
63 | @Override
64 | public void onThemeChanged(ThemeManager.OnThemeChangedEvent event) {
65 | int style = ThemeManager.getInstance().getCurrentStyle(mStyleId);
66 | if(mCurrentStyle != style){
67 | mCurrentStyle = style;
68 | applyStyle(mCurrentStyle);
69 | }
70 | }
71 |
72 | @Override
73 | protected void onAttachedToWindow() {
74 | super.onAttachedToWindow();
75 | if(mStyleId != 0) {
76 | ThemeManager.getInstance().registerOnThemeChangedListener(this);
77 | onThemeChanged(null);
78 | }
79 | }
80 |
81 | @Override
82 | protected void onDetachedFromWindow() {
83 | super.onDetachedFromWindow();
84 | if(mStyleId != 0)
85 | ThemeManager.getInstance().unregisterOnThemeChangedListener(this);
86 | }
87 |
88 | @Override
89 | public void setRecyclerListener(RecyclerListener listener) {
90 | mRecyclerListener = listener;
91 | }
92 |
93 | }
94 |
--------------------------------------------------------------------------------
/material/src/main/java/com/rey/material/widget/PopupWindow.java:
--------------------------------------------------------------------------------
1 | package com.rey.material.widget;
2 |
3 | import android.annotation.TargetApi;
4 | import android.content.Context;
5 | import android.content.res.TypedArray;
6 | import android.os.Build;
7 | import android.util.AttributeSet;
8 | import android.view.View;
9 |
10 | import com.rey.material.R;
11 |
12 | public class PopupWindow extends android.widget.PopupWindow {
13 |
14 | private final boolean mOverlapAnchor;
15 |
16 | public PopupWindow(Context context, AttributeSet attrs, int defStyleAttr) {
17 | super(context, attrs, defStyleAttr);
18 |
19 | TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PopupWindow, defStyleAttr, 0);
20 | mOverlapAnchor = a.getBoolean(R.styleable.PopupWindow_overlapAnchor, false);
21 | a.recycle();
22 |
23 | }
24 |
25 | @Override
26 | public void showAsDropDown(View anchor, int xoff, int yoff) {
27 | if (Build.VERSION.SDK_INT < 21 && mOverlapAnchor) {
28 | // If we're pre-L, emulate overlapAnchor by modifying the yOff
29 | yoff -= anchor.getHeight();
30 | }
31 | super.showAsDropDown(anchor, xoff, yoff);
32 | }
33 |
34 | @TargetApi(Build.VERSION_CODES.KITKAT)
35 | @Override
36 | public void showAsDropDown(View anchor, int xoff, int yoff, int gravity) {
37 | if (Build.VERSION.SDK_INT < 21 && mOverlapAnchor) {
38 | // If we're pre-L, emulate overlapAnchor by modifying the yOff
39 | yoff -= anchor.getHeight();
40 | }
41 | super.showAsDropDown(anchor, xoff, yoff, gravity);
42 | }
43 |
44 | @Override
45 | public void update(View anchor, int xoff, int yoff, int width, int height) {
46 | if (Build.VERSION.SDK_INT < 21 && mOverlapAnchor) {
47 | // If we're pre-L, emulate overlapAnchor by modifying the yOff
48 | yoff -= anchor.getHeight();
49 | }
50 | super.update(anchor, xoff, yoff, width, height);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/material/src/main/java/com/rey/material/widget/RadioButton.java:
--------------------------------------------------------------------------------
1 | package com.rey.material.widget;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 |
6 | import com.rey.material.drawable.RadioButtonDrawable;
7 |
8 | public class RadioButton extends CompoundButton {
9 |
10 | public RadioButton(Context context) {
11 | super(context);
12 | }
13 |
14 | public RadioButton(Context context, AttributeSet attrs) {
15 | super(context, attrs);
16 | }
17 |
18 | public RadioButton(Context context, AttributeSet attrs, int defStyleAttr) {
19 | super(context, attrs, defStyleAttr);
20 | }
21 |
22 | @Override
23 | protected void applyStyle(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes){
24 | super.applyStyle(context, attrs, defStyleAttr, defStyleRes);
25 |
26 | RadioButtonDrawable drawable = new RadioButtonDrawable.Builder(context, attrs, defStyleAttr, defStyleRes).build();
27 | drawable.setInEditMode(isInEditMode());
28 | drawable.setAnimEnable(false);
29 | setButtonDrawable(drawable);
30 | drawable.setAnimEnable(true);
31 | }
32 |
33 | @Override
34 | public void toggle() {
35 | // we override to prevent toggle when the radio is already
36 | // checked (as opposed to check boxes widgets)
37 | if (!isChecked()) {
38 | super.toggle();
39 | }
40 | }
41 |
42 | /**
43 | * Change the checked state of this button immediately without showing animation.
44 | * @param checked The checked state.
45 | */
46 | public void setCheckedImmediately(boolean checked){
47 | if(getButtonDrawable() instanceof RadioButtonDrawable){
48 | RadioButtonDrawable drawable = (RadioButtonDrawable)getButtonDrawable();
49 | drawable.setAnimEnable(false);
50 | setChecked(checked);
51 | drawable.setAnimEnable(true);
52 | }
53 | else
54 | setChecked(checked);
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/material/src/main/java/com/rey/material/widget/RelativeLayout.java:
--------------------------------------------------------------------------------
1 | package com.rey.material.widget;
2 |
3 | import android.content.Context;
4 | import android.graphics.drawable.Drawable;
5 | import androidx.annotation.NonNull;
6 | import android.util.AttributeSet;
7 | import android.view.MotionEvent;
8 |
9 | import com.rey.material.app.ThemeManager;
10 | import com.rey.material.drawable.RippleDrawable;
11 | import com.rey.material.util.ViewUtil;
12 |
13 | public class RelativeLayout extends android.widget.RelativeLayout implements ThemeManager.OnThemeChangedListener{
14 |
15 | private RippleManager mRippleManager;
16 |
17 | protected int mStyleId;
18 | protected int mCurrentStyle = ThemeManager.THEME_UNDEFINED;
19 |
20 | public RelativeLayout(Context context) {
21 | super(context);
22 |
23 | init(context, null, 0, 0);
24 | }
25 |
26 | public RelativeLayout(Context context, AttributeSet attrs) {
27 | super(context, attrs);
28 |
29 | init(context, attrs, 0, 0);
30 | }
31 |
32 | public RelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
33 | super(context, attrs, defStyleAttr);
34 |
35 | init(context, attrs, defStyleAttr, 0);
36 | }
37 |
38 | protected void init(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes){
39 | applyStyle(context, attrs, defStyleAttr, defStyleRes);
40 | if(!isInEditMode())
41 | mStyleId = ThemeManager.getStyleId(context, attrs, defStyleAttr, defStyleRes);
42 | }
43 |
44 | public void applyStyle(int resId){
45 | ViewUtil.applyStyle(this, resId);
46 | applyStyle(getContext(), null, 0, resId);
47 | }
48 |
49 | protected void applyStyle(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes){
50 | getRippleManager().onCreate(this, context, attrs, defStyleAttr, defStyleRes);
51 | }
52 |
53 | @Override
54 | public void onThemeChanged(ThemeManager.OnThemeChangedEvent event) {
55 | int style = ThemeManager.getInstance().getCurrentStyle(mStyleId);
56 | if(mCurrentStyle != style){
57 | mCurrentStyle = style;
58 | applyStyle(mCurrentStyle);
59 | }
60 | }
61 |
62 | @Override
63 | protected void onAttachedToWindow() {
64 | super.onAttachedToWindow();
65 | if(mStyleId != 0) {
66 | ThemeManager.getInstance().registerOnThemeChangedListener(this);
67 | onThemeChanged(null);
68 | }
69 | }
70 |
71 | @Override
72 | protected void onDetachedFromWindow() {
73 | super.onDetachedFromWindow();
74 | RippleManager.cancelRipple(this);
75 | if(mStyleId != 0)
76 | ThemeManager.getInstance().unregisterOnThemeChangedListener(this);
77 | }
78 |
79 | @Override
80 | public void setBackgroundDrawable(Drawable drawable) {
81 | Drawable background = getBackground();
82 | if(background instanceof RippleDrawable && !(drawable instanceof RippleDrawable))
83 | ((RippleDrawable) background).setBackgroundDrawable(drawable);
84 | else
85 | super.setBackgroundDrawable(drawable);
86 | }
87 |
88 | protected RippleManager getRippleManager(){
89 | if(mRippleManager == null){
90 | synchronized (RippleManager.class){
91 | if(mRippleManager == null)
92 | mRippleManager = new RippleManager();
93 | }
94 | }
95 |
96 | return mRippleManager;
97 | }
98 |
99 | @Override
100 | public void setOnClickListener(OnClickListener l) {
101 | RippleManager rippleManager = getRippleManager();
102 | if (l == rippleManager)
103 | super.setOnClickListener(l);
104 | else {
105 | rippleManager.setOnClickListener(l);
106 | setOnClickListener(rippleManager);
107 | }
108 | }
109 |
110 | @Override
111 | public boolean onTouchEvent(@NonNull MotionEvent event) {
112 | boolean result = super.onTouchEvent(event);
113 | return getRippleManager().onTouchEvent(this, event) || result;
114 | }
115 |
116 | }
117 |
--------------------------------------------------------------------------------
/material/src/main/java/com/rey/material/widget/RippleManager.java:
--------------------------------------------------------------------------------
1 | package com.rey.material.widget;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.graphics.drawable.Drawable;
6 | import android.util.AttributeSet;
7 | import android.view.MotionEvent;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 |
11 | import com.rey.material.R;
12 | import com.rey.material.drawable.RippleDrawable;
13 | import com.rey.material.drawable.ToolbarRippleDrawable;
14 | import com.rey.material.util.ViewUtil;
15 |
16 | public final class RippleManager implements View.OnClickListener{
17 |
18 | private View.OnClickListener mClickListener;
19 | private boolean mClickScheduled = false;
20 |
21 | public RippleManager(){}
22 |
23 | /**
24 | * Should be called in the construction method of view to create a RippleDrawable.
25 | * @param v
26 | * @param context
27 | * @param attrs
28 | * @param defStyleAttr
29 | * @param defStyleRes
30 | */
31 | public void onCreate(View v, Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes){
32 | if(v.isInEditMode())
33 | return;
34 |
35 | TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RippleView, defStyleAttr, defStyleRes);
36 | int rippleStyle = a.getResourceId(R.styleable.RippleView_rd_style, 0);
37 | RippleDrawable drawable = null;
38 |
39 | if(rippleStyle != 0)
40 | drawable = new RippleDrawable.Builder(context, rippleStyle).backgroundDrawable(getBackground(v)).build();
41 | else{
42 | boolean rippleEnable = a.getBoolean(R.styleable.RippleView_rd_enable, false);
43 | if(rippleEnable)
44 | drawable = new RippleDrawable.Builder(context, attrs, defStyleAttr, defStyleRes).backgroundDrawable(getBackground(v)).build();
45 | }
46 |
47 | a.recycle();
48 |
49 | if(drawable != null)
50 | ViewUtil.setBackground(v, drawable);
51 | }
52 |
53 | private Drawable getBackground(View v){
54 | Drawable background = v.getBackground();
55 | if(background == null)
56 | return null;
57 |
58 | if(background instanceof RippleDrawable)
59 | return ((RippleDrawable)background).getBackgroundDrawable();
60 |
61 | return background;
62 | }
63 |
64 | public void setOnClickListener(View.OnClickListener l) {
65 | mClickListener = l;
66 | }
67 |
68 | public boolean onTouchEvent(View v, MotionEvent event){
69 | Drawable background = v.getBackground();
70 | return background != null && background instanceof RippleDrawable && ((RippleDrawable) background).onTouch(v, event);
71 | }
72 |
73 | @Override
74 | public void onClick(View v) {
75 | Drawable background = v.getBackground();
76 | long delay = 0;
77 |
78 | if(background != null) {
79 | if (background instanceof RippleDrawable)
80 | delay = ((RippleDrawable) background).getClickDelayTime();
81 | else if (background instanceof ToolbarRippleDrawable)
82 | delay = ((ToolbarRippleDrawable) background).getClickDelayTime();
83 | }
84 |
85 | if(delay > 0 && v.getHandler() != null) {
86 | if(!mClickScheduled){
87 | mClickScheduled = true;
88 | v.getHandler().postDelayed(new ClickRunnable(v), delay);
89 | }
90 | }
91 | else
92 | dispatchClickEvent(v);
93 | }
94 |
95 | private void dispatchClickEvent(View v){
96 | if(mClickListener != null)
97 | mClickListener.onClick(v);
98 | }
99 |
100 | /**
101 | * Cancel the ripple effect of this view and all of it's children.
102 | * @param v
103 | */
104 | public static void cancelRipple(View v){
105 | Drawable background = v.getBackground();
106 | if(background instanceof RippleDrawable)
107 | ((RippleDrawable)background).cancel();
108 | else if(background instanceof ToolbarRippleDrawable)
109 | ((ToolbarRippleDrawable)background).cancel();
110 |
111 | if(v instanceof ViewGroup){
112 | ViewGroup vg = (ViewGroup)v;
113 | for(int i = 0, count = vg.getChildCount(); i < count; i++)
114 | RippleManager.cancelRipple(vg.getChildAt(i));
115 | }
116 | }
117 |
118 | class ClickRunnable implements Runnable{
119 | View mView;
120 |
121 | public ClickRunnable(View v){
122 | mView = v;
123 | }
124 |
125 | @Override
126 | public void run() {
127 | mClickScheduled = false;
128 | dispatchClickEvent(mView);
129 | }
130 | }
131 |
132 | }
133 |
--------------------------------------------------------------------------------
/material/src/main/java/com/rey/material/widget/TextView.java:
--------------------------------------------------------------------------------
1 | package com.rey.material.widget;
2 |
3 | import android.content.Context;
4 | import android.graphics.drawable.Drawable;
5 | import android.util.AttributeSet;
6 | import android.view.MotionEvent;
7 | import android.view.View;
8 |
9 | import androidx.annotation.NonNull;
10 | import androidx.appcompat.widget.AppCompatTextView;
11 |
12 | import com.rey.material.app.ThemeManager;
13 | import com.rey.material.drawable.RippleDrawable;
14 | import com.rey.material.util.ViewUtil;
15 |
16 | public class TextView extends AppCompatTextView implements ThemeManager.OnThemeChangedListener{
17 |
18 | private RippleManager mRippleManager;
19 | protected int mStyleId;
20 | protected int mCurrentStyle = ThemeManager.THEME_UNDEFINED;
21 |
22 | public interface OnSelectionChangedListener{
23 | void onSelectionChanged(View v, int selStart, int selEnd);
24 | }
25 |
26 | private OnSelectionChangedListener mOnSelectionChangedListener;
27 |
28 | public TextView(Context context) {
29 | super(context);
30 |
31 | init(context, null, 0, 0);
32 | }
33 |
34 | public TextView(Context context, AttributeSet attrs) {
35 | super(context, attrs);
36 |
37 | init(context, attrs, 0, 0);
38 | }
39 |
40 | public TextView(Context context, AttributeSet attrs, int defStyleAttr) {
41 | super(context, attrs, defStyleAttr);
42 |
43 | init(context, attrs, defStyleAttr, 0);
44 | }
45 |
46 | protected void init(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes){
47 | ViewUtil.applyFont(this, attrs, defStyleAttr, defStyleRes);
48 | applyStyle(context, attrs, defStyleAttr, defStyleRes);
49 | if(!isInEditMode())
50 | mStyleId = ThemeManager.getStyleId(context, attrs, defStyleAttr, defStyleRes);
51 | }
52 |
53 | public void applyStyle(int resId){
54 | ViewUtil.applyStyle(this, resId);
55 | applyStyle(getContext(), null, 0, resId);
56 | }
57 |
58 | protected void applyStyle(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes){
59 | getRippleManager().onCreate(this, context, attrs, defStyleAttr, defStyleRes);
60 | }
61 |
62 | @Override
63 | public void setTextAppearance(int resId) {
64 | ViewUtil.applyTextAppearance(this, resId);
65 | }
66 |
67 | @Override
68 | public void setTextAppearance(Context context, int resId) {
69 | ViewUtil.applyTextAppearance(this, resId);
70 | }
71 |
72 | @Override
73 | public void onThemeChanged(ThemeManager.OnThemeChangedEvent event) {
74 | int style = ThemeManager.getInstance().getCurrentStyle(mStyleId);
75 | if(mCurrentStyle != style){
76 | mCurrentStyle = style;
77 | applyStyle(mCurrentStyle);
78 | }
79 | }
80 |
81 | @Override
82 | protected void onAttachedToWindow() {
83 | super.onAttachedToWindow();
84 | if(mStyleId != 0) {
85 | ThemeManager.getInstance().registerOnThemeChangedListener(this);
86 | onThemeChanged(null);
87 | }
88 | }
89 |
90 | @Override
91 | protected void onDetachedFromWindow() {
92 | super.onDetachedFromWindow();
93 | RippleManager.cancelRipple(this);
94 | if(mStyleId != 0)
95 | ThemeManager.getInstance().unregisterOnThemeChangedListener(this);
96 | }
97 |
98 | @Override
99 | public void setBackgroundDrawable(Drawable drawable) {
100 | Drawable background = getBackground();
101 | if(background instanceof RippleDrawable && !(drawable instanceof RippleDrawable))
102 | ((RippleDrawable) background).setBackgroundDrawable(drawable);
103 | else
104 | super.setBackgroundDrawable(drawable);
105 | }
106 |
107 | protected RippleManager getRippleManager(){
108 | if(mRippleManager == null){
109 | synchronized (RippleManager.class){
110 | if(mRippleManager == null)
111 | mRippleManager = new RippleManager();
112 | }
113 | }
114 |
115 | return mRippleManager;
116 | }
117 |
118 | @Override
119 | public void setOnClickListener(OnClickListener l) {
120 | RippleManager rippleManager = getRippleManager();
121 | if (l == rippleManager)
122 | super.setOnClickListener(l);
123 | else {
124 | rippleManager.setOnClickListener(l);
125 | setOnClickListener(rippleManager);
126 | }
127 | }
128 |
129 | @Override
130 | public boolean onTouchEvent(@NonNull MotionEvent event) {
131 | boolean result = super.onTouchEvent(event);
132 | return getRippleManager().onTouchEvent(this, event) || result;
133 | }
134 |
135 | public void setOnSelectionChangedListener(OnSelectionChangedListener listener){
136 | mOnSelectionChangedListener = listener;
137 | }
138 |
139 | @Override
140 | protected void onSelectionChanged(int selStart, int selEnd) {
141 | super.onSelectionChanged(selStart, selEnd);
142 |
143 | if(mOnSelectionChangedListener != null)
144 | mOnSelectionChangedListener.onSelectionChanged(this, selStart, selEnd);
145 | }
146 | }
147 |
--------------------------------------------------------------------------------
/material/src/main/res/xml/nav_states.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | - 0
7 | - 0.15
8 | - 1
9 | - 0.15
10 | - 0
11 | - 0.5
12 | - 1
13 | - 0.5
14 | - 0
15 | - 0.85
16 | - 1
17 | - 0.85
18 |
19 |
20 |
21 |
22 |
23 | - 0.5
24 | - 0
25 | - 1
26 | - 0.5
27 | - 0
28 | - 0.5
29 | - 1
30 | - 0.5
31 | - 0.5
32 | - 1
33 | - 1
34 | - 0.5
35 |
36 |
37 |
38 | - 0
39 | - 2
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':material'
2 |
--------------------------------------------------------------------------------