Initial commit retro music app
This commit is contained in:
parent
ab332473bc
commit
fe890632fd
932 changed files with 83126 additions and 0 deletions
|
@ -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());
|
||||
}
|
||||
}
|
1
appthemehelper/src/main/AndroidManifest.xml
Normal file
1
appthemehelper/src/main/AndroidManifest.xml
Normal file
|
@ -0,0 +1 @@
|
|||
<manifest package="code.name.monkey.appthemehelper" />
|
122
appthemehelper/src/main/java/code/name/monkey/appthemehelper/ATH.java
Executable file
122
appthemehelper/src/main/java/code/name/monkey/appthemehelper/ATH.java
Executable 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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
325
appthemehelper/src/main/java/code/name/monkey/appthemehelper/ThemeStore.java
Executable file
325
appthemehelper/src/main/java/code/name/monkey/appthemehelper/ThemeStore.java
Executable 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();
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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";
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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()));
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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) {
|
||||
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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() {
|
||||
}
|
||||
}
|
|
@ -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() {
|
||||
}
|
||||
}
|
|
@ -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() {
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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() {
|
||||
}
|
||||
}
|
|
@ -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() {
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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() {
|
||||
}
|
||||
}
|
|
@ -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() {
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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() {
|
||||
}
|
||||
}
|
9
appthemehelper/src/main/res/drawable/ate_check.xml
Executable file
9
appthemehelper/src/main/res/drawable/ate_check.xml
Executable 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>
|
7
appthemehelper/src/main/res/drawable/ate_switch.xml
Normal file
7
appthemehelper/src/main/res/drawable/ate_switch.xml
Normal 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>
|
10
appthemehelper/src/main/res/drawable/ic_toggle_switch.xml
Normal file
10
appthemehelper/src/main/res/drawable/ic_toggle_switch.xml
Normal 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>
|
|
@ -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>
|
13
appthemehelper/src/main/res/layout/ate_preference_category.xml
Executable file
13
appthemehelper/src/main/res/layout/ate_preference_category.xml
Executable 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" />
|
9
appthemehelper/src/main/res/layout/ate_preference_checkbox.xml
Executable file
9
appthemehelper/src/main/res/layout/ate_preference_checkbox.xml
Executable 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" />
|
6
appthemehelper/src/main/res/layout/ate_preference_color.xml
Executable file
6
appthemehelper/src/main/res/layout/ate_preference_color.xml
Executable 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" />
|
73
appthemehelper/src/main/res/layout/ate_preference_custom.xml
Executable file
73
appthemehelper/src/main/res/layout/ate_preference_custom.xml
Executable 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 -->
|
73
appthemehelper/src/main/res/layout/ate_preference_custom_support.xml
Executable file
73
appthemehelper/src/main/res/layout/ate_preference_custom_support.xml
Executable 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 -->
|
9
appthemehelper/src/main/res/layout/ate_preference_switch.xml
Executable file
9
appthemehelper/src/main/res/layout/ate_preference_switch.xml
Executable 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"/>
|
8
appthemehelper/src/main/res/layout/ate_preference_switch_support.xml
Executable file
8
appthemehelper/src/main/res/layout/ate_preference_switch_support.xml
Executable 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"/>
|
6
appthemehelper/src/main/res/values-large/dimens.xml
Executable file
6
appthemehelper/src/main/res/values-large/dimens.xml
Executable file
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<dimen name="ate_preference_inset">28dp</dimen>
|
||||
|
||||
</resources>
|
42
appthemehelper/src/main/res/values/attrs.xml
Executable file
42
appthemehelper/src/main/res/values/attrs.xml
Executable 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>
|
52
appthemehelper/src/main/res/values/colors.xml
Executable file
52
appthemehelper/src/main/res/values/colors.xml
Executable 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>
|
338
appthemehelper/src/main/res/values/colors_material_design.xml
Executable file
338
appthemehelper/src/main/res/values/colors_material_design.xml
Executable 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>
|
18
appthemehelper/src/main/res/values/dimens.xml
Executable file
18
appthemehelper/src/main/res/values/dimens.xml
Executable 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>
|
5
appthemehelper/src/main/res/values/ids.xml
Normal file
5
appthemehelper/src/main/res/values/ids.xml
Normal 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>
|
3
appthemehelper/src/main/res/values/strings.xml
Normal file
3
appthemehelper/src/main/res/values/strings.xml
Normal file
|
@ -0,0 +1,3 @@
|
|||
<resources>
|
||||
<string name="app_name">appthemehelper</string>
|
||||
</resources>
|
|
@ -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);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue