Initial commit retro music app

This commit is contained in:
h4h13 2018-07-27 18:37:33 +05:30
parent ab332473bc
commit fe890632fd
932 changed files with 83126 additions and 0 deletions

1
appthemehelper/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/build

View file

@ -0,0 +1,136 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id=":appthemehelper" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android-gradle" name="Android-Gradle">
<configuration>
<option name="GRADLE_PROJECT_PATH" value=":appthemehelper" />
</configuration>
</facet>
<facet type="android" name="Android">
<configuration>
<option name="SELECTED_BUILD_VARIANT" value="debug" />
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
<afterSyncTasks>
<task>generateDebugSources</task>
</afterSyncTasks>
<option name="ALLOW_USER_CONFIGURATION" value="false" />
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res" />
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
<option name="PROJECT_TYPE" value="1" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7">
<output url="file://$MODULE_DIR$/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes" />
<output-test url="file://$MODULE_DIR$/build/intermediates/javac/debugUnitTest/compileDebugUnitTestJavaWithJavac/classes" />
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/not_namespaced_r_class_sources/debug/generateDebugRFile/out" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/not_namespaced_r_class_sources/debugAndroidTest/processDebugAndroidTestResources/r" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/test/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/shaders" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/shaders" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/shaders" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/shaders" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/shaders" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/aapt_friendly_merged_manifests" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/annotation_processor_list" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/check-manifest" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/intermediate-jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/javac" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/library_assets" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/merged_manifests" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/packaged_res" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/platform_r_txt" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/public_res" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/shader_assets" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/shaders" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/transforms" />
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
</content>
<orderEntry type="jdk" jdkName="Android API 27 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Gradle: com.android.support:transition-27.1.1" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:support-v4-27.1.1" level="project" />
<orderEntry type="library" name="Gradle: android.arch.lifecycle:common:1.1.0@jar" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:support-fragment-27.1.1" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:support-annotations:27.1.1@jar" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:cardview-v7-27.1.1" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:animated-vector-drawable-27.1.1" level="project" />
<orderEntry type="library" name="Gradle: android.arch.core:runtime-1.1.0" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:support-compat-27.1.1" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:design-27.1.1" level="project" />
<orderEntry type="library" name="Gradle: com.afollestad.material-dialogs:core-0.9.6.0" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:appcompat-v7-27.1.1" level="project" />
<orderEntry type="library" name="Gradle: android.arch.lifecycle:viewmodel-1.1.0" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:preference-v7-27.1.1" level="project" />
<orderEntry type="library" name="Gradle: me.zhanghai.android.materialprogressbar:library-1.4.2" level="project" />
<orderEntry type="library" name="Gradle: android.arch.lifecycle:livedata-core-1.1.0" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:recyclerview-v7-27.1.1" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:support-vector-drawable-27.1.1" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:support-media-compat-27.1.1" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:support-core-ui-27.1.1" level="project" />
<orderEntry type="library" name="Gradle: android.arch.core:common:1.1.0@jar" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:support-core-utils-27.1.1" level="project" />
<orderEntry type="library" name="Gradle: com.afollestad.material-dialogs:commons-0.9.6.0" level="project" />
<orderEntry type="library" name="Gradle: android.arch.lifecycle:runtime-1.1.0" level="project" />
</component>
</module>

View file

@ -0,0 +1,34 @@
apply plugin: 'com.android.library'
android {
compileSdkVersion 27
defaultConfig {
minSdkVersion 21
targetSdkVersion 27
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
buildToolsVersion '27.0.3'
productFlavors {
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support:design:27.1.1'
implementation 'com.android.support:preference-v7:27.1.1'
implementation 'com.android.support:cardview-v7:27.1.1'
// Used for the list preference classes
implementation 'com.afollestad.material-dialogs:core:0.9.6.0'
implementation 'com.afollestad.material-dialogs:commons:0.9.6.0'
}

21
appthemehelper/proguard-rules.pro vendored Normal file
View file

@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View file

@ -0,0 +1,26 @@
package code.name.monkey.appthemehelper;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() throws Exception {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("code.name.monkey.appthemehelper.test", appContext.getPackageName());
}
}

View file

@ -0,0 +1 @@
<manifest package="code.name.monkey.appthemehelper" />

View file

@ -0,0 +1,122 @@
package code.name.monkey.appthemehelper;
import static android.view.View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
import android.os.Build;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.widget.Toolbar;
import android.view.View;
import code.name.monkey.appthemehelper.util.ColorUtil;
import code.name.monkey.appthemehelper.util.TintHelper;
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public final class ATH {
private ATH() {
}
@SuppressLint("CommitPrefEdits")
public static boolean didThemeValuesChange(@NonNull Context context, long since) {
return ThemeStore.isConfigured(context)
&& ThemeStore.prefs(context).getLong(ThemeStore.VALUES_CHANGED, -1) > since;
}
public static void setStatusbarColorAuto(Activity activity) {
setStatusbarColor(activity, ThemeStore.statusBarColor(activity));
}
public static void setStatusbarColor(Activity activity, int color) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
activity.getWindow().setStatusBarColor(color);
setLightStatusbarAuto(activity, color);
}
}
public static void setLightStatusbarAuto(Activity activity, int bgColor) {
setLightStatusbar(activity, ColorUtil.isColorLight(bgColor));
}
public static void setLightStatusbar(Activity activity, boolean enabled) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
final View decorView = activity.getWindow().getDecorView();
final int systemUiVisibility = decorView.getSystemUiVisibility();
if (enabled) {
decorView.setSystemUiVisibility(systemUiVisibility | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
} else {
decorView.setSystemUiVisibility(systemUiVisibility & ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
}
}
}
public static void setLightNavigationbar(Activity activity, boolean enabled) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
final View decorView = activity.getWindow().getDecorView();
int systemUiVisibility = decorView.getSystemUiVisibility();
if (enabled) {
systemUiVisibility |= SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
} else {
systemUiVisibility &= ~SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
}
decorView.setSystemUiVisibility(systemUiVisibility);
}
}
public static void setLightNavigationbarAuto(Activity activity, int bgColor) {
setLightNavigationbar(activity, ColorUtil.isColorLight(bgColor));
}
public static void setNavigationbarColorAuto(Activity activity) {
setNavigationbarColor(activity, ThemeStore.navigationBarColor(activity));
}
public static void setNavigationbarColor(Activity activity, int color) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
activity.getWindow().setNavigationBarColor(color);
setLightNavigationbarAuto(activity, color);
}
}
public static void setActivityToolbarColorAuto(Activity activity, @Nullable Toolbar toolbar) {
setActivityToolbarColor(activity, toolbar, ThemeStore.primaryColor(activity));
}
public static void setActivityToolbarColor(Activity activity, @Nullable Toolbar toolbar,
int color) {
if (toolbar == null) {
return;
}
toolbar.setBackgroundColor(color);
ToolbarContentTintHelper.setToolbarContentColorBasedOnToolbarColor(activity, toolbar, color);
}
public static void setTaskDescriptionColorAuto(@NonNull Activity activity) {
setTaskDescriptionColor(activity, ThemeStore.primaryColor(activity));
}
public static void setTaskDescriptionColor(@NonNull Activity activity, @ColorInt int color) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// Task description requires fully opaque color
color = ColorUtil.stripAlpha(color);
// Sets color of entry in the system recents page
activity.setTaskDescription(
new ActivityManager.TaskDescription((String) activity.getTitle(), null, color));
}
}
public static void setTint(@NonNull View view, @ColorInt int color) {
TintHelper.setTintAuto(view, color, false);
}
public static void setBackgroundTint(@NonNull View view, @ColorInt int color) {
TintHelper.setTintAuto(view, color, true);
}
}

View file

@ -0,0 +1,49 @@
package code.name.monkey.appthemehelper;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.StyleRes;
import android.support.v7.app.AppCompatActivity;
/**
* @author Aidan Follestad (afollestad), Karim Abou Zeid (kabouzeid)
*/
public class ATHActivity extends AppCompatActivity {
private long updateTime = -1;
@Override
protected void onCreate(Bundle savedInstanceState) {
setTheme(getThemeRes());
super.onCreate(savedInstanceState);
updateTime = System.currentTimeMillis();
}
@Override
protected void onResume() {
super.onResume();
if (ATH.didThemeValuesChange(this, updateTime)) {
onThemeChanged();
}
}
public void onThemeChanged() {
postRecreate();
}
public void postRecreate() {
// hack to prevent java.lang.RuntimeException: Performing pause of activity that is not resumed
// makes sure recreate() is called right after and not in onResume()
new Handler().post(new Runnable() {
@Override
public void run() {
recreate();
}
});
}
@StyleRes
protected int getThemeRes() {
return ThemeStore.activityTheme(this);
}
}

View file

@ -0,0 +1,325 @@
package code.name.monkey.appthemehelper;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.support.annotation.AttrRes;
import android.support.annotation.CheckResult;
import android.support.annotation.ColorInt;
import android.support.annotation.ColorRes;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.annotation.StyleRes;
import android.support.v4.content.ContextCompat;
import code.name.monkey.appthemehelper.util.ATHUtil;
import code.name.monkey.appthemehelper.util.ColorUtil;
/**
* @author Aidan Follestad (afollestad), Karim Abou Zeid (kabouzeid)
*/
public final class ThemeStore implements ThemeStorePrefKeys, ThemeStoreInterface {
private final Context mContext;
private final SharedPreferences.Editor mEditor;
@SuppressLint("CommitPrefEdits")
private ThemeStore(@NonNull Context context) {
mContext = context;
mEditor = prefs(context).edit();
}
public static ThemeStore editTheme(@NonNull Context context) {
return new ThemeStore(context);
}
@CheckResult
@NonNull
protected static SharedPreferences prefs(@NonNull Context context) {
return context.getSharedPreferences(CONFIG_PREFS_KEY_DEFAULT, Context.MODE_PRIVATE);
}
public static void markChanged(@NonNull Context context) {
new ThemeStore(context).commit();
}
@CheckResult
@StyleRes
public static int activityTheme(@NonNull Context context) {
return prefs(context).getInt(KEY_ACTIVITY_THEME, 0);
}
@CheckResult
@ColorInt
public static int primaryColor(@NonNull Context context) {
return prefs(context).getInt(KEY_PRIMARY_COLOR, ATHUtil.resolveColor(context, R.attr.colorPrimary, Color.parseColor("#455A64")));
}
@CheckResult
@ColorInt
public static int primaryColorDark(@NonNull Context context) {
return prefs(context).getInt(KEY_PRIMARY_COLOR_DARK, ATHUtil.resolveColor(context, R.attr.colorPrimaryDark, Color.parseColor("#37474F")));
}
@CheckResult
@ColorInt
public static int accentColor(@NonNull Context context) {
return prefs(context).getInt(KEY_ACCENT_COLOR, ATHUtil.resolveColor(context, R.attr.colorAccent, Color.parseColor("#263238")));
}
@CheckResult
@ColorInt
public static int statusBarColor(@NonNull Context context) {
if (!coloredStatusBar(context)) {
return Color.BLACK;
}
return prefs(context).getInt(KEY_STATUS_BAR_COLOR, primaryColorDark(context));
}
@CheckResult
@ColorInt
public static int navigationBarColor(@NonNull Context context) {
if (!coloredNavigationBar(context)) {
return Color.BLACK;
}
return prefs(context).getInt(KEY_NAVIGATION_BAR_COLOR, primaryColor(context));
}
@CheckResult
@ColorInt
public static int textColorPrimary(@NonNull Context context) {
return prefs(context).getInt(KEY_TEXT_COLOR_PRIMARY, ATHUtil.resolveColor(context, android.R.attr.textColorPrimary));
}
@CheckResult
@ColorInt
public static int textColorPrimaryInverse(@NonNull Context context) {
return prefs(context).getInt(KEY_TEXT_COLOR_PRIMARY_INVERSE, ATHUtil.resolveColor(context, android.R.attr.textColorPrimaryInverse));
}
@CheckResult
@ColorInt
public static int textColorSecondary(@NonNull Context context) {
return prefs(context).getInt(KEY_TEXT_COLOR_SECONDARY, ATHUtil.resolveColor(context, android.R.attr.textColorSecondary));
}
@CheckResult
@ColorInt
public static int textColorSecondaryInverse(@NonNull Context context) {
return prefs(context).getInt(KEY_TEXT_COLOR_SECONDARY_INVERSE, ATHUtil.resolveColor(context, android.R.attr.textColorSecondaryInverse));
}
@CheckResult
public static boolean coloredStatusBar(@NonNull Context context) {
return prefs(context).getBoolean(KEY_APPLY_PRIMARYDARK_STATUSBAR, true);
}
@CheckResult
public static boolean coloredNavigationBar(@NonNull Context context) {
return prefs(context).getBoolean(KEY_APPLY_PRIMARY_NAVBAR, false);
}
@CheckResult
public static boolean autoGeneratePrimaryDark(@NonNull Context context) {
return prefs(context).getBoolean(KEY_AUTO_GENERATE_PRIMARYDARK, true);
}
@CheckResult
public static boolean isConfigured(Context context) {
return prefs(context).getBoolean(IS_CONFIGURED_KEY, false);
}
@SuppressLint("CommitPrefEdits")
public static boolean isConfigured(Context context, @IntRange(from = 0, to = Integer.MAX_VALUE) int version) {
final SharedPreferences prefs = prefs(context);
final int lastVersion = prefs.getInt(IS_CONFIGURED_VERSION_KEY, -1);
if (version > lastVersion) {
prefs.edit().putInt(IS_CONFIGURED_VERSION_KEY, version).commit();
return false;
}
return true;
}
@Override
public ThemeStore activityTheme(@StyleRes int theme) {
mEditor.putInt(KEY_ACTIVITY_THEME, theme);
return this;
}
@Override
public ThemeStore primaryColor(@ColorInt int color) {
mEditor.putInt(KEY_PRIMARY_COLOR, color);
if (autoGeneratePrimaryDark(mContext))
primaryColorDark(ColorUtil.darkenColor(color));
return this;
}
@Override
public ThemeStore primaryColorRes(@ColorRes int colorRes) {
return primaryColor(ContextCompat.getColor(mContext, colorRes));
}
@Override
public ThemeStore primaryColorAttr(@AttrRes int colorAttr) {
return primaryColor(ATHUtil.resolveColor(mContext, colorAttr));
}
@Override
public ThemeStore primaryColorDark(@ColorInt int color) {
mEditor.putInt(KEY_PRIMARY_COLOR_DARK, color);
return this;
}
@Override
public ThemeStore primaryColorDarkRes(@ColorRes int colorRes) {
return primaryColorDark(ContextCompat.getColor(mContext, colorRes));
}
@Override
public ThemeStore primaryColorDarkAttr(@AttrRes int colorAttr) {
return primaryColorDark(ATHUtil.resolveColor(mContext, colorAttr));
}
@Override
public ThemeStore accentColor(@ColorInt int color) {
mEditor.putInt(KEY_ACCENT_COLOR, color);
return this;
}
@Override
public ThemeStore accentColorRes(@ColorRes int colorRes) {
return accentColor(ContextCompat.getColor(mContext, colorRes));
}
@Override
public ThemeStore accentColorAttr(@AttrRes int colorAttr) {
return accentColor(ATHUtil.resolveColor(mContext, colorAttr));
}
@Override
public ThemeStore statusBarColor(@ColorInt int color) {
mEditor.putInt(KEY_STATUS_BAR_COLOR, color);
return this;
}
@Override
public ThemeStore statusBarColorRes(@ColorRes int colorRes) {
return statusBarColor(ContextCompat.getColor(mContext, colorRes));
}
@Override
public ThemeStore statusBarColorAttr(@AttrRes int colorAttr) {
return statusBarColor(ATHUtil.resolveColor(mContext, colorAttr));
}
@Override
public ThemeStore navigationBarColor(@ColorInt int color) {
mEditor.putInt(KEY_NAVIGATION_BAR_COLOR, color);
return this;
}
// Commit method
@Override
public ThemeStore navigationBarColorRes(@ColorRes int colorRes) {
return navigationBarColor(ContextCompat.getColor(mContext, colorRes));
}
// Static getters
@Override
public ThemeStore navigationBarColorAttr(@AttrRes int colorAttr) {
return navigationBarColor(ATHUtil.resolveColor(mContext, colorAttr));
}
@Override
public ThemeStore textColorPrimary(@ColorInt int color) {
mEditor.putInt(KEY_TEXT_COLOR_PRIMARY, color);
return this;
}
@Override
public ThemeStore textColorPrimaryRes(@ColorRes int colorRes) {
return textColorPrimary(ContextCompat.getColor(mContext, colorRes));
}
@Override
public ThemeStore textColorPrimaryAttr(@AttrRes int colorAttr) {
return textColorPrimary(ATHUtil.resolveColor(mContext, colorAttr));
}
@Override
public ThemeStore textColorPrimaryInverse(@ColorInt int color) {
mEditor.putInt(KEY_TEXT_COLOR_PRIMARY_INVERSE, color);
return this;
}
@Override
public ThemeStore textColorPrimaryInverseRes(@ColorRes int colorRes) {
return textColorPrimaryInverse(ContextCompat.getColor(mContext, colorRes));
}
@Override
public ThemeStore textColorPrimaryInverseAttr(@AttrRes int colorAttr) {
return textColorPrimaryInverse(ATHUtil.resolveColor(mContext, colorAttr));
}
@Override
public ThemeStore textColorSecondary(@ColorInt int color) {
mEditor.putInt(KEY_TEXT_COLOR_SECONDARY, color);
return this;
}
@Override
public ThemeStore textColorSecondaryRes(@ColorRes int colorRes) {
return textColorSecondary(ContextCompat.getColor(mContext, colorRes));
}
@Override
public ThemeStore textColorSecondaryAttr(@AttrRes int colorAttr) {
return textColorSecondary(ATHUtil.resolveColor(mContext, colorAttr));
}
@Override
public ThemeStore textColorSecondaryInverse(@ColorInt int color) {
mEditor.putInt(KEY_TEXT_COLOR_SECONDARY_INVERSE, color);
return this;
}
@Override
public ThemeStore textColorSecondaryInverseRes(@ColorRes int colorRes) {
return textColorSecondaryInverse(ContextCompat.getColor(mContext, colorRes));
}
@Override
public ThemeStore textColorSecondaryInverseAttr(@AttrRes int colorAttr) {
return textColorSecondaryInverse(ATHUtil.resolveColor(mContext, colorAttr));
}
@Override
public ThemeStore coloredStatusBar(boolean colored) {
mEditor.putBoolean(KEY_APPLY_PRIMARYDARK_STATUSBAR, colored);
return this;
}
@Override
public ThemeStore coloredNavigationBar(boolean applyToNavBar) {
mEditor.putBoolean(KEY_APPLY_PRIMARY_NAVBAR, applyToNavBar);
return this;
}
@Override
public ThemeStore autoGeneratePrimaryDark(boolean autoGenerate) {
mEditor.putBoolean(KEY_AUTO_GENERATE_PRIMARYDARK, autoGenerate);
return this;
}
@SuppressWarnings("unchecked")
@Override
public void commit() {
mEditor.putLong(VALUES_CHANGED, System.currentTimeMillis())
.putBoolean(IS_CONFIGURED_KEY, true)
.commit();
}
}

View file

@ -0,0 +1,94 @@
package code.name.monkey.appthemehelper;
import android.support.annotation.AttrRes;
import android.support.annotation.ColorInt;
import android.support.annotation.ColorRes;
import android.support.annotation.StyleRes;
/**
* @author Aidan Follestad (afollestad), Karim Abou Zeid (kabouzeid)
*/
interface ThemeStoreInterface {
// Activity theme
ThemeStore activityTheme(@StyleRes int theme);
// Primary colors
ThemeStore primaryColor(@ColorInt int color);
ThemeStore primaryColorRes(@ColorRes int colorRes);
ThemeStore primaryColorAttr(@AttrRes int colorAttr);
ThemeStore autoGeneratePrimaryDark(boolean autoGenerate);
ThemeStore primaryColorDark(@ColorInt int color);
ThemeStore primaryColorDarkRes(@ColorRes int colorRes);
ThemeStore primaryColorDarkAttr(@AttrRes int colorAttr);
// Accent colors
ThemeStore accentColor(@ColorInt int color);
ThemeStore accentColorRes(@ColorRes int colorRes);
ThemeStore accentColorAttr(@AttrRes int colorAttr);
// Status bar color
ThemeStore statusBarColor(@ColorInt int color);
ThemeStore statusBarColorRes(@ColorRes int colorRes);
ThemeStore statusBarColorAttr(@AttrRes int colorAttr);
// Navigation bar color
ThemeStore navigationBarColor(@ColorInt int color);
ThemeStore navigationBarColorRes(@ColorRes int colorRes);
ThemeStore navigationBarColorAttr(@AttrRes int colorAttr);
// Primary text color
ThemeStore textColorPrimary(@ColorInt int color);
ThemeStore textColorPrimaryRes(@ColorRes int colorRes);
ThemeStore textColorPrimaryAttr(@AttrRes int colorAttr);
ThemeStore textColorPrimaryInverse(@ColorInt int color);
ThemeStore textColorPrimaryInverseRes(@ColorRes int colorRes);
ThemeStore textColorPrimaryInverseAttr(@AttrRes int colorAttr);
// Secondary text color
ThemeStore textColorSecondary(@ColorInt int color);
ThemeStore textColorSecondaryRes(@ColorRes int colorRes);
ThemeStore textColorSecondaryAttr(@AttrRes int colorAttr);
ThemeStore textColorSecondaryInverse(@ColorInt int color);
ThemeStore textColorSecondaryInverseRes(@ColorRes int colorRes);
ThemeStore textColorSecondaryInverseAttr(@AttrRes int colorAttr);
// Toggle configurations
ThemeStore coloredStatusBar(boolean colored);
ThemeStore coloredNavigationBar(boolean applyToNavBar);
// Commit/apply
void commit();
}

View file

@ -0,0 +1,29 @@
package code.name.monkey.appthemehelper;
/**
* @author Aidan Follestad (afollestad), Karim Abou Zeid (kabouzeid)
*/
interface ThemeStorePrefKeys {
String CONFIG_PREFS_KEY_DEFAULT = "[[kabouzeid_app-theme-helper]]";
String IS_CONFIGURED_KEY = "is_configured";
String IS_CONFIGURED_VERSION_KEY = "is_configured_version";
String VALUES_CHANGED = "values_changed";
String KEY_ACTIVITY_THEME = "activity_theme";
String KEY_PRIMARY_COLOR = "primary_color";
String KEY_PRIMARY_COLOR_DARK = "primary_color_dark";
String KEY_ACCENT_COLOR = "accent_color";
String KEY_STATUS_BAR_COLOR = "status_bar_color";
String KEY_NAVIGATION_BAR_COLOR = "navigation_bar_color";
String KEY_TEXT_COLOR_PRIMARY = "text_color_primary";
String KEY_TEXT_COLOR_PRIMARY_INVERSE = "text_color_primary_inverse";
String KEY_TEXT_COLOR_SECONDARY = "text_color_secondary";
String KEY_TEXT_COLOR_SECONDARY_INVERSE = "text_color_secondary_inverse";
String KEY_APPLY_PRIMARYDARK_STATUSBAR = "apply_primarydark_statusbar";
String KEY_APPLY_PRIMARY_NAVBAR = "apply_primary_navbar";
String KEY_AUTO_GENERATE_PRIMARYDARK = "auto_generate_primarydark";
}

View file

@ -0,0 +1,13 @@
package code.name.monkey.appthemehelper.common;
import android.support.v7.widget.Toolbar;
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper;
public class ATHActionBarActivity extends ATHToolbarActivity {
@Override
protected Toolbar getATHToolbar() {
return ToolbarContentTintHelper.getSupportActionBarView(getSupportActionBar());
}
}

View file

@ -0,0 +1,46 @@
package code.name.monkey.appthemehelper.common;
import android.graphics.drawable.ColorDrawable;
import android.support.annotation.Nullable;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import code.name.monkey.appthemehelper.ATHActivity;
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper;
public class ATHToolbarActivity extends ATHActivity {
private Toolbar toolbar;
@Override
public boolean onCreateOptionsMenu(Menu menu) {
Toolbar toolbar = getATHToolbar();
ToolbarContentTintHelper.handleOnCreateOptionsMenu(this, toolbar, menu, getToolbarBackgroundColor(toolbar));
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
ToolbarContentTintHelper.handleOnPrepareOptionsMenu(this, getATHToolbar());
return super.onPrepareOptionsMenu(menu);
}
@Override
public void setSupportActionBar(@Nullable Toolbar toolbar) {
this.toolbar = toolbar;
super.setSupportActionBar(toolbar);
}
protected Toolbar getATHToolbar() {
return toolbar;
}
public static int getToolbarBackgroundColor(Toolbar toolbar) {
if (toolbar != null) {
if (toolbar.getBackground() instanceof ColorDrawable) {
return ((ColorDrawable) toolbar.getBackground()).getColor();
}
}
return 0;
}
}

View file

@ -0,0 +1,91 @@
package code.name.monkey.appthemehelper.common.prefs;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import java.lang.reflect.Field;
import code.name.monkey.appthemehelper.ATH;
import code.name.monkey.appthemehelper.R;
import code.name.monkey.appthemehelper.ThemeStore;
/**
* @author Aidan Follestad (afollestad)
*/
public class ATECheckBoxPreference extends CheckBoxPreference {
public ATECheckBoxPreference(Context context) {
super(context);
init(context, null);
}
public ATECheckBoxPreference(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public ATECheckBoxPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public ATECheckBoxPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
setLayoutResource(R.layout.ate_preference_custom);
try {
Field canRecycleLayoutField = Preference.class.getDeclaredField("mCanRecycleLayout");
canRecycleLayoutField.setAccessible(true);
canRecycleLayoutField.setBoolean(this, true);
} catch (Exception ignored) {
}
try {
Field hasSpecifiedLayout = Preference.class.getDeclaredField("mHasSpecifiedLayout");
hasSpecifiedLayout.setAccessible(true);
hasSpecifiedLayout.setBoolean(this, true);
} catch (Exception ignored) {
}
}
@Override
protected void onBindView(View view) {
super.onBindView(view);
View parentCheckbox = findCheckboxView(view);
if (parentCheckbox != null) {
ATH.setTint(parentCheckbox, ThemeStore.accentColor(view.getContext()));
}
}
@Nullable
private View findCheckboxView(View view) {
if (view instanceof ViewGroup) {
for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
View child = ((ViewGroup) view).getChildAt(i);
if (child instanceof CheckBox) {
return child;
} else if (child instanceof ViewGroup) {
View potentialCheckbox = findCheckboxView(child);
if (potentialCheckbox != null) return potentialCheckbox;
}
}
} else if (view instanceof CheckBox) {
return view;
}
return null;
}
}

View file

@ -0,0 +1,66 @@
package code.name.monkey.appthemehelper.common.prefs;
import android.content.Context;
import android.preference.Preference;
import android.util.AttributeSet;
import android.view.View;
import code.name.monkey.appthemehelper.R;
/**
* @author Aidan Follestad (afollestad)
*/
public class ATEColorPreference extends Preference {
private View mView;
private int color;
private int border;
public ATEColorPreference(Context context) {
this(context, null, 0);
init(context, null);
}
public ATEColorPreference(Context context, AttributeSet attrs) {
this(context, attrs, 0);
init(context, attrs);
}
public ATEColorPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
setLayoutResource(R.layout.ate_preference_custom);
setWidgetLayoutResource(R.layout.ate_preference_color);
setPersistent(false);
}
@Override
protected void onBindView(View view) {
super.onBindView(view);
mView = view;
invalidateColor();
}
public void setColor(int color, int border) {
this.color = color;
this.border = border;
invalidateColor();
}
private void invalidateColor() {
if (mView != null) {
BorderCircleView circle = mView.findViewById(R.id.circle);
if (this.color != 0) {
circle.setVisibility(View.VISIBLE);
circle.setBackgroundColor(color);
circle.setBorderColor(border);
} else {
circle.setVisibility(View.GONE);
}
}
}
}

View file

@ -0,0 +1,38 @@
package code.name.monkey.appthemehelper.common.prefs;
import android.content.Context;
import android.util.AttributeSet;
import com.afollestad.materialdialogs.prefs.MaterialDialogPreference;
import code.name.monkey.appthemehelper.R;
/**
* @author Aidan Follestad (afollestad)
*/
public class ATEDialogPreference extends MaterialDialogPreference {
public ATEDialogPreference(Context context) {
super(context);
init(context, null);
}
public ATEDialogPreference(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public ATEDialogPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
public ATEDialogPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
setLayoutResource(R.layout.ate_preference_custom);
}
}

View file

@ -0,0 +1,36 @@
package code.name.monkey.appthemehelper.common.prefs;
import android.content.Context;
import android.util.AttributeSet;
import com.afollestad.materialdialogs.prefs.MaterialEditTextPreference;
/**
* @author Aidan Follestad (afollestad)
*/
public class ATEEditTextPreference extends MaterialEditTextPreference {
public ATEEditTextPreference(Context context) {
super(context);
init(context, null);
}
public ATEEditTextPreference(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public ATEEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
public ATEEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
setLayoutResource(code.name.monkey.appthemehelper.R.layout.ate_preference_custom);
}
}

View file

@ -0,0 +1,39 @@
package code.name.monkey.appthemehelper.common.prefs;
import android.content.Context;
import android.util.AttributeSet;
import com.afollestad.materialdialogs.prefs.MaterialListPreference;
import code.name.monkey.appthemehelper.R;
/**
* @author Aidan Follestad (afollestad)
*/
public class ATEListPreference extends MaterialListPreference {
public ATEListPreference(Context context) {
super(context);
init(context, null);
}
public ATEListPreference(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public ATEListPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
public ATEListPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
setLayoutResource(R.layout.ate_preference_custom);
if (getSummary() == null || getSummary().toString().trim().isEmpty())
setSummary("%s");
}
}

View file

@ -0,0 +1,37 @@
package code.name.monkey.appthemehelper.common.prefs;
import android.content.Context;
import android.util.AttributeSet;
import com.afollestad.materialdialogs.prefs.MaterialListPreference;
import code.name.monkey.appthemehelper.R;
/**
* @author Aidan Follestad (afollestad)
*/
public class ATEMultiSelectPreference extends MaterialListPreference {
public ATEMultiSelectPreference(Context context) {
super(context);
init(context, null);
}
public ATEMultiSelectPreference(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public ATEMultiSelectPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
public ATEMultiSelectPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
setLayoutResource(R.layout.ate_preference_custom);
}
}

View file

@ -0,0 +1,40 @@
package code.name.monkey.appthemehelper.common.prefs;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.preference.Preference;
import android.util.AttributeSet;
import code.name.monkey.appthemehelper.R;
/**
* @author Aidan Follestad (afollestad)
*/
public class ATEPreference extends Preference {
public ATEPreference(Context context) {
super(context);
init(context, null);
}
public ATEPreference(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public ATEPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public ATEPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
setLayoutResource(R.layout.ate_preference_custom);
}
}

View file

@ -0,0 +1,38 @@
package code.name.monkey.appthemehelper.common.prefs;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.preference.PreferenceCategory;
import android.util.AttributeSet;
import android.view.View;
import android.widget.TextView;
import code.name.monkey.appthemehelper.ThemeStore;
public class ATEPreferenceCategory extends PreferenceCategory {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public ATEPreferenceCategory(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public ATEPreferenceCategory(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public ATEPreferenceCategory(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ATEPreferenceCategory(Context context) {
super(context);
}
@Override
protected void onBindView(View view) {
super.onBindView(view);
TextView mTitle = (TextView) view.findViewById(android.R.id.title);
mTitle.setTextColor(ThemeStore.accentColor(view.getContext()));
}
}

View file

@ -0,0 +1,114 @@
package code.name.monkey.appthemehelper.common.prefs;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.preference.Preference;
import android.preference.SwitchPreference;
import android.support.annotation.Nullable;
import android.support.v7.widget.SwitchCompat;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Switch;
import code.name.monkey.appthemehelper.ATH;
import code.name.monkey.appthemehelper.R;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.appthemehelper.common.views.ATESwitch;
import java.lang.reflect.Field;
/**
* @author Aidan Follestad (afollestad)
*/
public class ATESwitchPreference extends SwitchPreference {
static final boolean COMPAT_MODE = Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP;
private ATESwitch mSwitch;
public ATESwitchPreference(Context context) {
super(context);
init(context, null);
}
public ATESwitchPreference(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public ATESwitchPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public ATESwitchPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
setLayoutResource(R.layout.ate_preference_custom);
if (COMPAT_MODE) {
setWidgetLayoutResource(R.layout.ate_preference_switch);
} else {
try {
Field canRecycleLayoutField = Preference.class.getDeclaredField("mCanRecycleLayout");
canRecycleLayoutField.setAccessible(true);
canRecycleLayoutField.setBoolean(this, true);
} catch (Exception ignored) {
}
try {
Field hasSpecifiedLayout = Preference.class.getDeclaredField("mHasSpecifiedLayout");
hasSpecifiedLayout.setAccessible(true);
hasSpecifiedLayout.setBoolean(this, true);
} catch (Exception ignored) {
}
}
}
@Override
protected void onBindView(View view) {
super.onBindView(view);
if (COMPAT_MODE) {
mSwitch = (ATESwitch) view.findViewById(R.id.switchWidget);
mSwitch.setChecked(isChecked());
} else {
View parentSwitch = findSwitchView(view);
if (parentSwitch != null) {
ATH.setTint(parentSwitch, ThemeStore.accentColor(view.getContext()));
}
}
}
@Nullable
private View findSwitchView(View view) {
if (view instanceof ViewGroup) {
for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
View child = ((ViewGroup) view).getChildAt(i);
if (child instanceof Switch || child instanceof SwitchCompat) {
return child;
} else if (child instanceof ViewGroup) {
View potentialSwitch = findSwitchView(child);
if (potentialSwitch != null) return potentialSwitch;
}
}
} else if (view instanceof Switch || view instanceof SwitchCompat) {
return view;
}
return null;
}
@Override
public void setChecked(boolean checked) {
super.setChecked(checked);
if (COMPAT_MODE) {
if (mSwitch != null) {
mSwitch.setChecked(checked);
}
}
}
}

View file

@ -0,0 +1,112 @@
package code.name.monkey.appthemehelper.common.prefs;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.Drawable;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.widget.FrameLayout;
import code.name.monkey.appthemehelper.R;
public class BorderCircleView extends FrameLayout {
private final Drawable mCheck;
private final Paint paint;
private final Paint paintBorder;
private final int borderWidth;
private Paint paintCheck;
private PorterDuffColorFilter blackFilter;
private PorterDuffColorFilter whiteFilter;
public BorderCircleView(Context context) {
this(context, null, 0);
}
public BorderCircleView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public BorderCircleView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mCheck = ContextCompat.getDrawable(context, R.drawable.ate_check);
borderWidth = (int) getResources().getDimension(R.dimen.ate_circleview_border);
paint = new Paint();
paint.setAntiAlias(true);
paintBorder = new Paint();
paintBorder.setAntiAlias(true);
paintBorder.setColor(Color.BLACK);
setWillNotDraw(false);
}
@Override
public void setBackgroundColor(int color) {
paint.setColor(color);
requestLayout();
invalidate();
}
public void setBorderColor(int color) {
paintBorder.setColor(color);
requestLayout();
invalidate();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if (widthMode == MeasureSpec.EXACTLY && heightMode != MeasureSpec.EXACTLY) {
int width = MeasureSpec.getSize(widthMeasureSpec);
//noinspection SuspiciousNameCombination
int height = width;
if (heightMode == MeasureSpec.AT_MOST) {
height = Math.min(height, MeasureSpec.getSize(heightMeasureSpec));
}
setMeasuredDimension(width, height);
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int canvasSize = canvas.getWidth();
if (canvas.getHeight() < canvasSize) {
canvasSize = canvas.getHeight();
}
int circleCenter = (canvasSize - (borderWidth * 2)) / 2;
canvas.drawCircle(circleCenter + borderWidth, circleCenter + borderWidth, ((canvasSize - (borderWidth * 2)) / 2) + borderWidth - 4.0f, paintBorder);
canvas.drawCircle(circleCenter + borderWidth, circleCenter + borderWidth, ((canvasSize - (borderWidth * 2)) / 2) - 4.0f, paint);
if (isActivated()) {
final int offset = (canvasSize / 2) - (mCheck.getIntrinsicWidth() / 2);
if (paintCheck == null) {
paintCheck = new Paint();
paintCheck.setAntiAlias(true);
}
if (whiteFilter == null || blackFilter == null) {
blackFilter = new PorterDuffColorFilter(Color.BLACK, PorterDuff.Mode.SRC_IN);
whiteFilter = new PorterDuffColorFilter(Color.WHITE, PorterDuff.Mode.SRC_IN);
}
if (paint.getColor() == Color.WHITE) {
paintCheck.setColorFilter(blackFilter);
} else {
paintCheck.setColorFilter(whiteFilter);
}
mCheck.setBounds(offset, offset, mCheck.getIntrinsicWidth() - offset, mCheck.getIntrinsicHeight() - offset);
mCheck.draw(canvas);
}
}
}

View file

@ -0,0 +1,41 @@
package code.name.monkey.appthemehelper.common.prefs.supportv7;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.support.v7.preference.CheckBoxPreference;
import android.util.AttributeSet;
import code.name.monkey.appthemehelper.R;
/**
* @author Aidan Follestad (afollestad)
*/
public class ATECheckBoxPreference extends CheckBoxPreference {
public ATECheckBoxPreference(Context context) {
super(context);
init(context, null);
}
public ATECheckBoxPreference(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public ATECheckBoxPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public ATECheckBoxPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
setLayoutResource(R.layout.ate_preference_custom_support);
setWidgetLayoutResource(R.layout.ate_preference_checkbox);
}
}

View file

@ -0,0 +1,68 @@
package code.name.monkey.appthemehelper.common.prefs.supportv7;
import android.content.Context;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceViewHolder;
import android.util.AttributeSet;
import android.view.View;
import code.name.monkey.appthemehelper.R;
import code.name.monkey.appthemehelper.common.prefs.BorderCircleView;
/**
* @author Aidan Follestad (afollestad)
*/
public class ATEColorPreference extends Preference {
private View mView;
private int color;
private int border;
public ATEColorPreference(Context context) {
this(context, null, 0);
init(context, null);
}
public ATEColorPreference(Context context, AttributeSet attrs) {
this(context, attrs, 0);
init(context, attrs);
}
public ATEColorPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
setLayoutResource(R.layout.ate_preference_custom_support);
setWidgetLayoutResource(R.layout.ate_preference_color);
setPersistent(false);
}
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
mView = holder.itemView;
invalidateColor();
}
public void setColor(int color, int border) {
this.color = color;
this.border = border;
invalidateColor();
}
private void invalidateColor() {
if (mView != null) {
BorderCircleView circle = (BorderCircleView) mView.findViewById(R.id.circle);
if (this.color != 0) {
circle.setVisibility(View.VISIBLE);
circle.setBackgroundColor(color);
circle.setBorderColor(border);
} else {
circle.setVisibility(View.GONE);
}
}
}
}

View file

@ -0,0 +1,37 @@
package code.name.monkey.appthemehelper.common.prefs.supportv7;
import android.content.Context;
import android.support.v7.preference.DialogPreference;
import android.util.AttributeSet;
import code.name.monkey.appthemehelper.R;
/**
* @author Aidan Follestad (afollestad)
*/
public class ATEDialogPreference extends DialogPreference {
public ATEDialogPreference(Context context) {
super(context);
init(context, null);
}
public ATEDialogPreference(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public ATEDialogPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
public ATEDialogPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
setLayoutResource(R.layout.ate_preference_custom_support);
}
}

View file

@ -0,0 +1,37 @@
package code.name.monkey.appthemehelper.common.prefs.supportv7;
import android.content.Context;
import android.support.v7.preference.EditTextPreference;
import android.util.AttributeSet;
import code.name.monkey.appthemehelper.R;
/**
* @author Aidan Follestad (afollestad)
*/
public class ATEEditTextPreference extends EditTextPreference {
public ATEEditTextPreference(Context context) {
super(context);
init(context, null);
}
public ATEEditTextPreference(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public ATEEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
public ATEEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
setLayoutResource(R.layout.ate_preference_custom_support);
}
}

View file

@ -0,0 +1,39 @@
package code.name.monkey.appthemehelper.common.prefs.supportv7;
import android.content.Context;
import android.support.v7.preference.ListPreference;
import android.util.AttributeSet;
import code.name.monkey.appthemehelper.R;
/**
* @author Aidan Follestad (afollestad)
*/
public class ATEListPreference extends ListPreference {
public ATEListPreference(Context context) {
super(context);
init(context, null);
}
public ATEListPreference(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public ATEListPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
public ATEListPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
setLayoutResource(R.layout.ate_preference_custom_support);
if (getSummary() == null || getSummary().toString().trim().isEmpty())
setSummary("%s");
}
}

View file

@ -0,0 +1,40 @@
package code.name.monkey.appthemehelper.common.prefs.supportv7;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.support.v7.preference.Preference;
import android.util.AttributeSet;
import code.name.monkey.appthemehelper.R;
/**
* @author Aidan Follestad (afollestad)
*/
public class ATEPreference extends Preference {
public ATEPreference(Context context) {
super(context);
init(context, null);
}
public ATEPreference(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public ATEPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public ATEPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
setLayoutResource(R.layout.ate_preference_custom_support);
}
}

View file

@ -0,0 +1,47 @@
package code.name.monkey.appthemehelper.common.prefs.supportv7;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.support.v7.preference.PreferenceCategory;
import android.support.v7.preference.PreferenceViewHolder;
import android.util.AttributeSet;
import android.widget.TextView;
import code.name.monkey.appthemehelper.R;
import code.name.monkey.appthemehelper.ThemeStore;
public class ATEPreferenceCategory extends PreferenceCategory {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public ATEPreferenceCategory(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
}
public ATEPreferenceCategory(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
public ATEPreferenceCategory(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public ATEPreferenceCategory(Context context) {
super(context);
init(context, null);
}
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
TextView mTitle = (TextView) holder.itemView;
mTitle.setTextColor(ThemeStore.accentColor(getContext()));
}
private void init(Context context, AttributeSet attrs) {
setLayoutResource(R.layout.ate_preference_category);
}
}

View file

@ -0,0 +1,50 @@
package code.name.monkey.appthemehelper.common.prefs.supportv7;
import android.support.annotation.Nullable;
import android.support.v4.app.DialogFragment;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceFragmentCompat;
import code.name.monkey.appthemehelper.common.prefs.supportv7.dialogs.ATEEditTextPreferenceDialogFragmentCompat;
import code.name.monkey.appthemehelper.common.prefs.supportv7.dialogs.ATEListPreferenceDialogFragmentCompat;
import code.name.monkey.appthemehelper.common.prefs.supportv7.dialogs.ATEPreferenceDialogFragment;
public abstract class ATEPreferenceFragmentCompat extends PreferenceFragmentCompat {
@Override
public void onDisplayPreferenceDialog(Preference preference) {
if (this.getCallbackFragment() instanceof PreferenceFragmentCompat.OnPreferenceDisplayDialogCallback) {
((PreferenceFragmentCompat.OnPreferenceDisplayDialogCallback) this.getCallbackFragment()).onPreferenceDisplayDialog(this, preference);
return;
}
if (this.getActivity() instanceof PreferenceFragmentCompat.OnPreferenceDisplayDialogCallback) {
((PreferenceFragmentCompat.OnPreferenceDisplayDialogCallback) this.getActivity()).onPreferenceDisplayDialog(this, preference);
return;
}
if (this.getFragmentManager().findFragmentByTag("android.support.v7.preference.PreferenceFragment.DIALOG") == null) {
DialogFragment dialogFragment = onCreatePreferenceDialog(preference);
if (dialogFragment != null) {
dialogFragment.setTargetFragment(this, 0);
dialogFragment.show(this.getFragmentManager(), "android.support.v7.preference.PreferenceFragment.DIALOG");
return;
}
}
super.onDisplayPreferenceDialog(preference);
}
@Nullable
public DialogFragment onCreatePreferenceDialog(Preference preference) {
if (preference instanceof ATEEditTextPreference) {
return ATEEditTextPreferenceDialogFragmentCompat.newInstance(preference.getKey());
} else if (preference instanceof ATEListPreference) {
return ATEListPreferenceDialogFragmentCompat.newInstance(preference.getKey());
} else if (preference instanceof ATEDialogPreference) {
return ATEPreferenceDialogFragment.newInstance(preference.getKey());
}
return null;
}
}

View file

@ -0,0 +1,41 @@
package code.name.monkey.appthemehelper.common.prefs.supportv7;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.support.v7.preference.CheckBoxPreference;
import android.util.AttributeSet;
import code.name.monkey.appthemehelper.R;
/**
* @author Aidan Follestad (afollestad)
*/
public class ATESwitchPreference extends CheckBoxPreference {
public ATESwitchPreference(Context context) {
super(context);
init(context, null);
}
public ATESwitchPreference(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public ATESwitchPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public ATESwitchPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
setLayoutResource(R.layout.ate_preference_custom_support);
setWidgetLayoutResource(R.layout.ate_preference_switch_support);
}
}

View file

@ -0,0 +1,50 @@
package code.name.monkey.appthemehelper.common.prefs.supportv7.dialogs;
import android.os.Bundle;
import android.support.annotation.NonNull;
import com.afollestad.materialdialogs.MaterialDialog;
import code.name.monkey.appthemehelper.common.prefs.supportv7.ATEEditTextPreference;
public class ATEEditTextPreferenceDialogFragmentCompat extends ATEPreferenceDialogFragment implements MaterialDialog.InputCallback {
private CharSequence input;
public static ATEEditTextPreferenceDialogFragmentCompat newInstance(String key) {
ATEEditTextPreferenceDialogFragmentCompat fragment = new ATEEditTextPreferenceDialogFragmentCompat();
Bundle b = new Bundle(1);
b.putString(ARG_KEY, key);
fragment.setArguments(b);
return fragment;
}
private ATEEditTextPreference getEditTextPreference() {
return (ATEEditTextPreference) getPreference();
}
@Override
protected void onPrepareDialogBuilder(MaterialDialog.Builder builder) {
super.onPrepareDialogBuilder(builder);
builder.input("", getEditTextPreference().getText(), this);
}
protected boolean needInputMethod() {
return true;
}
public void onDialogClosed(boolean positiveResult) {
if (positiveResult) {
String value = input.toString();
if (this.getEditTextPreference().callChangeListener(value)) {
this.getEditTextPreference().setText(value);
}
}
}
@Override
public void onInput(@NonNull MaterialDialog dialog, CharSequence input) {
this.input = input;
}
}

View file

@ -0,0 +1,72 @@
package code.name.monkey.appthemehelper.common.prefs.supportv7.dialogs;
import android.os.Bundle;
import android.support.v7.preference.ListPreference;
import android.view.View;
import com.afollestad.materialdialogs.DialogAction;
import com.afollestad.materialdialogs.MaterialDialog;
import code.name.monkey.appthemehelper.common.prefs.supportv7.ATEListPreference;
public class ATEListPreferenceDialogFragmentCompat extends ATEPreferenceDialogFragment implements MaterialDialog.ListCallbackSingleChoice {
private int mClickedDialogEntryIndex;
public static ATEListPreferenceDialogFragmentCompat newInstance(String key) {
final ATEListPreferenceDialogFragmentCompat fragment = new ATEListPreferenceDialogFragmentCompat();
final Bundle b = new Bundle(1);
b.putString(ARG_KEY, key);
fragment.setArguments(b);
return fragment;
}
private ATEListPreference getListPreference() {
return (ATEListPreference) getPreference();
}
@Override
protected void onPrepareDialogBuilder(MaterialDialog.Builder builder) {
super.onPrepareDialogBuilder(builder);
final ListPreference preference = getListPreference();
if (preference.getEntries() == null || preference.getEntryValues() == null) {
throw new IllegalStateException(
"ListPreference requires an entries array and an entryValues array.");
}
mClickedDialogEntryIndex = preference.findIndexOfValue(preference.getValue());
builder.items(preference.getEntries())
.alwaysCallSingleChoiceCallback()
.itemsCallbackSingleChoice(mClickedDialogEntryIndex, this);
/*
* The typical interaction for list-based dialogs is to have
* click-on-an-item dismiss the dialog instead of the user having to
* press 'Ok'.
*/
builder.positiveText("");
builder.negativeText("");
builder.neutralText("");
}
@Override
public void onDialogClosed(boolean positiveResult) {
final ListPreference preference = getListPreference();
if (positiveResult && mClickedDialogEntryIndex >= 0 &&
preference.getEntryValues() != null) {
String value = preference.getEntryValues()[mClickedDialogEntryIndex].toString();
if (preference.callChangeListener(value)) {
preference.setValue(value);
}
}
}
@Override
public boolean onSelection(MaterialDialog dialog, View itemView, int which, CharSequence text) {
mClickedDialogEntryIndex = which;
onClick(dialog, DialogAction.POSITIVE);
dismiss();
return true;
}
}

View file

@ -0,0 +1,93 @@
package code.name.monkey.appthemehelper.common.prefs.supportv7.dialogs;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v7.preference.DialogPreference;
import android.view.Window;
import com.afollestad.materialdialogs.DialogAction;
import com.afollestad.materialdialogs.MaterialDialog;
public class ATEPreferenceDialogFragment extends DialogFragment implements MaterialDialog.SingleButtonCallback {
private DialogAction mWhichButtonClicked;
protected static final String ARG_KEY = "key";
private DialogPreference mPreference;
public static ATEPreferenceDialogFragment newInstance(String key) {
ATEPreferenceDialogFragment fragment = new ATEPreferenceDialogFragment();
Bundle b = new Bundle(1);
b.putString(ARG_KEY, key);
fragment.setArguments(b);
return fragment;
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Fragment rawFragment = this.getTargetFragment();
if (!(rawFragment instanceof DialogPreference.TargetFragment)) {
throw new IllegalStateException("Target fragment must implement TargetFragment interface");
} else {
DialogPreference.TargetFragment fragment = (DialogPreference.TargetFragment) rawFragment;
String key = this.getArguments().getString(ARG_KEY);
this.mPreference = (DialogPreference) fragment.findPreference(key);
}
}
@NonNull
public Dialog onCreateDialog(Bundle savedInstanceState) {
FragmentActivity context = this.getActivity();
MaterialDialog.Builder builder = new MaterialDialog.Builder(context)
.title(this.mPreference.getDialogTitle())
.icon(this.mPreference.getDialogIcon())
.onAny(this)
.positiveText(this.mPreference.getPositiveButtonText())
.negativeText(this.mPreference.getNegativeButtonText());
builder.content(this.mPreference.getDialogMessage());
this.onPrepareDialogBuilder(builder);
MaterialDialog dialog = builder.build();
if (this.needInputMethod()) {
this.requestInputMethod(dialog);
}
return dialog;
}
public DialogPreference getPreference() {
return this.mPreference;
}
protected void onPrepareDialogBuilder(MaterialDialog.Builder builder) {
}
protected boolean needInputMethod() {
return false;
}
private void requestInputMethod(Dialog dialog) {
Window window = dialog.getWindow();
window.setSoftInputMode(5);
}
@Override
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
mWhichButtonClicked = which;
}
@Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
onDialogClosed(mWhichButtonClicked == DialogAction.POSITIVE);
}
public void onDialogClosed(boolean positiveResult) {
}
}

View file

@ -0,0 +1,33 @@
package code.name.monkey.appthemehelper.common.views;
import android.content.Context;
import android.support.v7.widget.AppCompatCheckBox;
import android.util.AttributeSet;
import code.name.monkey.appthemehelper.ATH;
import code.name.monkey.appthemehelper.ThemeStore;
/**
* @author Aidan Follestad (afollestad)
*/
public class ATECheckBox extends AppCompatCheckBox {
public ATECheckBox(Context context) {
super(context);
init(context, null);
}
public ATECheckBox(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public ATECheckBox(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
ATH.setTint(this, ThemeStore.accentColor(context));
}
}

View file

@ -0,0 +1,42 @@
package code.name.monkey.appthemehelper.common.views;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
import android.widget.EditText;
import code.name.monkey.appthemehelper.ATH;
import code.name.monkey.appthemehelper.ThemeStore;
/**
* @author Aidan Follestad (afollestad)
*/
public class ATEEditText extends EditText {
public ATEEditText(Context context) {
super(context);
init(context, null);
}
public ATEEditText(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public ATEEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public ATEEditText(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
ATH.setTint(this, ThemeStore.accentColor(context));
setTextColor(ThemeStore.textColorPrimary(context));
}
}

View file

@ -0,0 +1,31 @@
package code.name.monkey.appthemehelper.common.views;
import android.content.Context;
import android.util.AttributeSet;
import code.name.monkey.appthemehelper.ThemeStore;
/**
* @author Aidan Follestad (afollestad)
*/
public class ATEPrimaryTextView extends android.support.v7.widget.AppCompatTextView {
public ATEPrimaryTextView(Context context) {
super(context);
init(context, null);
}
public ATEPrimaryTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public ATEPrimaryTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
setTextColor(ThemeStore.textColorPrimary(context));
}
}

View file

@ -0,0 +1,41 @@
package code.name.monkey.appthemehelper.common.views;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
import android.widget.ProgressBar;
import code.name.monkey.appthemehelper.ATH;
import code.name.monkey.appthemehelper.ThemeStore;
/**
* @author Aidan Follestad (afollestad)
*/
public class ATEProgressBar extends ProgressBar {
public ATEProgressBar(Context context) {
super(context);
init(context, null);
}
public ATEProgressBar(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public ATEProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public ATEProgressBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
ATH.setTint(this, ThemeStore.accentColor(context));
}
}

View file

@ -0,0 +1,41 @@
package code.name.monkey.appthemehelper.common.views;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
import android.widget.RadioButton;
import code.name.monkey.appthemehelper.ATH;
import code.name.monkey.appthemehelper.ThemeStore;
/**
* @author Aidan Follestad (afollestad)
*/
public class ATERadioButton extends RadioButton {
public ATERadioButton(Context context) {
super(context);
init(context, null);
}
public ATERadioButton(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public ATERadioButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public ATERadioButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
ATH.setTint(this, ThemeStore.accentColor(context));
}
}

View file

@ -0,0 +1,34 @@
package code.name.monkey.appthemehelper.common.views;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
import android.widget.TextView;
import code.name.monkey.appthemehelper.ThemeStore;
/**
* @author Aidan Follestad (afollestad)
*/
public class ATESecondaryTextView extends android.support.v7.widget.AppCompatTextView {
public ATESecondaryTextView(Context context) {
super(context);
init(context, null);
}
public ATESecondaryTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public ATESecondaryTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
setTextColor(ThemeStore.textColorSecondary(context));
}
}

View file

@ -0,0 +1,32 @@
package code.name.monkey.appthemehelper.common.views;
import android.content.Context;
import android.util.AttributeSet;
import code.name.monkey.appthemehelper.ATH;
import code.name.monkey.appthemehelper.ThemeStore;
/**
* @author Aidan Follestad (afollestad)
*/
public class ATESeekBar extends android.support.v7.widget.AppCompatSeekBar {
public ATESeekBar(Context context) {
super(context);
init(context, null);
}
public ATESeekBar(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public ATESeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
ATH.setTint(this, ThemeStore.accentColor(context));
}
}

View file

@ -0,0 +1,39 @@
package code.name.monkey.appthemehelper.common.views;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.Switch;
import code.name.monkey.appthemehelper.ATH;
import code.name.monkey.appthemehelper.ThemeStore;
/**
* @author Aidan Follestad (afollestad)
*/
public class ATEStockSwitch extends Switch {
public ATEStockSwitch(Context context) {
super(context);
init(context, null);
}
public ATEStockSwitch(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public ATEStockSwitch(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
ATH.setTint(this, ThemeStore.accentColor(context));
}
@Override
public boolean isShown() {
return getParent() != null && getVisibility() == View.VISIBLE;
}
}

View file

@ -0,0 +1,39 @@
package code.name.monkey.appthemehelper.common.views;
import android.content.Context;
import android.support.v7.widget.SwitchCompat;
import android.util.AttributeSet;
import android.view.View;
import code.name.monkey.appthemehelper.ATH;
import code.name.monkey.appthemehelper.ThemeStore;
/**
* @author Aidan Follestad (afollestad)
*/
public class ATESwitch extends SwitchCompat {
public ATESwitch(Context context) {
super(context);
init(context, null);
}
public ATESwitch(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public ATESwitch(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
ATH.setTint(this, ThemeStore.accentColor(context));
}
@Override
public boolean isShown() {
return getParent() != null && getVisibility() == View.VISIBLE;
}
}

View file

@ -0,0 +1,50 @@
package code.name.monkey.appthemehelper.util;
import android.content.Context;
import android.content.res.TypedArray;
import android.support.annotation.AttrRes;
import android.support.annotation.NonNull;
import code.name.monkey.appthemehelper.util.ColorUtil;
/**
* @author Aidan Follestad (afollestad)
*/
public final class ATHUtil {
public static boolean isWindowBackgroundDark(Context context) {
return !ColorUtil.isColorLight(ATHUtil.resolveColor(context, android.R.attr.windowBackground));
}
public static int resolveColor(Context context, @AttrRes int attr) {
return resolveColor(context, attr, 0);
}
public static int resolveColor(Context context, @AttrRes int attr, int fallback) {
TypedArray a = context.getTheme().obtainStyledAttributes(new int[]{attr});
try {
return a.getColor(0, fallback);
} finally {
a.recycle();
}
}
public static boolean isInClassPath(@NonNull String clsName) {
try {
return inClassPath(clsName) != null;
} catch (Throwable t) {
return false;
}
}
public static Class<?> inClassPath(@NonNull String clsName) {
try {
return Class.forName(clsName);
} catch (Throwable t) {
throw new IllegalStateException(String.format("%s is not in your class path! You must include the associated library.", clsName));
}
}
private ATHUtil() {
}
}

View file

@ -0,0 +1,77 @@
package code.name.monkey.appthemehelper.util;
import android.graphics.Color;
import android.support.annotation.ColorInt;
import android.support.annotation.FloatRange;
public final class ColorUtil {
public static int stripAlpha(@ColorInt int color) {
return 0xff000000 | color;
}
@ColorInt
public static int shiftColor(@ColorInt int color, @FloatRange(from = 0.0f, to = 2.0f) float by) {
if (by == 1f) return color;
int alpha = Color.alpha(color);
float[] hsv = new float[3];
Color.colorToHSV(color, hsv);
hsv[2] *= by; // value component
return (alpha << 24) + (0x00ffffff & Color.HSVToColor(hsv));
}
@ColorInt
public static int darkenColor(@ColorInt int color) {
return shiftColor(color, 0.9f);
}
@ColorInt
public static int lightenColor(@ColorInt int color) {
return shiftColor(color, 1.1f);
}
public static boolean isColorLight(@ColorInt int color) {
final double darkness = 1 - (0.299 * Color.red(color) + 0.587 * Color.green(color) + 0.114 * Color.blue(color)) / 255;
return darkness < 0.4;
}
@ColorInt
public static int invertColor(@ColorInt int color) {
final int r = 255 - Color.red(color);
final int g = 255 - Color.green(color);
final int b = 255 - Color.blue(color);
return Color.argb(Color.alpha(color), r, g, b);
}
@ColorInt
public static int adjustAlpha(@ColorInt int color, @FloatRange(from = 0.0, to = 1.0) float factor) {
int alpha = Math.round(Color.alpha(color) * factor);
int red = Color.red(color);
int green = Color.green(color);
int blue = Color.blue(color);
return Color.argb(alpha, red, green, blue);
}
@ColorInt
public static int withAlpha(@ColorInt int baseColor, @FloatRange(from = 0.0, to = 1.0) float alpha) {
int a = Math.min(255, Math.max(0, (int) (alpha * 255))) << 24;
int rgb = 0x00ffffff & baseColor;
return a + rgb;
}
/**
* Taken from CollapsingToolbarLayout's CollapsingTextHelper class.
*/
public static int blendColors(int color1, int color2, @FloatRange(from = 0.0, to = 1.0) float ratio) {
final float inverseRatio = 1f - ratio;
float a = (Color.alpha(color1) * inverseRatio) + (Color.alpha(color2) * ratio);
float r = (Color.red(color1) * inverseRatio) + (Color.red(color2) * ratio);
float g = (Color.green(color1) * inverseRatio) + (Color.green(color2) * ratio);
float b = (Color.blue(color1) * inverseRatio) + (Color.blue(color2) * ratio);
return Color.argb((int) a, (int) r, (int) g, (int) b);
}
private ColorUtil() {
}
}

View file

@ -0,0 +1,26 @@
package code.name.monkey.appthemehelper.util;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.TransitionDrawable;
import android.support.annotation.ColorInt;
public final class DrawableUtil {
public static TransitionDrawable createTransitionDrawable(@ColorInt int startColor, @ColorInt int endColor) {
return createTransitionDrawable(new ColorDrawable(startColor), new ColorDrawable(endColor));
}
public static TransitionDrawable createTransitionDrawable(Drawable start, Drawable end) {
final Drawable[] drawables = new Drawable[2];
drawables[0] = start;
drawables[1] = end;
return new TransitionDrawable(drawables);
}
private DrawableUtil() {
}
}

View file

@ -0,0 +1,334 @@
package code.name.monkey.appthemehelper.util;
import android.annotation.TargetApi;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.view.ViewPager;
import android.support.v4.widget.EdgeEffectCompat;
import android.support.v4.widget.NestedScrollView;
import android.support.v7.widget.RecyclerView;
import android.widget.AbsListView;
import android.widget.EdgeEffect;
import android.widget.ScrollView;
import code.name.monkey.appthemehelper.BuildConfig;
import java.lang.reflect.Field;
public class EdgeGlowUtil {
protected EdgeGlowUtil() {
}
// Invalidation methods
private static Field EDGE_GLOW_FIELD_EDGE;
private static Field EDGE_GLOW_FIELD_GLOW;
private static Field EDGE_EFFECT_COMPAT_FIELD_EDGE_EFFECT;
private static void invalidateEdgeEffectFields() {
if (EDGE_GLOW_FIELD_EDGE != null && EDGE_GLOW_FIELD_GLOW != null &&
EDGE_EFFECT_COMPAT_FIELD_EDGE_EFFECT != null) {
EDGE_GLOW_FIELD_EDGE.setAccessible(true);
EDGE_GLOW_FIELD_GLOW.setAccessible(true);
EDGE_EFFECT_COMPAT_FIELD_EDGE_EFFECT.setAccessible(true);
return;
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
Field edge = null, glow = null;
Class cls = null;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
try {
cls = Class.forName("android.widget.EdgeGlow");
} catch (ClassNotFoundException e) {
if (BuildConfig.DEBUG) e.printStackTrace();
}
} else {
cls = EdgeEffect.class;
}
if (cls != null) {
for (Field f : cls.getDeclaredFields()) {
switch (f.getName()) {
case "mEdge":
f.setAccessible(true);
edge = f;
break;
case "mGlow":
f.setAccessible(true);
glow = f;
break;
}
}
}
EDGE_GLOW_FIELD_EDGE = edge;
EDGE_GLOW_FIELD_GLOW = glow;
} else {
EDGE_GLOW_FIELD_EDGE = null;
EDGE_GLOW_FIELD_GLOW = null;
}
Field efc = null;
try {
efc = EdgeEffectCompat.class.getDeclaredField("mEdgeEffect");
} catch (NoSuchFieldException e) {
if (BuildConfig.DEBUG) e.printStackTrace();
}
EDGE_EFFECT_COMPAT_FIELD_EDGE_EFFECT = efc;
}
private static Field SCROLL_VIEW_FIELD_EDGE_GLOW_TOP;
private static Field SCROLL_VIEW_FIELD_EDGE_GLOW_BOTTOM;
private static void invalidateScrollViewFields() {
if (SCROLL_VIEW_FIELD_EDGE_GLOW_TOP != null && SCROLL_VIEW_FIELD_EDGE_GLOW_BOTTOM != null) {
SCROLL_VIEW_FIELD_EDGE_GLOW_TOP.setAccessible(true);
SCROLL_VIEW_FIELD_EDGE_GLOW_BOTTOM.setAccessible(true);
return;
}
final Class<?> cls = ScrollView.class;
for (Field f : cls.getDeclaredFields()) {
switch (f.getName()) {
case "mEdgeGlowTop":
f.setAccessible(true);
SCROLL_VIEW_FIELD_EDGE_GLOW_TOP = f;
break;
case "mEdgeGlowBottom":
f.setAccessible(true);
SCROLL_VIEW_FIELD_EDGE_GLOW_BOTTOM = f;
break;
}
}
}
private static Field NESTED_SCROLL_VIEW_FIELD_EDGE_GLOW_TOP;
private static Field NESTED_SCROLL_VIEW_FIELD_EDGE_GLOW_BOTTOM;
private static void invalidateNestedScrollViewFields() {
if (NESTED_SCROLL_VIEW_FIELD_EDGE_GLOW_TOP != null && NESTED_SCROLL_VIEW_FIELD_EDGE_GLOW_BOTTOM != null) {
NESTED_SCROLL_VIEW_FIELD_EDGE_GLOW_TOP.setAccessible(true);
NESTED_SCROLL_VIEW_FIELD_EDGE_GLOW_BOTTOM.setAccessible(true);
return;
}
final Class<?> cls = ATHUtil.inClassPath("android.support.v4.widget.NestedScrollView");
for (Field f : cls.getDeclaredFields()) {
switch (f.getName()) {
case "mEdgeGlowTop":
f.setAccessible(true);
NESTED_SCROLL_VIEW_FIELD_EDGE_GLOW_TOP = f;
break;
case "mEdgeGlowBottom":
f.setAccessible(true);
NESTED_SCROLL_VIEW_FIELD_EDGE_GLOW_BOTTOM = f;
break;
}
}
}
private static Field LIST_VIEW_FIELD_EDGE_GLOW_TOP;
private static Field LIST_VIEW_FIELD_EDGE_GLOW_BOTTOM;
private static void invalidateListViewFields() {
if (LIST_VIEW_FIELD_EDGE_GLOW_TOP != null && LIST_VIEW_FIELD_EDGE_GLOW_BOTTOM != null) {
LIST_VIEW_FIELD_EDGE_GLOW_TOP.setAccessible(true);
LIST_VIEW_FIELD_EDGE_GLOW_BOTTOM.setAccessible(true);
return;
}
final Class<?> cls = AbsListView.class;
for (Field f : cls.getDeclaredFields()) {
switch (f.getName()) {
case "mEdgeGlowTop":
f.setAccessible(true);
LIST_VIEW_FIELD_EDGE_GLOW_TOP = f;
break;
case "mEdgeGlowBottom":
f.setAccessible(true);
LIST_VIEW_FIELD_EDGE_GLOW_BOTTOM = f;
break;
}
}
}
private static Field RECYCLER_VIEW_FIELD_EDGE_GLOW_TOP;
private static Field RECYCLER_VIEW_FIELD_EDGE_GLOW_LEFT;
private static Field RECYCLER_VIEW_FIELD_EDGE_GLOW_RIGHT;
private static Field RECYCLER_VIEW_FIELD_EDGE_GLOW_BOTTOM;
private static void invalidateRecyclerViewFields() {
if (RECYCLER_VIEW_FIELD_EDGE_GLOW_TOP != null && RECYCLER_VIEW_FIELD_EDGE_GLOW_LEFT != null &&
RECYCLER_VIEW_FIELD_EDGE_GLOW_RIGHT != null && RECYCLER_VIEW_FIELD_EDGE_GLOW_BOTTOM != null) {
RECYCLER_VIEW_FIELD_EDGE_GLOW_TOP.setAccessible(true);
RECYCLER_VIEW_FIELD_EDGE_GLOW_LEFT.setAccessible(true);
RECYCLER_VIEW_FIELD_EDGE_GLOW_RIGHT.setAccessible(true);
RECYCLER_VIEW_FIELD_EDGE_GLOW_BOTTOM.setAccessible(true);
return;
}
final Class<?> cls = ATHUtil.inClassPath("android.support.v7.widget.RecyclerView");
for (Field f : cls.getDeclaredFields()) {
switch (f.getName()) {
case "mTopGlow":
f.setAccessible(true);
RECYCLER_VIEW_FIELD_EDGE_GLOW_TOP = f;
break;
case "mBottomGlow":
f.setAccessible(true);
RECYCLER_VIEW_FIELD_EDGE_GLOW_BOTTOM = f;
break;
case "mLeftGlow":
f.setAccessible(true);
RECYCLER_VIEW_FIELD_EDGE_GLOW_LEFT = f;
break;
case "mRightGlow":
f.setAccessible(true);
RECYCLER_VIEW_FIELD_EDGE_GLOW_RIGHT = f;
break;
}
}
}
private static Field VIEW_PAGER_FIELD_EDGE_GLOW_LEFT;
private static Field VIEW_PAGER_FIELD_EDGE_GLOW_RIGHT;
private static void invalidateViewPagerFields() {
if (VIEW_PAGER_FIELD_EDGE_GLOW_LEFT != null && VIEW_PAGER_FIELD_EDGE_GLOW_RIGHT != null) {
VIEW_PAGER_FIELD_EDGE_GLOW_LEFT.setAccessible(true);
VIEW_PAGER_FIELD_EDGE_GLOW_RIGHT.setAccessible(true);
return;
}
final Class<?> cls = ATHUtil.inClassPath("android.support.v4.view.ViewPager");
for (Field f : cls.getDeclaredFields()) {
switch (f.getName()) {
case "mLeftEdge":
f.setAccessible(true);
VIEW_PAGER_FIELD_EDGE_GLOW_LEFT = f;
break;
case "mRightEdge":
f.setAccessible(true);
VIEW_PAGER_FIELD_EDGE_GLOW_RIGHT = f;
break;
}
}
}
// Setter methods
public static void setEdgeGlowColor(@NonNull ScrollView scrollView, @ColorInt int color) {
invalidateScrollViewFields();
try {
Object ee;
ee = SCROLL_VIEW_FIELD_EDGE_GLOW_TOP.get(scrollView);
setEffectColor(ee, color);
ee = SCROLL_VIEW_FIELD_EDGE_GLOW_BOTTOM.get(scrollView);
setEffectColor(ee, color);
} catch (Exception ex) {
if (BuildConfig.DEBUG) ex.printStackTrace();
}
}
public static void setEdgeGlowColor(@NonNull NestedScrollView scrollView, @ColorInt int color) {
invalidateNestedScrollViewFields();
try {
Object ee;
ee = NESTED_SCROLL_VIEW_FIELD_EDGE_GLOW_TOP.get(scrollView);
setEffectColor(ee, color);
ee = NESTED_SCROLL_VIEW_FIELD_EDGE_GLOW_BOTTOM.get(scrollView);
setEffectColor(ee, color);
} catch (Exception ex) {
if (BuildConfig.DEBUG) ex.printStackTrace();
}
}
public static void setEdgeGlowColor(@NonNull AbsListView listView, @ColorInt int color) {
invalidateListViewFields();
try {
Object ee;
ee = LIST_VIEW_FIELD_EDGE_GLOW_TOP.get(listView);
setEffectColor(ee, color);
ee = LIST_VIEW_FIELD_EDGE_GLOW_BOTTOM.get(listView);
setEffectColor(ee, color);
} catch (Exception ex) {
if (BuildConfig.DEBUG) ex.printStackTrace();
}
}
public static void setEdgeGlowColor(@NonNull RecyclerView scrollView, final @ColorInt int color, @Nullable RecyclerView.OnScrollListener scrollListener) {
invalidateRecyclerViewFields();
invalidateRecyclerViewFields();
if (scrollListener == null) {
scrollListener = new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
EdgeGlowUtil.setEdgeGlowColor(recyclerView, color, this);
}
};
scrollView.addOnScrollListener(scrollListener);
}
try {
Object ee;
ee = RECYCLER_VIEW_FIELD_EDGE_GLOW_TOP.get(scrollView);
setEffectColor(ee, color);
ee = RECYCLER_VIEW_FIELD_EDGE_GLOW_BOTTOM.get(scrollView);
setEffectColor(ee, color);
ee = RECYCLER_VIEW_FIELD_EDGE_GLOW_LEFT.get(scrollView);
setEffectColor(ee, color);
ee = RECYCLER_VIEW_FIELD_EDGE_GLOW_RIGHT.get(scrollView);
setEffectColor(ee, color);
} catch (Exception ex) {
if (BuildConfig.DEBUG) ex.printStackTrace();
}
}
public static void setEdgeGlowColor(@NonNull ViewPager pager, @ColorInt int color) {
invalidateViewPagerFields();
try {
Object ee;
ee = VIEW_PAGER_FIELD_EDGE_GLOW_LEFT.get(pager);
setEffectColor(ee, color);
ee = VIEW_PAGER_FIELD_EDGE_GLOW_RIGHT.get(pager);
setEffectColor(ee, color);
} catch (Exception ex) {
if (BuildConfig.DEBUG) ex.printStackTrace();
}
}
// Utilities
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private static void setEffectColor(Object edgeEffect, @ColorInt int color) {
invalidateEdgeEffectFields();
if (edgeEffect instanceof EdgeEffectCompat) {
// EdgeEffectCompat
try {
EDGE_EFFECT_COMPAT_FIELD_EDGE_EFFECT.setAccessible(true);
edgeEffect = EDGE_EFFECT_COMPAT_FIELD_EDGE_EFFECT.get(edgeEffect);
} catch (IllegalAccessException e) {
e.printStackTrace();
return;
}
}
if (edgeEffect == null)
return;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
// EdgeGlow
try {
EDGE_GLOW_FIELD_EDGE.setAccessible(true);
final Drawable mEdge = (Drawable) EDGE_GLOW_FIELD_EDGE.get(edgeEffect);
EDGE_GLOW_FIELD_GLOW.setAccessible(true);
final Drawable mGlow = (Drawable) EDGE_GLOW_FIELD_GLOW.get(edgeEffect);
mEdge.setColorFilter(color, PorterDuff.Mode.SRC_IN);
mGlow.setColorFilter(color, PorterDuff.Mode.SRC_IN);
mEdge.setCallback(null); // free up any references
mGlow.setCallback(null); // free up any references
} catch (Exception ex) {
ex.printStackTrace();
}
} else {
// EdgeEffect
((EdgeEffect) edgeEffect).setColor(color);
}
}
}

View file

@ -0,0 +1,27 @@
package code.name.monkey.appthemehelper.util;
import android.content.Context;
import android.content.res.ColorStateList;
import com.afollestad.materialdialogs.internal.ThemeSingleton;
import code.name.monkey.appthemehelper.ThemeStore;
public final class MaterialDialogsUtil {
public static void updateMaterialDialogsThemeSingleton(Context context) {
final ThemeSingleton md = ThemeSingleton.get();
md.titleColor = ThemeStore.textColorPrimary(context);
md.contentColor = ThemeStore.textColorSecondary(context);
md.itemColor = md.titleColor;
md.widgetColor = ThemeStore.accentColor(context);
md.linkColor = ColorStateList.valueOf(md.widgetColor);
md.positiveColor = ColorStateList.valueOf(md.widgetColor);
md.neutralColor = ColorStateList.valueOf(md.widgetColor);
md.negativeColor = ColorStateList.valueOf(md.widgetColor);
md.darkTheme = ATHUtil.isWindowBackgroundDark(context);
}
private MaterialDialogsUtil() {
}
}

View file

@ -0,0 +1,51 @@
package code.name.monkey.appthemehelper.util;
import android.annotation.SuppressLint;
import android.content.Context;
import android.support.annotation.ColorInt;
import android.support.v4.content.ContextCompat;
import code.name.monkey.appthemehelper.R;
public final class MaterialValueHelper {
@SuppressLint("PrivateResource")
@ColorInt
public static int getPrimaryTextColor(final Context context, boolean dark) {
if (dark) {
return ContextCompat.getColor(context, R.color.primary_text_default_material_light);
}
return ContextCompat.getColor(context, R.color.primary_text_default_material_dark);
}
@SuppressLint("PrivateResource")
@ColorInt
public static int getSecondaryTextColor(final Context context, boolean dark) {
if (dark) {
return ContextCompat.getColor(context, R.color.secondary_text_default_material_light);
}
return ContextCompat.getColor(context, R.color.secondary_text_default_material_dark);
}
@SuppressLint("PrivateResource")
@ColorInt
public static int getPrimaryDisabledTextColor(final Context context, boolean dark) {
if (dark) {
return ContextCompat.getColor(context, R.color.primary_text_disabled_material_light);
}
return ContextCompat.getColor(context, R.color.primary_text_disabled_material_dark);
}
@SuppressLint("PrivateResource")
@ColorInt
public static int getSecondaryDisabledTextColor(final Context context, boolean dark) {
if (dark) {
return ContextCompat.getColor(context, R.color.secondary_text_disabled_material_light);
}
return ContextCompat.getColor(context, R.color.secondary_text_disabled_material_dark);
}
private MaterialValueHelper() {
}
}

View file

@ -0,0 +1,728 @@
package code.name.monkey.appthemehelper.util;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.os.Build;
import android.support.annotation.ColorInt;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.design.widget.CoordinatorLayout;
import android.support.v4.widget.DrawerLayout;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.LinearLayout;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import code.name.monkey.appthemehelper.R;
/**
* @author Hemanth S (h4h13).
*/
public class StatusBarUtil {
public static final int DEFAULT_STATUS_BAR_ALPHA = 112;
private static final int FAKE_STATUS_BAR_VIEW_ID = R.id.statusbarutil_fake_status_bar_view;
private static final int FAKE_TRANSLUCENT_VIEW_ID = R.id.statusbarutil_translucent_view;
private static final int TAG_KEY_HAVE_SET_OFFSET = -123;
/**
* 设置状态栏颜色
*
* @param activity 需要设置的 activity
* @param color 状态栏颜色值
*/
public static void setColor(Activity activity, @ColorInt int color) {
setColor(activity, color, DEFAULT_STATUS_BAR_ALPHA);
}
/**
* 设置状态栏颜色
*
* @param activity 需要设置的activity
* @param color 状态栏颜色值
* @param statusBarAlpha 状态栏透明度
*/
public static void setColor(Activity activity, @ColorInt int color, @IntRange(from = 0, to = 255) int statusBarAlpha) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
activity.getWindow().setStatusBarColor(calculateStatusColor(color, statusBarAlpha));
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
View fakeStatusBarView = decorView.findViewById(FAKE_STATUS_BAR_VIEW_ID);
if (fakeStatusBarView != null) {
if (fakeStatusBarView.getVisibility() == View.GONE) {
fakeStatusBarView.setVisibility(View.VISIBLE);
}
fakeStatusBarView.setBackgroundColor(calculateStatusColor(color, statusBarAlpha));
} else {
decorView.addView(createStatusBarView(activity, color, statusBarAlpha));
}
setRootView(activity);
}
}
/**
* 为滑动返回界面设置状态栏颜色
*
* @param activity 需要设置的activity
* @param color 状态栏颜色值
*/
public static void setColorForSwipeBack(Activity activity, int color) {
setColorForSwipeBack(activity, color, DEFAULT_STATUS_BAR_ALPHA);
}
/**
* 为滑动返回界面设置状态栏颜色
*
* @param activity 需要设置的activity
* @param color 状态栏颜色值
* @param statusBarAlpha 状态栏透明度
*/
public static void setColorForSwipeBack(Activity activity, @ColorInt int color,
@IntRange(from = 0, to = 255) int statusBarAlpha) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
ViewGroup contentView = ((ViewGroup) activity.findViewById(android.R.id.content));
View rootView = contentView.getChildAt(0);
int statusBarHeight = getStatusBarHeight(activity);
if (rootView != null && rootView instanceof CoordinatorLayout) {
final CoordinatorLayout coordinatorLayout = (CoordinatorLayout) rootView;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
coordinatorLayout.setFitsSystemWindows(false);
contentView.setBackgroundColor(calculateStatusColor(color, statusBarAlpha));
boolean isNeedRequestLayout = contentView.getPaddingTop() < statusBarHeight;
if (isNeedRequestLayout) {
contentView.setPadding(0, statusBarHeight, 0, 0);
coordinatorLayout.post(new Runnable() {
@Override
public void run() {
coordinatorLayout.requestLayout();
}
});
}
} else {
coordinatorLayout.setStatusBarBackgroundColor(calculateStatusColor(color, statusBarAlpha));
}
} else {
contentView.setPadding(0, statusBarHeight, 0, 0);
contentView.setBackgroundColor(calculateStatusColor(color, statusBarAlpha));
}
setTransparentForWindow(activity);
}
}
/**
* 设置状态栏纯色 不加半透明效果
*
* @param activity 需要设置的 activity
* @param color 状态栏颜色值
*/
public static void setColorNoTranslucent(Activity activity, @ColorInt int color) {
setColor(activity, color, 0);
}
/**
* 设置状态栏颜色(5.0以下无半透明效果,不建议使用)
*
* @param activity 需要设置的 activity
* @param color 状态栏颜色值
*/
@Deprecated
public static void setColorDiff(Activity activity, @ColorInt int color) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
return;
}
transparentStatusBar(activity);
ViewGroup contentView = (ViewGroup) activity.findViewById(android.R.id.content);
// 移除半透明矩形,以免叠加
View fakeStatusBarView = contentView.findViewById(FAKE_STATUS_BAR_VIEW_ID);
if (fakeStatusBarView != null) {
if (fakeStatusBarView.getVisibility() == View.GONE) {
fakeStatusBarView.setVisibility(View.VISIBLE);
}
fakeStatusBarView.setBackgroundColor(color);
} else {
contentView.addView(createStatusBarView(activity, color));
}
setRootView(activity);
}
/**
* 使状态栏半透明
* <p>
* 适用于图片作为背景的界面,此时需要图片填充到状态栏
*
* @param activity 需要设置的activity
*/
public static void setTranslucent(Activity activity) {
setTranslucent(activity, DEFAULT_STATUS_BAR_ALPHA);
}
/**
* 使状态栏半透明
* <p>
* 适用于图片作为背景的界面,此时需要图片填充到状态栏
*
* @param activity 需要设置的activity
* @param statusBarAlpha 状态栏透明度
*/
public static void setTranslucent(Activity activity, @IntRange(from = 0, to = 255) int statusBarAlpha) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
return;
}
setTransparent(activity);
addTranslucentView(activity, statusBarAlpha);
}
/**
* 针对根布局是 CoordinatorLayout, 使状态栏半透明
* <p>
* 适用于图片作为背景的界面,此时需要图片填充到状态栏
*
* @param activity 需要设置的activity
* @param statusBarAlpha 状态栏透明度
*/
public static void setTranslucentForCoordinatorLayout(Activity activity, @IntRange(from = 0, to = 255) int statusBarAlpha) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
return;
}
transparentStatusBar(activity);
addTranslucentView(activity, statusBarAlpha);
}
/**
* 设置状态栏全透明
*
* @param activity 需要设置的activity
*/
public static void setTransparent(Activity activity) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
return;
}
transparentStatusBar(activity);
setRootView(activity);
}
/**
* 使状态栏透明(5.0以上半透明效果,不建议使用)
* <p>
* 适用于图片作为背景的界面,此时需要图片填充到状态栏
*
* @param activity 需要设置的activity
*/
@Deprecated
public static void setTranslucentDiff(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
// 设置状态栏透明
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
setRootView(activity);
}
}
/**
* 为DrawerLayout 布局设置状态栏变色
*
* @param activity 需要设置的activity
* @param drawerLayout DrawerLayout
* @param color 状态栏颜色值
*/
public static void setColorForDrawerLayout(Activity activity, DrawerLayout drawerLayout, @ColorInt int color) {
setColorForDrawerLayout(activity, drawerLayout, color, DEFAULT_STATUS_BAR_ALPHA);
}
/**
* 为DrawerLayout 布局设置状态栏颜色,纯色
*
* @param activity 需要设置的activity
* @param drawerLayout DrawerLayout
* @param color 状态栏颜色值
*/
public static void setColorNoTranslucentForDrawerLayout(Activity activity, DrawerLayout drawerLayout, @ColorInt int color) {
setColorForDrawerLayout(activity, drawerLayout, color, 0);
}
/**
* 为DrawerLayout 布局设置状态栏变色
*
* @param activity 需要设置的activity
* @param drawerLayout DrawerLayout
* @param color 状态栏颜色值
* @param statusBarAlpha 状态栏透明度
*/
public static void setColorForDrawerLayout(Activity activity, DrawerLayout drawerLayout, @ColorInt int color,
@IntRange(from = 0, to = 255) int statusBarAlpha) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
return;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
} else {
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
// 生成一个状态栏大小的矩形
// 添加 statusBarView 到布局中
ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0);
View fakeStatusBarView = contentLayout.findViewById(FAKE_STATUS_BAR_VIEW_ID);
if (fakeStatusBarView != null) {
if (fakeStatusBarView.getVisibility() == View.GONE) {
fakeStatusBarView.setVisibility(View.VISIBLE);
}
fakeStatusBarView.setBackgroundColor(color);
} else {
contentLayout.addView(createStatusBarView(activity, color), 0);
}
// 内容布局不是 LinearLayout ,设置padding top
if (!(contentLayout instanceof LinearLayout) && contentLayout.getChildAt(1) != null) {
contentLayout.getChildAt(1)
.setPadding(contentLayout.getPaddingLeft(), getStatusBarHeight(activity) + contentLayout.getPaddingTop(),
contentLayout.getPaddingRight(), contentLayout.getPaddingBottom());
}
// 设置属性
setDrawerLayoutProperty(drawerLayout, contentLayout);
addTranslucentView(activity, statusBarAlpha);
}
/**
* 设置 DrawerLayout 属性
*
* @param drawerLayout DrawerLayout
* @param drawerLayoutContentLayout DrawerLayout 的内容布局
*/
private static void setDrawerLayoutProperty(DrawerLayout drawerLayout, ViewGroup drawerLayoutContentLayout) {
ViewGroup drawer = (ViewGroup) drawerLayout.getChildAt(1);
drawerLayout.setFitsSystemWindows(false);
drawerLayoutContentLayout.setFitsSystemWindows(false);
drawerLayoutContentLayout.setClipToPadding(true);
drawer.setFitsSystemWindows(false);
}
/**
* 为DrawerLayout 布局设置状态栏变色(5.0以下无半透明效果,不建议使用)
*
* @param activity 需要设置的activity
* @param drawerLayout DrawerLayout
* @param color 状态栏颜色值
*/
@Deprecated
public static void setColorForDrawerLayoutDiff(Activity activity, DrawerLayout drawerLayout, @ColorInt int color) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
// 生成一个状态栏大小的矩形
ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0);
View fakeStatusBarView = contentLayout.findViewById(FAKE_STATUS_BAR_VIEW_ID);
if (fakeStatusBarView != null) {
if (fakeStatusBarView.getVisibility() == View.GONE) {
fakeStatusBarView.setVisibility(View.VISIBLE);
}
fakeStatusBarView.setBackgroundColor(calculateStatusColor(color, DEFAULT_STATUS_BAR_ALPHA));
} else {
// 添加 statusBarView 到布局中
contentLayout.addView(createStatusBarView(activity, color), 0);
}
// 内容布局不是 LinearLayout ,设置padding top
if (!(contentLayout instanceof LinearLayout) && contentLayout.getChildAt(1) != null) {
contentLayout.getChildAt(1).setPadding(0, getStatusBarHeight(activity), 0, 0);
}
// 设置属性
setDrawerLayoutProperty(drawerLayout, contentLayout);
}
}
/**
* DrawerLayout 布局设置状态栏透明
*
* @param activity 需要设置的activity
* @param drawerLayout DrawerLayout
*/
public static void setTranslucentForDrawerLayout(Activity activity, DrawerLayout drawerLayout) {
setTranslucentForDrawerLayout(activity, drawerLayout, DEFAULT_STATUS_BAR_ALPHA);
}
/**
* DrawerLayout 布局设置状态栏透明
*
* @param activity 需要设置的activity
* @param drawerLayout DrawerLayout
*/
public static void setTranslucentForDrawerLayout(Activity activity, DrawerLayout drawerLayout,
@IntRange(from = 0, to = 255) int statusBarAlpha) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
return;
}
setTransparentForDrawerLayout(activity, drawerLayout);
addTranslucentView(activity, statusBarAlpha);
}
/**
* DrawerLayout 布局设置状态栏透明
*
* @param activity 需要设置的activity
* @param drawerLayout DrawerLayout
*/
public static void setTransparentForDrawerLayout(Activity activity, DrawerLayout drawerLayout) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
return;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
} else {
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0);
// 内容布局不是 LinearLayout ,设置padding top
if (!(contentLayout instanceof LinearLayout) && contentLayout.getChildAt(1) != null) {
contentLayout.getChildAt(1).setPadding(0, getStatusBarHeight(activity), 0, 0);
}
// 设置属性
setDrawerLayoutProperty(drawerLayout, contentLayout);
}
/**
* DrawerLayout 布局设置状态栏透明(5.0以上半透明效果,不建议使用)
*
* @param activity 需要设置的activity
* @param drawerLayout DrawerLayout
*/
@Deprecated
public static void setTranslucentForDrawerLayoutDiff(Activity activity, DrawerLayout drawerLayout) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
// 设置状态栏透明
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
// 设置内容布局属性
ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0);
contentLayout.setFitsSystemWindows(true);
contentLayout.setClipToPadding(true);
// 设置抽屉布局属性
ViewGroup vg = (ViewGroup) drawerLayout.getChildAt(1);
vg.setFitsSystemWindows(false);
// 设置 DrawerLayout 属性
drawerLayout.setFitsSystemWindows(false);
}
}
/**
* 为头部是 ImageView 的界面设置状态栏全透明
*
* @param activity 需要设置的activity
* @param needOffsetView 需要向下偏移的 View
*/
public static void setTransparentForImageView(Activity activity, View needOffsetView) {
setTranslucentForImageView(activity, 0, needOffsetView);
}
/**
* 为头部是 ImageView 的界面设置状态栏透明(使用默认透明度)
*
* @param activity 需要设置的activity
* @param needOffsetView 需要向下偏移的 View
*/
public static void setTranslucentForImageView(Activity activity, View needOffsetView) {
setTranslucentForImageView(activity, DEFAULT_STATUS_BAR_ALPHA, needOffsetView);
}
/**
* 为头部是 ImageView 的界面设置状态栏透明
*
* @param activity 需要设置的activity
* @param statusBarAlpha 状态栏透明度
* @param needOffsetView 需要向下偏移的 View
*/
public static void setTranslucentForImageView(Activity activity, @IntRange(from = 0, to = 255) int statusBarAlpha,
View needOffsetView) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
return;
}
setTransparentForWindow(activity);
addTranslucentView(activity, statusBarAlpha);
if (needOffsetView != null) {
Object haveSetOffset = needOffsetView.getTag(TAG_KEY_HAVE_SET_OFFSET);
if (haveSetOffset != null && (Boolean) haveSetOffset) {
return;
}
ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) needOffsetView.getLayoutParams();
layoutParams.setMargins(layoutParams.leftMargin, layoutParams.topMargin + getStatusBarHeight(activity),
layoutParams.rightMargin, layoutParams.bottomMargin);
needOffsetView.setTag(TAG_KEY_HAVE_SET_OFFSET, true);
}
}
/**
* fragment 头部是 ImageView 的设置状态栏透明
*
* @param activity fragment 对应的 activity
* @param needOffsetView 需要向下偏移的 View
*/
public static void setTranslucentForImageViewInFragment(Activity activity, View needOffsetView) {
setTranslucentForImageViewInFragment(activity, DEFAULT_STATUS_BAR_ALPHA, needOffsetView);
}
/**
* fragment 头部是 ImageView 的设置状态栏透明
*
* @param activity fragment 对应的 activity
* @param needOffsetView 需要向下偏移的 View
*/
public static void setTransparentForImageViewInFragment(Activity activity, View needOffsetView) {
setTranslucentForImageViewInFragment(activity, 0, needOffsetView);
}
/**
* fragment 头部是 ImageView 的设置状态栏透明
*
* @param activity fragment 对应的 activity
* @param statusBarAlpha 状态栏透明度
* @param needOffsetView 需要向下偏移的 View
*/
public static void setTranslucentForImageViewInFragment(Activity activity, @IntRange(from = 0, to = 255) int statusBarAlpha,
View needOffsetView) {
setTranslucentForImageView(activity, statusBarAlpha, needOffsetView);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
clearPreviousSetting(activity);
}
}
/**
* 隐藏伪状态栏 View
*
* @param activity 调用的 Activity
*/
public static void hideFakeStatusBarView(Activity activity) {
ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
View fakeStatusBarView = decorView.findViewById(FAKE_STATUS_BAR_VIEW_ID);
if (fakeStatusBarView != null) {
fakeStatusBarView.setVisibility(View.GONE);
}
View fakeTranslucentView = decorView.findViewById(FAKE_TRANSLUCENT_VIEW_ID);
if (fakeTranslucentView != null) {
fakeTranslucentView.setVisibility(View.GONE);
}
}
@TargetApi(Build.VERSION_CODES.M)
public static void setLightMode(Activity activity) {
setMIUIStatusBarDarkIcon(activity, true);
setMeizuStatusBarDarkIcon(activity, true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
}
}
@TargetApi(Build.VERSION_CODES.M)
public static void setDarkMode(Activity activity) {
setMIUIStatusBarDarkIcon(activity, false);
setMeizuStatusBarDarkIcon(activity, false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
}
}
/**
* 修改 MIUI V6 以上状态栏颜色
*/
private static void setMIUIStatusBarDarkIcon(@NonNull Activity activity, boolean darkIcon) {
Class<? extends Window> clazz = activity.getWindow().getClass();
try {
Class<?> layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
int darkModeFlag = field.getInt(layoutParams);
Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
extraFlagField.invoke(activity.getWindow(), darkIcon ? darkModeFlag : 0, darkModeFlag);
} catch (Exception e) {
//e.printStackTrace();
}
}
/**
* 修改魅族状态栏字体颜色 Flyme 4.0
*/
private static void setMeizuStatusBarDarkIcon(@NonNull Activity activity, boolean darkIcon) {
try {
WindowManager.LayoutParams lp = activity.getWindow().getAttributes();
Field darkFlag = WindowManager.LayoutParams.class.getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON");
Field meizuFlags = WindowManager.LayoutParams.class.getDeclaredField("meizuFlags");
darkFlag.setAccessible(true);
meizuFlags.setAccessible(true);
int bit = darkFlag.getInt(null);
int value = meizuFlags.getInt(lp);
if (darkIcon) {
value |= bit;
} else {
value &= ~bit;
}
meizuFlags.setInt(lp, value);
activity.getWindow().setAttributes(lp);
} catch (Exception e) {
//e.printStackTrace();
}
}
///////////////////////////////////////////////////////////////////////////////////
@TargetApi(Build.VERSION_CODES.KITKAT)
private static void clearPreviousSetting(Activity activity) {
ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
View fakeStatusBarView = decorView.findViewById(FAKE_STATUS_BAR_VIEW_ID);
if (fakeStatusBarView != null) {
decorView.removeView(fakeStatusBarView);
ViewGroup rootView = (ViewGroup) ((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0);
rootView.setPadding(0, 0, 0, 0);
}
}
/**
* 添加半透明矩形条
*
* @param activity 需要设置的 activity
* @param statusBarAlpha 透明值
*/
private static void addTranslucentView(Activity activity, @IntRange(from = 0, to = 255) int statusBarAlpha) {
ViewGroup contentView = (ViewGroup) activity.findViewById(android.R.id.content);
View fakeTranslucentView = contentView.findViewById(FAKE_TRANSLUCENT_VIEW_ID);
if (fakeTranslucentView != null) {
if (fakeTranslucentView.getVisibility() == View.GONE) {
fakeTranslucentView.setVisibility(View.VISIBLE);
}
fakeTranslucentView.setBackgroundColor(Color.argb(statusBarAlpha, 0, 0, 0));
} else {
contentView.addView(createTranslucentStatusBarView(activity, statusBarAlpha));
}
}
/**
* 生成一个和状态栏大小相同的彩色矩形条
*
* @param activity 需要设置的 activity
* @param color 状态栏颜色值
* @return 状态栏矩形条
*/
private static View createStatusBarView(Activity activity, @ColorInt int color) {
return createStatusBarView(activity, color, 0);
}
/**
* 生成一个和状态栏大小相同的半透明矩形条
*
* @param activity 需要设置的activity
* @param color 状态栏颜色值
* @param alpha 透明值
* @return 状态栏矩形条
*/
private static View createStatusBarView(Activity activity, @ColorInt int color, int alpha) {
// 绘制一个和状态栏一样高的矩形
View statusBarView = new View(activity);
LinearLayout.LayoutParams params =
new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity));
statusBarView.setLayoutParams(params);
statusBarView.setBackgroundColor(calculateStatusColor(color, alpha));
statusBarView.setId(FAKE_STATUS_BAR_VIEW_ID);
return statusBarView;
}
/**
* 设置根布局参数
*/
private static void setRootView(Activity activity) {
ViewGroup parent = (ViewGroup) activity.findViewById(android.R.id.content);
for (int i = 0, count = parent.getChildCount(); i < count; i++) {
View childView = parent.getChildAt(i);
if (childView instanceof ViewGroup) {
childView.setFitsSystemWindows(true);
((ViewGroup) childView).setClipToPadding(true);
}
}
}
/**
* 设置透明
*/
private static void setTransparentForWindow(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
activity.getWindow()
.getDecorView()
.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
activity.getWindow()
.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
}
/**
* 使状态栏透明
*/
@TargetApi(Build.VERSION_CODES.KITKAT)
private static void transparentStatusBar(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
} else {
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
}
/**
* 创建半透明矩形 View
*
* @param alpha 透明值
* @return 半透明 View
*/
private static View createTranslucentStatusBarView(Activity activity, int alpha) {
// 绘制一个和状态栏一样高的矩形
View statusBarView = new View(activity);
LinearLayout.LayoutParams params =
new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity));
statusBarView.setLayoutParams(params);
statusBarView.setBackgroundColor(Color.argb(alpha, 0, 0, 0));
statusBarView.setId(FAKE_TRANSLUCENT_VIEW_ID);
return statusBarView;
}
/**
* 获取状态栏高度
*
* @param context context
* @return 状态栏高度
*/
private static int getStatusBarHeight(Context context) {
// 获得状态栏高度
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
return context.getResources().getDimensionPixelSize(resourceId);
}
/**
* 计算状态栏颜色
*
* @param color color值
* @param alpha alpha值
* @return 最终的状态栏颜色
*/
private static int calculateStatusColor(@ColorInt int color, int alpha) {
if (alpha == 0) {
return color;
}
float a = 1 - alpha / 255f;
int red = color >> 16 & 0xff;
int green = color >> 8 & 0xff;
int blue = color & 0xff;
red = (int) (red * a + 0.5);
green = (int) (green * a + 0.5);
blue = (int) (blue * a + 0.5);
return 0xff << 24 | red << 16 | green << 8 | blue;
}
}

View file

@ -0,0 +1,33 @@
package code.name.monkey.appthemehelper.util;
import android.content.res.ColorStateList;
import android.support.annotation.ColorInt;
import android.support.annotation.Nullable;
import android.support.design.widget.TabLayout;
public final class TabLayoutUtil {
public static void setTabIconColors(@Nullable TabLayout tabLayout, @ColorInt int normalColor, @ColorInt int selectedColor) {
if (tabLayout == null)
return;
final ColorStateList sl = new ColorStateList(new int[][]{
new int[]{-android.R.attr.state_selected},
new int[]{android.R.attr.state_selected}
},
new int[]{
normalColor,
selectedColor
});
for (int i = 0; i < tabLayout.getTabCount(); i++) {
final TabLayout.Tab tab = tabLayout.getTabAt(i);
if (tab != null && tab.getIcon() != null) {
tab.setIcon(TintHelper.createTintedDrawable(tab.getIcon(), sl));
}
}
}
private TabLayoutUtil() {
}
}

View file

@ -0,0 +1,37 @@
package code.name.monkey.appthemehelper.util;
import android.content.res.ColorStateList;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.design.widget.TextInputLayout;
import java.lang.reflect.Field;
/**
* @author Aidan Follestad (afollestad)
*/
public final class TextInputLayoutUtil {
public static void setHint(@NonNull TextInputLayout view, @ColorInt int hintColor) {
try {
final Field mDefaultTextColorField = TextInputLayout.class.getDeclaredField("mDefaultTextColor");
mDefaultTextColorField.setAccessible(true);
mDefaultTextColorField.set(view, ColorStateList.valueOf(hintColor));
} catch (Throwable t) {
throw new RuntimeException("Failed to set TextInputLayout hint (collapsed) color: " + t.getLocalizedMessage(), t);
}
}
public static void setAccent(@NonNull TextInputLayout view, @ColorInt int accentColor) {
try {
final Field mFocusedTextColorField = TextInputLayout.class.getDeclaredField("mFocusedTextColor");
mFocusedTextColorField.setAccessible(true);
mFocusedTextColorField.set(view, ColorStateList.valueOf(accentColor));
} catch (Throwable t) {
throw new RuntimeException("Failed to set TextInputLayout accent (expanded) color: " + t.getLocalizedMessage(), t);
}
}
private TextInputLayoutUtil() {
}
}

View file

@ -0,0 +1,399 @@
package code.name.monkey.appthemehelper.util;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.RippleDrawable;
import android.os.Build;
import android.support.annotation.CheckResult;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.content.ContextCompat;
import android.support.v4.graphics.drawable.DrawableCompat;
import android.support.v7.widget.AppCompatEditText;
import android.support.v7.widget.SwitchCompat;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.RadioButton;
import android.widget.SeekBar;
import android.widget.Switch;
import android.widget.TextView;
import code.name.monkey.appthemehelper.R;
import java.lang.reflect.Field;
/**
* @author afollestad, plusCubed
*/
public final class TintHelper {
@SuppressLint("PrivateResource")
@ColorInt
private static int getDefaultRippleColor(@NonNull Context context, boolean useDarkRipple) {
// Light ripple is actually translucent black, and vice versa
return ContextCompat.getColor(context, useDarkRipple ?
R.color.ripple_material_light : R.color.ripple_material_dark);
}
@NonNull
private static ColorStateList getDisabledColorStateList(@ColorInt int normal, @ColorInt int disabled) {
return new ColorStateList(new int[][]{
new int[]{-android.R.attr.state_enabled},
new int[]{android.R.attr.state_enabled}
}, new int[]{
disabled,
normal
});
}
@SuppressWarnings("deprecation")
public static void setTintSelector(@NonNull View view, @ColorInt final int color, final boolean darker, final boolean useDarkTheme) {
final boolean isColorLight = ColorUtil.isColorLight(color);
final int disabled = ContextCompat.getColor(view.getContext(), useDarkTheme ? R.color.ate_button_disabled_dark : R.color.ate_button_disabled_light);
final int pressed = ColorUtil.shiftColor(color, darker ? 0.9f : 1.1f);
final int activated = ColorUtil.shiftColor(color, darker ? 1.1f : 0.9f);
final int rippleColor = getDefaultRippleColor(view.getContext(), isColorLight);
final int textColor = ContextCompat.getColor(view.getContext(), isColorLight ? R.color.ate_primary_text_light : R.color.ate_primary_text_dark);
final ColorStateList sl;
if (view instanceof Button) {
sl = getDisabledColorStateList(color, disabled);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP &&
view.getBackground() instanceof RippleDrawable) {
RippleDrawable rd = (RippleDrawable) view.getBackground();
rd.setColor(ColorStateList.valueOf(rippleColor));
}
// Disabled text color state for buttons, may get overridden later by ATE tags
final Button button = (Button) view;
button.setTextColor(getDisabledColorStateList(textColor, ContextCompat.getColor(view.getContext(), useDarkTheme ? R.color.ate_button_text_disabled_dark : R.color.ate_button_text_disabled_light)));
} else if (view instanceof FloatingActionButton) {
// FloatingActionButton doesn't support disabled state?
sl = new ColorStateList(new int[][]{
new int[]{-android.R.attr.state_pressed},
new int[]{android.R.attr.state_pressed}
}, new int[]{
color,
pressed
});
final FloatingActionButton fab = (FloatingActionButton) view;
fab.setRippleColor(rippleColor);
fab.setBackgroundTintList(sl);
if (fab.getDrawable() != null)
fab.setImageDrawable(createTintedDrawable(fab.getDrawable(), textColor));
return;
} else {
sl = new ColorStateList(
new int[][]{
new int[]{-android.R.attr.state_enabled},
new int[]{android.R.attr.state_enabled},
new int[]{android.R.attr.state_enabled, android.R.attr.state_pressed},
new int[]{android.R.attr.state_enabled, android.R.attr.state_activated},
new int[]{android.R.attr.state_enabled, android.R.attr.state_checked}
},
new int[]{
disabled,
color,
pressed,
activated,
activated
}
);
}
Drawable drawable = view.getBackground();
if (drawable != null) {
drawable = createTintedDrawable(drawable, sl);
ViewUtil.setBackgroundCompat(view, drawable);
}
if (view instanceof TextView && !(view instanceof Button)) {
final TextView tv = (TextView) view;
tv.setTextColor(getDisabledColorStateList(textColor, ContextCompat.getColor(view.getContext(), isColorLight ? R.color.ate_text_disabled_light : R.color.ate_text_disabled_dark)));
}
}
public static void setTintAuto(final @NonNull View view, final @ColorInt int color,
boolean background) {
setTintAuto(view, color, background, ATHUtil.isWindowBackgroundDark(view.getContext()));
}
@SuppressWarnings("deprecation")
public static void setTintAuto(final @NonNull View view, final @ColorInt int color,
boolean background, final boolean isDark) {
if (!background) {
if (view instanceof RadioButton)
setTint((RadioButton) view, color, isDark);
else if (view instanceof SeekBar)
setTint((SeekBar) view, color, isDark);
else if (view instanceof ProgressBar)
setTint((ProgressBar) view, color);
else if (view instanceof EditText)
setTint((EditText) view, color, isDark);
else if (view instanceof CheckBox)
setTint((CheckBox) view, color, isDark);
else if (view instanceof ImageView)
setTint((ImageView) view, color);
else if (view instanceof Switch)
setTint((Switch) view, color, isDark);
else if (view instanceof SwitchCompat)
setTint((SwitchCompat) view, color, isDark);
else background = true;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP &&
!background && view.getBackground() instanceof RippleDrawable) {
// Ripples for the above views (e.g. when you tap and hold a switch or checkbox)
RippleDrawable rd = (RippleDrawable) view.getBackground();
@SuppressLint("PrivateResource")
final int unchecked = ContextCompat.getColor(view.getContext(),
isDark ? R.color.ripple_material_dark : R.color.ripple_material_light);
final int checked = ColorUtil.adjustAlpha(color, 0.4f);
final ColorStateList sl = new ColorStateList(
new int[][]{
new int[]{-android.R.attr.state_activated, -android.R.attr.state_checked},
new int[]{android.R.attr.state_activated},
new int[]{android.R.attr.state_checked}
},
new int[]{
unchecked,
checked,
checked
}
);
rd.setColor(sl);
}
}
if (background) {
// Need to tint the background of a view
if (view instanceof FloatingActionButton || view instanceof Button) {
setTintSelector(view, color, false, isDark);
} else if (view.getBackground() != null) {
Drawable drawable = view.getBackground();
if (drawable != null) {
drawable = createTintedDrawable(drawable, color);
ViewUtil.setBackgroundCompat(view, drawable);
}
}
}
}
public static void setTint(@NonNull RadioButton radioButton, @ColorInt int color, boolean useDarker) {
ColorStateList sl = new ColorStateList(new int[][]{
new int[]{-android.R.attr.state_enabled},
new int[]{android.R.attr.state_enabled, -android.R.attr.state_checked},
new int[]{android.R.attr.state_enabled, android.R.attr.state_checked}
}, new int[]{
// Rdio button includes own alpha for disabled state
ColorUtil.stripAlpha(ContextCompat.getColor(radioButton.getContext(), useDarker ? R.color.ate_control_disabled_dark : R.color.ate_control_disabled_light)),
ContextCompat.getColor(radioButton.getContext(), useDarker ? R.color.ate_control_normal_dark : R.color.ate_control_normal_light),
color
});
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
radioButton.setButtonTintList(sl);
} else {
Drawable d = createTintedDrawable(ContextCompat.getDrawable(radioButton.getContext(), R.drawable.abc_btn_radio_material), sl);
radioButton.setButtonDrawable(d);
}
}
public static void setTint(@NonNull SeekBar seekBar, @ColorInt int color, boolean useDarker) {
final ColorStateList s1 = getDisabledColorStateList(color,
ContextCompat.getColor(seekBar.getContext(), useDarker ? R.color.ate_control_disabled_dark : R.color.ate_control_disabled_light));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
seekBar.setThumbTintList(s1);
seekBar.setProgressTintList(s1);
} else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.GINGERBREAD_MR1) {
Drawable progressDrawable = createTintedDrawable(seekBar.getProgressDrawable(), s1);
seekBar.setProgressDrawable(progressDrawable);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
Drawable thumbDrawable = createTintedDrawable(seekBar.getThumb(), s1);
seekBar.setThumb(thumbDrawable);
}
} else {
PorterDuff.Mode mode = PorterDuff.Mode.SRC_IN;
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) {
mode = PorterDuff.Mode.MULTIPLY;
}
if (seekBar.getIndeterminateDrawable() != null)
seekBar.getIndeterminateDrawable().setColorFilter(color, mode);
if (seekBar.getProgressDrawable() != null)
seekBar.getProgressDrawable().setColorFilter(color, mode);
}
}
public static void setTint(@NonNull ProgressBar progressBar, @ColorInt int color) {
setTint(progressBar, color, false);
}
public static void setTint(@NonNull ProgressBar progressBar, @ColorInt int color, boolean skipIndeterminate) {
ColorStateList sl = ColorStateList.valueOf(color);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
progressBar.setProgressTintList(sl);
progressBar.setSecondaryProgressTintList(sl);
if (!skipIndeterminate)
progressBar.setIndeterminateTintList(sl);
} else {
PorterDuff.Mode mode = PorterDuff.Mode.SRC_IN;
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) {
mode = PorterDuff.Mode.MULTIPLY;
}
if (!skipIndeterminate && progressBar.getIndeterminateDrawable() != null)
progressBar.getIndeterminateDrawable().setColorFilter(color, mode);
if (progressBar.getProgressDrawable() != null)
progressBar.getProgressDrawable().setColorFilter(color, mode);
}
}
public static void setTint(@NonNull EditText editText, @ColorInt int color, boolean useDarker) {
final ColorStateList editTextColorStateList = new ColorStateList(new int[][]{
new int[]{-android.R.attr.state_enabled},
new int[]{android.R.attr.state_enabled, -android.R.attr.state_pressed, -android.R.attr.state_focused},
new int[]{}
}, new int[]{
ContextCompat.getColor(editText.getContext(), useDarker ? R.color.ate_text_disabled_dark : R.color.ate_text_disabled_light),
ContextCompat.getColor(editText.getContext(), useDarker ? R.color.ate_control_normal_dark : R.color.ate_control_normal_light),
color
});
if (editText instanceof AppCompatEditText) {
((AppCompatEditText) editText).setSupportBackgroundTintList(editTextColorStateList);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
editText.setBackgroundTintList(editTextColorStateList);
}
setCursorTint(editText, color);
}
public static void setTint(@NonNull CheckBox box, @ColorInt int color, boolean useDarker) {
ColorStateList sl = new ColorStateList(new int[][]{
new int[]{-android.R.attr.state_enabled},
new int[]{android.R.attr.state_enabled, -android.R.attr.state_checked},
new int[]{android.R.attr.state_enabled, android.R.attr.state_checked}
}, new int[]{
ContextCompat.getColor(box.getContext(), useDarker ? R.color.ate_control_disabled_dark : R.color.ate_control_disabled_light),
ContextCompat.getColor(box.getContext(), useDarker ? R.color.ate_control_normal_dark : R.color.ate_control_normal_light),
color
});
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
box.setButtonTintList(sl);
} else {
Drawable drawable = createTintedDrawable(ContextCompat.getDrawable(box.getContext(), R.drawable.abc_btn_check_material), sl);
box.setButtonDrawable(drawable);
}
}
public static void setTint(@NonNull ImageView image, @ColorInt int color) {
image.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
}
private static Drawable modifySwitchDrawable(@NonNull Context context, @NonNull Drawable from, @ColorInt int tint, boolean thumb, boolean compatSwitch, boolean useDarker) {
if (useDarker) {
tint = ColorUtil.shiftColor(tint, 1.1f);
}
tint = ColorUtil.adjustAlpha(tint, (compatSwitch && !thumb) ? 0.5f : 1.0f);
int disabled;
int normal;
if (thumb) {
disabled = ContextCompat.getColor(context, useDarker ? R.color.ate_switch_thumb_disabled_dark : R.color.ate_switch_thumb_disabled_light);
normal = ContextCompat.getColor(context, useDarker ? R.color.ate_switch_thumb_normal_dark : R.color.ate_switch_thumb_normal_light);
} else {
disabled = ContextCompat.getColor(context, useDarker ? R.color.ate_switch_track_disabled_dark : R.color.ate_switch_track_disabled_light);
normal = ContextCompat.getColor(context, useDarker ? R.color.ate_switch_track_normal_dark : R.color.ate_switch_track_normal_light);
}
// Stock switch includes its own alpha
if (!compatSwitch) {
normal = ColorUtil.stripAlpha(normal);
}
final ColorStateList sl = new ColorStateList(
new int[][]{
new int[]{-android.R.attr.state_enabled},
new int[]{android.R.attr.state_enabled, -android.R.attr.state_activated, -android.R.attr.state_checked},
new int[]{android.R.attr.state_enabled, android.R.attr.state_activated},
new int[]{android.R.attr.state_enabled, android.R.attr.state_checked}
},
new int[]{
disabled,
normal,
tint,
tint
}
);
return createTintedDrawable(from, sl);
}
public static void setTint(@NonNull Switch switchView, @ColorInt int color, boolean useDarker) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) return;
if (switchView.getTrackDrawable() != null) {
switchView.setTrackDrawable(modifySwitchDrawable(switchView.getContext(),
switchView.getTrackDrawable(), color, false, false, useDarker));
}
if (switchView.getThumbDrawable() != null) {
switchView.setThumbDrawable(modifySwitchDrawable(switchView.getContext(),
switchView.getThumbDrawable(), color, true, false, useDarker));
}
}
public static void setTint(@NonNull SwitchCompat switchView, @ColorInt int color, boolean useDarker) {
if (switchView.getTrackDrawable() != null) {
switchView.setTrackDrawable(modifySwitchDrawable(switchView.getContext(),
switchView.getTrackDrawable(), color, false, true, useDarker));
}
if (switchView.getThumbDrawable() != null) {
switchView.setThumbDrawable(modifySwitchDrawable(switchView.getContext(),
switchView.getThumbDrawable(), color, true, true, useDarker));
}
}
// This returns a NEW Drawable because of the mutate() call. The mutate() call is necessary because Drawables with the same resource have shared states otherwise.
@CheckResult
@Nullable
public static Drawable createTintedDrawable(@Nullable Drawable drawable, @ColorInt int color) {
if (drawable == null) return null;
drawable = DrawableCompat.wrap(drawable.mutate());
DrawableCompat.setTintMode(drawable, PorterDuff.Mode.SRC_IN);
DrawableCompat.setTint(drawable, color);
return drawable;
}
// This returns a NEW Drawable because of the mutate() call. The mutate() call is necessary because Drawables with the same resource have shared states otherwise.
@CheckResult
@Nullable
public static Drawable createTintedDrawable(@Nullable Drawable drawable, @NonNull ColorStateList sl) {
if (drawable == null) return null;
drawable = DrawableCompat.wrap(drawable.mutate());
DrawableCompat.setTintList(drawable, sl);
return drawable;
}
public static void setCursorTint(@NonNull EditText editText, @ColorInt int color) {
try {
Field fCursorDrawableRes = TextView.class.getDeclaredField("mCursorDrawableRes");
fCursorDrawableRes.setAccessible(true);
int mCursorDrawableRes = fCursorDrawableRes.getInt(editText);
Field fEditor = TextView.class.getDeclaredField("mEditor");
fEditor.setAccessible(true);
Object editor = fEditor.get(editText);
Class<?> clazz = editor.getClass();
Field fCursorDrawable = clazz.getDeclaredField("mCursorDrawable");
fCursorDrawable.setAccessible(true);
Drawable[] drawables = new Drawable[2];
drawables[0] = ContextCompat.getDrawable(editText.getContext(), mCursorDrawableRes);
drawables[0] = createTintedDrawable(drawables[0], color);
drawables[1] = ContextCompat.getDrawable(editText.getContext(), mCursorDrawableRes);
drawables[1] = createTintedDrawable(drawables[1], color);
fCursorDrawable.set(editor, drawables);
} catch (Exception e) {
e.printStackTrace();
}
}
}

View file

@ -0,0 +1,551 @@
package code.name.monkey.appthemehelper.util;
import android.app.Activity;
import android.content.Context;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.annotation.CheckResult;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.graphics.drawable.DrawableCompat;
import android.support.v7.app.ActionBar;
import android.support.v7.app.WindowDecorActionBar;
import android.support.v7.view.menu.ActionMenuItemView;
import android.support.v7.view.menu.BaseMenuPresenter;
import android.support.v7.view.menu.ListMenuItemView;
import android.support.v7.view.menu.MenuBuilder;
import android.support.v7.view.menu.MenuPopupHelper;
import android.support.v7.view.menu.MenuPresenter;
import android.support.v7.view.menu.ShowableListMenu;
import android.support.v7.widget.ActionMenuView;
import android.support.v7.widget.AppCompatImageView;
import android.support.v7.widget.Toolbar;
import android.support.v7.widget.ToolbarWidgetWrapper;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.RadioButton;
import code.name.monkey.appthemehelper.R;
import code.name.monkey.appthemehelper.ThemeStore;
import java.lang.reflect.Field;
import java.util.ArrayList;
public final class ToolbarContentTintHelper {
private ToolbarContentTintHelper() {
}
/**
* Use this method to colorize toolbar icons to the desired target color
*
* @param toolbarView toolbar view being colored
* @param toolbarIconsColor the target color of toolbar icons
* @param activity reference to activity needed to register observers
*/
public static void colorizeToolbar(Toolbar toolbarView, int toolbarIconsColor,
Activity activity) {
final PorterDuffColorFilter colorFilter = new PorterDuffColorFilter(toolbarIconsColor,
PorterDuff.Mode.MULTIPLY);
for (int i = 0; i < toolbarView.getChildCount(); i++) {
final View v = toolbarView.getChildAt(i);
//Step 1 : Changing the color of back button (or open drawer button).
if (v instanceof ImageButton) {
//Action Bar back button
((ImageButton) v).getDrawable().setColorFilter(colorFilter);
}
if (v instanceof ActionMenuView) {
for (int j = 0; j < ((ActionMenuView) v).getChildCount(); j++) {
//Step 2: Changing the color of any ActionMenuViews - icons that are not back button, nor text, nor overflow menu icon.
//Colorize the ActionViews -> all icons that are NOT: back button | overflow menu
final View innerView = ((ActionMenuView) v).getChildAt(j);
if (innerView instanceof ActionMenuItemView) {
for (int k = 0; k < ((ActionMenuItemView) innerView).getCompoundDrawables().length;
k++) {
if (((ActionMenuItemView) innerView).getCompoundDrawables()[k] != null) {
final int finalK = k;
//Important to set the color filter in seperate thread, by adding it to the message queue
//Won't work otherwise.
innerView.post(new Runnable() {
@Override
public void run() {
((ActionMenuItemView) innerView).getCompoundDrawables()[finalK]
.setColorFilter(colorFilter);
}
});
}
}
}
}
}
//Step 3: Changing the color of title and subtitle.
toolbarView.setTitleTextColor(ThemeStore.textColorPrimary(activity));
toolbarView.setSubtitleTextColor(ThemeStore.textColorSecondary(activity));
//Step 4: Changing the color of the Overflow Menu icon.
setOverflowButtonColor(activity, toolbarView, toolbarIconsColor);
}
}
/**
* It's important to set overflowDescription atribute in styles, so we can grab the reference to
* the overflow icon. Check: res/values/styles.xml
*/
private static void setOverflowButtonColor(final Activity activity,
final PorterDuffColorFilter colorFilter) {
final String overflowDescription = activity
.getString(R.string.abc_action_menu_overflow_description);
final ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
final ViewTreeObserver viewTreeObserver = decorView.getViewTreeObserver();
viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
final ArrayList<View> outViews = new ArrayList<View>();
decorView.findViewsWithText(outViews, overflowDescription,
View.FIND_VIEWS_WITH_CONTENT_DESCRIPTION);
if (outViews.isEmpty()) {
return;
}
final ActionMenuView overflowViewParent = (ActionMenuView) outViews.get(0).getParent();
overflowViewParent.getOverflowIcon().setColorFilter(colorFilter);
removeOnGlobalLayoutListener(decorView, this);
}
});
}
private static void setOverflowButtonColor(final Activity activity, final Toolbar toolbar,
final int toolbarIconsColor) {
final ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
final ViewTreeObserver viewTreeObserver = decorView.getViewTreeObserver();
viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if (toolbar != null && toolbar.getOverflowIcon() != null) {
Drawable bg = DrawableCompat.wrap(toolbar.getOverflowIcon());
DrawableCompat.setTint(bg, toolbarIconsColor);
}
removeOnGlobalLayoutListener(decorView, this);
}
});
}
private static void removeOnGlobalLayoutListener(View v,
ViewTreeObserver.OnGlobalLayoutListener listener) {
v.getViewTreeObserver().removeOnGlobalLayoutListener(listener);
}
public static void setToolbarContentColorBasedOnToolbarColor(@NonNull Context context,
Toolbar toolbar, int toolbarColor) {
setToolbarContentColorBasedOnToolbarColor(context, toolbar, null, toolbarColor);
}
public static void setToolbarContentColorBasedOnToolbarColor(@NonNull Context context,
Toolbar toolbar, @Nullable Menu menu, int toolbarColor) {
setToolbarContentColorBasedOnToolbarColor(context, toolbar, menu, toolbarColor,
ThemeStore.accentColor(context));
}
public static void setToolbarContentColorBasedOnToolbarColor(@NonNull Context context,
Toolbar toolbar, @Nullable Menu menu, int toolbarColor, final @ColorInt int menuWidgetColor) {
setToolbarContentColor(context, toolbar, menu, toolbarContentColor(context, toolbarColor),
toolbarTitleColor(context, toolbarColor), toolbarSubtitleColor(context, toolbarColor),
menuWidgetColor);
}
public static void setToolbarContentColor(@NonNull Context context, Toolbar toolbar,
final @ColorInt int toolbarContentColor, final @ColorInt int primaryTextColor,
final @ColorInt int secondaryTextColor, final @ColorInt int menuWidgetColor) {
setToolbarContentColor(context, toolbar, null, toolbarContentColor, primaryTextColor,
secondaryTextColor, menuWidgetColor);
}
@SuppressWarnings("unchecked")
public static void setToolbarContentColor(@NonNull Context context, Toolbar toolbar,
@Nullable Menu menu, final @ColorInt int toolbarContentColor,
final @ColorInt int titleTextColor, final @ColorInt int subtitleTextColor,
final @ColorInt int menuWidgetColor) {
if (toolbar == null) {
return;
}
if (menu == null) {
menu = toolbar.getMenu();
}
toolbar.setTitleTextColor(titleTextColor);
toolbar.setSubtitleTextColor(subtitleTextColor);
if (toolbar.getNavigationIcon() != null) {
// Tint the toolbar navigation icon (e.g. back, drawer, etc.)
toolbar.setNavigationIcon(
TintHelper.createTintedDrawable(toolbar.getNavigationIcon(), toolbarContentColor));
}
InternalToolbarContentTintUtil.tintMenu(toolbar, menu, toolbarContentColor);
InternalToolbarContentTintUtil.applyOverflowMenuTint(context, toolbar, menuWidgetColor);
if (context instanceof Activity) {
InternalToolbarContentTintUtil
.setOverflowButtonColor((Activity) context, toolbarContentColor);
}
try {
// Tint immediate overflow menu items
final Field menuField = Toolbar.class.getDeclaredField("mMenuBuilderCallback");
menuField.setAccessible(true);
final Field presenterField = Toolbar.class.getDeclaredField("mActionMenuPresenterCallback");
presenterField.setAccessible(true);
final Field menuViewField = Toolbar.class.getDeclaredField("mMenuView");
menuViewField.setAccessible(true);
final MenuPresenter.Callback currentPresenterCb = (MenuPresenter.Callback) presenterField
.get(toolbar);
if (!(currentPresenterCb instanceof ATHMenuPresenterCallback)) {
final ATHMenuPresenterCallback newPresenterCb = new ATHMenuPresenterCallback(context,
menuWidgetColor, currentPresenterCb, toolbar);
final MenuBuilder.Callback currentMenuCb = (MenuBuilder.Callback) menuField.get(toolbar);
toolbar.setMenuCallbacks(newPresenterCb, currentMenuCb);
ActionMenuView menuView = (ActionMenuView) menuViewField.get(toolbar);
if (menuView != null) {
menuView.setMenuCallbacks(newPresenterCb, currentMenuCb);
}
}
// OnMenuItemClickListener to tint submenu items
final Field menuItemClickListener = Toolbar.class
.getDeclaredField("mOnMenuItemClickListener");
menuItemClickListener.setAccessible(true);
Toolbar.OnMenuItemClickListener currentClickListener = (Toolbar.OnMenuItemClickListener) menuItemClickListener
.get(toolbar);
if (!(currentClickListener instanceof ATHOnMenuItemClickListener)) {
final ATHOnMenuItemClickListener newClickListener = new ATHOnMenuItemClickListener(context,
menuWidgetColor, currentClickListener, toolbar);
toolbar.setOnMenuItemClickListener(newClickListener);
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Nullable
public static Toolbar getSupportActionBarView(@Nullable ActionBar ab) {
if (ab == null || !(ab instanceof WindowDecorActionBar)) {
return null;
}
try {
WindowDecorActionBar decorAb = (WindowDecorActionBar) ab;
Field field = WindowDecorActionBar.class.getDeclaredField("mDecorToolbar");
field.setAccessible(true);
ToolbarWidgetWrapper wrapper = (ToolbarWidgetWrapper) field.get(decorAb);
field = ToolbarWidgetWrapper.class.getDeclaredField("mToolbar");
field.setAccessible(true);
return (Toolbar) field.get(wrapper);
} catch (Throwable t) {
throw new RuntimeException(
"Failed to retrieve Toolbar from AppCompat support ActionBar: " + t.getMessage(), t);
}
}
public static void handleOnPrepareOptionsMenu(Activity activity, Toolbar toolbar) {
handleOnPrepareOptionsMenu(activity, toolbar, ThemeStore.accentColor(activity));
}
public static void handleOnPrepareOptionsMenu(Activity activity, Toolbar toolbar,
int widgetColor) {
InternalToolbarContentTintUtil.applyOverflowMenuTint(activity, toolbar, widgetColor);
}
public static void handleOnCreateOptionsMenu(Context context, Toolbar toolbar, Menu menu,
int toolbarColor) {
setToolbarContentColorBasedOnToolbarColor(context, toolbar, menu, toolbarColor);
}
public static void handleOnCreateOptionsMenu(Context context, Toolbar toolbar, Menu menu,
@ColorInt int toolbarContentColor, @ColorInt int titleTextColor,
@ColorInt int subtitleTextColor, @ColorInt int menuWidgetColor) {
setToolbarContentColor(context, toolbar, menu, toolbarContentColor, titleTextColor,
subtitleTextColor, menuWidgetColor);
}
@CheckResult
@ColorInt
public static int toolbarContentColor(@NonNull Context context, @ColorInt int toolbarColor) {
if (ColorUtil.isColorLight(toolbarColor)) {
return toolbarSubtitleColor(context, toolbarColor);
}
return toolbarTitleColor(context, toolbarColor);
}
@CheckResult
@ColorInt
public static int toolbarSubtitleColor(@NonNull Context context, @ColorInt int toolbarColor) {
return MaterialValueHelper.getSecondaryTextColor(context, ColorUtil.isColorLight(toolbarColor));
}
@CheckResult
@ColorInt
public static int toolbarTitleColor(@NonNull Context context, @ColorInt int toolbarColor) {
return MaterialValueHelper.getPrimaryTextColor(context, ColorUtil.isColorLight(toolbarColor));
}
private static class ATHMenuPresenterCallback implements MenuPresenter.Callback {
private Context mContext;
private int mColor;
private MenuPresenter.Callback mParentCb;
private Toolbar mToolbar;
public ATHMenuPresenterCallback(Context context, final @ColorInt int color,
MenuPresenter.Callback parentCb, Toolbar toolbar) {
mContext = context;
mColor = color;
mParentCb = parentCb;
mToolbar = toolbar;
}
@Override
public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
if (mParentCb != null) {
mParentCb.onCloseMenu(menu, allMenusAreClosing);
}
}
@Override
public boolean onOpenSubMenu(MenuBuilder subMenu) {
InternalToolbarContentTintUtil.applyOverflowMenuTint(mContext, mToolbar, mColor);
return mParentCb != null && mParentCb.onOpenSubMenu(subMenu);
}
}
private static class ATHOnMenuItemClickListener implements Toolbar.OnMenuItemClickListener {
private Context mContext;
private int mColor;
private Toolbar.OnMenuItemClickListener mParentListener;
private Toolbar mToolbar;
public ATHOnMenuItemClickListener(Context context, final @ColorInt int color,
Toolbar.OnMenuItemClickListener parentCb, Toolbar toolbar) {
mContext = context;
mColor = color;
mParentListener = parentCb;
mToolbar = toolbar;
}
@Override
public boolean onMenuItemClick(MenuItem item) {
InternalToolbarContentTintUtil.applyOverflowMenuTint(mContext, mToolbar, mColor);
return mParentListener != null && mParentListener.onMenuItemClick(item);
}
}
public static class InternalToolbarContentTintUtil {
private InternalToolbarContentTintUtil() {
}
@SuppressWarnings("unchecked")
public static void tintMenu(@NonNull Toolbar toolbar, @Nullable Menu menu,
final @ColorInt int color) {
try {
final Field field = Toolbar.class.getDeclaredField("mCollapseIcon");
field.setAccessible(true);
Drawable collapseIcon = (Drawable) field.get(toolbar);
if (collapseIcon != null) {
field.set(toolbar, TintHelper.createTintedDrawable(collapseIcon, color));
}
} catch (Exception e) {
e.printStackTrace();
}
if (menu != null && menu.size() > 0) {
for (int i = 0; i < menu.size(); i++) {
final MenuItem item = menu.getItem(i);
if (item.getIcon() != null) {
item.setIcon(TintHelper.createTintedDrawable(item.getIcon(), color));
}
// Search view theming
if (item.getActionView() != null && (
item.getActionView() instanceof android.widget.SearchView || item
.getActionView() instanceof android.support.v7.widget.SearchView)) {
SearchViewTintUtil.setSearchViewContentColor(item.getActionView(), color);
}
}
}
}
public static void applyOverflowMenuTint(final @NonNull Context context, final Toolbar toolbar,
final @ColorInt int color) {
if (toolbar == null) {
return;
}
toolbar.post(new Runnable() {
@Override
public void run() {
try {
Field f1 = Toolbar.class.getDeclaredField("mMenuView");
f1.setAccessible(true);
ActionMenuView actionMenuView = (ActionMenuView) f1.get(toolbar);
Field f2 = ActionMenuView.class.getDeclaredField("mPresenter");
f2.setAccessible(true);
// Actually ActionMenuPresenter
BaseMenuPresenter presenter = (BaseMenuPresenter) f2.get(actionMenuView);
Field f3 = presenter.getClass().getDeclaredField("mOverflowPopup");
f3.setAccessible(true);
MenuPopupHelper overflowMenuPopupHelper = (MenuPopupHelper) f3.get(presenter);
setTintForMenuPopupHelper(context, overflowMenuPopupHelper, color);
Field f4 = presenter.getClass().getDeclaredField("mActionButtonPopup");
f4.setAccessible(true);
MenuPopupHelper subMenuPopupHelper = (MenuPopupHelper) f4.get(presenter);
setTintForMenuPopupHelper(context, subMenuPopupHelper, color);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public static void setTintForMenuPopupHelper(final @NonNull Context context,
@Nullable MenuPopupHelper menuPopupHelper, final @ColorInt int color) {
try {
if (menuPopupHelper != null) {
final ListView listView = ((ShowableListMenu) menuPopupHelper.getPopup()).getListView();
listView.getViewTreeObserver()
.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
try {
Field checkboxField = ListMenuItemView.class.getDeclaredField("mCheckBox");
checkboxField.setAccessible(true);
Field radioButtonField = ListMenuItemView.class
.getDeclaredField("mRadioButton");
radioButtonField.setAccessible(true);
final boolean isDark = !ColorUtil.isColorLight(
ATHUtil.resolveColor(context, android.R.attr.windowBackground));
for (int i = 0; i < listView.getChildCount(); i++) {
View v = listView.getChildAt(i);
if (!(v instanceof ListMenuItemView)) {
continue;
}
ListMenuItemView iv = (ListMenuItemView) v;
CheckBox check = (CheckBox) checkboxField.get(iv);
if (check != null) {
TintHelper.setTint(check, color, isDark);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
check.setBackground(null);
}
}
RadioButton radioButton = (RadioButton) radioButtonField.get(iv);
if (radioButton != null) {
TintHelper.setTint(radioButton, color, isDark);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
radioButton.setBackground(null);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
listView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
} else {
//noinspection deprecation
listView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
}
});
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void setOverflowButtonColor(@NonNull Activity activity,
final @ColorInt int color) {
final String overflowDescription = activity
.getString(R.string.abc_action_menu_overflow_description);
final ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
final ViewTreeObserver viewTreeObserver = decorView.getViewTreeObserver();
viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
final ArrayList<View> outViews = new ArrayList<>();
decorView.findViewsWithText(outViews, overflowDescription,
View.FIND_VIEWS_WITH_CONTENT_DESCRIPTION);
if (outViews.isEmpty()) {
return;
}
final AppCompatImageView overflow = (AppCompatImageView) outViews.get(0);
overflow.setImageDrawable(TintHelper.createTintedDrawable(overflow.getDrawable(), color));
ViewUtil.removeOnGlobalLayoutListener(decorView, this);
}
});
}
public static final class SearchViewTintUtil {
private SearchViewTintUtil() {
}
private static void tintImageView(Object target, Field field, final @ColorInt int color)
throws Exception {
field.setAccessible(true);
final ImageView imageView = (ImageView) field.get(target);
if (imageView.getDrawable() != null) {
imageView
.setImageDrawable(
TintHelper.createTintedDrawable(imageView.getDrawable(), color));
}
}
public static void setSearchViewContentColor(View searchView, final @ColorInt int color) {
if (searchView == null) {
return;
}
final Class<?> cls = searchView.getClass();
try {
final Field mSearchSrcTextViewField = cls.getDeclaredField("mSearchSrcTextView");
mSearchSrcTextViewField.setAccessible(true);
final EditText mSearchSrcTextView = (EditText) mSearchSrcTextViewField.get(searchView);
mSearchSrcTextView.setTextColor(color);
mSearchSrcTextView.setHintTextColor(ColorUtil.adjustAlpha(color, 0.5f));
TintHelper.setCursorTint(mSearchSrcTextView, color);
Field field = cls.getDeclaredField("mSearchButton");
tintImageView(searchView, field, color);
field = cls.getDeclaredField("mGoButton");
tintImageView(searchView, field, color);
field = cls.getDeclaredField("mCloseButton");
tintImageView(searchView, field, color);
field = cls.getDeclaredField("mVoiceButton");
tintImageView(searchView, field, color);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}

View file

@ -0,0 +1,49 @@
package code.name.monkey.appthemehelper.util;
/**
* @author Aidan Follestad (afollestad)
*/
import android.content.Context;
import android.graphics.Typeface;
import android.support.v4.util.SimpleArrayMap;
/*
Each call to Typeface.createFromAsset will load a new instance of the typeface into memory,
and this memory is not consistently get garbage collected
http://code.google.com/p/android/issues/detail?id=9904
(It states released but even on Lollipop you can see the typefaces accumulate even after
multiple GC passes)
You can detect this by running:
adb shell dumpsys meminfo com.your.packagenage
You will see output like:
Asset Allocations
zip:/data/app/com.your.packagenage-1.apk:/assets/Roboto-Medium.ttf: 125K
zip:/data/app/com.your.packagenage-1.apk:/assets/Roboto-Medium.ttf: 125K
zip:/data/app/com.your.packagenage-1.apk:/assets/Roboto-Medium.ttf: 125K
zip:/data/app/com.your.packagenage-1.apk:/assets/Roboto-Regular.ttf: 123K
zip:/data/app/com.your.packagenage-1.apk:/assets/Roboto-Medium.ttf: 125K
*/
public final class TypefaceHelper {
private static final SimpleArrayMap<String, Typeface> cache = new SimpleArrayMap<>();
public static Typeface get(Context c, String name) {
synchronized (cache) {
if (!cache.containsKey(name)) {
try {
Typeface t = Typeface.createFromAsset(c.getAssets(), name);
cache.put(name, t);
return t;
} catch (RuntimeException e) {
return null;
}
}
return cache.get(name);
}
}
}

View file

@ -0,0 +1,59 @@
package code.name.monkey.appthemehelper.util;
import android.os.Build;
/**
* @author Hemanth S (h4h13).
*/
public final class VersionUtils {
/**
* @return true if device is running API >= 19
*/
public static boolean hasKitKat() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
}
/**
* @return true if device is running API >= 20
*/
public static boolean hasAndroidLPreview() {
return Build.VERSION.SDK_INT >= 20;
}
/**
* @return true if device is running API >= 21
*/
public static boolean hasLollipop() {
return Build.VERSION.SDK_INT >= 21;
}
/**
* @return true if device is running API >= 23
*/
public static boolean hasMarshmallow() {
return Build.VERSION.SDK_INT >= 23;
}
/**
* @return true if device is running API >= 24
*/
public static boolean hasNougat() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N;
}
/**
* @return true if device is running API >= 24
*/
public static boolean hasNougatMR() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1;
}
/**
* @return true if device is running API >= 26
*/
public static boolean hasOreo() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
}
}

View file

@ -0,0 +1,53 @@
package code.name.monkey.appthemehelper.util;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.TransitionDrawable;
import android.os.Build;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.View;
import android.view.ViewTreeObserver;
public final class ViewUtil {
@SuppressWarnings("deprecation")
public static void removeOnGlobalLayoutListener(View v, ViewTreeObserver.OnGlobalLayoutListener listener) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
v.getViewTreeObserver().removeGlobalOnLayoutListener(listener);
} else {
v.getViewTreeObserver().removeOnGlobalLayoutListener(listener);
}
}
@SuppressWarnings("deprecation")
public static void setBackgroundCompat(@NonNull View view, @Nullable Drawable drawable) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
view.setBackground(drawable);
else view.setBackgroundDrawable(drawable);
}
public static TransitionDrawable setBackgroundTransition(@NonNull View view, @NonNull Drawable newDrawable) {
TransitionDrawable transition = DrawableUtil.createTransitionDrawable(view.getBackground(), newDrawable);
setBackgroundCompat(view, transition);
return transition;
}
public static TransitionDrawable setBackgroundColorTransition(@NonNull View view, @ColorInt int newColor) {
final Drawable oldColor = view.getBackground();
Drawable start = oldColor != null ? oldColor : new ColorDrawable(view.getSolidColor());
Drawable end = new ColorDrawable(newColor);
TransitionDrawable transition = DrawableUtil.createTransitionDrawable(start, end);
setBackgroundCompat(view, transition);
return transition;
}
private ViewUtil() {
}
}

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="52dp"
android:height="52dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#fff"
android:pathData="M9,16.2L4.8,12l-1.4,1.4L9,19 21,7l-1.4,-1.4L9,16.2z"/>
</vector>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_toggle_switch_off"
android:state_checked="false"/>
<item android:drawable="@drawable/ic_toggle_switch"
android:state_checked="true"/>
</selector>

View file

@ -0,0 +1,10 @@
<!-- drawable/toggle_switch.xml -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp">
<path
android:fillColor="#000"
android:pathData="M17,7A5,5 0 0,1 22,12A5,5 0 0,1 17,17A5,5 0 0,1 12,12A5,5 0 0,1 17,7M4,14A2,2 0 0,1 2,12A2,2 0 0,1 4,10H10V14H4Z"/>
</vector>

View file

@ -0,0 +1,8 @@
<!-- drawable/toggle_switch_off.xml -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:width="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path android:fillColor="#000" android:pathData="M7,7A5,5 0 0,1 12,12A5,5 0 0,1 7,17A5,5 0 0,1 2,12A5,5 0 0,1 7,7M20,14H14V10H20A2,2 0 0,1 22,12A2,2 0 0,1 20,14M7,9A3,3 0 0,0 4,12A3,3 0 0,0 7,15A3,3 0 0,0 10,12A3,3 0 0,0 7,9Z" />
</vector>

View file

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView android:id="@android:id/title"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingLeft="16dp"
android:paddingStart="16dp"
android:paddingTop="16dp"
android:textAppearance="@style/TextAppearance.AppCompat.Body2"
android:textColor="?android:textColorSecondary"
tools:ignore="RtlSymmetry" />

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<code.name.monkey.appthemehelper.common.views.ATECheckBox android:id="@android:id/checkbox"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@null"
android:layout_margin="6dp"
android:clickable="false"
android:focusable="false" />

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<code.name.monkey.appthemehelper.common.prefs.BorderCircleView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/circle"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_margin="6dp" />

View file

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:baselineAligned="false"
android:gravity="center_vertical"
android:minHeight="?android:attr/listPreferredItemHeight"
android:orientation="horizontal"
android:paddingEnd="?android:attr/scrollbarSize"
android:paddingRight="?android:attr/scrollbarSize"
tools:ignore="RtlSymmetry,UnusedAttribute">
<ImageView
android:id="@+android:id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="@dimen/ate_preference_inset"
android:layout_marginStart="@dimen/ate_preference_inset"
tools:ignore="ContentDescription" />
<RelativeLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="start|center_vertical"
android:layout_marginBottom="12dip"
android:layout_marginEnd="6dip"
android:layout_marginLeft="@dimen/ate_preference_inset"
android:layout_marginRight="6dip"
android:layout_marginStart="@dimen/ate_preference_inset"
android:layout_marginTop="12dip"
android:layout_weight="1">
<code.name.monkey.appthemehelper.common.views.ATEPrimaryTextView
android:id="@android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:ellipsize="marquee"
android:fadingEdge="horizontal"
android:fontFamily="sans-serif"
android:singleLine="true"
android:textSize="@dimen/ate_default_textsize_subheading"
tools:text="Title" />
<code.name.monkey.appthemehelper.common.views.ATESecondaryTextView
android:id="@android:id/summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@android:id/title"
android:layout_alignStart="@android:id/title"
android:layout_below="@android:id/title"
android:layout_marginTop="2dp"
android:fontFamily="sans-serif"
android:maxLines="4"
android:textSize="@dimen/ate_default_textsize_body"
tools:text="Summary" />
</RelativeLayout>
<!-- Preference should place its actual preference widget here. -->
<code.name.monkey.appthemehelper.common.views.ATESwitch xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/switchWidget"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@null"
android:button="@drawable/ate_switch"
android:clickable="false"
android:focusable="false"/>
</LinearLayout><!-- From: file:/home/jitpack/build/commons/src/main/res/layout/md_preference_custom.xml -->

View file

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:baselineAligned="false"
android:gravity="center_vertical"
android:minHeight="?android:attr/listPreferredItemHeight"
android:orientation="horizontal"
android:paddingEnd="?android:attr/scrollbarSize"
android:paddingRight="?android:attr/scrollbarSize"
android:background="?android:attr/selectableItemBackground"
tools:ignore="RtlSymmetry,UnusedAttribute">
<ImageView
android:id="@+android:id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="@dimen/ate_preference_inset"
android:layout_marginStart="@dimen/ate_preference_inset"
tools:ignore="ContentDescription" />
<RelativeLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="start|center_vertical"
android:layout_marginBottom="12dip"
android:layout_marginEnd="6dip"
android:layout_marginLeft="@dimen/ate_preference_inset"
android:layout_marginRight="6dip"
android:layout_marginStart="@dimen/ate_preference_inset"
android:layout_marginTop="12dip"
android:layout_weight="1">
<code.name.monkey.appthemehelper.common.views.ATEPrimaryTextView
android:id="@android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:ellipsize="marquee"
android:fadingEdge="horizontal"
android:fontFamily="sans-serif"
android:singleLine="true"
android:textSize="@dimen/ate_default_textsize_subheading"
tools:text="Title" />
<code.name.monkey.appthemehelper.common.views.ATESecondaryTextView
android:id="@android:id/summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@android:id/title"
android:layout_alignStart="@android:id/title"
android:layout_below="@android:id/title"
android:layout_marginTop="2dp"
android:fontFamily="sans-serif"
android:maxLines="4"
android:textSize="@dimen/ate_default_textsize_body"
tools:text="Summary" />
</RelativeLayout>
<!-- Preference should place its actual preference widget here. -->
<LinearLayout
android:id="@android:id/widget_frame"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="end|center_vertical"
android:gravity="center_vertical"
android:orientation="vertical" />
</LinearLayout><!-- From: file:/home/jitpack/build/commons/src/main/res/layout/md_preference_custom.xml -->

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<code.name.monkey.appthemehelper.common.views.ATESwitch xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/switchWidget"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@null"
android:button="@drawable/ate_switch"
android:clickable="false"
android:focusable="false"/>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<code.name.monkey.appthemehelper.common.views.ATESwitch xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@null"
android:clickable="false"
android:focusable="false"/>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="ate_preference_inset">28dp</dimen>
</resources>

View file

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Preferences -->
<declare-styleable name="ATEPreference">
<attr name="ateKey_pref" format="string" />
</declare-styleable>
<declare-styleable name="ATECheckBoxPreference">
<attr name="ateKey_pref_checkBox" format="string" />
</declare-styleable>
<declare-styleable name="ATESwitchPreference">
<attr name="ateKey_pref_switch" format="string" />
</declare-styleable>
<declare-styleable name="ATEColorPreference">
<attr name="ateKey_pref_color" format="string" />
</declare-styleable>
<declare-styleable name="ATEDialogPreference">
<attr name="ateKey_pref_dialog" format="string" />
</declare-styleable>
<declare-styleable name="ATEEditTextPreference">
<attr name="ateKey_pref_editText" format="string" />
</declare-styleable>
<declare-styleable name="ATEListPreference">
<attr name="ateKey_pref_list" format="string" />
</declare-styleable>
<declare-styleable name="ATEMultiSelectPreference">
<attr name="ateKey_pref_multiSelect" format="string" />
</declare-styleable>
<declare-styleable name="ATEPreferenceCategory">
<attr name="ateKey_prefCategory_textColor" format="string" />
</declare-styleable>
</resources>

View file

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!--"control" means checkbox / radio button-->
<!--LIGHT-->
<!--12%-->
<color name="ate_switch_track_disabled_light">#1F000000</color>
<color name="ate_button_disabled_light">#1F000000</color>
<!-- 26% -->
<color name="ate_control_disabled_light">#43000000</color>
<color name="ate_switch_track_normal_light">#43000000</color>
<color name="ate_button_text_disabled_light">#43000000</color>
<!-- 38% -->
<color name="ate_text_disabled_light">#61000000</color>
<!-- 54% -->
<color name="ate_secondary_text_light">#8A000000</color>
<color name="ate_icon_light">#8A000000</color>
<color name="ate_control_normal_light">#8A000000</color>
<!-- 87% -->
<color name="ate_primary_text_light">#DE000000</color>
<!--Grey 50, #FAFAFA, Opacity 100%-->
<color name="ate_switch_thumb_normal_light">#FFFAFAFA</color>
<!--Grey 400, #BDBDBD, Opacity 100%-->
<color name="ate_switch_thumb_disabled_light">#FFBDBDBD</color>
<!---->
<color name="ate_navigation_drawer_selected_light">#E8E8E8</color>
<!--DARK-->
<!--10%-->
<color name="ate_switch_track_disabled_dark">#1AFFFFFF</color>
<!--12%-->
<color name="ate_button_disabled_dark">#1F000000</color>
<!-- 30% -->
<color name="ate_control_disabled_dark">#4DFFFFFF</color>
<color name="ate_switch_track_normal_dark">#4DFFFFFF</color>
<color name="ate_button_text_disabled_dark">#4DFFFFFF</color>
<color name="ate_text_disabled_dark">#4DFFFFFF</color>
<!-- 70% -->
<color name="ate_secondary_text_dark">#B3FFFFFF</color>
<color name="ate_icon_dark">#B3FFFFFF</color>
<color name="ate_control_normal_dark">#B3FFFFFF</color>
<!-- 100% -->
<color name="ate_primary_text_dark">#FFFFFFFF</color>
<!--Grey 400, #BDBDBD, Opacity 100%-->
<color name="ate_switch_thumb_normal_dark">#FFBDBDBD</color>
<!--Grey 800, #424242, Opacity 100%-->
<color name="ate_switch_thumb_disabled_dark">#FF424242</color>
<!---->
<color name="ate_navigation_drawer_selected_dark">#202020</color>
<color name="black_p50">#7f000000</color>
</resources>

View file

@ -0,0 +1,338 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Google's Material Design colors from
https://www.google.com/design/spec/style/color.html#color-color-palette -->
<!-- Items Light -->
<color name="md_light_background">@color/md_grey_50</color>
<!-- 12% -->
<color name="md_light_dividers">#1F000000</color>
<!-- 38% -->
<color name="md_light_disabled">#61000000</color>
<!-- 54% -->
<color name="md_light_secondary">#8A000000</color>
<color name="md_light_primary_icon">#8A000000</color>
<!-- 87% -->
<color name="md_light_primary_text">#DE000000</color>
<!-- other specifications -->
<color name="md_light_statusbar">@color/md_grey_300</color>
<color name="md_light_appbar">@color/md_grey_100</color>
<color name="md_light_cards">@color/md_white_1000</color>
<color name="md_light_dialogs">@color/md_white_1000</color>
<!-- Items Dark -->
<color name="md_dark_background">@color/md_grey_850</color>
<!-- 12% -->
<color name="md_dark_dividers">#1FFFFFFF</color>
<!-- 30% -->
<color name="md_dark_disabled">#4DFFFFFF</color>
<!-- 70% -->
<color name="md_dark_secondary">#B3FFFFFF</color>
<color name="md_dark_primary_icon">#B3FFFFFF</color>
<!-- 100% -->
<color name="md_dark_primary_text">#FFFFFFFF</color>
<!-- other specifications -->
<color name="md_dark_statusbar">@color/md_black_1000</color>
<color name="md_dark_appbar">@color/md_grey_900</color>
<color name="md_dark_cards">@color/md_grey_800</color>
<color name="md_dark_dialogs">@color/md_grey_800</color>
<!-- Red -->
<color name="md_red_50">#FFEBEE</color>
<color name="md_red_100">#FFCDD2</color>
<color name="md_red_200">#EF9A9A</color>
<color name="md_red_300">#E57373</color>
<color name="md_red_400">#EF5350</color>
<color name="md_red_500">#F44336</color>
<color name="md_red_600">#E53935</color>
<color name="md_red_700">#D32F2F</color>
<color name="md_red_800">#C62828</color>
<color name="md_red_900">#B71C1C</color>
<color name="md_red_A100">#FF8A80</color>
<color name="md_red_A200">#FF5252</color>
<color name="md_red_A400">#FF1744</color>
<color name="md_red_A700">#D50000</color>
<!-- Pink -->
<color name="md_pink_50">#FCE4EC</color>
<color name="md_pink_100">#F8BBD0</color>
<color name="md_pink_200">#F48FB1</color>
<color name="md_pink_300">#F06292</color>
<color name="md_pink_400">#EC407A</color>
<color name="md_pink_500">#E91E63</color>
<color name="md_pink_600">#D81B60</color>
<color name="md_pink_700">#C2185B</color>
<color name="md_pink_800">#AD1457</color>
<color name="md_pink_900">#880E4F</color>
<color name="md_pink_A100">#FF80AB</color>
<color name="md_pink_A200">#FF4081</color>
<color name="md_pink_A400">#F50057</color>
<color name="md_pink_A700">#C51162</color>
<!-- Purple -->
<color name="md_purple_50">#F3E5F5</color>
<color name="md_purple_100">#E1BEE7</color>
<color name="md_purple_200">#CE93D8</color>
<color name="md_purple_300">#BA68C8</color>
<color name="md_purple_400">#AB47BC</color>
<color name="md_purple_500">#9C27B0</color>
<color name="md_purple_600">#8E24AA</color>
<color name="md_purple_700">#7B1FA2</color>
<color name="md_purple_800">#6A1B9A</color>
<color name="md_purple_900">#4A148C</color>
<color name="md_purple_A100">#EA80FC</color>
<color name="md_purple_A200">#E040FB</color>
<color name="md_purple_A400">#D500F9</color>
<color name="md_purple_A700">#AA00FF</color>
<!-- Deep Purple -->
<color name="md_deep_purple_50">#EDE7F6</color>
<color name="md_deep_purple_100">#D1C4E9</color>
<color name="md_deep_purple_200">#B39DDB</color>
<color name="md_deep_purple_300">#9575CD</color>
<color name="md_deep_purple_400">#7E57C2</color>
<color name="md_deep_purple_500">#673AB7</color>
<color name="md_deep_purple_600">#5E35B1</color>
<color name="md_deep_purple_700">#512DA8</color>
<color name="md_deep_purple_800">#4527A0</color>
<color name="md_deep_purple_900">#311B92</color>
<color name="md_deep_purple_A100">#B388FF</color>
<color name="md_deep_purple_A200">#7C4DFF</color>
<color name="md_deep_purple_A400">#651FFF</color>
<color name="md_deep_purple_A700">#6200EA</color>
<!-- Indigo -->
<color name="md_indigo_50">#E8EAF6</color>
<color name="md_indigo_100">#C5CAE9</color>
<color name="md_indigo_200">#9FA8DA</color>
<color name="md_indigo_300">#7986CB</color>
<color name="md_indigo_400">#5C6BC0</color>
<color name="md_indigo_500">#3F51B5</color>
<color name="md_indigo_600">#3949AB</color>
<color name="md_indigo_700">#303F9F</color>
<color name="md_indigo_800">#283593</color>
<color name="md_indigo_900">#1A237E</color>
<color name="md_indigo_A100">#8C9EFF</color>
<color name="md_indigo_A200">#536DFE</color>
<color name="md_indigo_A400">#3D5AFE</color>
<color name="md_indigo_A700">#304FFE</color>
<!-- Blue -->
<color name="md_blue_50">#E3F2FD</color>
<color name="md_blue_100">#BBDEFB</color>
<color name="md_blue_200">#90CAF9</color>
<color name="md_blue_300">#64B5F6</color>
<color name="md_blue_400">#42A5F5</color>
<color name="md_blue_500">#2196F3</color>
<color name="md_blue_600">#1E88E5</color>
<color name="md_blue_700">#1976D2</color>
<color name="md_blue_800">#1565C0</color>
<color name="md_blue_900">#0D47A1</color>
<color name="md_blue_A100">#82B1FF</color>
<color name="md_blue_A200">#448AFF</color>
<color name="md_blue_A400">#2979FF</color>
<color name="md_blue_A700">#2962FF</color>
<!-- Light Blue -->
<color name="md_light_blue_50">#E1F5FE</color>
<color name="md_light_blue_100">#B3E5FC</color>
<color name="md_light_blue_200">#81D4FA</color>
<color name="md_light_blue_300">#4FC3F7</color>
<color name="md_light_blue_400">#29B6F6</color>
<color name="md_light_blue_500">#03A9F4</color>
<color name="md_light_blue_600">#039BE5</color>
<color name="md_light_blue_700">#0288D1</color>
<color name="md_light_blue_800">#0277BD</color>
<color name="md_light_blue_900">#01579B</color>
<color name="md_light_blue_A100">#80D8FF</color>
<color name="md_light_blue_A200">#40C4FF</color>
<color name="md_light_blue_A400">#00B0FF</color>
<color name="md_light_blue_A700">#0091EA</color>
<!-- Cyan -->
<color name="md_cyan_50">#E0F7FA</color>
<color name="md_cyan_100">#B2EBF2</color>
<color name="md_cyan_200">#80DEEA</color>
<color name="md_cyan_300">#4DD0E1</color>
<color name="md_cyan_400">#26C6DA</color>
<color name="md_cyan_500">#00BCD4</color>
<color name="md_cyan_600">#00ACC1</color>
<color name="md_cyan_700">#0097A7</color>
<color name="md_cyan_800">#00838F</color>
<color name="md_cyan_900">#006064</color>
<color name="md_cyan_A100">#84FFFF</color>
<color name="md_cyan_A200">#18FFFF</color>
<color name="md_cyan_A400">#00E5FF</color>
<color name="md_cyan_A700">#00B8D4</color>
<!-- Teal -->
<color name="md_teal_50">#E0F2F1</color>
<color name="md_teal_100">#B2DFDB</color>
<color name="md_teal_200">#80CBC4</color>
<color name="md_teal_300">#4DB6AC</color>
<color name="md_teal_400">#26A69A</color>
<color name="md_teal_500">#009688</color>
<color name="md_teal_600">#00897B</color>
<color name="md_teal_700">#00796B</color>
<color name="md_teal_800">#00695C</color>
<color name="md_teal_900">#004D40</color>
<color name="md_teal_A100">#A7FFEB</color>
<color name="md_teal_A200">#64FFDA</color>
<color name="md_teal_A400">#1DE9B6</color>
<color name="md_teal_A700">#00BFA5</color>
<!-- Green -->
<color name="md_green_50">#E8F5E9</color>
<color name="md_green_100">#C8E6C9</color>
<color name="md_green_200">#A5D6A7</color>
<color name="md_green_300">#81C784</color>
<color name="md_green_400">#66BB6A</color>
<color name="md_green_500">#4CAF50</color>
<color name="md_green_600">#43A047</color>
<color name="md_green_700">#388E3C</color>
<color name="md_green_800">#2E7D32</color>
<color name="md_green_900">#1B5E20</color>
<color name="md_green_A100">#B9F6CA</color>
<color name="md_green_A200">#69F0AE</color>
<color name="md_green_A400">#00E676</color>
<color name="md_green_A700">#00C853</color>
<!-- Light Green -->
<color name="md_light_green_50">#F1F8E9</color>
<color name="md_light_green_100">#DCEDC8</color>
<color name="md_light_green_200">#C5E1A5</color>
<color name="md_light_green_300">#AED581</color>
<color name="md_light_green_400">#9CCC65</color>
<color name="md_light_green_500">#8BC34A</color>
<color name="md_light_green_600">#7CB342</color>
<color name="md_light_green_700">#689F38</color>
<color name="md_light_green_800">#558B2F</color>
<color name="md_light_green_900">#33691E</color>
<color name="md_light_green_A100">#CCFF90</color>
<color name="md_light_green_A200">#B2FF59</color>
<color name="md_light_green_A400">#76FF03</color>
<color name="md_light_green_A700">#64DD17</color>
<!-- Lime -->
<color name="md_lime_50">#F9FBE7</color>
<color name="md_lime_100">#F0F4C3</color>
<color name="md_lime_200">#E6EE9C</color>
<color name="md_lime_300">#DCE775</color>
<color name="md_lime_400">#D4E157</color>
<color name="md_lime_500">#CDDC39</color>
<color name="md_lime_600">#C0CA33</color>
<color name="md_lime_700">#AFB42B</color>
<color name="md_lime_800">#9E9D24</color>
<color name="md_lime_900">#827717</color>
<color name="md_lime_A100">#F4FF81</color>
<color name="md_lime_A200">#EEFF41</color>
<color name="md_lime_A400">#C6FF00</color>
<color name="md_lime_A700">#AEEA00</color>
<!-- Yellow -->
<color name="md_yellow_50">#FFFDE7</color>
<color name="md_yellow_100">#FFF9C4</color>
<color name="md_yellow_200">#FFF59D</color>
<color name="md_yellow_300">#FFF176</color>
<color name="md_yellow_400">#FFEE58</color>
<color name="md_yellow_500">#FFEB3B</color>
<color name="md_yellow_600">#FDD835</color>
<color name="md_yellow_700">#FBC02D</color>
<color name="md_yellow_800">#F9A825</color>
<color name="md_yellow_900">#F57F17</color>
<color name="md_yellow_A100">#FFFF8D</color>
<color name="md_yellow_A200">#FFFF00</color>
<color name="md_yellow_A400">#FFEA00</color>
<color name="md_yellow_A700">#FFD600</color>
<!-- Amber -->
<color name="md_amber_50">#FFF8E1</color>
<color name="md_amber_100">#FFECB3</color>
<color name="md_amber_200">#FFE082</color>
<color name="md_amber_300">#FFD54F</color>
<color name="md_amber_400">#FFCA28</color>
<color name="md_amber_500">#FFC107</color>
<color name="md_amber_600">#FFB300</color>
<color name="md_amber_700">#FFA000</color>
<color name="md_amber_800">#FF8F00</color>
<color name="md_amber_900">#FF6F00</color>
<color name="md_amber_A100">#FFE57F</color>
<color name="md_amber_A200">#FFD740</color>
<color name="md_amber_A400">#FFC400</color>
<color name="md_amber_A700">#FFAB00</color>
<!-- Orange -->
<color name="md_orange_50">#FFF3E0</color>
<color name="md_orange_100">#FFE0B2</color>
<color name="md_orange_200">#FFCC80</color>
<color name="md_orange_300">#FFB74D</color>
<color name="md_orange_400">#FFA726</color>
<color name="md_orange_500">#FF9800</color>
<color name="md_orange_600">#FB8C00</color>
<color name="md_orange_700">#F57C00</color>
<color name="md_orange_800">#EF6C00</color>
<color name="md_orange_900">#E65100</color>
<color name="md_orange_A100">#FFD180</color>
<color name="md_orange_A200">#FFAB40</color>
<color name="md_orange_A400">#FF9100</color>
<color name="md_orange_A700">#FF6D00</color>
<!-- Deep Orange -->
<color name="md_deep_orange_50">#FBE9E7</color>
<color name="md_deep_orange_100">#FFCCBC</color>
<color name="md_deep_orange_200">#FFAB91</color>
<color name="md_deep_orange_300">#FF8A65</color>
<color name="md_deep_orange_400">#FF7043</color>
<color name="md_deep_orange_500">#FF5722</color>
<color name="md_deep_orange_600">#F4511E</color>
<color name="md_deep_orange_700">#E64A19</color>
<color name="md_deep_orange_800">#D84315</color>
<color name="md_deep_orange_900">#BF360C</color>
<color name="md_deep_orange_A100">#FF9E80</color>
<color name="md_deep_orange_A200">#FF6E40</color>
<color name="md_deep_orange_A400">#FF3D00</color>
<color name="md_deep_orange_A700">#DD2C00</color>
<!-- Brown -->
<color name="md_brown_50">#EFEBE9</color>
<color name="md_brown_100">#D7CCC8</color>
<color name="md_brown_200">#BCAAA4</color>
<color name="md_brown_300">#A1887F</color>
<color name="md_brown_400">#8D6E63</color>
<color name="md_brown_500">#795548</color>
<color name="md_brown_600">#6D4C41</color>
<color name="md_brown_700">#5D4037</color>
<color name="md_brown_800">#4E342E</color>
<color name="md_brown_900">#3E2723</color>
<!-- Grey -->
<color name="md_grey_50">#FAFAFA</color>
<color name="md_grey_100">#F5F5F5</color>
<color name="md_grey_200">#EEEEEE</color>
<color name="md_grey_300">#E0E0E0</color>
<color name="md_grey_400">#BDBDBD</color>
<color name="md_grey_500">#9E9E9E</color>
<color name="md_grey_600">#757575</color>
<color name="md_grey_700">#616161</color>
<color name="md_grey_800">#424242</color>
<color name="md_grey_850">#303030</color>
<color name="md_grey_900">#212121</color>
<!-- Blue Grey -->
<color name="md_blue_grey_50">#ECEFF1</color>
<color name="md_blue_grey_100">#CFD8DC</color>
<color name="md_blue_grey_200">#B0BEC5</color>
<color name="md_blue_grey_300">#90A4AE</color>
<color name="md_blue_grey_400">#78909C</color>
<color name="md_blue_grey_500">#607D8B</color>
<color name="md_blue_grey_600">#546E7A</color>
<color name="md_blue_grey_700">#455A64</color>
<color name="md_blue_grey_800">#37474F</color>
<color name="md_blue_grey_900">#263238</color>
<!-- Black & White -->
<color name="md_black_1000">#000000</color>
<color name="md_white_1000">#FFFFFF</color>
</resources>

View file

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="ate_circleview_border">1dp</dimen>
<dimen name="ate_default_textsize_display4">112sp</dimen>
<dimen name="ate_default_textsize_display3">56sp</dimen>
<dimen name="ate_default_textsize_display2">45sp</dimen>
<dimen name="ate_default_textsize_display1">34sp</dimen>
<dimen name="ate_default_textsize_headline">24sp</dimen>
<dimen name="ate_default_textsize_title">20sp</dimen>
<dimen name="ate_default_textsize_subheading">16sp</dimen>
<dimen name="ate_default_textsize_body">14sp</dimen>
<dimen name="ate_default_textsize_caption">12sp</dimen>
<dimen name="ate_preference_inset">16dp</dimen>
</resources>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="statusbarutil_fake_status_bar_view" type="id" />
<item name="statusbarutil_translucent_view" type="id" />
</resources>

View file

@ -0,0 +1,3 @@
<resources>
<string name="app_name">appthemehelper</string>
</resources>

View file

@ -0,0 +1,17 @@
package code.name.monkey.appthemehelper;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() throws Exception {
assertEquals(4, 2 + 2);
}
}