├── .gitignore ├── MaterialLibrary ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── io │ │ └── doist │ │ └── material │ │ ├── color │ │ └── ColorPalette.java │ │ ├── drawable │ │ ├── AnimationMaterialDrawable.java │ │ ├── ColorMaterialDrawable.java │ │ ├── GradientMaterialDrawable.java │ │ ├── InsetMaterialDrawable.java │ │ ├── LayerMaterialDrawable.java │ │ ├── MaterialDrawableUtils.java │ │ ├── RippleMaterialDrawable.java │ │ ├── ScaleMaterialDrawable.java │ │ ├── StateListMaterialDrawable.java │ │ ├── TintDrawable.java │ │ └── WrapperDrawable.java │ │ ├── elevation │ │ ├── CompatElevationDelegate.java │ │ ├── CompatElevationDrawable.java │ │ └── CompatElevationUpdateRunnable.java │ │ ├── reflection │ │ └── ReflectionUtils.java │ │ ├── res │ │ ├── MaterialResources.java │ │ └── MaterialTypedArray.java │ │ └── widget │ │ ├── FloatingActionButton.java │ │ ├── MaterialAutoCompleteTextView.java │ │ ├── MaterialButton.java │ │ ├── MaterialCheckBox.java │ │ ├── MaterialCheckedTextView.java │ │ ├── MaterialEditText.java │ │ ├── MaterialFrameLayout.java │ │ ├── MaterialImageButton.java │ │ ├── MaterialImageView.java │ │ ├── MaterialLinearLayout.java │ │ ├── MaterialProgressBar.java │ │ ├── MaterialRadioButton.java │ │ ├── MaterialRelativeLayout.java │ │ ├── MaterialSpinner.java │ │ ├── MaterialSwitch.java │ │ ├── MaterialTextView.java │ │ ├── MaterialToggleButton.java │ │ ├── MaterialView.java │ │ └── utils │ │ └── MaterialWidgetHandler.java │ └── res │ ├── color │ └── btn_default_material_light.xml │ ├── drawable-hdpi │ ├── btn_check_to_on_mtrl_000.png │ ├── btn_check_to_on_mtrl_015.png │ ├── btn_mtrl_alpha.9.png │ ├── btn_radio_to_on_mtrl_000.png │ ├── btn_radio_to_on_mtrl_015.png │ ├── progress_mtrl_alpha.9.png │ └── text_cursor_mtrl_alpha.9.png │ ├── drawable-mdpi │ ├── btn_mtrl_alpha.9.png │ ├── progress_mtrl_alpha.9.png │ └── text_cursor_mtrl_alpha.9.png │ ├── drawable-xhdpi │ ├── btn_check_to_on_mtrl_000.png │ ├── btn_check_to_on_mtrl_015.png │ ├── btn_mtrl_alpha.9.png │ ├── btn_radio_to_on_mtrl_000.png │ ├── btn_radio_to_on_mtrl_015.png │ ├── progress_mtrl_alpha.9.png │ └── text_cursor_mtrl_alpha.9.png │ ├── drawable-xxhdpi │ ├── btn_check_to_on_mtrl_000.png │ ├── btn_check_to_on_mtrl_015.png │ ├── btn_mtrl_alpha.9.png │ ├── btn_radio_to_on_mtrl_000.png │ ├── btn_radio_to_on_mtrl_015.png │ ├── progress_mtrl_alpha.9.png │ └── text_cursor_mtrl_alpha.9.png │ ├── drawable-xxxhdpi │ ├── btn_check_to_on_mtrl_000.png │ ├── btn_check_to_on_mtrl_015.png │ ├── btn_radio_to_on_mtrl_000.png │ └── btn_radio_to_on_mtrl_015.png │ ├── drawable │ ├── btn_borderless_material.xml │ ├── btn_check_material.xml │ ├── btn_default_material.xml │ ├── btn_default_mtrl_shape.xml │ ├── btn_radio_material.xml │ ├── edit_text_material.xml │ ├── list_divider_material.xml │ ├── progress_horizontal_material.xml │ ├── spinner_background_material.xml │ ├── spinner_textfield_background_material.xml │ └── text_cursor_material.xml │ ├── layout-v17 │ ├── preference_category_material.xml │ ├── preference_child_material.xml │ └── preference_material.xml │ ├── layout │ ├── fragment_settings.xml │ ├── preference_category_material.xml │ ├── preference_child_material.xml │ ├── preference_material.xml │ └── preference_widget_checkbox.xml │ ├── values-ldrtl │ └── styles_widgets.xml │ ├── values-v21 │ ├── styles_material.xml │ └── themes_material.xml │ ├── values-w960dp │ └── dimens_fab.xml │ └── values │ ├── attrs_elevation_delegate.xml │ ├── attrs_fab.xml │ ├── attrs_material.xml │ ├── attrs_material_widgets.xml │ ├── dimens_abc.xml │ ├── dimens_fab.xml │ ├── donottranslate_material.xml │ ├── styles_material.xml │ ├── styles_widgets.xml │ └── themes_material.xml ├── MaterialSamples ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── io │ │ └── doist │ │ └── material │ │ └── sample │ │ ├── DemoElevatedTextView.java │ │ ├── MainActivity.java │ │ └── SettingsActivity.java │ └── res │ ├── color │ └── btn_sample.xml │ ├── drawable-hdpi │ └── ic_launcher.png │ ├── drawable-mdpi │ └── ic_launcher.png │ ├── drawable-xhdpi │ └── ic_launcher.png │ ├── drawable-xxhdpi │ └── ic_launcher.png │ ├── drawable │ └── roundrect_sample.xml │ ├── layout │ ├── activity_main.xml │ ├── activity_settings.xml │ ├── sample_elevation.xml │ ├── sample_fab.xml │ └── sample_material.xml │ ├── menu │ └── main.xml │ ├── values-w820dp │ └── dimens.xml │ ├── values │ ├── dimens.xml │ ├── strings.xml │ └── themes.xml │ └── xml │ └── preferences.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # Eclipse 2 | .project 3 | .classpath 4 | .settings 5 | .checkstyle 6 | 7 | # IntelliJ IDEA 8 | .idea 9 | *.iml 10 | *.ipr 11 | *.iws 12 | classes 13 | out 14 | gen-external-apklibs 15 | 16 | # Gradle 17 | .gradle 18 | build 19 | 20 | # Maven 21 | target 22 | release.properties 23 | pom.xml.* 24 | 25 | # Ant 26 | bin 27 | gen 28 | build.xml 29 | ant.properties 30 | local.properties 31 | proguard.cfg 32 | 33 | # Other 34 | .DS_Store 35 | Thumbs.db 36 | *~ 37 | *.swp 38 | tmp 39 | -------------------------------------------------------------------------------- /MaterialLibrary/.gitignore: -------------------------------------------------------------------------------- 1 | # Eclipse 2 | .project 3 | .classpath 4 | .settings 5 | .checkstyle 6 | 7 | # IntelliJ IDEA 8 | .idea 9 | *.iml 10 | *.ipr 11 | *.iws 12 | classes 13 | out 14 | gen-external-apklibs 15 | 16 | # Gradle 17 | .gradle 18 | build 19 | 20 | # Maven 21 | target 22 | release.properties 23 | pom.xml.* 24 | 25 | # Ant 26 | bin 27 | gen 28 | build.xml 29 | ant.properties 30 | local.properties 31 | proguard.cfg 32 | 33 | # Other 34 | .DS_Store 35 | Thumbs.db 36 | *~ 37 | *.swp 38 | tmp 39 | -------------------------------------------------------------------------------- /MaterialLibrary/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 30 5 | 6 | defaultConfig { 7 | minSdkVersion 16 8 | targetSdkVersion 30 9 | } 10 | 11 | compileOptions { 12 | sourceCompatibility JavaVersion.VERSION_1_8 13 | targetCompatibility JavaVersion.VERSION_1_8 14 | } 15 | 16 | buildTypes { 17 | release { 18 | minifyEnabled false 19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 20 | } 21 | } 22 | } 23 | 24 | dependencies { 25 | implementation 'androidx.legacy:legacy-support-v4:1.0.0' 26 | implementation 'androidx.appcompat:appcompat:1.2.0' 27 | } 28 | -------------------------------------------------------------------------------- /MaterialLibrary/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in C:\android-studio\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/java/io/doist/material/color/ColorPalette.java: -------------------------------------------------------------------------------- 1 | package io.doist.material.color; 2 | 3 | import android.content.Context; 4 | import android.os.Build; 5 | import android.util.TypedValue; 6 | 7 | import io.doist.material.R; 8 | 9 | public class ColorPalette { 10 | 11 | private ColorPalette() { 12 | throw new InstantiationError("Must not instantiate this class"); 13 | } 14 | 15 | public static int resolveAccentColor(Context context) { 16 | TypedValue value = new TypedValue(); 17 | int colorAccentAttrResId = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? 18 | android.R.attr.colorAccent : 19 | R.attr.colorAccent; 20 | return context.getTheme().resolveAttribute(colorAccentAttrResId, value, true) ? 21 | value.data : 22 | context.getResources().getColor(R.color.accent_material_light); // TODO: Make this theme dependent. 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/java/io/doist/material/drawable/AnimationMaterialDrawable.java: -------------------------------------------------------------------------------- 1 | package io.doist.material.drawable; 2 | 3 | import org.xmlpull.v1.XmlPullParser; 4 | import org.xmlpull.v1.XmlPullParserException; 5 | 6 | import android.content.Context; 7 | import android.content.res.Resources; 8 | import android.content.res.TypedArray; 9 | import android.graphics.drawable.AnimationDrawable; 10 | import android.graphics.drawable.Drawable; 11 | import android.graphics.drawable.DrawableContainer; 12 | import android.util.AttributeSet; 13 | 14 | import java.io.IOException; 15 | import java.lang.ref.WeakReference; 16 | 17 | import io.doist.material.R; 18 | import io.doist.material.reflection.ReflectionUtils; 19 | import io.doist.material.res.MaterialResources; 20 | 21 | public class AnimationMaterialDrawable extends AnimationDrawable { 22 | private final WeakReference mContext; 23 | 24 | AnimationMaterialDrawable(Context context) { 25 | mContext = new WeakReference<>(context); 26 | } 27 | 28 | @Override 29 | public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs) 30 | throws XmlPullParserException, IOException { 31 | TypedArray a = r.obtainAttributes(attrs, R.styleable.AnimationDrawable); 32 | 33 | inflateWithAttributes(r, parser, a, R.styleable.AnimationDrawable_android_visible); 34 | 35 | AnimationState mAnimationState = new AnimationState(this); 36 | 37 | mAnimationState.setVariablePadding(a.getBoolean(R.styleable.AnimationDrawable_android_variablePadding, false)); 38 | 39 | mAnimationState.setOneShot(a.getBoolean(R.styleable.AnimationDrawable_android_oneshot, false)); 40 | 41 | a.recycle(); 42 | 43 | int type; 44 | 45 | final int innerDepth = parser.getDepth()+1; 46 | int depth; 47 | while ((type=parser.next()) != XmlPullParser.END_DOCUMENT && 48 | ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) { 49 | if (type != XmlPullParser.START_TAG) { 50 | continue; 51 | } 52 | 53 | if (depth > innerDepth || !parser.getName().equals("item")) { 54 | continue; 55 | } 56 | 57 | a = r.obtainAttributes(attrs, R.styleable.AnimationDrawableItem); 58 | int duration = a.getInt( 59 | R.styleable.AnimationDrawableItem_android_duration, -1); 60 | if (duration < 0) { 61 | throw new XmlPullParserException( 62 | parser.getPositionDescription() 63 | + ": tag requires a 'duration' attribute"); 64 | } 65 | int drawableRes = a.getResourceId( 66 | R.styleable.AnimationDrawableItem_android_drawable, 0); 67 | 68 | a.recycle(); 69 | 70 | Context c = mContext.get(); 71 | Drawable dr; 72 | if (drawableRes != 0) { 73 | dr = MaterialResources.getInstance(c, r).getDrawable(drawableRes); 74 | } else { 75 | while ((type=parser.next()) == XmlPullParser.TEXT) { 76 | // Empty 77 | } 78 | if (type != XmlPullParser.START_TAG) { 79 | throw new XmlPullParserException(parser.getPositionDescription() + 80 | ": tag requires a 'drawable' attribute or child tag" + 81 | " defining a drawable"); 82 | } 83 | dr = MaterialDrawableUtils.createFromXmlInner(c, r, parser, attrs); 84 | } 85 | 86 | mAnimationState.addFrame(dr, duration); 87 | if (dr != null) { 88 | dr.setCallback(this); 89 | } 90 | } 91 | 92 | setFrame(0, true, false); 93 | } 94 | 95 | private void inflateWithAttributes(Resources r, XmlPullParser parser, TypedArray attrs, int visibleAttr) { 96 | ReflectionUtils.invokeDeclaredMethod( 97 | Drawable.class, 98 | "inflateWithAttributes", 99 | new Class[]{Resources.class, XmlPullParser.class, TypedArray.class, int.class}, 100 | this, 101 | new Object[]{r, parser, attrs, visibleAttr}); 102 | } 103 | 104 | private void setFrame(int frame, boolean unschedule, boolean animate) { 105 | ReflectionUtils.invokeDeclaredMethod( 106 | AnimationDrawable.class, 107 | "setFrame", 108 | new Class[] {int.class, boolean.class, boolean.class}, 109 | this, 110 | new Object[] {frame, unschedule, animate}); 111 | } 112 | 113 | /** 114 | * Helper class to manipulate internal member mAnimationState. 115 | */ 116 | private static class AnimationState { 117 | final Class AnimationStateClass; 118 | final Class DrawableContainerStateClass; 119 | final Object mAnimationState; 120 | 121 | public AnimationState(AnimationMaterialDrawable receiver) { 122 | AnimationStateClass = 123 | ReflectionUtils.getClass(AnimationDrawable.class.getName() + "$AnimationState"); 124 | DrawableContainerStateClass = 125 | ReflectionUtils.getClass(DrawableContainer.class.getName() + "$DrawableContainerState"); 126 | 127 | mAnimationState = ReflectionUtils.getDeclaredFieldValue( 128 | AnimationDrawable.class, 129 | "mAnimationState", 130 | receiver); 131 | } 132 | 133 | public void setVariablePadding(boolean variable) { 134 | ReflectionUtils.invokeDeclaredMethod( 135 | DrawableContainerStateClass, 136 | "setVariablePadding", 137 | new Class[] {boolean.class}, 138 | mAnimationState, 139 | new Object[] {variable}); 140 | } 141 | 142 | public void setOneShot(boolean oneShot) { 143 | ReflectionUtils.setDeclaredFieldValue( 144 | AnimationStateClass, 145 | "mOneShot", 146 | mAnimationState, 147 | oneShot); 148 | } 149 | 150 | public void addFrame(Drawable dr, int dur) { 151 | ReflectionUtils.invokeDeclaredMethod( 152 | AnimationStateClass, 153 | "addFrame", 154 | new Class[] {Drawable.class, int.class}, 155 | mAnimationState, 156 | new Object[] {dr, dur}); 157 | } 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/java/io/doist/material/drawable/ColorMaterialDrawable.java: -------------------------------------------------------------------------------- 1 | package io.doist.material.drawable; 2 | 3 | import org.xmlpull.v1.XmlPullParser; 4 | import org.xmlpull.v1.XmlPullParserException; 5 | 6 | import android.content.Context; 7 | import android.content.res.Resources; 8 | import android.content.res.TypedArray; 9 | import android.graphics.drawable.ColorDrawable; 10 | import android.util.AttributeSet; 11 | 12 | import java.io.IOException; 13 | import java.lang.ref.WeakReference; 14 | 15 | import io.doist.material.R; 16 | import io.doist.material.reflection.ReflectionUtils; 17 | 18 | public class ColorMaterialDrawable extends ColorDrawable { 19 | private final WeakReference mContext; 20 | 21 | ColorMaterialDrawable(Context context) { 22 | super(); 23 | mContext = new WeakReference<>(context); 24 | } 25 | 26 | @Override 27 | public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs) 28 | throws XmlPullParserException, IOException { 29 | Context c = mContext.get(); 30 | if (c == null) { 31 | return; 32 | } 33 | 34 | final TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.ColorDrawable); 35 | updateStateFromTypedArray(a); 36 | a.recycle(); 37 | } 38 | 39 | /** 40 | * Updates the constant state from the values in the typed array. 41 | */ 42 | private void updateStateFromTypedArray(TypedArray a) { 43 | final ColorState state = new ColorState(this); 44 | 45 | int baseColor = a.getColor(R.styleable.ColorDrawable_android_color, state.getBaseColor()); 46 | state.setBaseColor(baseColor); 47 | state.setUseColor(baseColor); 48 | } 49 | 50 | /** 51 | * Helper class to manipulate internal member mColorState. 52 | */ 53 | private static class ColorState { 54 | final Class ColorStateClass; 55 | final Object mState; 56 | 57 | public ColorState(ColorMaterialDrawable receiver) { 58 | ColorStateClass = ReflectionUtils.getClass(ColorDrawable.class.getName() + "$ColorState"); 59 | mState = ReflectionUtils.getDeclaredFieldValue(ColorDrawable.class, "mState", receiver); 60 | } 61 | 62 | public int getBaseColor() { 63 | Object result = ReflectionUtils.getDeclaredFieldValue(ColorStateClass, "mBaseColor", mState); 64 | return result != null ? (int) result : 0; 65 | } 66 | 67 | public void setBaseColor(int baseColor) { 68 | ReflectionUtils.setDeclaredFieldValue(ColorStateClass, "mBaseColor", mState, baseColor); 69 | } 70 | 71 | public void setUseColor(int useColor) { 72 | ReflectionUtils.setDeclaredFieldValue(ColorStateClass, "mUseColor", mState, useColor); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/java/io/doist/material/drawable/InsetMaterialDrawable.java: -------------------------------------------------------------------------------- 1 | package io.doist.material.drawable; 2 | 3 | import org.xmlpull.v1.XmlPullParser; 4 | import org.xmlpull.v1.XmlPullParserException; 5 | 6 | import android.content.Context; 7 | import android.content.res.Resources; 8 | import android.content.res.TypedArray; 9 | import android.graphics.drawable.Drawable; 10 | import android.graphics.drawable.InsetDrawable; 11 | import android.util.AttributeSet; 12 | import android.util.Log; 13 | 14 | import java.io.IOException; 15 | import java.lang.ref.WeakReference; 16 | 17 | import io.doist.material.R; 18 | import io.doist.material.reflection.ReflectionUtils; 19 | import io.doist.material.res.MaterialResources; 20 | 21 | public class InsetMaterialDrawable extends InsetDrawable { 22 | private final WeakReference mContext; 23 | 24 | public InsetMaterialDrawable(Context context) { 25 | super(null, 0); 26 | mContext = new WeakReference<>(context); 27 | } 28 | 29 | @Override 30 | public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs) 31 | throws XmlPullParserException, IOException { 32 | int type; 33 | 34 | TypedArray a = r.obtainAttributes(attrs, R.styleable.InsetDrawable); 35 | 36 | inflateWithAttributes(r, parser, a, R.styleable.InsetDrawable_android_visible); 37 | 38 | int drawableRes = a.getResourceId(R.styleable.InsetDrawable_android_drawable, 0); 39 | 40 | int inset = a.getDimensionPixelOffset(R.styleable.InsetDrawable_android_inset, 0); 41 | int inLeft = a.getDimensionPixelOffset(R.styleable.InsetDrawable_android_insetLeft, inset); 42 | int inTop = a.getDimensionPixelOffset(R.styleable.InsetDrawable_android_insetTop, inset); 43 | int inRight = a.getDimensionPixelOffset(R.styleable.InsetDrawable_android_insetRight, inset); 44 | int inBottom = a.getDimensionPixelOffset(R.styleable.InsetDrawable_android_insetBottom, inset); 45 | 46 | a.recycle(); 47 | 48 | Context c = mContext.get(); 49 | Drawable dr; 50 | if (drawableRes != 0) { 51 | dr = MaterialResources.getInstance(c, r).getDrawable(drawableRes); 52 | } else { 53 | while ((type = parser.next()) == XmlPullParser.TEXT) { 54 | } 55 | if (type != XmlPullParser.START_TAG) { 56 | throw new XmlPullParserException( 57 | parser.getPositionDescription() 58 | + ": tag requires a 'drawable' attribute or " 59 | + "child tag defining a drawable"); 60 | } 61 | dr = MaterialDrawableUtils.createFromXmlInner(c, r, parser, attrs); 62 | } 63 | 64 | if (dr == null) { 65 | Log.w("drawable", "No drawable specified for "); 66 | } 67 | 68 | InsetState mInsetState = new InsetState(this); 69 | mInsetState.setDrawable(dr); 70 | mInsetState.setInsetLeft(inLeft); 71 | mInsetState.setInsetRight(inRight); 72 | mInsetState.setInsetTop(inTop); 73 | mInsetState.setInsetBottom(inBottom); 74 | 75 | if (dr != null) { 76 | dr.setCallback(this); 77 | } 78 | } 79 | 80 | private void inflateWithAttributes(Resources r, XmlPullParser parser, TypedArray attrs, int visibleAttr) { 81 | ReflectionUtils.invokeDeclaredMethod( 82 | Drawable.class, 83 | "inflateWithAttributes", 84 | new Class[]{Resources.class, XmlPullParser.class, TypedArray.class, int.class}, 85 | this, 86 | new Object[]{r, parser, attrs, visibleAttr}); 87 | } 88 | 89 | /** 90 | * Helper class to manipulate internal member mInsetState. 91 | */ 92 | private static class InsetState { 93 | final Class InsetStateClass; 94 | final Object mInsetState; 95 | 96 | public InsetState(InsetMaterialDrawable receiver) { 97 | InsetStateClass = ReflectionUtils.getClass(InsetDrawable.class.getName() + "$InsetState"); 98 | 99 | mInsetState = ReflectionUtils.getDeclaredFieldValue( 100 | InsetDrawable.class, 101 | "mInsetState", 102 | receiver); 103 | } 104 | 105 | public void setDrawable(Drawable drawable) { 106 | setField("mDrawable", drawable); 107 | } 108 | 109 | public void setInsetLeft(int inLeft) { 110 | setField("mInsetLeft", inLeft); 111 | } 112 | 113 | public void setInsetRight(int inRight) { 114 | setField("mInsetRight", inRight); 115 | } 116 | 117 | public void setInsetTop(int inTop) { 118 | setField("mInsetTop", inTop); 119 | } 120 | 121 | public void setInsetBottom(int inBottom) { 122 | setField("mInsetBottom", inBottom); 123 | } 124 | 125 | private void setField(String fieldName, Object value) { 126 | ReflectionUtils.setDeclaredFieldValue(InsetStateClass, fieldName, mInsetState, value); 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/java/io/doist/material/drawable/MaterialDrawableUtils.java: -------------------------------------------------------------------------------- 1 | package io.doist.material.drawable; 2 | 3 | import org.xmlpull.v1.XmlPullParser; 4 | import org.xmlpull.v1.XmlPullParserException; 5 | 6 | import android.content.Context; 7 | import android.content.res.ColorStateList; 8 | import android.content.res.Resources; 9 | import android.graphics.drawable.BitmapDrawable; 10 | import android.graphics.drawable.Drawable; 11 | import android.graphics.drawable.NinePatchDrawable; 12 | import android.util.AttributeSet; 13 | import android.util.Xml; 14 | 15 | import java.io.IOException; 16 | 17 | public class MaterialDrawableUtils { 18 | 19 | private MaterialDrawableUtils() { 20 | throw new InstantiationError("Must not instantiate this class"); 21 | } 22 | 23 | public static Drawable createFromXml(Context c, Resources r, XmlPullParser parser) 24 | throws XmlPullParserException, IOException, NoSuchMethodException { 25 | AttributeSet attrs = Xml.asAttributeSet(parser); 26 | 27 | int type; 28 | while ((type = parser.next()) != XmlPullParser.START_TAG && 29 | type != XmlPullParser.END_DOCUMENT) { 30 | // Empty loop. 31 | } 32 | 33 | if (type != XmlPullParser.START_TAG) { 34 | throw new XmlPullParserException("No start tag found"); 35 | } 36 | 37 | Drawable drawable = createFromXmlInner(c, r, parser, attrs); 38 | 39 | if (drawable == null) { 40 | throw new RuntimeException("Unknown initial tag: " + parser.getName()); 41 | } 42 | 43 | return drawable; 44 | } 45 | 46 | @SuppressWarnings("deprecation") 47 | public static Drawable createFromXmlInner(Context c, Resources r, XmlPullParser parser, AttributeSet attrs) 48 | throws XmlPullParserException, IOException { 49 | Drawable drawable; 50 | 51 | final String name = parser.getName(); 52 | 53 | // TODO: add the remaining drawables that are not covered. 54 | if (name.equals("selector")) { 55 | drawable = new StateListMaterialDrawable(c); 56 | //} else if (name.equals("animated-selector")) { 57 | //} else if (name.equals("level-list")) { 58 | } else if (name.equals("layer-list")) { 59 | drawable = new LayerMaterialDrawable(c); 60 | //} else if (name.equals("transition")) { 61 | } else if (name.equals("ripple")) { 62 | drawable = new RippleMaterialDrawable(c); 63 | } else if (name.equals("color")) { 64 | drawable = new ColorMaterialDrawable(c); 65 | } else if (name.equals("shape")) { 66 | drawable = new GradientMaterialDrawable(c); 67 | //} else if (name.equals("vector")) { 68 | //} else if (name.equals("animated-vector")) { 69 | } else if (name.equals("scale")) { 70 | drawable = new ScaleMaterialDrawable(c); 71 | //} else if (name.equals("clip")) { 72 | //} else if (name.equals("rotate")) { 73 | //} else if (name.equals("animated-rotate")) { 74 | } else if (name.equals("animation-list")) { 75 | drawable = new AnimationMaterialDrawable(c); 76 | } else if (name.equals("inset")) { 77 | drawable = new InsetMaterialDrawable(c); 78 | } else if (name.equals("bitmap")) { 79 | drawable = new BitmapDrawable(); 80 | if (r != null) { 81 | ((BitmapDrawable) drawable).setTargetDensity(r.getDisplayMetrics()); 82 | } 83 | drawable = new TintDrawable(c, drawable); 84 | } else if (name.equals("nine-patch")) { 85 | drawable = new NinePatchDrawable(null, null); 86 | if (r != null) { 87 | ((NinePatchDrawable) drawable).setTargetDensity(r.getDisplayMetrics()); 88 | } 89 | drawable = new TintDrawable(c, drawable); 90 | } else { 91 | drawable = null; 92 | } 93 | 94 | if (drawable != null) { 95 | drawable.inflate(r, parser, attrs); 96 | 97 | if (drawable instanceof GradientMaterialDrawable) { 98 | // Before Lollipop, GradientDrawable does not support a ColorStateList solid color. 99 | // In the case of a stateful solid color, enclose the drawable inside a TintDrawable. 100 | ColorStateList solidColor = ((GradientMaterialDrawable) drawable).getSolidColor(); 101 | if (solidColor != null && solidColor.isStateful()) { 102 | drawable = new TintDrawable(c, drawable, solidColor); 103 | } 104 | } 105 | } else { 106 | drawable = Drawable.createFromXmlInner(r, parser, attrs); 107 | } 108 | 109 | return drawable; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/java/io/doist/material/drawable/ScaleMaterialDrawable.java: -------------------------------------------------------------------------------- 1 | package io.doist.material.drawable; 2 | 3 | import org.xmlpull.v1.XmlPullParser; 4 | import org.xmlpull.v1.XmlPullParserException; 5 | 6 | import android.content.Context; 7 | import android.content.res.Resources; 8 | import android.content.res.TypedArray; 9 | import android.graphics.drawable.Drawable; 10 | import android.graphics.drawable.ScaleDrawable; 11 | import android.util.AttributeSet; 12 | import android.view.Gravity; 13 | 14 | import java.io.IOException; 15 | import java.lang.ref.WeakReference; 16 | 17 | import io.doist.material.R; 18 | import io.doist.material.reflection.ReflectionUtils; 19 | import io.doist.material.res.MaterialResources; 20 | 21 | public class ScaleMaterialDrawable extends ScaleDrawable { 22 | private final WeakReference mContext; 23 | 24 | public ScaleMaterialDrawable(Context context) { 25 | super(null, Gravity.LEFT, -1.0f, -1.0f); 26 | mContext = new WeakReference<>(context); 27 | } 28 | 29 | private static float getPercent(TypedArray a, int name) { 30 | String s = a.getString(name); 31 | if (s != null) { 32 | if (s.endsWith("%")) { 33 | String f = s.substring(0, s.length() - 1); 34 | return Float.parseFloat(f) / 100.0f; 35 | } 36 | } 37 | return -1; 38 | } 39 | 40 | @Override 41 | public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs) 42 | throws XmlPullParserException, IOException { 43 | int type; 44 | 45 | TypedArray a = r.obtainAttributes(attrs, R.styleable.ScaleDrawable); 46 | 47 | float sw = getPercent(a, R.styleable.ScaleDrawable_android_scaleWidth); 48 | float sh = getPercent(a, R.styleable.ScaleDrawable_android_scaleHeight); 49 | int g = a.getInt(R.styleable.ScaleDrawable_android_scaleGravity, Gravity.LEFT); 50 | boolean min = a.getBoolean(R.styleable.ScaleDrawable_android_useIntrinsicSizeAsMinimum, false); 51 | int drawableRes = a.getResourceId(R.styleable.ScaleDrawable_android_drawable, 0); 52 | Context c = mContext.get(); 53 | Drawable dr = null; 54 | if (drawableRes != 0) { 55 | dr = MaterialResources.getInstance(c, r).getDrawable(drawableRes); 56 | } 57 | 58 | a.recycle(); 59 | 60 | final int outerDepth = parser.getDepth(); 61 | while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 62 | && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 63 | if (type != XmlPullParser.START_TAG) { 64 | continue; 65 | } 66 | dr = MaterialDrawableUtils.createFromXmlInner(c, r, parser, attrs); 67 | } 68 | 69 | if (dr == null) { 70 | throw new IllegalArgumentException("No drawable specified for "); 71 | } 72 | 73 | ScaleState mScaleState = new ScaleState(this); 74 | mScaleState.setDrawable(dr); 75 | mScaleState.setScaleWidth(sw); 76 | mScaleState.setScaleHeight(sh); 77 | mScaleState.setGravity(g); 78 | mScaleState.setUseIntrinsicSizeAsMin(min); 79 | 80 | if (dr != null) { 81 | dr.setCallback(this); 82 | } 83 | } 84 | 85 | /** 86 | * Helper class to manipulate internal member mScaleState. 87 | */ 88 | private static class ScaleState { 89 | final Class ScaleStateClass; 90 | final Object mScaleState; 91 | 92 | public ScaleState(ScaleMaterialDrawable receiver) { 93 | ScaleStateClass = ReflectionUtils.getClass(ScaleDrawable.class.getName() + "$ScaleState"); 94 | 95 | mScaleState = ReflectionUtils.getDeclaredFieldValue( 96 | ScaleDrawable.class, 97 | "mScaleState", 98 | receiver); 99 | } 100 | 101 | public void setDrawable(Drawable drawable) { 102 | setField("mDrawable", drawable); 103 | } 104 | 105 | public void setScaleWidth(float scaleWidth) { 106 | setField("mScaleWidth", scaleWidth); 107 | } 108 | 109 | public void setScaleHeight(float scaleHeight) { 110 | setField("mScaleHeight", scaleHeight); 111 | } 112 | 113 | public void setGravity(int gravity) { 114 | setField("mGravity", gravity); 115 | } 116 | 117 | public void setUseIntrinsicSizeAsMin(boolean useIntrinsicSizeAsMin) { 118 | setField("mUseIntrinsicSizeAsMin", useIntrinsicSizeAsMin); 119 | } 120 | 121 | private void setField(String fieldName, Object value) { 122 | ReflectionUtils.setDeclaredFieldValue(ScaleStateClass, fieldName, mScaleState, value); 123 | } 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/java/io/doist/material/drawable/StateListMaterialDrawable.java: -------------------------------------------------------------------------------- 1 | package io.doist.material.drawable; 2 | 3 | import org.xmlpull.v1.XmlPullParser; 4 | import org.xmlpull.v1.XmlPullParserException; 5 | 6 | import android.content.Context; 7 | import android.content.res.Resources; 8 | import android.content.res.TypedArray; 9 | import android.graphics.drawable.Drawable; 10 | import android.graphics.drawable.DrawableContainer; 11 | import android.graphics.drawable.StateListDrawable; 12 | import android.os.Build; 13 | import android.util.AttributeSet; 14 | import android.util.StateSet; 15 | 16 | import java.io.IOException; 17 | import java.lang.ref.WeakReference; 18 | 19 | import io.doist.material.R; 20 | import io.doist.material.reflection.ReflectionUtils; 21 | import io.doist.material.res.MaterialTypedArray; 22 | 23 | public class StateListMaterialDrawable extends StateListDrawable { 24 | private static final boolean DEFAULT_DITHER = true; 25 | 26 | private final WeakReference mContext; 27 | 28 | StateListMaterialDrawable(Context context) { 29 | mContext = new WeakReference<>(context); 30 | } 31 | 32 | @Override 33 | public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs) 34 | throws XmlPullParserException, IOException { 35 | TypedArray a = r.obtainAttributes(attrs, R.styleable.StateListDrawable); 36 | 37 | inflateWithAttributes(r, parser, a, R.styleable.StateListDrawable_android_visible); 38 | 39 | StateListState mStateListState = new StateListState(this); 40 | 41 | mStateListState.setVariablePadding( 42 | a.getBoolean(R.styleable.StateListDrawable_android_variablePadding, false)); 43 | mStateListState.setConstantSize(a.getBoolean( 44 | R.styleable.StateListDrawable_android_constantSize, false)); 45 | mStateListState.setEnterFadeDuration(a.getInt( 46 | R.styleable.StateListDrawable_android_enterFadeDuration, 0)); 47 | mStateListState.setExitFadeDuration(a.getInt( 48 | R.styleable.StateListDrawable_android_exitFadeDuration, 0)); 49 | 50 | setDither(a.getBoolean(R.styleable.StateListDrawable_android_dither, DEFAULT_DITHER)); 51 | 52 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 53 | setAutoMirrored(a.getBoolean(R.styleable.StateListDrawable_android_autoMirrored, false)); 54 | } 55 | 56 | a.recycle(); 57 | 58 | int type; 59 | 60 | final int innerDepth = parser.getDepth() + 1; 61 | int depth; 62 | while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 63 | && ((depth = parser.getDepth()) >= innerDepth 64 | || type != XmlPullParser.END_TAG)) { 65 | if (type != XmlPullParser.START_TAG) { 66 | continue; 67 | } 68 | 69 | if (depth > innerDepth || !parser.getName().equals("item")) { 70 | continue; 71 | } 72 | 73 | // This allows state list drawable item elements to be themed at 74 | // inflation time but does NOT make them work for Zygote preload. 75 | Context c = mContext.get(); 76 | if (c == null) { 77 | break; 78 | } 79 | a = obtainAttributes(c, r, attrs, R.styleable.StateListDrawableItem); 80 | Drawable dr = MaterialTypedArray.getDrawable(c, r, a, R.styleable.StateListDrawableItem_android_drawable); 81 | a.recycle(); 82 | 83 | final int[] states = extractStateSet(attrs); 84 | 85 | // Loading child elements modifies the state of the AttributeSet's 86 | // underlying parser, so it needs to happen after obtaining 87 | // attributes and extracting states. 88 | if (dr == null) { 89 | while ((type = parser.next()) == XmlPullParser.TEXT) { 90 | } 91 | if (type != XmlPullParser.START_TAG) { 92 | throw new XmlPullParserException( 93 | parser.getPositionDescription() 94 | + ": tag requires a 'drawable' attribute or " 95 | + "child tag defining a drawable"); 96 | } 97 | dr = MaterialDrawableUtils.createFromXmlInner(c, r, parser, attrs); 98 | } 99 | 100 | mStateListState.addStateSet(states, dr); 101 | } 102 | 103 | onStateChange(getState()); 104 | } 105 | 106 | private TypedArray obtainAttributes(Context context, Resources r, AttributeSet set, int[] attrs) { 107 | return context != null ? 108 | context.obtainStyledAttributes(set, attrs) : 109 | r.obtainAttributes(set, attrs); 110 | } 111 | 112 | private void inflateWithAttributes(Resources r, XmlPullParser parser, TypedArray attrs, int visibleAttr) { 113 | ReflectionUtils.invokeDeclaredMethod( 114 | Drawable.class, 115 | "inflateWithAttributes", 116 | new Class[]{Resources.class, XmlPullParser.class, TypedArray.class, int.class}, 117 | this, 118 | new Object[]{r, parser, attrs, visibleAttr}); 119 | } 120 | 121 | /** 122 | * Extracts state_ attributes from an attribute set. 123 | * 124 | * @param attrs The attribute set. 125 | * @return An array of state_ attributes. 126 | */ 127 | int[] extractStateSet(AttributeSet attrs) { 128 | int j = 0; 129 | final int numAttrs = attrs.getAttributeCount(); 130 | int[] states = new int[numAttrs]; 131 | for (int i = 0; i < numAttrs; i++) { 132 | final int stateResId = attrs.getAttributeNameResource(i); 133 | switch (stateResId) { 134 | case 0: 135 | break; 136 | case android.R.attr.drawable: 137 | case android.R.attr.id: 138 | // Ignore attributes from StateListDrawableItem. 139 | break; 140 | default: 141 | states[j++] = attrs.getAttributeBooleanValue(i, false) 142 | ? stateResId : -stateResId; 143 | } 144 | } 145 | states = StateSet.trimStateSet(states, j); 146 | return states; 147 | } 148 | 149 | /** 150 | * Helper class to manipulate internal member mStateListState. 151 | */ 152 | private static class StateListState { 153 | final Class StateListStateClass; 154 | final Class DrawableContainerStateClass; 155 | final Object mStateListState; 156 | 157 | public StateListState(StateListMaterialDrawable receiver) { 158 | StateListStateClass = 159 | ReflectionUtils.getClass(StateListDrawable.class.getName() + "$StateListState"); 160 | DrawableContainerStateClass = 161 | ReflectionUtils.getClass(DrawableContainer.class.getName() + "$DrawableContainerState"); 162 | 163 | mStateListState = ReflectionUtils.getDeclaredFieldValue( 164 | StateListDrawable.class, 165 | "mStateListState", 166 | receiver); 167 | } 168 | 169 | public int addStateSet(int[] stateSet, Drawable drawable) { 170 | Object result = ReflectionUtils.invokeDeclaredMethod( 171 | StateListStateClass, 172 | "addStateSet", 173 | new Class[] {int[].class, Drawable.class}, 174 | mStateListState, 175 | new Object[] {stateSet, drawable}); 176 | return result != null ? (int) result : 0; 177 | } 178 | 179 | public final void setVariablePadding(boolean variable) { 180 | ReflectionUtils.invokeDeclaredMethod( 181 | DrawableContainerStateClass, 182 | "setVariablePadding", 183 | new Class[] {boolean.class}, 184 | mStateListState, 185 | new Object[] {variable}); 186 | } 187 | 188 | public final void setConstantSize(boolean constant) { 189 | ReflectionUtils.invokeDeclaredMethod( 190 | DrawableContainerStateClass, 191 | "setConstantSize", 192 | new Class[] {boolean.class}, 193 | mStateListState, 194 | new Object[] {constant}); 195 | } 196 | 197 | public final void setEnterFadeDuration(int duration) { 198 | ReflectionUtils.invokeDeclaredMethod( 199 | DrawableContainerStateClass, 200 | "setEnterFadeDuration", 201 | new Class[] {int.class}, 202 | mStateListState, 203 | new Object[] {duration}); 204 | } 205 | 206 | public final void setExitFadeDuration(int duration) { 207 | ReflectionUtils.invokeDeclaredMethod( 208 | DrawableContainerStateClass, 209 | "setExitFadeDuration", 210 | new Class[] {int.class}, 211 | mStateListState, 212 | new Object[] {duration}); 213 | } 214 | } 215 | } 216 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/java/io/doist/material/drawable/TintDrawable.java: -------------------------------------------------------------------------------- 1 | package io.doist.material.drawable; 2 | 3 | import org.xmlpull.v1.XmlPullParser; 4 | import org.xmlpull.v1.XmlPullParserException; 5 | 6 | import android.content.Context; 7 | import android.content.res.ColorStateList; 8 | import android.content.res.Resources; 9 | import android.content.res.TypedArray; 10 | import android.graphics.Color; 11 | import android.graphics.ColorFilter; 12 | import android.graphics.Paint; 13 | import android.graphics.PorterDuff; 14 | import android.graphics.PorterDuffColorFilter; 15 | import android.graphics.drawable.ColorDrawable; 16 | import android.graphics.drawable.Drawable; 17 | import android.os.Parcel; 18 | import android.util.AttributeSet; 19 | import android.util.TypedValue; 20 | 21 | import java.io.IOException; 22 | import java.lang.ref.WeakReference; 23 | 24 | import io.doist.material.R; 25 | import io.doist.material.reflection.ReflectionUtils; 26 | 27 | public class TintDrawable extends WrapperDrawable { 28 | private static final PorterDuff.Mode DEFAULT_TINT_MODE = PorterDuff.Mode.SRC_IN; 29 | 30 | private WeakReference mContext; 31 | 32 | private TintState mTintState; 33 | 34 | private boolean mMutated = false; 35 | 36 | public TintDrawable(Context context, Drawable drawable) { 37 | this(context, drawable, null); 38 | } 39 | 40 | protected TintDrawable(TintState state, Resources res) { 41 | super(state, res); 42 | mTintState = (TintState) getConstantState(); 43 | updateTint(); 44 | updateAlpha(); 45 | } 46 | 47 | public TintDrawable(Context context, Drawable drawable, int tint) { 48 | this(context, drawable, ColorStateList.valueOf(tint)); 49 | } 50 | 51 | public TintDrawable(Context context, Drawable drawable, ColorStateList tint) { 52 | super(drawable); 53 | mContext = new WeakReference<>(context); 54 | mTintState = (TintState) getConstantState(); 55 | mTintState.mTint = tint; 56 | mTintState.mTintEnabled = true; 57 | updateTint(); 58 | } 59 | 60 | @Override 61 | public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs) 62 | throws XmlPullParserException, IOException { 63 | super.inflate(r, parser, attrs); 64 | 65 | final Context context = mContext != null ? mContext.get() : null; 66 | 67 | final TypedArray a; 68 | if (context != null) { 69 | a = context.obtainStyledAttributes(attrs, R.styleable.TintDrawable); 70 | } else { 71 | a = r.obtainAttributes(attrs, R.styleable.TintDrawable); 72 | } 73 | 74 | try { 75 | final TypedValue v = new TypedValue(); 76 | if (a.getValue(R.styleable.TintDrawable_android_tint, v)) { 77 | // Tint was successfully retrieved. 78 | if (v.type >= TypedValue.TYPE_FIRST_COLOR_INT 79 | && v.type <= TypedValue.TYPE_LAST_COLOR_INT) { 80 | mTintState.mTint = ColorStateList.valueOf( 81 | a.getColor(R.styleable.TintDrawable_android_tint, Color.TRANSPARENT)); 82 | } else { 83 | mTintState.mTint = a.getColorStateList(R.styleable.TintDrawable_android_tint); 84 | } 85 | mTintState.mTintEnabled = true; 86 | } 87 | 88 | // Initialize base alpha. 89 | mTintState.mBaseAlpha = (int) (a.getFloat(R.styleable.TintDrawable_android_alpha, 1.0f) * 255 + .5f); 90 | mTintState.mUseAlpha = mTintState.mBaseAlpha; 91 | } 92 | finally { 93 | a.recycle(); 94 | } 95 | 96 | updateTint(); 97 | updateAlpha(); 98 | } 99 | 100 | @Override 101 | public boolean isStateful() { 102 | // Drawable is stateful or tint is enable and has multiple states. 103 | return super.isStateful() || 104 | (mTintState.mTintEnabled && mTintState.mTint != null && mTintState.mTint.isStateful()); 105 | } 106 | 107 | @Override 108 | protected boolean onStateChange(int[] state) { 109 | if (mTintState.mTintEnabled && mTintState.mTint != null) { 110 | updateTint(); 111 | return true; 112 | } 113 | 114 | return false; 115 | } 116 | 117 | @Override 118 | public void setColorFilter(ColorFilter cf) { 119 | superSetColorFilter(cf); 120 | mTintState.mTintEnabled = cf == null; 121 | updateTint(); 122 | } 123 | 124 | private void superSetColorFilter(ColorFilter cf) { 125 | if (mTintState.mDrawable instanceof ColorDrawable) { 126 | Paint paint = 127 | (Paint) ReflectionUtils.getDeclaredFieldValue(ColorDrawable.class, "mPaint", mTintState.mDrawable); 128 | paint.setColorFilter(cf); 129 | } else { 130 | super.setColorFilter(cf); 131 | } 132 | } 133 | 134 | @Override 135 | public void setTint(int tint) { 136 | setTintList(ColorStateList.valueOf(tint)); 137 | } 138 | 139 | @Override 140 | public void setTintList(ColorStateList tint) { 141 | if (mTintState.mTint != tint) { 142 | mTintState.mTint = tint; 143 | updateTint(); 144 | } 145 | } 146 | 147 | @Override 148 | public void setTintMode(PorterDuff.Mode tintMode) { 149 | if (mTintState.mTintMode != tintMode) { 150 | mTintState.mTintMode = tintMode; 151 | updateTint(); 152 | } 153 | } 154 | 155 | private void updateTint() { 156 | if (mTintState.mTintEnabled && mTintState.mTint != null) { 157 | superSetColorFilter( 158 | new PorterDuffColorFilter( 159 | mTintState.mTint.getColorForState(getState(), mTintState.mTint.getDefaultColor()), 160 | mTintState.mTintMode != null ? mTintState.mTintMode : DEFAULT_TINT_MODE)); 161 | } 162 | } 163 | 164 | @Override 165 | public void setAlpha(int alpha) { 166 | if (mTintState.mUseAlpha != alpha) { 167 | mTintState.mUseAlpha = alpha; 168 | updateAlpha(); 169 | } 170 | } 171 | 172 | private void updateAlpha() { 173 | super.setAlpha(mTintState.mBaseAlpha * mTintState.mUseAlpha >> 8); 174 | } 175 | 176 | @Override 177 | public Drawable mutate() { 178 | if (!mMutated && super.mutate() == this) { 179 | // Get constant state, because we are creating a new one in super.mutate(). 180 | TintState tintState = (TintState) getConstantState(); 181 | 182 | if (mTintState.mTint != null) { 183 | // Clone mTint if not null. 184 | final Parcel p = Parcel.obtain(); 185 | mTintState.mTint.writeToParcel(p, 0); 186 | p.setDataPosition(0); 187 | tintState.mTint = ColorStateList.CREATOR.createFromParcel(p); 188 | } 189 | tintState.mTintMode = mTintState.mTintMode; 190 | tintState.mTintEnabled = mTintState.mTintEnabled; 191 | tintState.mBaseAlpha = mTintState.mBaseAlpha; 192 | tintState.mUseAlpha = mTintState.mUseAlpha; 193 | 194 | mTintState = tintState; 195 | mMutated = true; 196 | } 197 | return this; 198 | } 199 | 200 | @Override 201 | protected WrapperState createConstantState(WrapperState state) { 202 | return new TintState(state); 203 | } 204 | 205 | protected static class TintState extends WrapperState { 206 | ColorStateList mTint; 207 | PorterDuff.Mode mTintMode; 208 | boolean mTintEnabled; 209 | int mBaseAlpha = 255; 210 | int mUseAlpha = 255; 211 | 212 | public TintState(WrapperState state) { 213 | super(state); 214 | 215 | if (state != null) { 216 | TintState tintState = (TintState) state; 217 | mTint = tintState.mTint; 218 | mTintMode = tintState.mTintMode; 219 | mTintEnabled = tintState.mTintEnabled; 220 | mBaseAlpha = tintState.mBaseAlpha; 221 | mUseAlpha = tintState.mUseAlpha; 222 | } 223 | } 224 | 225 | @Override 226 | public void setDrawable(Drawable drawable, WrapperDrawable owner) { 227 | if (drawable.getClass().equals(TintDrawable.class)) { 228 | // Chained instances of TintDrawables are not possible and thus are unnecessary. 229 | drawable = ((WrapperState)drawable.getConstantState()).mDrawable; 230 | } 231 | super.setDrawable(drawable, owner); 232 | } 233 | 234 | @Override 235 | public Drawable newDrawable() { 236 | return newDrawable(null); 237 | } 238 | 239 | @Override 240 | public Drawable newDrawable(Resources res) { 241 | return new TintDrawable(this, res); 242 | } 243 | } 244 | 245 | } 246 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/java/io/doist/material/drawable/WrapperDrawable.java: -------------------------------------------------------------------------------- 1 | package io.doist.material.drawable; 2 | 3 | import org.xmlpull.v1.XmlPullParser; 4 | import org.xmlpull.v1.XmlPullParserException; 5 | 6 | import android.annotation.TargetApi; 7 | import android.content.res.ColorStateList; 8 | import android.content.res.Resources; 9 | import android.graphics.Canvas; 10 | import android.graphics.ColorFilter; 11 | import android.graphics.PorterDuff; 12 | import android.graphics.Rect; 13 | import android.graphics.Region; 14 | import android.graphics.drawable.Drawable; 15 | import android.os.Build; 16 | import android.util.AttributeSet; 17 | 18 | import java.io.IOException; 19 | import java.util.Arrays; 20 | 21 | public class WrapperDrawable extends Drawable implements Drawable.Callback { 22 | private WrapperState mWrapperState; 23 | private boolean mMutated = false; 24 | 25 | public WrapperDrawable(Drawable drawable) { 26 | mWrapperState = createConstantState(null); 27 | setWrappedDrawable(drawable); 28 | } 29 | 30 | protected WrapperDrawable(WrapperState state, Resources res) { 31 | mWrapperState = createConstantState(state); 32 | 33 | final Drawable drawable; 34 | if (res != null) { 35 | drawable = mWrapperState.mDrawable.getConstantState().newDrawable(res); 36 | } else { 37 | drawable = mWrapperState.mDrawable.getConstantState().newDrawable(); 38 | } 39 | mWrapperState.setDrawable(drawable, this); 40 | } 41 | 42 | public void setWrappedDrawable(Drawable drawable) { 43 | if (mWrapperState.mDrawable != null) { 44 | mWrapperState.mDrawable.setCallback(null); 45 | } 46 | mWrapperState.setDrawable(drawable, this); 47 | } 48 | 49 | public Drawable getWrappedDrawable() { 50 | return mWrapperState.mDrawable; 51 | } 52 | 53 | @Override 54 | public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs) 55 | throws XmlPullParserException, IOException { 56 | mWrapperState.mDrawable.inflate(r, parser, attrs); 57 | } 58 | 59 | @Override 60 | public void draw(Canvas canvas) { 61 | mWrapperState.mDrawable.draw(canvas); 62 | } 63 | 64 | @Override 65 | public void setChangingConfigurations(int configs) { 66 | mWrapperState.mChangingConfigurations = configs; 67 | } 68 | 69 | @Override 70 | public int getChangingConfigurations() { 71 | return super.getChangingConfigurations() | mWrapperState.mChangingConfigurations; 72 | } 73 | 74 | @Override 75 | public void setDither(boolean dither) { 76 | mWrapperState.mDrawable.setDither(dither); 77 | } 78 | 79 | @Override 80 | public void setFilterBitmap(boolean filter) { 81 | mWrapperState.mDrawable.setFilterBitmap(filter); 82 | } 83 | 84 | @Override 85 | public void setAlpha(int alpha) { 86 | mWrapperState.mDrawable.setAlpha(alpha); 87 | } 88 | 89 | @TargetApi(Build.VERSION_CODES.KITKAT) 90 | @Override 91 | public int getAlpha() { 92 | return mWrapperState.mDrawable.getAlpha(); 93 | } 94 | 95 | @Override 96 | public void setColorFilter(ColorFilter cf) { 97 | mWrapperState.mDrawable.setColorFilter(cf); 98 | } 99 | 100 | @Override 101 | public boolean isStateful() { 102 | return mWrapperState.mDrawable.isStateful(); 103 | } 104 | 105 | @Override 106 | public boolean setState(int[] stateSet) { 107 | if (!Arrays.equals(getState(), stateSet)) { 108 | boolean stateChanged = mWrapperState.mDrawable.setState(stateSet); 109 | return onStateChange(stateSet) || stateChanged; 110 | } 111 | return false; 112 | } 113 | 114 | @Override 115 | public int[] getState() { 116 | return mWrapperState.mDrawable.getState(); 117 | } 118 | 119 | @Override 120 | protected boolean onStateChange(int[] state) { 121 | return false; 122 | } 123 | 124 | @Override 125 | public void jumpToCurrentState() { 126 | mWrapperState.mDrawable.jumpToCurrentState(); 127 | } 128 | 129 | @Override 130 | public Drawable getCurrent() { 131 | return mWrapperState.mDrawable.getCurrent(); 132 | } 133 | 134 | @Override 135 | protected boolean onLevelChange(int level) { 136 | return mWrapperState.mDrawable.setLevel(level); 137 | } 138 | 139 | @Override 140 | protected void onBoundsChange(Rect bounds) { 141 | mWrapperState.mDrawable.setBounds(bounds.left, bounds.top, bounds.right, bounds.bottom); 142 | } 143 | 144 | @Override 145 | public boolean setVisible(boolean visible, boolean restart) { 146 | return mWrapperState.mDrawable.setVisible(visible, restart) | 147 | super.setVisible(mWrapperState.mDrawable.isVisible(), restart); 148 | } 149 | 150 | @TargetApi(Build.VERSION_CODES.KITKAT) 151 | @Override 152 | public void setAutoMirrored(boolean mirrored) { 153 | mWrapperState.mDrawable.setAutoMirrored(mirrored); 154 | } 155 | 156 | @TargetApi(Build.VERSION_CODES.KITKAT) 157 | @Override 158 | public boolean isAutoMirrored() { 159 | return mWrapperState.mDrawable.isAutoMirrored(); 160 | } 161 | 162 | @Override 163 | public int getOpacity() { 164 | return mWrapperState.mDrawable.getOpacity(); 165 | } 166 | 167 | @Override 168 | public Region getTransparentRegion() { 169 | return mWrapperState.mDrawable.getTransparentRegion(); 170 | } 171 | 172 | @Override 173 | public int getIntrinsicWidth() { 174 | return mWrapperState.mDrawable.getIntrinsicWidth(); 175 | } 176 | 177 | @Override 178 | public int getIntrinsicHeight() { 179 | return mWrapperState.mDrawable.getIntrinsicHeight(); 180 | } 181 | 182 | @Override 183 | public int getMinimumWidth() { 184 | return mWrapperState.mDrawable.getMinimumWidth(); 185 | } 186 | 187 | @Override 188 | public int getMinimumHeight() { 189 | return mWrapperState.mDrawable.getMinimumHeight(); 190 | } 191 | 192 | @Override 193 | public boolean getPadding(Rect padding) { 194 | return mWrapperState.mDrawable.getPadding(padding); 195 | } 196 | 197 | @TargetApi(Build.VERSION_CODES.LOLLIPOP) 198 | @Override 199 | public void setTint(int tint) { 200 | mWrapperState.mDrawable.setTint(tint); 201 | } 202 | 203 | @TargetApi(Build.VERSION_CODES.LOLLIPOP) 204 | @Override 205 | public void setTintList(ColorStateList tint) { 206 | mWrapperState.mDrawable.setTintList(tint); 207 | } 208 | 209 | @TargetApi(Build.VERSION_CODES.LOLLIPOP) 210 | @Override 211 | public void setTintMode(PorterDuff.Mode tintMode) { 212 | mWrapperState.mDrawable.setTintMode(tintMode); 213 | } 214 | 215 | @TargetApi(Build.VERSION_CODES.LOLLIPOP) 216 | @Override 217 | public void setHotspot(float x, float y) { 218 | mWrapperState.mDrawable.setHotspot(x, y); 219 | } 220 | 221 | @TargetApi(Build.VERSION_CODES.LOLLIPOP) 222 | @Override 223 | public void setHotspotBounds(int left, int top, int right, int bottom) { 224 | mWrapperState.mDrawable.setHotspotBounds(left, top, right, bottom); 225 | } 226 | 227 | /* 228 | * Wrapper drawable state. 229 | */ 230 | 231 | @Override 232 | public Drawable mutate() { 233 | if (!mMutated && super.mutate() == this) { 234 | mWrapperState = createConstantState(mWrapperState); 235 | mWrapperState.mDrawable.mutate(); 236 | mMutated = true; 237 | } 238 | return this; 239 | } 240 | 241 | @Override 242 | public ConstantState getConstantState() { 243 | if (mWrapperState.canConstantState()) { 244 | mWrapperState.mChangingConfigurations = getChangingConfigurations(); 245 | return mWrapperState; 246 | } 247 | return null; 248 | } 249 | 250 | protected WrapperState createConstantState(WrapperState state) { 251 | return new WrapperState(state); 252 | } 253 | 254 | protected static class WrapperState extends ConstantState { 255 | Drawable mDrawable; 256 | int mChangingConfigurations; 257 | int mChildChangingConfigurations; 258 | 259 | public WrapperState(WrapperState state) { 260 | if (state != null) { 261 | mDrawable = state.mDrawable; 262 | mChangingConfigurations = state.mChangingConfigurations; 263 | mChildChangingConfigurations = state.mChildChangingConfigurations; 264 | } 265 | } 266 | 267 | public void setDrawable(Drawable drawable, WrapperDrawable owner) { 268 | mDrawable = drawable; 269 | mDrawable.setCallback(owner); 270 | mChildChangingConfigurations = mDrawable.getChangingConfigurations(); 271 | } 272 | 273 | @Override 274 | public Drawable newDrawable() { 275 | return newDrawable(null); 276 | } 277 | 278 | @Override 279 | public Drawable newDrawable(Resources res) { 280 | return new WrapperDrawable(this, res); 281 | } 282 | 283 | @Override 284 | public int getChangingConfigurations() { 285 | return mChangingConfigurations; 286 | } 287 | 288 | protected boolean canConstantState() { 289 | return mDrawable.getConstantState() != null; 290 | } 291 | } 292 | 293 | /* 294 | * Overrides from Drawable.Callback. 295 | */ 296 | 297 | @Override 298 | public void invalidateDrawable(Drawable who) { 299 | invalidateSelf(); 300 | } 301 | 302 | @Override 303 | public void scheduleDrawable(Drawable who, Runnable what, long when) { 304 | scheduleSelf(what, when); 305 | } 306 | 307 | @Override 308 | public void unscheduleDrawable(Drawable who, Runnable what) { 309 | unscheduleSelf(what); 310 | } 311 | } 312 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/java/io/doist/material/reflection/ReflectionUtils.java: -------------------------------------------------------------------------------- 1 | package io.doist.material.reflection; 2 | 3 | import android.util.Log; 4 | 5 | import java.lang.reflect.Field; 6 | import java.lang.reflect.InvocationTargetException; 7 | import java.lang.reflect.Method; 8 | import java.util.Map; 9 | import java.util.concurrent.ConcurrentHashMap; 10 | 11 | public class ReflectionUtils { 12 | private static final String LOG_TAG = ReflectionUtils.class.getSimpleName(); 13 | 14 | public static final Class[] EMPTY_TYPES = new Class[0]; 15 | public static final Object[] EMPTY_PARAMETERS = new Object[0]; 16 | 17 | private static final Map> sClassCache = new ConcurrentHashMap<>(8); 18 | private static final Map, Map> sClassMethodCache = new ConcurrentHashMap<>(8); 19 | private static final Map, Map> sClassFieldCache = new ConcurrentHashMap<>(8); 20 | 21 | private ReflectionUtils() { 22 | throw new InstantiationError("Must not instantiate this class"); 23 | } 24 | 25 | private static Map ensureMethodCache(Class clazz) { 26 | Map methodCache = sClassMethodCache.get(clazz); 27 | if (methodCache == null) { 28 | methodCache = new ConcurrentHashMap<>(4); 29 | sClassMethodCache.put(clazz, methodCache); 30 | } 31 | return methodCache; 32 | } 33 | 34 | private static Map ensureFieldCache(Class clazz) { 35 | Map fieldCache = sClassFieldCache.get(clazz); 36 | if (fieldCache == null) { 37 | fieldCache = new ConcurrentHashMap<>(4); 38 | sClassFieldCache.put(clazz, fieldCache); 39 | } 40 | return fieldCache; 41 | } 42 | 43 | public static Class getClass(String className) { 44 | Class clazz = sClassCache.get(className); 45 | if (clazz == null) { 46 | try { 47 | clazz = Class.forName(className); 48 | sClassCache.put(className, clazz); 49 | } catch (ClassNotFoundException e) { 50 | Log.w(LOG_TAG, e); 51 | } 52 | } 53 | return clazz; 54 | } 55 | 56 | public static Method getDeclaredMethod(Class clazz, String methodName, Class... parameterTypes) { 57 | Method method = null; 58 | if (clazz != null) { 59 | final Map methodCache = ensureMethodCache(clazz); 60 | method = methodCache.get(methodName); 61 | if (method == null) { 62 | try { 63 | method = clazz.getDeclaredMethod(methodName, parameterTypes); 64 | method.setAccessible(true); 65 | // Cache method. 66 | methodCache.put(methodName, method); 67 | } catch (NoSuchMethodException e) { 68 | Log.w(LOG_TAG, e); 69 | } 70 | } 71 | } 72 | return method; 73 | } 74 | 75 | public static Field getDeclaredField(Class clazz, String fieldName) { 76 | Field field = null; 77 | if (clazz != null) { 78 | final Map fieldCache = ensureFieldCache(clazz); 79 | field = fieldCache.get(fieldName); 80 | if (field == null) { 81 | try { 82 | field = clazz.getDeclaredField(fieldName); 83 | field.setAccessible(true); 84 | // Cache field. 85 | fieldCache.put(fieldName, field); 86 | } catch (NoSuchFieldException e) { 87 | Log.w(LOG_TAG, e); 88 | } 89 | } 90 | } 91 | return field; 92 | } 93 | 94 | public static Object invokeDeclaredMethod(Class clazz, String methodName, Class[] parameterTypes, 95 | Object receiver, Object[] parameters) { 96 | Object result = null; 97 | if (clazz != null) { 98 | Method method = getDeclaredMethod(clazz, methodName, parameterTypes); 99 | if (method != null) { 100 | try { 101 | result = method.invoke(receiver, parameters); 102 | } catch (InvocationTargetException e) { 103 | Log.w(LOG_TAG, e); 104 | } catch (IllegalAccessException e) { 105 | Log.w(LOG_TAG, e); 106 | } 107 | } 108 | } 109 | return result; 110 | } 111 | 112 | public static Object getDeclaredFieldValue(Class clazz, String fieldName, Object receiver) { 113 | Object value = null; 114 | if (clazz != null) { 115 | final Field field = getDeclaredField(clazz, fieldName); 116 | if (field != null) { 117 | try { 118 | value = field.get(receiver); 119 | } catch (IllegalAccessException e) { 120 | Log.w(LOG_TAG, e); 121 | } 122 | } 123 | } 124 | return value; 125 | } 126 | 127 | public static void setDeclaredFieldValue(Class clazz, String fieldName, Object receiver, Object value) { 128 | if (clazz != null) { 129 | final Field field = getDeclaredField(clazz, fieldName); 130 | if (field != null) { 131 | try { 132 | field.set(receiver, value); 133 | } catch (IllegalAccessException e) { 134 | Log.w(LOG_TAG, e); 135 | } 136 | } 137 | } 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/java/io/doist/material/res/MaterialTypedArray.java: -------------------------------------------------------------------------------- 1 | package io.doist.material.res; 2 | 3 | import android.content.Context; 4 | import android.content.res.Resources; 5 | import android.content.res.TypedArray; 6 | import android.graphics.drawable.Drawable; 7 | import android.util.TypedValue; 8 | 9 | import androidx.annotation.Nullable; 10 | 11 | /** 12 | * Helper class for methods of {@link TypedArray} working with {@link MaterialResources}. 13 | */ 14 | public class MaterialTypedArray { 15 | private MaterialTypedArray() { 16 | } 17 | 18 | /** 19 | * @see TypedArray#getDrawable(int) 20 | */ 21 | @Nullable 22 | public static Drawable getDrawable(Context context, Resources resources, TypedArray typedArray, int index) { 23 | final TypedValue value = new TypedValue(); 24 | if (typedArray.getValue(index, value)) { 25 | if (value.type == TypedValue.TYPE_ATTRIBUTE) { 26 | throw new RuntimeException("Failed to resolve attribute at index " + index); 27 | } 28 | MaterialResources materialResources = MaterialResources.getInstance(context, resources); 29 | return materialResources.loadDrawable(context, resources, value, value.resourceId); 30 | } 31 | return null; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/java/io/doist/material/widget/FloatingActionButton.java: -------------------------------------------------------------------------------- 1 | package io.doist.material.widget; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.content.Context; 5 | import android.content.res.ColorStateList; 6 | import android.content.res.TypedArray; 7 | import android.graphics.drawable.Drawable; 8 | import android.graphics.drawable.GradientDrawable; 9 | import android.graphics.drawable.RippleDrawable; 10 | import android.os.Build; 11 | import android.util.AttributeSet; 12 | import android.view.View; 13 | import android.view.ViewGroup; 14 | import android.widget.ImageButton; 15 | 16 | import io.doist.material.R; 17 | import io.doist.material.color.ColorPalette; 18 | import io.doist.material.drawable.RippleMaterialDrawable; 19 | import io.doist.material.drawable.TintDrawable; 20 | import io.doist.material.elevation.CompatElevationDelegate; 21 | import io.doist.material.widget.utils.MaterialWidgetHandler; 22 | 23 | @SuppressLint("AppCompatCustomView") 24 | public class FloatingActionButton extends ImageButton { 25 | private static final int DEFAULT_ELEVATION_DP = 6; 26 | 27 | private ColorStateList mColor; 28 | 29 | private boolean mIsMini; 30 | private int mSize; 31 | 32 | private GradientDrawable mCircleDrawable; // To change the color of the circle. 33 | private TintDrawable mTintDrawable; // To change the color of the circle in compat mode. 34 | 35 | private CompatElevationDelegate mCompatElevationDelegate; 36 | 37 | public FloatingActionButton(Context context) { 38 | this(context, null); 39 | } 40 | 41 | public FloatingActionButton(Context context, AttributeSet attrs) { 42 | this(context, attrs, 0); 43 | } 44 | 45 | public FloatingActionButton(Context context, AttributeSet attrs, int defStyleAttr) { 46 | super(MaterialWidgetHandler.themifyContext(context, attrs), attrs, defStyleAttr); 47 | init(MaterialWidgetHandler.themifyContext(context, attrs), attrs, defStyleAttr); 48 | } 49 | 50 | @SuppressWarnings("ConstantConditions") 51 | private void init(Context context, AttributeSet attrs, int defStyleAttr) { 52 | boolean inCompat = Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP; 53 | int elevation = (int) (DEFAULT_ELEVATION_DP * context.getResources().getDisplayMetrics().density + .5f); 54 | ColorStateList color = null; 55 | boolean isMini = false; 56 | 57 | if (attrs != null) { 58 | TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.FloatingActionButton, defStyleAttr, 0); 59 | try { 60 | if (ta.getInt(R.styleable.FloatingActionButton_android_layout_width, 0) 61 | != ViewGroup.LayoutParams.WRAP_CONTENT 62 | || ta.getInt(R.styleable.FloatingActionButton_android_layout_height, 0) 63 | != ViewGroup.LayoutParams.WRAP_CONTENT) { 64 | throw new IllegalStateException( 65 | "FloatingActionButton 'android:width' and 'android:height' values must be 'wrap_content'. " 66 | + "Use the 'isMini' attribute to manipulate size."); 67 | } 68 | 69 | if (ta.getDrawable(R.styleable.FloatingActionButton_android_background) != null) { 70 | throw new IllegalStateException( 71 | "FloatingActionButton does not support 'android:background' attribute."); 72 | } 73 | 74 | inCompat |= ta.getBoolean(R.styleable.FloatingActionButton_inCompat, inCompat); 75 | 76 | if (inCompat) { 77 | elevation = ta.getDimensionPixelOffset( 78 | R.styleable.FloatingActionButton_elevation, 79 | elevation); 80 | } else { 81 | elevation = ta.getDimensionPixelOffset( 82 | R.styleable.FloatingActionButton_android_elevation, 83 | elevation); 84 | } 85 | 86 | // Resolve color or colorStateList. 87 | color = ta.getColorStateList(R.styleable.FloatingActionButton_android_color); 88 | 89 | // Resolve size. 90 | isMini = ta.getBoolean(R.styleable.FloatingActionButton_isMini, isMini); 91 | } finally { 92 | ta.recycle(); 93 | } 94 | } 95 | 96 | initElevation(inCompat, elevation); 97 | 98 | initDrawables(context, inCompat); 99 | 100 | initColor(context, color); 101 | 102 | internalSetIsMini(isMini); 103 | 104 | setScaleType(ScaleType.CENTER); 105 | setFocusable(true); 106 | setClickable(true); 107 | } 108 | 109 | private void initElevation(boolean inCompat, float elevation) { 110 | if (inCompat) { 111 | mCompatElevationDelegate = new CompatElevationDelegate(this); 112 | } 113 | setElevation(elevation); 114 | } 115 | 116 | @SuppressLint("NewApi") 117 | private void initDrawables(Context context, boolean inCompat) { 118 | // TODO: Make this theme dependent. 119 | ColorStateList rippleColor = ColorStateList.valueOf(getResources().getColor(R.color.ripple_material_light)); 120 | 121 | GradientDrawable circleDrawable = new GradientDrawable(); 122 | circleDrawable.setShape(GradientDrawable.OVAL); 123 | 124 | Drawable background; 125 | if (inCompat) { 126 | // Pre-L androids or force compat mode. 127 | mTintDrawable = new TintDrawable(context, circleDrawable); 128 | background = new RippleMaterialDrawable(context, rippleColor, mTintDrawable, null); 129 | } else { 130 | // Lollipop androids. 131 | mCircleDrawable = circleDrawable; 132 | background = new RippleDrawable(rippleColor, circleDrawable, null); 133 | } 134 | 135 | setBackground(background); 136 | } 137 | 138 | private void initColor(Context context, ColorStateList color) { 139 | if (color != null) { 140 | setColor(color); 141 | } else { 142 | // If the user didn't specify any color, try to resolve the current theme's accent color. 143 | setColor(ColorPalette.resolveAccentColor(context)); 144 | } 145 | } 146 | 147 | @Override 148 | public void setElevation(float elevation) { 149 | if (mCompatElevationDelegate != null) { 150 | mCompatElevationDelegate.setElevation(elevation); 151 | } else { 152 | super.setElevation(elevation); 153 | } 154 | } 155 | 156 | @Override 157 | public float getElevation() { 158 | if (mCompatElevationDelegate != null) { 159 | return mCompatElevationDelegate.getElevation(); 160 | } else { 161 | return super.getElevation(); 162 | } 163 | } 164 | 165 | public void setColor(int color) { 166 | setColor(ColorStateList.valueOf(color)); 167 | } 168 | 169 | @SuppressLint("NewApi") 170 | public void setColor(ColorStateList color) { 171 | mColor = color; 172 | 173 | if (mCircleDrawable != null) { 174 | mCircleDrawable.setColor(mColor); 175 | } 176 | 177 | if (mTintDrawable != null) { 178 | mTintDrawable.setTintList(mColor); 179 | } 180 | } 181 | 182 | public ColorStateList getColor() { 183 | return mColor; 184 | } 185 | 186 | public void setIsMini(boolean isMini) { 187 | if (mIsMini != isMini) { 188 | internalSetIsMini(isMini); 189 | } 190 | } 191 | 192 | private void internalSetIsMini(boolean isMini) { 193 | mIsMini = isMini; 194 | int radius = getResources().getDimensionPixelOffset(isMini ? R.dimen.fab_mini_radius : R.dimen.fab_radius); 195 | mSize = radius * 2; 196 | 197 | if (mCompatElevationDelegate != null) { 198 | mCompatElevationDelegate.setCornerRadius(radius); 199 | } 200 | 201 | // Re-set layout params so that width and height are adjusted accordingly. 202 | ViewGroup.LayoutParams params = getLayoutParams(); 203 | if (params != null) { 204 | boolean isAttached = getWindowVisibility() == View.VISIBLE; 205 | if (mCompatElevationDelegate != null && isAttached) { 206 | mCompatElevationDelegate.onDetachedFromWindow(); 207 | } 208 | 209 | params.width = ViewGroup.LayoutParams.WRAP_CONTENT; 210 | params.height = ViewGroup.LayoutParams.WRAP_CONTENT; 211 | setLayoutParams(params); 212 | 213 | if (mCompatElevationDelegate != null && isAttached) { 214 | mCompatElevationDelegate.onAttachedToWindow(); 215 | } 216 | } 217 | } 218 | 219 | public boolean isMini() { 220 | return mIsMini; 221 | } 222 | 223 | @Override 224 | public void setLayoutParams(ViewGroup.LayoutParams params) { 225 | if (params.width == ViewGroup.LayoutParams.WRAP_CONTENT) { 226 | params.width = mSize; 227 | } 228 | if (params.height == ViewGroup.LayoutParams.WRAP_CONTENT) { 229 | params.height = mSize; 230 | } 231 | 232 | super.setLayoutParams(params); 233 | } 234 | 235 | @Override 236 | protected void onAttachedToWindow() { 237 | super.onAttachedToWindow(); 238 | 239 | if (mCompatElevationDelegate != null) { 240 | mCompatElevationDelegate.onAttachedToWindow(); 241 | } 242 | } 243 | 244 | @Override 245 | protected void onDetachedFromWindow() { 246 | super.onDetachedFromWindow(); 247 | 248 | if (mCompatElevationDelegate != null) { 249 | mCompatElevationDelegate.onDetachedFromWindow(); 250 | } 251 | } 252 | } 253 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/java/io/doist/material/widget/MaterialAutoCompleteTextView.java: -------------------------------------------------------------------------------- 1 | package io.doist.material.widget; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.annotation.TargetApi; 5 | import android.content.Context; 6 | import android.os.Build; 7 | import android.util.AttributeSet; 8 | import android.widget.AutoCompleteTextView; 9 | 10 | import androidx.annotation.DrawableRes; 11 | import io.doist.material.widget.utils.MaterialWidgetHandler; 12 | 13 | @SuppressLint("AppCompatCustomView") 14 | public class MaterialAutoCompleteTextView extends AutoCompleteTextView { 15 | private static final boolean sNative = Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT; 16 | 17 | private static final MaterialWidgetHandler.Styleable[] sHiddenStyleables = { 18 | MaterialWidgetHandler.Styleable.TEXT_VIEW, 19 | MaterialWidgetHandler.Styleable.VIEW 20 | }; 21 | 22 | public MaterialAutoCompleteTextView(Context context) { 23 | this(context, null); 24 | } 25 | 26 | public MaterialAutoCompleteTextView(Context context, AttributeSet attrs) { 27 | this(context, attrs, android.R.attr.autoCompleteTextViewStyle); 28 | } 29 | 30 | public MaterialAutoCompleteTextView(Context context, AttributeSet attrs, int defStyle) { 31 | super(MaterialWidgetHandler.themifyContext(context, attrs), 32 | MaterialWidgetHandler.hideStyleableAttributes(attrs, sHiddenStyleables), defStyle); 33 | MaterialWidgetHandler.restoreStyleableAttributes(sHiddenStyleables); 34 | MaterialWidgetHandler.init(this, attrs, defStyle, sHiddenStyleables); 35 | } 36 | 37 | @Override 38 | public void setCompoundDrawablesWithIntrinsicBounds(@DrawableRes int left, @DrawableRes int top, 39 | @DrawableRes int right, @DrawableRes int bottom) { 40 | if (sNative) { 41 | super.setCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom); 42 | } else { 43 | super.setCompoundDrawablesWithIntrinsicBounds( 44 | MaterialWidgetHandler.getDrawable(this, left), MaterialWidgetHandler.getDrawable(this, top), 45 | MaterialWidgetHandler.getDrawable(this, right), MaterialWidgetHandler.getDrawable(this, bottom)); 46 | } 47 | } 48 | 49 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) 50 | @Override 51 | public void setCompoundDrawablesRelativeWithIntrinsicBounds(@DrawableRes int start, @DrawableRes int top, 52 | @DrawableRes int end, @DrawableRes int bottom) { 53 | if (sNative) { 54 | super.setCompoundDrawablesRelativeWithIntrinsicBounds(start, top, end, bottom); 55 | } else { 56 | super.setCompoundDrawablesRelativeWithIntrinsicBounds( 57 | MaterialWidgetHandler.getDrawable(this, start), MaterialWidgetHandler.getDrawable(this, top), 58 | MaterialWidgetHandler.getDrawable(this, end), MaterialWidgetHandler.getDrawable(this, bottom)); 59 | } 60 | } 61 | 62 | @Override 63 | public void setBackgroundResource(@DrawableRes int resId) { 64 | if (sNative) { 65 | super.setBackgroundResource(resId); 66 | } else { 67 | super.setBackground(MaterialWidgetHandler.getDrawable(this, resId)); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/java/io/doist/material/widget/MaterialButton.java: -------------------------------------------------------------------------------- 1 | package io.doist.material.widget; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.annotation.TargetApi; 5 | import android.content.Context; 6 | import android.os.Build; 7 | import android.util.AttributeSet; 8 | import android.widget.Button; 9 | 10 | import androidx.annotation.DrawableRes; 11 | import io.doist.material.widget.utils.MaterialWidgetHandler; 12 | 13 | @SuppressLint("AppCompatCustomView") 14 | public class MaterialButton extends Button { 15 | private static final boolean sNative = Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT; 16 | 17 | private static final MaterialWidgetHandler.Styleable[] sHiddenStyleables = { 18 | MaterialWidgetHandler.Styleable.TEXT_VIEW, 19 | MaterialWidgetHandler.Styleable.VIEW 20 | }; 21 | 22 | public MaterialButton(Context context) { 23 | this(context, null); 24 | } 25 | 26 | public MaterialButton(Context context, AttributeSet attrs) { 27 | this(context, attrs, android.R.attr.buttonStyle); 28 | } 29 | 30 | public MaterialButton(Context context, AttributeSet attrs, int defStyle) { 31 | super(MaterialWidgetHandler.themifyContext(context, attrs), 32 | MaterialWidgetHandler.hideStyleableAttributes(attrs, sHiddenStyleables), defStyle); 33 | MaterialWidgetHandler.restoreStyleableAttributes(sHiddenStyleables); 34 | MaterialWidgetHandler.init(this, attrs, defStyle, sHiddenStyleables); 35 | } 36 | 37 | @Override 38 | public void setCompoundDrawablesWithIntrinsicBounds(@DrawableRes int left, @DrawableRes int top, 39 | @DrawableRes int right, @DrawableRes int bottom) { 40 | if (sNative) { 41 | super.setCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom); 42 | } else { 43 | super.setCompoundDrawablesWithIntrinsicBounds( 44 | MaterialWidgetHandler.getDrawable(this, left), MaterialWidgetHandler.getDrawable(this, top), 45 | MaterialWidgetHandler.getDrawable(this, right), MaterialWidgetHandler.getDrawable(this, bottom)); 46 | } 47 | } 48 | 49 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) 50 | @Override 51 | public void setCompoundDrawablesRelativeWithIntrinsicBounds(@DrawableRes int start, @DrawableRes int top, 52 | @DrawableRes int end, @DrawableRes int bottom) { 53 | if (sNative) { 54 | super.setCompoundDrawablesRelativeWithIntrinsicBounds(start, top, end, bottom); 55 | } else { 56 | super.setCompoundDrawablesRelativeWithIntrinsicBounds( 57 | MaterialWidgetHandler.getDrawable(this, start), MaterialWidgetHandler.getDrawable(this, top), 58 | MaterialWidgetHandler.getDrawable(this, end), MaterialWidgetHandler.getDrawable(this, bottom)); 59 | } 60 | } 61 | 62 | @Override 63 | public void setBackgroundResource(@DrawableRes int resId) { 64 | if (sNative) { 65 | super.setBackgroundResource(resId); 66 | } else { 67 | super.setBackground(MaterialWidgetHandler.getDrawable(this, resId)); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/java/io/doist/material/widget/MaterialCheckBox.java: -------------------------------------------------------------------------------- 1 | package io.doist.material.widget; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.annotation.TargetApi; 5 | import android.content.Context; 6 | import android.os.Build; 7 | import android.util.AttributeSet; 8 | import android.widget.CheckBox; 9 | 10 | import androidx.annotation.DrawableRes; 11 | import io.doist.material.widget.utils.MaterialWidgetHandler; 12 | 13 | @SuppressLint("AppCompatCustomView") 14 | public class MaterialCheckBox extends CheckBox { 15 | private static final boolean sNative = Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT; 16 | 17 | private static final MaterialWidgetHandler.Styleable[] sHiddenStyleables = { 18 | MaterialWidgetHandler.Styleable.COMPOUND_BUTTON, 19 | MaterialWidgetHandler.Styleable.TEXT_VIEW, 20 | MaterialWidgetHandler.Styleable.VIEW 21 | }; 22 | 23 | public MaterialCheckBox(Context context) { 24 | this(context, null); 25 | } 26 | 27 | public MaterialCheckBox(Context context, AttributeSet attrs) { 28 | this(context, attrs, android.R.attr.checkboxStyle); 29 | } 30 | 31 | public MaterialCheckBox(Context context, AttributeSet attrs, int defStyle) { 32 | super(MaterialWidgetHandler.themifyContext(context, attrs), 33 | MaterialWidgetHandler.hideStyleableAttributes(attrs, sHiddenStyleables), defStyle); 34 | MaterialWidgetHandler.restoreStyleableAttributes(sHiddenStyleables); 35 | MaterialWidgetHandler.init(this, attrs, defStyle, sHiddenStyleables); 36 | } 37 | 38 | @Override 39 | public void setButtonDrawable(@DrawableRes int resId) { 40 | if (sNative) { 41 | super.setButtonDrawable(resId); 42 | } else { 43 | super.setButtonDrawable(MaterialWidgetHandler.getDrawable(this, resId)); 44 | } 45 | } 46 | 47 | @Override 48 | public void setCompoundDrawablesWithIntrinsicBounds(@DrawableRes int left, @DrawableRes int top, 49 | @DrawableRes int right, @DrawableRes int bottom) { 50 | if (sNative) { 51 | super.setCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom); 52 | } else { 53 | super.setCompoundDrawablesWithIntrinsicBounds( 54 | MaterialWidgetHandler.getDrawable(this, left), MaterialWidgetHandler.getDrawable(this, top), 55 | MaterialWidgetHandler.getDrawable(this, right), MaterialWidgetHandler.getDrawable(this, bottom)); 56 | } 57 | } 58 | 59 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) 60 | @Override 61 | public void setCompoundDrawablesRelativeWithIntrinsicBounds(@DrawableRes int start, @DrawableRes int top, 62 | @DrawableRes int end, @DrawableRes int bottom) { 63 | if (sNative) { 64 | super.setCompoundDrawablesRelativeWithIntrinsicBounds(start, top, end, bottom); 65 | } else { 66 | super.setCompoundDrawablesRelativeWithIntrinsicBounds( 67 | MaterialWidgetHandler.getDrawable(this, start), MaterialWidgetHandler.getDrawable(this, top), 68 | MaterialWidgetHandler.getDrawable(this, end), MaterialWidgetHandler.getDrawable(this, bottom)); 69 | } 70 | } 71 | 72 | @Override 73 | public void setBackgroundResource(@DrawableRes int resId) { 74 | if (sNative) { 75 | super.setBackgroundResource(resId); 76 | } else { 77 | super.setBackground(MaterialWidgetHandler.getDrawable(this, resId)); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/java/io/doist/material/widget/MaterialCheckedTextView.java: -------------------------------------------------------------------------------- 1 | package io.doist.material.widget; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.annotation.TargetApi; 5 | import android.content.Context; 6 | import android.os.Build; 7 | import android.util.AttributeSet; 8 | import android.widget.CheckedTextView; 9 | 10 | import androidx.annotation.DrawableRes; 11 | import io.doist.material.widget.utils.MaterialWidgetHandler; 12 | 13 | @SuppressLint("AppCompatCustomView") 14 | public class MaterialCheckedTextView extends CheckedTextView { 15 | private static final boolean sNative = Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT; 16 | 17 | private static final MaterialWidgetHandler.Styleable[] sHiddenStyleables = { 18 | MaterialWidgetHandler.Styleable.CHECKED_TEXT_VIEW, 19 | MaterialWidgetHandler.Styleable.TEXT_VIEW, 20 | MaterialWidgetHandler.Styleable.VIEW 21 | }; 22 | 23 | public MaterialCheckedTextView(Context context) { 24 | this(context, null); 25 | } 26 | 27 | @SuppressLint("InlinedApi") 28 | public MaterialCheckedTextView(Context context, AttributeSet attrs) { 29 | this(context, attrs, 30 | Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN ? android.R.attr.checkedTextViewStyle : 0); 31 | } 32 | 33 | public MaterialCheckedTextView(Context context, AttributeSet attrs, int defStyle) { 34 | super(MaterialWidgetHandler.themifyContext(context, attrs), 35 | MaterialWidgetHandler.hideStyleableAttributes(attrs, sHiddenStyleables), defStyle); 36 | MaterialWidgetHandler.restoreStyleableAttributes(sHiddenStyleables); 37 | MaterialWidgetHandler.init(this, attrs, defStyle, sHiddenStyleables); 38 | } 39 | 40 | @Override 41 | public void setCheckMarkDrawable(@DrawableRes int resId) { 42 | if (sNative) { 43 | super.setCheckMarkDrawable(resId); 44 | } else { 45 | super.setCheckMarkDrawable(MaterialWidgetHandler.getDrawable(this, resId)); 46 | } 47 | } 48 | 49 | @Override 50 | public void setCompoundDrawablesWithIntrinsicBounds(@DrawableRes int left, @DrawableRes int top, 51 | @DrawableRes int right, @DrawableRes int bottom) { 52 | if (sNative) { 53 | super.setCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom); 54 | } else { 55 | super.setCompoundDrawablesWithIntrinsicBounds( 56 | MaterialWidgetHandler.getDrawable(this, left), MaterialWidgetHandler.getDrawable(this, top), 57 | MaterialWidgetHandler.getDrawable(this, right), MaterialWidgetHandler.getDrawable(this, bottom)); 58 | } 59 | } 60 | 61 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) 62 | @Override 63 | public void setCompoundDrawablesRelativeWithIntrinsicBounds(@DrawableRes int start, @DrawableRes int top, 64 | @DrawableRes int end, @DrawableRes int bottom) { 65 | if (sNative) { 66 | // Don't set compound drawables relative because it breaks spinner popup width calculation. 67 | boolean isRtl = getResources().getConfiguration().getLayoutDirection() == LAYOUT_DIRECTION_RTL; 68 | int left = isRtl ? end : start; 69 | int right = isRtl ? start : end; 70 | super.setCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom); 71 | } else { 72 | super.setCompoundDrawablesRelativeWithIntrinsicBounds( 73 | MaterialWidgetHandler.getDrawable(this, start), MaterialWidgetHandler.getDrawable(this, top), 74 | MaterialWidgetHandler.getDrawable(this, end), MaterialWidgetHandler.getDrawable(this, bottom)); 75 | } 76 | } 77 | 78 | @Override 79 | public void setBackgroundResource(@DrawableRes int resId) { 80 | if (sNative) { 81 | super.setBackgroundResource(resId); 82 | } else { 83 | super.setBackground(MaterialWidgetHandler.getDrawable(this, resId)); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/java/io/doist/material/widget/MaterialEditText.java: -------------------------------------------------------------------------------- 1 | package io.doist.material.widget; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.annotation.TargetApi; 5 | import android.content.Context; 6 | import android.os.Build; 7 | import android.util.AttributeSet; 8 | import android.widget.EditText; 9 | 10 | import androidx.annotation.DrawableRes; 11 | import io.doist.material.widget.utils.MaterialWidgetHandler; 12 | 13 | @SuppressLint("AppCompatCustomView") 14 | public class MaterialEditText extends EditText { 15 | private static final boolean sNative = Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT; 16 | 17 | private static final MaterialWidgetHandler.Styleable[] sHiddenStyleables = { 18 | MaterialWidgetHandler.Styleable.TEXT_VIEW, 19 | MaterialWidgetHandler.Styleable.VIEW 20 | }; 21 | 22 | public MaterialEditText(Context context) { 23 | this(context, null); 24 | } 25 | 26 | public MaterialEditText(Context context, AttributeSet attrs) { 27 | this(context, attrs, android.R.attr.editTextStyle); 28 | } 29 | 30 | public MaterialEditText(Context context, AttributeSet attrs, int defStyle) { 31 | super(MaterialWidgetHandler.themifyContext(context, attrs), 32 | MaterialWidgetHandler.hideStyleableAttributes(attrs, sHiddenStyleables), defStyle); 33 | MaterialWidgetHandler.restoreStyleableAttributes(sHiddenStyleables); 34 | MaterialWidgetHandler.init(this, attrs, defStyle, sHiddenStyleables); 35 | } 36 | 37 | @Override 38 | public void setCompoundDrawablesWithIntrinsicBounds(@DrawableRes int left, @DrawableRes int top, 39 | @DrawableRes int right, @DrawableRes int bottom) { 40 | if (sNative) { 41 | super.setCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom); 42 | } else { 43 | super.setCompoundDrawablesWithIntrinsicBounds( 44 | MaterialWidgetHandler.getDrawable(this, left), MaterialWidgetHandler.getDrawable(this, top), 45 | MaterialWidgetHandler.getDrawable(this, right), MaterialWidgetHandler.getDrawable(this, bottom)); 46 | } 47 | } 48 | 49 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) 50 | @Override 51 | public void setCompoundDrawablesRelativeWithIntrinsicBounds(@DrawableRes int start, @DrawableRes int top, 52 | @DrawableRes int end, @DrawableRes int bottom) { 53 | if (sNative) { 54 | super.setCompoundDrawablesRelativeWithIntrinsicBounds(start, top, end, bottom); 55 | } else { 56 | super.setCompoundDrawablesRelativeWithIntrinsicBounds( 57 | MaterialWidgetHandler.getDrawable(this, start), MaterialWidgetHandler.getDrawable(this, top), 58 | MaterialWidgetHandler.getDrawable(this, end), MaterialWidgetHandler.getDrawable(this, bottom)); 59 | } 60 | } 61 | 62 | @Override 63 | public void setBackgroundResource(@DrawableRes int resId) { 64 | if (sNative) { 65 | super.setBackgroundResource(resId); 66 | } else { 67 | super.setBackground(MaterialWidgetHandler.getDrawable(this, resId)); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/java/io/doist/material/widget/MaterialFrameLayout.java: -------------------------------------------------------------------------------- 1 | package io.doist.material.widget; 2 | 3 | import android.content.Context; 4 | import android.os.Build; 5 | import android.util.AttributeSet; 6 | import android.widget.FrameLayout; 7 | 8 | import androidx.annotation.DrawableRes; 9 | import io.doist.material.widget.utils.MaterialWidgetHandler; 10 | 11 | public class MaterialFrameLayout extends FrameLayout { 12 | private static final boolean sNative = Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT; 13 | 14 | private static final MaterialWidgetHandler.Styleable[] sHiddenStyleables = { 15 | MaterialWidgetHandler.Styleable.VIEW, 16 | MaterialWidgetHandler.Styleable.FRAME_LAYOUT 17 | }; 18 | 19 | public MaterialFrameLayout(Context context) { 20 | this(context, null); 21 | } 22 | 23 | public MaterialFrameLayout(Context context, AttributeSet attrs) { 24 | this(context, attrs, 0); 25 | } 26 | 27 | public MaterialFrameLayout(Context context, AttributeSet attrs, int defStyle) { 28 | super(MaterialWidgetHandler.themifyContext(context, attrs), 29 | MaterialWidgetHandler.hideStyleableAttributes(attrs, sHiddenStyleables), defStyle); 30 | MaterialWidgetHandler.restoreStyleableAttributes(sHiddenStyleables); 31 | MaterialWidgetHandler.init(this, attrs, defStyle, sHiddenStyleables); 32 | } 33 | 34 | @Override 35 | public void setBackgroundResource(@DrawableRes int resId) { 36 | if (sNative) { 37 | super.setBackgroundResource(resId); 38 | } else { 39 | super.setBackground(MaterialWidgetHandler.getDrawable(this, resId)); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/java/io/doist/material/widget/MaterialImageButton.java: -------------------------------------------------------------------------------- 1 | package io.doist.material.widget; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.content.Context; 5 | import android.os.Build; 6 | import android.util.AttributeSet; 7 | import android.widget.ImageButton; 8 | 9 | import androidx.annotation.DrawableRes; 10 | import io.doist.material.widget.utils.MaterialWidgetHandler; 11 | 12 | @SuppressLint("AppCompatCustomView") 13 | public class MaterialImageButton extends ImageButton { 14 | private static final boolean sNative = Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT; 15 | 16 | private static final MaterialWidgetHandler.Styleable[] sHiddenStyleables = { 17 | MaterialWidgetHandler.Styleable.VIEW, 18 | MaterialWidgetHandler.Styleable.IMAGE_VIEW 19 | }; 20 | 21 | public MaterialImageButton(Context context) { 22 | this(context, null); 23 | } 24 | 25 | public MaterialImageButton(Context context, AttributeSet attrs) { 26 | this(context, attrs, android.R.attr.imageButtonStyle); 27 | } 28 | 29 | public MaterialImageButton(Context context, AttributeSet attrs, int defStyle) { 30 | super(MaterialWidgetHandler.themifyContext(context, attrs), 31 | MaterialWidgetHandler.hideStyleableAttributes(attrs, sHiddenStyleables), defStyle); 32 | MaterialWidgetHandler.restoreStyleableAttributes(sHiddenStyleables); 33 | MaterialWidgetHandler.init(this, attrs, defStyle, sHiddenStyleables); 34 | } 35 | 36 | @Override 37 | public void setBackgroundResource(@DrawableRes int resId) { 38 | if (sNative) { 39 | super.setBackgroundResource(resId); 40 | } else { 41 | super.setBackground(MaterialWidgetHandler.getDrawable(this, resId)); 42 | } 43 | } 44 | 45 | @Override 46 | public void setImageResource(@DrawableRes int resId) { 47 | if (sNative) { 48 | super.setImageResource(resId); 49 | } else { 50 | super.setImageDrawable(MaterialWidgetHandler.getDrawable(this, resId)); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/java/io/doist/material/widget/MaterialImageView.java: -------------------------------------------------------------------------------- 1 | package io.doist.material.widget; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.content.Context; 5 | import android.os.Build; 6 | import android.util.AttributeSet; 7 | import android.widget.ImageView; 8 | 9 | import androidx.annotation.DrawableRes; 10 | import io.doist.material.widget.utils.MaterialWidgetHandler; 11 | 12 | @SuppressLint("AppCompatCustomView") 13 | public class MaterialImageView extends ImageView { 14 | private static final boolean sNative = Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT; 15 | 16 | private static final MaterialWidgetHandler.Styleable[] sHiddenStyleables = { 17 | MaterialWidgetHandler.Styleable.VIEW, 18 | MaterialWidgetHandler.Styleable.IMAGE_VIEW 19 | }; 20 | 21 | public MaterialImageView(Context context) { 22 | this(context, null); 23 | } 24 | 25 | public MaterialImageView(Context context, AttributeSet attrs) { 26 | this(context, attrs, 0); 27 | } 28 | 29 | public MaterialImageView(Context context, AttributeSet attrs, int defStyle) { 30 | super(MaterialWidgetHandler.themifyContext(context, attrs), 31 | MaterialWidgetHandler.hideStyleableAttributes(attrs, sHiddenStyleables), defStyle); 32 | MaterialWidgetHandler.restoreStyleableAttributes(sHiddenStyleables); 33 | MaterialWidgetHandler.init(this, attrs, defStyle, sHiddenStyleables); 34 | } 35 | 36 | @Override 37 | public void setBackgroundResource(@DrawableRes int resId) { 38 | if (sNative) { 39 | super.setBackgroundResource(resId); 40 | } else { 41 | super.setBackground(MaterialWidgetHandler.getDrawable(this, resId)); 42 | } 43 | } 44 | 45 | @Override 46 | public void setImageResource(@DrawableRes int resId) { 47 | if (sNative) { 48 | super.setImageResource(resId); 49 | } else { 50 | super.setImageDrawable(MaterialWidgetHandler.getDrawable(this, resId)); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/java/io/doist/material/widget/MaterialLinearLayout.java: -------------------------------------------------------------------------------- 1 | package io.doist.material.widget; 2 | 3 | import android.content.Context; 4 | import android.os.Build; 5 | import android.util.AttributeSet; 6 | import android.widget.LinearLayout; 7 | 8 | import androidx.annotation.DrawableRes; 9 | import io.doist.material.widget.utils.MaterialWidgetHandler; 10 | 11 | public class MaterialLinearLayout extends LinearLayout { 12 | private static final boolean sNative = Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT; 13 | 14 | private static final MaterialWidgetHandler.Styleable[] sHiddenStyleables = { 15 | MaterialWidgetHandler.Styleable.VIEW 16 | }; 17 | 18 | public MaterialLinearLayout(Context context) { 19 | this(context, null); 20 | } 21 | 22 | public MaterialLinearLayout(Context context, AttributeSet attrs) { 23 | this(context, attrs, 0); 24 | } 25 | 26 | public MaterialLinearLayout(Context context, AttributeSet attrs, int defStyle) { 27 | super(MaterialWidgetHandler.themifyContext(context, attrs), 28 | MaterialWidgetHandler.hideStyleableAttributes(attrs, sHiddenStyleables), defStyle); 29 | MaterialWidgetHandler.restoreStyleableAttributes(sHiddenStyleables); 30 | MaterialWidgetHandler.init(this, attrs, defStyle, sHiddenStyleables); 31 | } 32 | 33 | @Override 34 | public void setBackgroundResource(@DrawableRes int resId) { 35 | if (sNative) { 36 | super.setBackgroundResource(resId); 37 | } else { 38 | super.setBackground(MaterialWidgetHandler.getDrawable(this, resId)); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/java/io/doist/material/widget/MaterialProgressBar.java: -------------------------------------------------------------------------------- 1 | package io.doist.material.widget; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.widget.ProgressBar; 6 | 7 | import io.doist.material.widget.utils.MaterialWidgetHandler; 8 | 9 | public class MaterialProgressBar extends ProgressBar { 10 | private static final MaterialWidgetHandler.Styleable[] sHiddenStyleables = { 11 | MaterialWidgetHandler.Styleable.PROGRESS_BAR, 12 | MaterialWidgetHandler.Styleable.VIEW 13 | }; 14 | 15 | public MaterialProgressBar(Context context) { 16 | this(context, null); 17 | } 18 | 19 | public MaterialProgressBar(Context context, AttributeSet attrs) { 20 | this(context, attrs, android.R.attr.progressBarStyle); 21 | } 22 | 23 | public MaterialProgressBar(Context context, AttributeSet attrs, int defStyle) { 24 | super(MaterialWidgetHandler.themifyContext(context, attrs), 25 | MaterialWidgetHandler.hideStyleableAttributes(attrs, sHiddenStyleables), defStyle); 26 | MaterialWidgetHandler.restoreStyleableAttributes(sHiddenStyleables); 27 | MaterialWidgetHandler.init(this, attrs, defStyle, sHiddenStyleables); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/java/io/doist/material/widget/MaterialRadioButton.java: -------------------------------------------------------------------------------- 1 | package io.doist.material.widget; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.annotation.TargetApi; 5 | import android.content.Context; 6 | import android.os.Build; 7 | import android.util.AttributeSet; 8 | import android.widget.RadioButton; 9 | 10 | import androidx.annotation.DrawableRes; 11 | import io.doist.material.widget.utils.MaterialWidgetHandler; 12 | 13 | @SuppressLint("AppCompatCustomView") 14 | public class MaterialRadioButton extends RadioButton { 15 | private static final boolean sNative = Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT; 16 | 17 | private static final MaterialWidgetHandler.Styleable[] sHiddenStyleables = { 18 | MaterialWidgetHandler.Styleable.COMPOUND_BUTTON, 19 | MaterialWidgetHandler.Styleable.TEXT_VIEW, 20 | MaterialWidgetHandler.Styleable.VIEW 21 | }; 22 | 23 | public MaterialRadioButton(Context context) { 24 | this(context, null); 25 | } 26 | 27 | public MaterialRadioButton(Context context, AttributeSet attrs) { 28 | this(context, attrs, android.R.attr.radioButtonStyle); 29 | } 30 | 31 | public MaterialRadioButton(Context context, AttributeSet attrs, int defStyle) { 32 | super(MaterialWidgetHandler.themifyContext(context, attrs), 33 | MaterialWidgetHandler.hideStyleableAttributes(attrs, sHiddenStyleables), defStyle); 34 | MaterialWidgetHandler.restoreStyleableAttributes(sHiddenStyleables); 35 | MaterialWidgetHandler.init(this, attrs, defStyle, sHiddenStyleables); 36 | } 37 | 38 | @Override 39 | public void setButtonDrawable(@DrawableRes int resId) { 40 | if (sNative) { 41 | super.setButtonDrawable(resId); 42 | } else { 43 | super.setButtonDrawable(MaterialWidgetHandler.getDrawable(this, resId)); 44 | } 45 | } 46 | 47 | @Override 48 | public void setCompoundDrawablesWithIntrinsicBounds(@DrawableRes int left, @DrawableRes int top, 49 | @DrawableRes int right, @DrawableRes int bottom) { 50 | if (sNative) { 51 | super.setCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom); 52 | } else { 53 | super.setCompoundDrawablesWithIntrinsicBounds( 54 | MaterialWidgetHandler.getDrawable(this, left), MaterialWidgetHandler.getDrawable(this, top), 55 | MaterialWidgetHandler.getDrawable(this, right), MaterialWidgetHandler.getDrawable(this, bottom)); 56 | } 57 | } 58 | 59 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) 60 | @Override 61 | public void setCompoundDrawablesRelativeWithIntrinsicBounds(@DrawableRes int start, @DrawableRes int top, 62 | @DrawableRes int end, @DrawableRes int bottom) { 63 | if (sNative) { 64 | super.setCompoundDrawablesRelativeWithIntrinsicBounds(start, top, end, bottom); 65 | } else { 66 | super.setCompoundDrawablesRelativeWithIntrinsicBounds( 67 | MaterialWidgetHandler.getDrawable(this, start), MaterialWidgetHandler.getDrawable(this, top), 68 | MaterialWidgetHandler.getDrawable(this, end), MaterialWidgetHandler.getDrawable(this, bottom)); 69 | } 70 | } 71 | 72 | @Override 73 | public void setBackgroundResource(@DrawableRes int resId) { 74 | if (sNative) { 75 | super.setBackgroundResource(resId); 76 | } else { 77 | super.setBackground(MaterialWidgetHandler.getDrawable(this, resId)); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/java/io/doist/material/widget/MaterialRelativeLayout.java: -------------------------------------------------------------------------------- 1 | package io.doist.material.widget; 2 | 3 | import android.content.Context; 4 | import android.os.Build; 5 | import android.util.AttributeSet; 6 | import android.widget.RelativeLayout; 7 | 8 | import androidx.annotation.DrawableRes; 9 | import io.doist.material.widget.utils.MaterialWidgetHandler; 10 | 11 | public class MaterialRelativeLayout extends RelativeLayout { 12 | private static final boolean sNative = Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT; 13 | 14 | private static final MaterialWidgetHandler.Styleable[] sHiddenStyleables = { 15 | MaterialWidgetHandler.Styleable.VIEW 16 | }; 17 | 18 | public MaterialRelativeLayout(Context context) { 19 | this(context, null); 20 | } 21 | 22 | public MaterialRelativeLayout(Context context, AttributeSet attrs) { 23 | this(context, attrs, 0); 24 | } 25 | 26 | public MaterialRelativeLayout(Context context, AttributeSet attrs, int defStyle) { 27 | super(MaterialWidgetHandler.themifyContext(context, attrs), 28 | MaterialWidgetHandler.hideStyleableAttributes(attrs, sHiddenStyleables), defStyle); 29 | MaterialWidgetHandler.restoreStyleableAttributes(sHiddenStyleables); 30 | MaterialWidgetHandler.init(this, attrs, defStyle, sHiddenStyleables); 31 | } 32 | 33 | @Override 34 | public void setBackgroundResource(@DrawableRes int resId) { 35 | if (sNative) { 36 | super.setBackgroundResource(resId); 37 | } else { 38 | super.setBackground(MaterialWidgetHandler.getDrawable(this, resId)); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/java/io/doist/material/widget/MaterialSpinner.java: -------------------------------------------------------------------------------- 1 | package io.doist.material.widget; 2 | 3 | import android.content.Context; 4 | import android.os.Build; 5 | import android.util.AttributeSet; 6 | 7 | import androidx.annotation.DrawableRes; 8 | import androidx.appcompat.widget.AppCompatSpinner; 9 | import io.doist.material.widget.utils.MaterialWidgetHandler; 10 | 11 | public class MaterialSpinner extends AppCompatSpinner { 12 | private static final boolean sNative = Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT; 13 | 14 | private static final MaterialWidgetHandler.Styleable[] sHiddenStyleables = { 15 | MaterialWidgetHandler.Styleable.VIEW, 16 | MaterialWidgetHandler.Styleable.SPINNER 17 | }; 18 | 19 | public MaterialSpinner(Context context) { 20 | this(context, null); 21 | } 22 | 23 | public MaterialSpinner(Context context, AttributeSet attrs) { 24 | this(context, attrs, android.R.attr.spinnerStyle); 25 | } 26 | 27 | public MaterialSpinner(Context context, AttributeSet attrs, int defStyle) { 28 | this(context, attrs, defStyle, -1); 29 | } 30 | 31 | public MaterialSpinner(Context context, int mode) { 32 | this(context, null, android.R.attr.spinnerStyle, mode); 33 | } 34 | 35 | public MaterialSpinner(Context context, AttributeSet attrs, int defStyle, int mode) { 36 | super(MaterialWidgetHandler.themifyContext(context, attrs), 37 | MaterialWidgetHandler.hideStyleableAttributes(attrs, sHiddenStyleables), defStyle, mode); 38 | MaterialWidgetHandler.restoreStyleableAttributes(sHiddenStyleables); 39 | MaterialWidgetHandler.init(this, attrs, defStyle, sHiddenStyleables); 40 | } 41 | 42 | @Override 43 | public void setBackgroundResource(@DrawableRes int resId) { 44 | if (sNative) { 45 | super.setBackgroundResource(resId); 46 | } else { 47 | super.setBackground(MaterialWidgetHandler.getDrawable(this, resId)); 48 | } 49 | } 50 | 51 | @Override 52 | public void setPopupBackgroundResource(@DrawableRes int resId) { 53 | if (sNative) { 54 | super.setPopupBackgroundResource(resId); 55 | } else { 56 | super.setPopupBackgroundDrawable(MaterialWidgetHandler.getDrawable(this, resId)); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/java/io/doist/material/widget/MaterialSwitch.java: -------------------------------------------------------------------------------- 1 | package io.doist.material.widget; 2 | 3 | import android.content.Context; 4 | import android.os.Build; 5 | import android.util.AttributeSet; 6 | 7 | import androidx.annotation.DrawableRes; 8 | import androidx.appcompat.widget.SwitchCompat; 9 | import io.doist.material.R; 10 | import io.doist.material.widget.utils.MaterialWidgetHandler; 11 | 12 | public class MaterialSwitch extends SwitchCompat { 13 | private static final boolean sNative = Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT; 14 | 15 | private static final MaterialWidgetHandler.Styleable[] sHiddenStyleables = { 16 | MaterialWidgetHandler.Styleable.VIEW 17 | }; 18 | 19 | public MaterialSwitch(Context context) { 20 | super(context); 21 | } 22 | 23 | public MaterialSwitch(Context context, AttributeSet attrs) { 24 | this(context, attrs, R.attr.switchStyle); 25 | } 26 | 27 | public MaterialSwitch(Context context, AttributeSet attrs, int defStyle) { 28 | super(MaterialWidgetHandler.themifyContext(context, attrs), 29 | MaterialWidgetHandler.hideStyleableAttributes(attrs, sHiddenStyleables), defStyle); 30 | MaterialWidgetHandler.restoreStyleableAttributes(sHiddenStyleables); 31 | MaterialWidgetHandler.init(this, attrs, defStyle, sHiddenStyleables); 32 | } 33 | 34 | @Override 35 | public void setBackgroundResource(@DrawableRes int resId) { 36 | if (sNative) { 37 | super.setBackgroundResource(resId); 38 | } else { 39 | super.setBackground(MaterialWidgetHandler.getDrawable(this, resId)); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/java/io/doist/material/widget/MaterialTextView.java: -------------------------------------------------------------------------------- 1 | package io.doist.material.widget; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.annotation.TargetApi; 5 | import android.content.Context; 6 | import android.os.Build; 7 | import android.util.AttributeSet; 8 | import android.widget.TextView; 9 | 10 | import androidx.annotation.DrawableRes; 11 | import io.doist.material.widget.utils.MaterialWidgetHandler; 12 | 13 | @SuppressLint("AppCompatCustomView") 14 | public class MaterialTextView extends TextView { 15 | private static final boolean sNative = Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT; 16 | 17 | private static final MaterialWidgetHandler.Styleable[] sHiddenStyleables = { 18 | MaterialWidgetHandler.Styleable.TEXT_VIEW, 19 | MaterialWidgetHandler.Styleable.VIEW 20 | }; 21 | 22 | public MaterialTextView(Context context) { 23 | this(context, null); 24 | } 25 | 26 | public MaterialTextView(Context context, AttributeSet attrs) { 27 | this(context, attrs, android.R.attr.textViewStyle); 28 | } 29 | 30 | public MaterialTextView(Context context, AttributeSet attrs, int defStyle) { 31 | super(MaterialWidgetHandler.themifyContext(context, attrs), 32 | MaterialWidgetHandler.hideStyleableAttributes(attrs, sHiddenStyleables), defStyle); 33 | MaterialWidgetHandler.restoreStyleableAttributes(sHiddenStyleables); 34 | MaterialWidgetHandler.init(this, attrs, defStyle, sHiddenStyleables); 35 | } 36 | 37 | @Override 38 | public void setCompoundDrawablesWithIntrinsicBounds(@DrawableRes int left, @DrawableRes int top, 39 | @DrawableRes int right, @DrawableRes int bottom) { 40 | if (sNative) { 41 | super.setCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom); 42 | } else { 43 | super.setCompoundDrawablesWithIntrinsicBounds( 44 | MaterialWidgetHandler.getDrawable(this, left), MaterialWidgetHandler.getDrawable(this, top), 45 | MaterialWidgetHandler.getDrawable(this, right), MaterialWidgetHandler.getDrawable(this, bottom)); 46 | } 47 | } 48 | 49 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) 50 | @Override 51 | public void setCompoundDrawablesRelativeWithIntrinsicBounds(@DrawableRes int start, @DrawableRes int top, 52 | @DrawableRes int end, @DrawableRes int bottom) { 53 | if (sNative) { 54 | super.setCompoundDrawablesRelativeWithIntrinsicBounds(start, top, end, bottom); 55 | } else { 56 | super.setCompoundDrawablesRelativeWithIntrinsicBounds( 57 | MaterialWidgetHandler.getDrawable(this, start), MaterialWidgetHandler.getDrawable(this, top), 58 | MaterialWidgetHandler.getDrawable(this, end), MaterialWidgetHandler.getDrawable(this, bottom)); 59 | } 60 | } 61 | 62 | @Override 63 | public void setBackgroundResource(@DrawableRes int resId) { 64 | if (sNative) { 65 | super.setBackgroundResource(resId); 66 | } else { 67 | super.setBackground(MaterialWidgetHandler.getDrawable(this, resId)); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/java/io/doist/material/widget/MaterialToggleButton.java: -------------------------------------------------------------------------------- 1 | package io.doist.material.widget; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.content.Context; 5 | import android.os.Build; 6 | import android.util.AttributeSet; 7 | import android.widget.ToggleButton; 8 | 9 | import androidx.annotation.DrawableRes; 10 | import io.doist.material.widget.utils.MaterialWidgetHandler; 11 | 12 | @SuppressLint("AppCompatCustomView") 13 | public class MaterialToggleButton extends ToggleButton { 14 | private static final boolean sNative = Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT; 15 | 16 | private static final MaterialWidgetHandler.Styleable[] sHiddenStyleables = { 17 | MaterialWidgetHandler.Styleable.VIEW 18 | }; 19 | 20 | public MaterialToggleButton(Context context) { 21 | this(context, null); 22 | } 23 | 24 | public MaterialToggleButton(Context context, AttributeSet attrs) { 25 | this(context, attrs, android.R.attr.buttonStyleToggle); 26 | } 27 | 28 | public MaterialToggleButton(Context context, AttributeSet attrs, int defStyle) { 29 | super(MaterialWidgetHandler.themifyContext(context, attrs), 30 | MaterialWidgetHandler.hideStyleableAttributes(attrs, sHiddenStyleables), defStyle); 31 | MaterialWidgetHandler.restoreStyleableAttributes(sHiddenStyleables); 32 | MaterialWidgetHandler.init(this, attrs, defStyle, sHiddenStyleables); 33 | } 34 | 35 | @Override 36 | public void setBackgroundResource(@DrawableRes int resId) { 37 | if (sNative) { 38 | super.setBackgroundResource(resId); 39 | } else { 40 | super.setBackground(MaterialWidgetHandler.getDrawable(this, resId)); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/java/io/doist/material/widget/MaterialView.java: -------------------------------------------------------------------------------- 1 | package io.doist.material.widget; 2 | 3 | import android.content.Context; 4 | import android.os.Build; 5 | import android.util.AttributeSet; 6 | import android.view.View; 7 | 8 | import androidx.annotation.DrawableRes; 9 | import io.doist.material.widget.utils.MaterialWidgetHandler; 10 | 11 | public class MaterialView extends View { 12 | private static final boolean sNative = Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT; 13 | 14 | private static final MaterialWidgetHandler.Styleable[] sHiddenStyleables = { 15 | MaterialWidgetHandler.Styleable.VIEW 16 | }; 17 | 18 | public MaterialView(Context context) { 19 | this(context, null); 20 | } 21 | 22 | public MaterialView(Context context, AttributeSet attrs) { 23 | this(context, attrs, 0); 24 | } 25 | 26 | public MaterialView(Context context, AttributeSet attrs, int defStyle) { 27 | super(MaterialWidgetHandler.themifyContext(context, attrs), 28 | MaterialWidgetHandler.hideStyleableAttributes(attrs, sHiddenStyleables), defStyle); 29 | MaterialWidgetHandler.restoreStyleableAttributes(sHiddenStyleables); 30 | MaterialWidgetHandler.init(this, attrs, defStyle, sHiddenStyleables); 31 | } 32 | 33 | @Override 34 | public void setBackgroundResource(@DrawableRes int resId) { 35 | if (sNative) { 36 | super.setBackgroundResource(resId); 37 | } else { 38 | super.setBackground(MaterialWidgetHandler.getDrawable(this, resId)); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/color/btn_default_material_light.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 18 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/drawable-hdpi/btn_check_to_on_mtrl_000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Doist/AndroidMaterial/097a3f69394597cba353bbdeaf2070555d94f2f6/MaterialLibrary/src/main/res/drawable-hdpi/btn_check_to_on_mtrl_000.png -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/drawable-hdpi/btn_check_to_on_mtrl_015.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Doist/AndroidMaterial/097a3f69394597cba353bbdeaf2070555d94f2f6/MaterialLibrary/src/main/res/drawable-hdpi/btn_check_to_on_mtrl_015.png -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/drawable-hdpi/btn_mtrl_alpha.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Doist/AndroidMaterial/097a3f69394597cba353bbdeaf2070555d94f2f6/MaterialLibrary/src/main/res/drawable-hdpi/btn_mtrl_alpha.9.png -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/drawable-hdpi/btn_radio_to_on_mtrl_000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Doist/AndroidMaterial/097a3f69394597cba353bbdeaf2070555d94f2f6/MaterialLibrary/src/main/res/drawable-hdpi/btn_radio_to_on_mtrl_000.png -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/drawable-hdpi/btn_radio_to_on_mtrl_015.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Doist/AndroidMaterial/097a3f69394597cba353bbdeaf2070555d94f2f6/MaterialLibrary/src/main/res/drawable-hdpi/btn_radio_to_on_mtrl_015.png -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/drawable-hdpi/progress_mtrl_alpha.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Doist/AndroidMaterial/097a3f69394597cba353bbdeaf2070555d94f2f6/MaterialLibrary/src/main/res/drawable-hdpi/progress_mtrl_alpha.9.png -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/drawable-hdpi/text_cursor_mtrl_alpha.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Doist/AndroidMaterial/097a3f69394597cba353bbdeaf2070555d94f2f6/MaterialLibrary/src/main/res/drawable-hdpi/text_cursor_mtrl_alpha.9.png -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/drawable-mdpi/btn_mtrl_alpha.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Doist/AndroidMaterial/097a3f69394597cba353bbdeaf2070555d94f2f6/MaterialLibrary/src/main/res/drawable-mdpi/btn_mtrl_alpha.9.png -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/drawable-mdpi/progress_mtrl_alpha.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Doist/AndroidMaterial/097a3f69394597cba353bbdeaf2070555d94f2f6/MaterialLibrary/src/main/res/drawable-mdpi/progress_mtrl_alpha.9.png -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/drawable-mdpi/text_cursor_mtrl_alpha.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Doist/AndroidMaterial/097a3f69394597cba353bbdeaf2070555d94f2f6/MaterialLibrary/src/main/res/drawable-mdpi/text_cursor_mtrl_alpha.9.png -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/drawable-xhdpi/btn_check_to_on_mtrl_000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Doist/AndroidMaterial/097a3f69394597cba353bbdeaf2070555d94f2f6/MaterialLibrary/src/main/res/drawable-xhdpi/btn_check_to_on_mtrl_000.png -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/drawable-xhdpi/btn_check_to_on_mtrl_015.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Doist/AndroidMaterial/097a3f69394597cba353bbdeaf2070555d94f2f6/MaterialLibrary/src/main/res/drawable-xhdpi/btn_check_to_on_mtrl_015.png -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/drawable-xhdpi/btn_mtrl_alpha.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Doist/AndroidMaterial/097a3f69394597cba353bbdeaf2070555d94f2f6/MaterialLibrary/src/main/res/drawable-xhdpi/btn_mtrl_alpha.9.png -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/drawable-xhdpi/btn_radio_to_on_mtrl_000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Doist/AndroidMaterial/097a3f69394597cba353bbdeaf2070555d94f2f6/MaterialLibrary/src/main/res/drawable-xhdpi/btn_radio_to_on_mtrl_000.png -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/drawable-xhdpi/btn_radio_to_on_mtrl_015.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Doist/AndroidMaterial/097a3f69394597cba353bbdeaf2070555d94f2f6/MaterialLibrary/src/main/res/drawable-xhdpi/btn_radio_to_on_mtrl_015.png -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/drawable-xhdpi/progress_mtrl_alpha.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Doist/AndroidMaterial/097a3f69394597cba353bbdeaf2070555d94f2f6/MaterialLibrary/src/main/res/drawable-xhdpi/progress_mtrl_alpha.9.png -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/drawable-xhdpi/text_cursor_mtrl_alpha.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Doist/AndroidMaterial/097a3f69394597cba353bbdeaf2070555d94f2f6/MaterialLibrary/src/main/res/drawable-xhdpi/text_cursor_mtrl_alpha.9.png -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/drawable-xxhdpi/btn_check_to_on_mtrl_000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Doist/AndroidMaterial/097a3f69394597cba353bbdeaf2070555d94f2f6/MaterialLibrary/src/main/res/drawable-xxhdpi/btn_check_to_on_mtrl_000.png -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/drawable-xxhdpi/btn_check_to_on_mtrl_015.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Doist/AndroidMaterial/097a3f69394597cba353bbdeaf2070555d94f2f6/MaterialLibrary/src/main/res/drawable-xxhdpi/btn_check_to_on_mtrl_015.png -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/drawable-xxhdpi/btn_mtrl_alpha.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Doist/AndroidMaterial/097a3f69394597cba353bbdeaf2070555d94f2f6/MaterialLibrary/src/main/res/drawable-xxhdpi/btn_mtrl_alpha.9.png -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/drawable-xxhdpi/btn_radio_to_on_mtrl_000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Doist/AndroidMaterial/097a3f69394597cba353bbdeaf2070555d94f2f6/MaterialLibrary/src/main/res/drawable-xxhdpi/btn_radio_to_on_mtrl_000.png -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/drawable-xxhdpi/btn_radio_to_on_mtrl_015.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Doist/AndroidMaterial/097a3f69394597cba353bbdeaf2070555d94f2f6/MaterialLibrary/src/main/res/drawable-xxhdpi/btn_radio_to_on_mtrl_015.png -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/drawable-xxhdpi/progress_mtrl_alpha.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Doist/AndroidMaterial/097a3f69394597cba353bbdeaf2070555d94f2f6/MaterialLibrary/src/main/res/drawable-xxhdpi/progress_mtrl_alpha.9.png -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/drawable-xxhdpi/text_cursor_mtrl_alpha.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Doist/AndroidMaterial/097a3f69394597cba353bbdeaf2070555d94f2f6/MaterialLibrary/src/main/res/drawable-xxhdpi/text_cursor_mtrl_alpha.9.png -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/drawable-xxxhdpi/btn_check_to_on_mtrl_000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Doist/AndroidMaterial/097a3f69394597cba353bbdeaf2070555d94f2f6/MaterialLibrary/src/main/res/drawable-xxxhdpi/btn_check_to_on_mtrl_000.png -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/drawable-xxxhdpi/btn_check_to_on_mtrl_015.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Doist/AndroidMaterial/097a3f69394597cba353bbdeaf2070555d94f2f6/MaterialLibrary/src/main/res/drawable-xxxhdpi/btn_check_to_on_mtrl_015.png -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/drawable-xxxhdpi/btn_radio_to_on_mtrl_000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Doist/AndroidMaterial/097a3f69394597cba353bbdeaf2070555d94f2f6/MaterialLibrary/src/main/res/drawable-xxxhdpi/btn_radio_to_on_mtrl_000.png -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/drawable-xxxhdpi/btn_radio_to_on_mtrl_015.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Doist/AndroidMaterial/097a3f69394597cba353bbdeaf2070555d94f2f6/MaterialLibrary/src/main/res/drawable-xxxhdpi/btn_radio_to_on_mtrl_015.png -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/drawable/btn_borderless_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 21 | 24 | 25 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/drawable/btn_check_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/drawable/btn_default_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/drawable/btn_default_mtrl_shape.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 18 | 19 | 24 | 25 | 26 | 27 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/drawable/btn_radio_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/drawable/edit_text_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 12 | 13 | 16 | 19 | 20 | 21 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/drawable/list_divider_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 23 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/drawable/progress_horizontal_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 19 | 20 | 24 | 25 | 26 | 27 | 31 | 32 | 33 | 34 | 35 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/drawable/spinner_background_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 18 | 19 | 22 | 23 | 24 | 26 | 27 | 28 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/drawable/spinner_textfield_background_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 19 | 20 | 21 | 22 | 23 | 25 | 26 | 27 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 37 | 38 | 39 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/drawable/text_cursor_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/layout-v17/preference_category_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 18 | 28 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/layout-v17/preference_child_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 18 | 26 | 27 | 30 | 31 | 36 | 37 | 43 | 44 | 52 | 53 | 62 | 63 | 64 | 65 | 66 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/layout-v17/preference_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 20 | 29 | 30 | 37 | 38 | 44 | 45 | 53 | 54 | 63 | 64 | 65 | 66 | 67 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/layout/fragment_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/layout/preference_category_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 18 | 28 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/layout/preference_child_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 18 | 26 | 27 | 30 | 31 | 36 | 37 | 43 | 44 | 52 | 53 | 62 | 63 | 64 | 65 | 66 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/layout/preference_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 20 | 29 | 30 | 37 | 38 | 44 | 45 | 53 | 54 | 63 | 64 | 65 | 66 | 67 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/layout/preference_widget_checkbox.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/values-ldrtl/styles_widgets.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/values-v21/styles_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 18 | 19 | 20 | 21 | 24 | 25 | 26 | 27 | 30 | 31 | 32 | 43 | 44 | 45 | 49 | 50 | 51 | 55 | 56 | 62 | 63 | 66 | 67 | 68 | 69 | 73 | 74 | 75 | 76 | 81 | 82 | 90 | 91 | 94 | 95 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/values/styles_widgets.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | -------------------------------------------------------------------------------- /MaterialLibrary/src/main/res/values/themes_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 38 | 39 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /MaterialSamples/.gitignore: -------------------------------------------------------------------------------- 1 | # Eclipse 2 | .project 3 | .classpath 4 | .settings 5 | .checkstyle 6 | 7 | # IntelliJ IDEA 8 | .idea 9 | *.iml 10 | *.ipr 11 | *.iws 12 | classes 13 | out 14 | gen-external-apklibs 15 | 16 | # Gradle 17 | .gradle 18 | build 19 | 20 | # Maven 21 | target 22 | release.properties 23 | pom.xml.* 24 | 25 | # Ant 26 | bin 27 | gen 28 | build.xml 29 | ant.properties 30 | local.properties 31 | proguard.cfg 32 | 33 | # Other 34 | .DS_Store 35 | Thumbs.db 36 | *~ 37 | *.swp 38 | tmp 39 | -------------------------------------------------------------------------------- /MaterialSamples/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 30 5 | 6 | defaultConfig { 7 | applicationId "io.doist.material.sample" 8 | minSdkVersion 16 9 | targetSdkVersion 30 10 | versionCode 1 11 | versionName "1.0" 12 | } 13 | 14 | compileOptions { 15 | sourceCompatibility JavaVersion.VERSION_1_8 16 | targetCompatibility JavaVersion.VERSION_1_8 17 | } 18 | 19 | buildTypes { 20 | release { 21 | minifyEnabled false 22 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 23 | } 24 | } 25 | } 26 | 27 | dependencies { 28 | implementation 'androidx.appcompat:appcompat:1.2.0' 29 | implementation project(':MaterialLibrary') 30 | } 31 | -------------------------------------------------------------------------------- /MaterialSamples/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in C:\android-studio\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /MaterialSamples/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /MaterialSamples/src/main/java/io/doist/material/sample/DemoElevatedTextView.java: -------------------------------------------------------------------------------- 1 | package io.doist.material.sample; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.content.Context; 5 | import android.util.AttributeSet; 6 | import android.widget.TextView; 7 | 8 | import io.doist.material.elevation.CompatElevationDelegate; 9 | 10 | @SuppressLint("AppCompatCustomView") 11 | public class DemoElevatedTextView extends TextView { 12 | private CompatElevationDelegate mCompatElevationDelegate; 13 | 14 | public DemoElevatedTextView(Context context) { 15 | super(context); 16 | init(null, 0); 17 | } 18 | 19 | public DemoElevatedTextView(Context context, AttributeSet attrs) { 20 | super(context, attrs); 21 | init(attrs, 0); 22 | } 23 | 24 | public DemoElevatedTextView(Context context, AttributeSet attrs, int defStyleAttr) { 25 | super(context, attrs, defStyleAttr); 26 | init(attrs, defStyleAttr); 27 | } 28 | 29 | private void init(AttributeSet attrs, int defStyleAttr) { 30 | mCompatElevationDelegate = new CompatElevationDelegate(this, attrs, defStyleAttr); 31 | } 32 | 33 | @Override 34 | protected void onAttachedToWindow() { 35 | super.onAttachedToWindow(); 36 | 37 | mCompatElevationDelegate.onAttachedToWindow(); 38 | } 39 | 40 | @Override 41 | protected void onDetachedFromWindow() { 42 | super.onDetachedFromWindow(); 43 | 44 | mCompatElevationDelegate.onDetachedFromWindow(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /MaterialSamples/src/main/java/io/doist/material/sample/MainActivity.java: -------------------------------------------------------------------------------- 1 | package io.doist.material.sample; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import androidx.appcompat.app.AppCompatActivity; 6 | import android.view.Menu; 7 | import android.view.MenuItem; 8 | import android.view.View; 9 | import android.widget.ArrayAdapter; 10 | import android.widget.AutoCompleteTextView; 11 | import android.widget.ProgressBar; 12 | import android.widget.Spinner; 13 | import android.widget.Toast; 14 | 15 | public class MainActivity extends AppCompatActivity { 16 | 17 | @Override 18 | protected void onCreate(Bundle savedInstanceState) { 19 | super.onCreate(savedInstanceState); 20 | setContentView(R.layout.activity_main); 21 | 22 | findViewById(R.id.fab).setOnClickListener(new View.OnClickListener() { 23 | @Override 24 | public void onClick(View v) { 25 | onFabClick(v); 26 | } 27 | }); 28 | 29 | String[] array = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"}; 30 | ArrayAdapter adapter = new ArrayAdapter<>(this, android.R.layout.simple_dropdown_item_1line, array); 31 | AutoCompleteTextView autoCompleteTextView = findViewById(R.id.autocomplete); 32 | autoCompleteTextView.setAdapter(adapter); 33 | 34 | Spinner spinner = findViewById(R.id.spinner); 35 | spinner.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_spinner_dropdown_item, array)); 36 | 37 | final ProgressBar progress = findViewById(R.id.progress); 38 | findViewById(android.R.id.button1).setOnClickListener(new View.OnClickListener() { 39 | @Override 40 | public void onClick(View v) { 41 | progress.setProgress(0); 42 | progress.post(new Runnable() { 43 | @Override 44 | public void run() { 45 | progress.setProgress(progress.getProgress() + progress.getMax() / 100); 46 | 47 | if (progress.getProgress() != progress.getMax()) { 48 | progress.postDelayed(this, 16); 49 | } 50 | } 51 | }); 52 | } 53 | }); 54 | } 55 | 56 | @Override 57 | public boolean onCreateOptionsMenu(Menu menu) { 58 | getMenuInflater().inflate(R.menu.main, menu); 59 | return true; 60 | } 61 | 62 | @Override 63 | public boolean onOptionsItemSelected(MenuItem item) { 64 | if (item.getItemId() == R.id.action_settings) { 65 | startActivity(new Intent(this, SettingsActivity.class)); 66 | return true; 67 | } 68 | return super.onOptionsItemSelected(item); 69 | } 70 | 71 | public void onFabClick(View view) { 72 | Toast.makeText(this, "Click!", Toast.LENGTH_SHORT).show(); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /MaterialSamples/src/main/java/io/doist/material/sample/SettingsActivity.java: -------------------------------------------------------------------------------- 1 | package io.doist.material.sample; 2 | 3 | import android.os.Bundle; 4 | import android.preference.PreferenceFragment; 5 | import android.view.LayoutInflater; 6 | import android.view.MenuItem; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | 10 | import androidx.annotation.NonNull; 11 | import androidx.appcompat.app.AppCompatActivity; 12 | import androidx.core.app.NavUtils; 13 | 14 | public class SettingsActivity extends AppCompatActivity { 15 | @Override 16 | protected void onCreate(Bundle savedInstanceState) { 17 | super.onCreate(savedInstanceState); 18 | 19 | setContentView(R.layout.activity_settings); 20 | 21 | getSupportActionBar().setDisplayHomeAsUpEnabled(true); 22 | 23 | if (savedInstanceState == null) { 24 | getFragmentManager().beginTransaction().add(R.id.settings_frame, new SettingsFragment()).commit(); 25 | } 26 | } 27 | 28 | @Override 29 | public boolean onOptionsItemSelected(MenuItem item) { 30 | switch (item.getItemId()) { 31 | case android.R.id.home: 32 | NavUtils.navigateUpFromSameTask(this); 33 | return true; 34 | default: 35 | break; 36 | } 37 | return super.onOptionsItemSelected(item); 38 | } 39 | 40 | public static class SettingsFragment extends PreferenceFragment { 41 | @Override 42 | public void onCreate(Bundle savedInstanceState) { 43 | super.onCreate(savedInstanceState); 44 | addPreferencesFromResource(R.xml.preferences); 45 | } 46 | 47 | @Override 48 | public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 49 | return inflater.inflate(R.layout.fragment_settings, container, false); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /MaterialSamples/src/main/res/color/btn_sample.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /MaterialSamples/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Doist/AndroidMaterial/097a3f69394597cba353bbdeaf2070555d94f2f6/MaterialSamples/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /MaterialSamples/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Doist/AndroidMaterial/097a3f69394597cba353bbdeaf2070555d94f2f6/MaterialSamples/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /MaterialSamples/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Doist/AndroidMaterial/097a3f69394597cba353bbdeaf2070555d94f2f6/MaterialSamples/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /MaterialSamples/src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Doist/AndroidMaterial/097a3f69394597cba353bbdeaf2070555d94f2f6/MaterialSamples/src/main/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /MaterialSamples/src/main/res/drawable/roundrect_sample.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /MaterialSamples/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 17 | 18 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /MaterialSamples/src/main/res/layout/activity_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | -------------------------------------------------------------------------------- /MaterialSamples/src/main/res/layout/sample_elevation.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 20 | 21 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /MaterialSamples/src/main/res/layout/sample_fab.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 17 | 18 | 28 | 29 | 30 | 31 | 40 | 41 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /MaterialSamples/src/main/res/layout/sample_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 15 | 16 | 20 | 21 | 25 | 26 | 31 | 32 | 37 | 38 | 42 | 43 | 47 | 48 | 52 | 53 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /MaterialSamples/src/main/res/menu/main.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /MaterialSamples/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /MaterialSamples/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | -------------------------------------------------------------------------------- /MaterialSamples/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | MaterialSamples 5 | Settings 6 | 7 | Hello world! 8 | 9 | This is a phrase (Roboto regular) 10 | This is a phrase (Roboto regular (bold)) 11 | This is a phrase (Roboto regular (italic)) 12 | This is a phrase (Roboto regular (bold / italic)) 13 | This is a phrase (Roboto light) 14 | This is a phrase (Roboto light (fake bold)) 15 | This is a phrase (Roboto light (italic)) 16 | This is a phrase (Roboto light (fake bold / italic)) 17 | This is a phrase (Roboto medium) 18 | This is a phrase (Roboto medium (fake bold)) 19 | This is a phrase (Roboto medium (italic)) 20 | This is a phrase (Roboto medium (fake bold / italic)) 21 | This is a phrase (Roboto condensed) 22 | This is a phrase (Roboto condensed (bold)) 23 | This is a phrase (Roboto condensed (italic)) 24 | This is a phrase (Roboto condensed (bold / italic)) 25 | This is a phrase (Roboto condensed light) 26 | This is a phrase (Roboto condensed light (fake bold)) 27 | This is a phrase (Roboto condensed light (italic)) 28 | This is a phrase (Roboto condensed light (fake bold / italic)) 29 | 30 | AutoCompleteTextView 31 | 32 | MaterialEditText #1 33 | MaterialEditText #2 34 | 35 | MaterialCheckBox 36 | MaterialRadioButton 37 | MaterialSwitch 38 | 39 | Screen 40 | Preference 41 | Summary 42 | CheckBox 43 | Ringtone 44 | Dependent on CheckBox 45 | Category 46 | EditText 47 | Switch 48 | 49 | 50 | -------------------------------------------------------------------------------- /MaterialSamples/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /MaterialSamples/src/main/res/xml/preferences.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 10 | 14 | 15 | 21 | 22 | 23 | 24 | 27 | 28 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | google() 4 | mavenCentral() 5 | } 6 | 7 | dependencies { 8 | classpath "com.android.tools.build:gradle:7.0.0-alpha14" 9 | } 10 | } 11 | 12 | allprojects { 13 | repositories { 14 | google() 15 | mavenCentral() 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | android.useAndroidX=true 2 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Doist/AndroidMaterial/097a3f69394597cba353bbdeaf2070555d94f2f6/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | 86 | # Determine the Java command to use to start the JVM. 87 | if [ -n "$JAVA_HOME" ] ; then 88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 89 | # IBM's JDK on AIX uses strange locations for the executables 90 | JAVACMD="$JAVA_HOME/jre/sh/java" 91 | else 92 | JAVACMD="$JAVA_HOME/bin/java" 93 | fi 94 | if [ ! -x "$JAVACMD" ] ; then 95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 96 | 97 | Please set the JAVA_HOME variable in your environment to match the 98 | location of your Java installation." 99 | fi 100 | else 101 | JAVACMD="java" 102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 103 | 104 | Please set the JAVA_HOME variable in your environment to match the 105 | location of your Java installation." 106 | fi 107 | 108 | # Increase the maximum file descriptors if we can. 109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 110 | MAX_FD_LIMIT=`ulimit -H -n` 111 | if [ $? -eq 0 ] ; then 112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 113 | MAX_FD="$MAX_FD_LIMIT" 114 | fi 115 | ulimit -n $MAX_FD 116 | if [ $? -ne 0 ] ; then 117 | warn "Could not set maximum file descriptor limit: $MAX_FD" 118 | fi 119 | else 120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 121 | fi 122 | fi 123 | 124 | # For Darwin, add options to specify how the application appears in the dock 125 | if $darwin; then 126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 127 | fi 128 | 129 | # For Cygwin or MSYS, switch paths to Windows format before running java 130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 133 | 134 | JAVACMD=`cygpath --unix "$JAVACMD"` 135 | 136 | # We build the pattern for arguments to be converted via cygpath 137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 138 | SEP="" 139 | for dir in $ROOTDIRSRAW ; do 140 | ROOTDIRS="$ROOTDIRS$SEP$dir" 141 | SEP="|" 142 | done 143 | OURCYGPATTERN="(^($ROOTDIRS))" 144 | # Add a user-defined pattern to the cygpath arguments 145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 147 | fi 148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 149 | i=0 150 | for arg in "$@" ; do 151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 153 | 154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 156 | else 157 | eval `echo args$i`="\"$arg\"" 158 | fi 159 | i=`expr $i + 1` 160 | done 161 | case $i in 162 | 0) set -- ;; 163 | 1) set -- "$args0" ;; 164 | 2) set -- "$args0" "$args1" ;; 165 | 3) set -- "$args0" "$args1" "$args2" ;; 166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 172 | esac 173 | fi 174 | 175 | # Escape application args 176 | save () { 177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 178 | echo " " 179 | } 180 | APP_ARGS=`save "$@"` 181 | 182 | # Collect all arguments for the java command, following the shell quoting and substitution rules 183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 184 | 185 | exec "$JAVACMD" "$@" 186 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':MaterialLibrary' 2 | include ':MaterialSamples' 3 | --------------------------------------------------------------------------------