├── app ├── .gitignore ├── src │ └── main │ │ ├── res │ │ ├── drawable-hdpi │ │ │ └── ic_share.png │ │ ├── drawable-mdpi │ │ │ └── ic_share.png │ │ ├── drawable-xhdpi │ │ │ └── ic_share.png │ │ ├── drawable-xxhdpi │ │ │ └── ic_share.png │ │ ├── drawable-xxxhdpi │ │ │ └── ic_share.png │ │ ├── mipmap-hdpi │ │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ │ └── ic_launcher.png │ │ ├── values │ │ │ ├── strings.xml │ │ │ ├── dimens.xml │ │ │ ├── arrays.xml │ │ │ └── styles.xml │ │ ├── values-w820dp │ │ │ └── dimens.xml │ │ ├── menu │ │ │ └── menu_main.xml │ │ └── layout │ │ │ ├── activity_kotlin.xml │ │ │ └── activity_main.xml │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── com │ │ └── commit451 │ │ └── easel │ │ └── sample │ │ └── MainActivity.kt ├── proguard-rules.pro └── build.gradle ├── easel ├── .gitignore ├── src │ └── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── com │ │ └── commit451 │ │ └── easel │ │ ├── spinner.kt │ │ ├── button.kt │ │ ├── menuitem.kt │ │ ├── menu.kt │ │ ├── edittext.kt │ │ ├── switchcompat.kt │ │ ├── toolbar.kt │ │ ├── progressbar.kt │ │ ├── ReflectionUtil.kt │ │ ├── checkbox.kt │ │ ├── radiobutton.kt │ │ ├── view.kt │ │ ├── seekbar.kt │ │ ├── Easel.kt │ │ └── textview.kt ├── proguard-rules.pro └── build.gradle ├── settings.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .travis.yml ├── gradle.properties ├── .gitignore ├── README.md ├── gradlew.bat ├── gradlew └── LICENSE.txt /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /easel/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':easel' 2 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Commit451/Easel/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /easel/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Commit451/Easel/HEAD/app/src/main/res/drawable-hdpi/ic_share.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Commit451/Easel/HEAD/app/src/main/res/drawable-mdpi/ic_share.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Commit451/Easel/HEAD/app/src/main/res/drawable-xhdpi/ic_share.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Commit451/Easel/HEAD/app/src/main/res/drawable-xxhdpi/ic_share.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Commit451/Easel/HEAD/app/src/main/res/drawable-xxxhdpi/ic_share.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Commit451/Easel/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Commit451/Easel/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Commit451/Easel/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Commit451/Easel/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Easel Sample 3 | 4 | About 5 | Share 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: android 2 | 3 | jdk: 4 | - oraclejdk8 5 | 6 | before_install: 7 | - mkdir "$ANDROID_HOME/licenses" || true 8 | - echo "d56f5187479451eabf01fb78af6dfcb131a6481e" > "$ANDROID_HOME/licenses/android-sdk-license" 9 | 10 | script: "./gradlew build" -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat Dec 15 01:03:42 PST 2018 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/arrays.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Item 1 5 | Item 2 6 | Item 3 7 | Item 4 8 | 9 | -------------------------------------------------------------------------------- /easel/src/main/java/com/commit451/easel/spinner.kt: -------------------------------------------------------------------------------- 1 | package com.commit451.easel 2 | 3 | import android.graphics.PorterDuff 4 | import androidx.annotation.ColorInt 5 | import android.widget.Spinner 6 | 7 | fun Spinner.tint(@ColorInt color: Int) { 8 | background.setColorFilter(color, PorterDuff.Mode.SRC_ATOP) 9 | } -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /easel/src/main/java/com/commit451/easel/button.kt: -------------------------------------------------------------------------------- 1 | package com.commit451.easel 2 | 3 | import android.content.res.ColorStateList 4 | import androidx.annotation.ColorInt 5 | import androidx.core.view.ViewCompat 6 | import android.widget.Button 7 | 8 | /** 9 | * Tint the button 10 | * 11 | * @param color the color 12 | */ 13 | fun Button.tint(@ColorInt color: Int) { 14 | val sl = ColorStateList(arrayOf(intArrayOf()), intArrayOf(color)) 15 | ViewCompat.setBackgroundTintList(this, sl) 16 | } 17 | -------------------------------------------------------------------------------- /easel/src/main/java/com/commit451/easel/menuitem.kt: -------------------------------------------------------------------------------- 1 | package com.commit451.easel 2 | 3 | import android.graphics.PorterDuff 4 | import androidx.annotation.ColorInt 5 | import android.view.MenuItem 6 | 7 | /** 8 | * Tint a menu item 9 | * 10 | * @param color the color 11 | */ 12 | fun MenuItem.tint(@ColorInt color: Int) { 13 | val icon = icon 14 | if (icon != null) { 15 | icon.setColorFilter(color, PorterDuff.Mode.MULTIPLY) 16 | } else { 17 | throw IllegalArgumentException("Menu item does not have an icon") 18 | } 19 | } -------------------------------------------------------------------------------- /easel/src/main/java/com/commit451/easel/menu.kt: -------------------------------------------------------------------------------- 1 | package com.commit451.easel 2 | 3 | import androidx.annotation.ColorInt 4 | import android.view.Menu 5 | 6 | /** 7 | * Tint all menu items within a menu to be a certain color. Note that this does not tint the 8 | * overflow menu. Call tintOverflow for that. 9 | * 10 | * @param color the color 11 | */ 12 | fun Menu.tint(@ColorInt color: Int) { 13 | for (i in 0 until size()) { 14 | val menuItem = getItem(i) 15 | if (menuItem.icon != null) { 16 | menuItem.tint(color) 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in Z:\Code\ADT\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 | -------------------------------------------------------------------------------- /easel/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 Z:\Code\ADT\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 | -------------------------------------------------------------------------------- /easel/src/main/java/com/commit451/easel/edittext.kt: -------------------------------------------------------------------------------- 1 | package com.commit451.easel 2 | 3 | import android.annotation.SuppressLint 4 | import android.os.Build 5 | import androidx.annotation.ColorInt 6 | import androidx.appcompat.widget.AppCompatEditText 7 | import android.widget.EditText 8 | import android.widget.TextView 9 | 10 | @SuppressLint("RestrictedApi") 11 | fun EditText.tint(@ColorInt color : Int) { 12 | val editTextColorStateList = Easel.createEditTextColorStateList(this.getContext(), color) 13 | if (this is AppCompatEditText) { 14 | supportBackgroundTintList = editTextColorStateList 15 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 16 | setBackgroundTintList(editTextColorStateList) 17 | } 18 | (this as TextView).tint(color) 19 | } 20 | -------------------------------------------------------------------------------- /easel/src/main/java/com/commit451/easel/switchcompat.kt: -------------------------------------------------------------------------------- 1 | package com.commit451.easel 2 | 3 | import android.content.res.ColorStateList 4 | import androidx.annotation.ColorInt 5 | import androidx.core.graphics.drawable.DrawableCompat 6 | import androidx.appcompat.widget.SwitchCompat 7 | import com.commit451.easel.Easel.getThemeAttrColor 8 | 9 | fun SwitchCompat.tint(@ColorInt color: Int, @ColorInt unpressedColor: Int = getThemeAttrColor(context, R.attr.colorSwitchThumbNormal)) { 10 | val sl = ColorStateList(arrayOf(intArrayOf(-android.R.attr.state_checked), intArrayOf(android.R.attr.state_checked)), intArrayOf(unpressedColor, color)) 11 | DrawableCompat.setTintList(thumbDrawable, sl) 12 | DrawableCompat.setTintList(trackDrawable, Easel.createSwitchTrackColorStateList(context, color)) 13 | } -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_main.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 11 | 12 | 16 | 17 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | apply plugin: 'kotlin-android' 4 | 5 | android { 6 | compileSdkVersion rootProject.ext.compileSdkVersion 7 | 8 | defaultConfig { 9 | applicationId "com.commit451.easel.sample" 10 | minSdkVersion rootProject.ext.minSdkVersion 11 | targetSdkVersion rootProject.ext.targetSdkVersion 12 | versionCode 1 13 | versionName "1.0" 14 | } 15 | buildTypes { 16 | release { 17 | minifyEnabled false 18 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 19 | } 20 | } 21 | lintOptions { 22 | abortOnError false 23 | } 24 | } 25 | 26 | dependencies { 27 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 28 | 29 | implementation 'androidx.appcompat:appcompat:1.0.2' 30 | 31 | implementation project(':easel') 32 | } 33 | -------------------------------------------------------------------------------- /easel/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | apply plugin: 'kotlin-android' 4 | 5 | android { 6 | compileSdkVersion rootProject.ext.compileSdkVersion 7 | 8 | defaultConfig { 9 | minSdkVersion rootProject.ext.minSdkVersion 10 | targetSdkVersion rootProject.ext.targetSdkVersion 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | lintOptions { 21 | abortOnError false 22 | } 23 | } 24 | 25 | dependencies { 26 | api "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 27 | api 'androidx.appcompat:appcompat:1.0.2' 28 | } 29 | 30 | apply from: 'https://raw.githubusercontent.com/Commit451/gradle-android-javadocs/1.0.0/gradle-android-javadocs.gradle' 31 | 32 | -------------------------------------------------------------------------------- /easel/src/main/java/com/commit451/easel/toolbar.kt: -------------------------------------------------------------------------------- 1 | package com.commit451.easel 2 | 3 | import android.annotation.SuppressLint 4 | import androidx.annotation.ColorInt 5 | import androidx.appcompat.widget.Toolbar 6 | import android.view.View 7 | import android.widget.ImageView 8 | import java.util.* 9 | 10 | /** 11 | * Sets the color of the overflow menu item within the Toolbar. 12 | * 13 | * @param color color to set the overflow icon to 14 | * @return true if tint was set. 15 | */ 16 | fun Toolbar.tintOverflow(@ColorInt color: Int): Boolean { 17 | @SuppressLint("PrivateResource") 18 | val overflowDescription = context.getString(R.string.abc_action_menu_overflow_description) 19 | val outViews = ArrayList() 20 | findViewsWithText(outViews, overflowDescription, 21 | View.FIND_VIEWS_WITH_CONTENT_DESCRIPTION) 22 | if (outViews.isEmpty()) { 23 | return false 24 | } 25 | val overflow = outViews[0] as ImageView 26 | overflow.setColorFilter(color) 27 | return true 28 | } -------------------------------------------------------------------------------- /easel/src/main/java/com/commit451/easel/progressbar.kt: -------------------------------------------------------------------------------- 1 | package com.commit451.easel 2 | 3 | import android.content.res.ColorStateList 4 | import android.graphics.PorterDuff 5 | import android.os.Build 6 | import androidx.annotation.ColorInt 7 | import android.widget.ProgressBar 8 | 9 | fun ProgressBar.tint(@ColorInt color: Int, skipIndeterminate: Boolean = false) { 10 | val sl = ColorStateList.valueOf(color) 11 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 12 | progressTintList = sl 13 | secondaryProgressTintList = sl 14 | if (!skipIndeterminate) { 15 | indeterminateTintList = sl 16 | } 17 | } else { 18 | var mode: PorterDuff.Mode = PorterDuff.Mode.SRC_IN 19 | if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) { 20 | mode = PorterDuff.Mode.MULTIPLY 21 | } 22 | if (!skipIndeterminate && indeterminateDrawable != null) { 23 | indeterminateDrawable.setColorFilter(color, mode) 24 | } 25 | if (progressDrawable != null) { 26 | progressDrawable.setColorFilter(color, mode) 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /easel/src/main/java/com/commit451/easel/ReflectionUtil.kt: -------------------------------------------------------------------------------- 1 | package com.commit451.easel 2 | 3 | import android.graphics.PorterDuff 4 | import androidx.annotation.ColorInt 5 | import androidx.annotation.DrawableRes 6 | import androidx.core.content.ContextCompat 7 | import android.widget.TextView 8 | import java.lang.reflect.Field 9 | 10 | /** 11 | * Reflection is fun 12 | */ 13 | internal object ReflectionUtil { 14 | 15 | fun getField(clazz: Class<*>, fieldName: String): Field { 16 | val field = clazz.getDeclaredField(fieldName) 17 | field.isAccessible = true 18 | return field 19 | } 20 | 21 | fun getEditorField(): Field { 22 | val fEditor = TextView::class.java.getDeclaredField("mEditor") 23 | fEditor.isAccessible = true 24 | return fEditor 25 | } 26 | 27 | fun setDrawable(textView: TextView, editor: Any, field: Field, @ColorInt color: Int, 28 | @DrawableRes drawableRes: Int) { 29 | val drawable = ContextCompat.getDrawable(textView.context, drawableRes) 30 | ?.mutate() 31 | drawable?.setColorFilter(color, PorterDuff.Mode.SRC_IN) 32 | field.set(editor, drawable) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_kotlin.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 18 | 19 |