commit
b9766fa94c
@ -0,0 +1,71 @@ |
||||
package io.legado.app.data.dao |
||||
|
||||
import androidx.paging.DataSource |
||||
import androidx.room.* |
||||
import io.legado.app.data.entities.ExploreSearchUrl |
||||
|
||||
|
||||
@Dao |
||||
interface ExploreSearchUrlDao { |
||||
|
||||
companion object { |
||||
private const val ORDER_DEFAULT = "ORDER BY sourceId ASC, defOrder ASC" |
||||
private const val ORDER_USAGE = "ORDER BY usage DESC, lastUseTime DESC" |
||||
private const val ORDER_TIME = "ORDER BY lastUseTime DESC" |
||||
private const val QUERY_NAME = "name LIKE '%' || :name || '%'" |
||||
private const val QUERY_ENABLED_EXPLORE = "WHERE type = 0 AND isEnabled = 1" |
||||
} |
||||
|
||||
// 用于发现列表,默认排序 |
||||
@Query("SELECT * FROM explore_search_urls $QUERY_ENABLED_EXPLORE $ORDER_DEFAULT") |
||||
fun observeExploreUrls(): DataSource.Factory<Int, ExploreSearchUrl> |
||||
|
||||
// 用于发现列表,按使用次数排序 |
||||
@Query("SELECT * FROM explore_search_urls $QUERY_ENABLED_EXPLORE $ORDER_USAGE") |
||||
fun observeExploreUrlsByUsage(): DataSource.Factory<Int, ExploreSearchUrl> |
||||
|
||||
// 用于发现列表,按使用时间排序 |
||||
@Query("SELECT * FROM explore_search_urls $QUERY_ENABLED_EXPLORE $ORDER_TIME") |
||||
fun observeExploreUrlsByTime(): DataSource.Factory<Int, ExploreSearchUrl> |
||||
|
||||
// 用于搜索时的发现列表,默认排序 |
||||
@Query("SELECT * FROM explore_search_urls $QUERY_ENABLED_EXPLORE AND $QUERY_NAME $ORDER_DEFAULT") |
||||
fun observeFilteredExploreUrls(name: String): DataSource.Factory<Int, ExploreSearchUrl> |
||||
|
||||
// 用于搜索时的发现列表,按使用次数排序 |
||||
@Query("SELECT * FROM explore_search_urls $QUERY_ENABLED_EXPLORE AND $QUERY_NAME $ORDER_USAGE") |
||||
fun observeFilteredExploreUrlsByUsage(): DataSource.Factory<Int, ExploreSearchUrl> |
||||
|
||||
// 用于搜索时的发现列表,按使用时间排序 |
||||
@Query("SELECT * FROM explore_search_urls $QUERY_ENABLED_EXPLORE AND $QUERY_NAME $ORDER_TIME") |
||||
fun observeFilteredExploreUrlsByTime(): DataSource.Factory<Int, ExploreSearchUrl> |
||||
|
||||
// 获取特定书源的发现 |
||||
@Query("SELECT * FROM explore_search_urls $QUERY_ENABLED_EXPLORE AND sourceId = :sourceId") |
||||
fun findExploreUrlsBySourceId(sourceId: Int): List<ExploreSearchUrl> |
||||
|
||||
// 获取特定书源的搜索链接 |
||||
@Query("SELECT * FROM explore_search_urls WHERE type = 1 AND sourceId = :sourceId") |
||||
fun findSearchUrlsBySourceId(sourceId: Int): List<ExploreSearchUrl> |
||||
|
||||
// 所有的搜索链接 |
||||
@get:Query("SELECT * FROM explore_search_urls WHERE type = 1") |
||||
val allSearchUrls: List<ExploreSearchUrl> |
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE) |
||||
fun insert(vararg keywords: ExploreSearchUrl) |
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE) |
||||
fun insert(keyword: ExploreSearchUrl): Long |
||||
|
||||
@Update |
||||
fun update(vararg keywords: ExploreSearchUrl) |
||||
|
||||
@Delete |
||||
fun delete(vararg keywords: ExploreSearchUrl) |
||||
|
||||
// 批量删除特定书源的发现和搜索链接,一般用于更新书源时 |
||||
@Query("DELETE FROM explore_search_urls WHERE sourceId = :sourceId") |
||||
fun deleteBySourceId(sourceId: Int) |
||||
|
||||
} |
@ -0,0 +1,32 @@ |
||||
package io.legado.app.data.dao |
||||
|
||||
import androidx.paging.DataSource |
||||
import androidx.room.* |
||||
import io.legado.app.data.entities.SearchKeyword |
||||
|
||||
|
||||
@Dao |
||||
interface SearchKeywordDao { |
||||
|
||||
@Query("SELECT * FROM search_keywords ORDER BY usage DESC") |
||||
fun observeByUsage(): DataSource.Factory<Int, SearchKeyword> |
||||
|
||||
@Query("SELECT * FROM search_keywords ORDER BY lastUseTime DESC") |
||||
fun observeByTime(): DataSource.Factory<Int, SearchKeyword> |
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE) |
||||
fun insert(vararg keywords: SearchKeyword) |
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE) |
||||
fun insert(keyword: SearchKeyword): Long |
||||
|
||||
@Update |
||||
fun update(vararg keywords: SearchKeyword) |
||||
|
||||
@Delete |
||||
fun delete(vararg keywords: SearchKeyword) |
||||
|
||||
@Query("DELETE FROM search_keywords") |
||||
fun deleteAll() |
||||
|
||||
} |
@ -0,0 +1,29 @@ |
||||
package io.legado.app.data.entities |
||||
|
||||
import android.os.Parcelable |
||||
import androidx.room.Entity |
||||
import androidx.room.ForeignKey |
||||
import androidx.room.Index |
||||
import androidx.room.PrimaryKey |
||||
import kotlinx.android.parcel.Parcelize |
||||
|
||||
@Parcelize |
||||
@Entity(tableName = "explore_search_urls", |
||||
indices = [(Index(value = ["sourceId", "url"], unique = true))], |
||||
foreignKeys = [(ForeignKey(entity = Source::class, |
||||
parentColumns = ["sourceId"], |
||||
childColumns = ["sourceId"], |
||||
onDelete = ForeignKey.CASCADE))]) // 删除书源时自动删除章节 |
||||
data class ExploreSearchUrl ( |
||||
@PrimaryKey(autoGenerate = true) |
||||
var esId: Int = 0, // 编号 |
||||
var sourceId: Int = 0, // 书源Id |
||||
var name: String = "", // 发现名称,搜索可以没有 |
||||
var url: String = "", // 地址 |
||||
var type: Int = 0, // 类型,0 为发现,1 为搜索 |
||||
var isEnabled: Boolean = true, // 是否启用 |
||||
var defOrder: Int = 0, // 默认排序,是在编辑书源的时候的顺序 |
||||
var usage: Int = 0, // 使用次数,用于按使用次数排序 |
||||
var lastUseTime: Long = 0L // 最后一次使用的时间 |
||||
) : Parcelable |
||||
|
@ -0,0 +1,17 @@ |
||||
package io.legado.app.data.entities |
||||
|
||||
import android.os.Parcelable |
||||
import androidx.room.Entity |
||||
import androidx.room.Index |
||||
import androidx.room.PrimaryKey |
||||
import kotlinx.android.parcel.Parcelize |
||||
|
||||
|
||||
@Parcelize |
||||
@Entity(tableName = "search_keywords", indices = [(Index(value = ["word"], unique = true))]) |
||||
data class SearchKeyword ( |
||||
@PrimaryKey |
||||
var word: String = "", // 搜索关键词 |
||||
var usage: Int = 1, // 使用次数 |
||||
var lastUseTime: Long = 0 // 最后一次使用时间 |
||||
): Parcelable |
@ -0,0 +1,117 @@ |
||||
package io.legado.app.lib.theme; |
||||
|
||||
import android.annotation.SuppressLint; |
||||
import android.app.Activity; |
||||
import android.app.ActivityManager; |
||||
import android.content.Context; |
||||
import android.content.res.ColorStateList; |
||||
import android.os.Build; |
||||
import android.view.View; |
||||
import androidx.annotation.ColorInt; |
||||
import androidx.annotation.NonNull; |
||||
import androidx.appcompat.app.AlertDialog; |
||||
|
||||
import static android.view.View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR; |
||||
|
||||
/** |
||||
* @author Karim Abou Zeid (kabouzeid) |
||||
*/ |
||||
public final class 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 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); |
||||
} |
||||
|
||||
public static void setAlertDialogTint(@NonNull AlertDialog dialog) { |
||||
ColorStateList colorStateList = Selector.colorBuild() |
||||
.setDefaultColor(ThemeStore.accentColor(dialog.getContext())) |
||||
.setPressedColor(ColorUtil.darkenColor(ThemeStore.accentColor(dialog.getContext()))) |
||||
.create(); |
||||
if (dialog.getButton(androidx.appcompat.app.AlertDialog.BUTTON_NEGATIVE) != null) { |
||||
dialog.getButton(androidx.appcompat.app.AlertDialog.BUTTON_NEGATIVE).setTextColor(colorStateList); |
||||
} |
||||
if (dialog.getButton(androidx.appcompat.app.AlertDialog.BUTTON_POSITIVE) != null) { |
||||
dialog.getButton(androidx.appcompat.app.AlertDialog.BUTTON_POSITIVE).setTextColor(colorStateList); |
||||
} |
||||
} |
||||
|
||||
private ATH() { |
||||
} |
||||
} |
@ -0,0 +1,31 @@ |
||||
package io.legado.app.lib.theme; |
||||
|
||||
import android.content.Context; |
||||
import android.content.res.TypedArray; |
||||
import androidx.annotation.AttrRes; |
||||
|
||||
/** |
||||
* @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(); |
||||
} |
||||
} |
||||
|
||||
private ATHUtil() { |
||||
} |
||||
} |
@ -0,0 +1,80 @@ |
||||
package io.legado.app.lib.theme; |
||||
|
||||
import android.graphics.Color; |
||||
import androidx.annotation.ColorInt; |
||||
import androidx.annotation.FloatRange; |
||||
|
||||
@SuppressWarnings({"unused", "WeakerAccess"}) |
||||
public class ColorUtil { |
||||
|
||||
public static String intToString(int intColor) { |
||||
return String.format("#%06X", 0xFFFFFF & intColor); |
||||
} |
||||
|
||||
|
||||
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); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,28 @@ |
||||
package io.legado.app.lib.theme; |
||||
|
||||
import android.graphics.drawable.ColorDrawable; |
||||
import android.graphics.drawable.Drawable; |
||||
import android.graphics.drawable.TransitionDrawable; |
||||
import androidx.annotation.ColorInt; |
||||
|
||||
/** |
||||
* @author Karim Abou Zeid (kabouzeid) |
||||
*/ |
||||
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,52 @@ |
||||
package io.legado.app.lib.theme; |
||||
|
||||
import android.annotation.SuppressLint; |
||||
import android.content.Context; |
||||
import androidx.annotation.ColorInt; |
||||
import androidx.core.content.ContextCompat; |
||||
import io.legado.app.R; |
||||
|
||||
/** |
||||
* @author Karim Abou Zeid (kabouzeid) |
||||
*/ |
||||
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,55 @@ |
||||
package io.legado.app.lib.theme; |
||||
|
||||
import android.content.res.ColorStateList; |
||||
import androidx.annotation.ColorInt; |
||||
import androidx.annotation.NonNull; |
||||
import com.google.android.material.internal.NavigationMenuView; |
||||
import com.google.android.material.navigation.NavigationView; |
||||
|
||||
/** |
||||
* @author Karim Abou Zeid (kabouzeid) |
||||
*/ |
||||
public final class NavigationViewUtil { |
||||
|
||||
public static void setItemIconColors(@NonNull NavigationView navigationView, @ColorInt int normalColor, @ColorInt int selectedColor) { |
||||
final ColorStateList iconSl = new ColorStateList( |
||||
new int[][]{ |
||||
new int[]{-android.R.attr.state_checked}, |
||||
new int[]{android.R.attr.state_checked} |
||||
}, |
||||
new int[]{ |
||||
normalColor, |
||||
selectedColor |
||||
}); |
||||
navigationView.setItemIconTintList(iconSl); |
||||
} |
||||
|
||||
public static void setItemTextColors(@NonNull NavigationView navigationView, @ColorInt int normalColor, @ColorInt int selectedColor) { |
||||
final ColorStateList textSl = new ColorStateList( |
||||
new int[][]{ |
||||
new int[]{-android.R.attr.state_checked}, |
||||
new int[]{android.R.attr.state_checked} |
||||
}, |
||||
new int[]{ |
||||
normalColor, |
||||
selectedColor |
||||
}); |
||||
navigationView.setItemTextColor(textSl); |
||||
} |
||||
|
||||
/** |
||||
* 去掉navigationView的滚动条 |
||||
* @param navigationView NavigationView |
||||
*/ |
||||
public static void disableScrollbar(NavigationView navigationView) { |
||||
if (navigationView != null) { |
||||
NavigationMenuView navigationMenuView = (NavigationMenuView) navigationView.getChildAt(0); |
||||
if (navigationMenuView != null) { |
||||
navigationMenuView.setVerticalScrollBarEnabled(false); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private NavigationViewUtil() { |
||||
} |
||||
} |
@ -0,0 +1,430 @@ |
||||
package io.legado.app.lib.theme; |
||||
|
||||
import android.content.Context; |
||||
import android.content.res.ColorStateList; |
||||
import android.graphics.Color; |
||||
import android.graphics.drawable.ColorDrawable; |
||||
import android.graphics.drawable.Drawable; |
||||
import android.graphics.drawable.GradientDrawable; |
||||
import android.graphics.drawable.StateListDrawable; |
||||
import androidx.annotation.ColorInt; |
||||
import androidx.annotation.Dimension; |
||||
import androidx.annotation.DrawableRes; |
||||
import androidx.annotation.IntDef; |
||||
import androidx.core.content.ContextCompat; |
||||
|
||||
public class Selector { |
||||
public static ShapeSelector shapeBuild() { |
||||
return new ShapeSelector(); |
||||
} |
||||
|
||||
public static ColorSelector colorBuild() { |
||||
return new ColorSelector(); |
||||
} |
||||
|
||||
public static DrawableSelector drawableBuild() { |
||||
return new DrawableSelector(); |
||||
} |
||||
|
||||
/** |
||||
* 形状ShapeSelector |
||||
* |
||||
* @author hjy |
||||
* created at 2017/12/11 22:26 |
||||
*/ |
||||
public static final class ShapeSelector { |
||||
@IntDef({GradientDrawable.RECTANGLE, GradientDrawable.OVAL, |
||||
GradientDrawable.LINE, GradientDrawable.RING}) |
||||
private @interface Shape { |
||||
} |
||||
|
||||
private int mShape; //the shape of background
|
||||
private int mDefaultBgColor; //default background color
|
||||
private int mDisabledBgColor; //state_enabled = false
|
||||
private int mPressedBgColor; //state_pressed = true
|
||||
private int mSelectedBgColor; //state_selected = true
|
||||
private int mFocusedBgColor; //state_focused = true
|
||||
private int mCheckedBgColor; //state_checked = true
|
||||
private int mStrokeWidth; //stroke width in pixel
|
||||
private int mDefaultStrokeColor; //default stroke color
|
||||
private int mDisabledStrokeColor; //state_enabled = false
|
||||
private int mPressedStrokeColor; //state_pressed = true
|
||||
private int mSelectedStrokeColor; //state_selected = true
|
||||
private int mFocusedStrokeColor; //state_focused = true
|
||||
private int mCheckedStrokeColor; //state_checked = true
|
||||
private int mCornerRadius; //corner radius
|
||||
|
||||
private boolean hasSetDisabledBgColor = false; |
||||
private boolean hasSetPressedBgColor = false; |
||||
private boolean hasSetSelectedBgColor = false; |
||||
private boolean hasSetFocusedBgColor = false; |
||||
private boolean hasSetCheckedBgColor = false; |
||||
|
||||
private boolean hasSetDisabledStrokeColor = false; |
||||
private boolean hasSetPressedStrokeColor = false; |
||||
private boolean hasSetSelectedStrokeColor = false; |
||||
private boolean hasSetFocusedStrokeColor = false; |
||||
private boolean hasSetCheckedStrokeColor = false; |
||||
|
||||
public ShapeSelector() { |
||||
//initialize default values
|
||||
mShape = GradientDrawable.RECTANGLE; |
||||
mDefaultBgColor = Color.TRANSPARENT; |
||||
mDisabledBgColor = Color.TRANSPARENT; |
||||
mPressedBgColor = Color.TRANSPARENT; |
||||
mSelectedBgColor = Color.TRANSPARENT; |
||||
mFocusedBgColor = Color.TRANSPARENT; |
||||
mStrokeWidth = 0; |
||||
mDefaultStrokeColor = Color.TRANSPARENT; |
||||
mDisabledStrokeColor = Color.TRANSPARENT; |
||||
mPressedStrokeColor = Color.TRANSPARENT; |
||||
mSelectedStrokeColor = Color.TRANSPARENT; |
||||
mFocusedStrokeColor = Color.TRANSPARENT; |
||||
mCornerRadius = 0; |
||||
} |
||||
|
||||
public ShapeSelector setShape(@Shape int shape) { |
||||
mShape = shape; |
||||
return this; |
||||
} |
||||
|
||||
public ShapeSelector setDefaultBgColor(@ColorInt int color) { |
||||
mDefaultBgColor = color; |
||||
if (!hasSetDisabledBgColor) |
||||
mDisabledBgColor = color; |
||||
if (!hasSetPressedBgColor) |
||||
mPressedBgColor = color; |
||||
if (!hasSetSelectedBgColor) |
||||
mSelectedBgColor = color; |
||||
if (!hasSetFocusedBgColor) |
||||
mFocusedBgColor = color; |
||||
return this; |
||||
} |
||||
|
||||
public ShapeSelector setDisabledBgColor(@ColorInt int color) { |
||||
mDisabledBgColor = color; |
||||
hasSetDisabledBgColor = true; |
||||
return this; |
||||
} |
||||
|
||||
public ShapeSelector setPressedBgColor(@ColorInt int color) { |
||||
mPressedBgColor = color; |
||||
hasSetPressedBgColor = true; |
||||
return this; |
||||
} |
||||
|
||||
public ShapeSelector setSelectedBgColor(@ColorInt int color) { |
||||
mSelectedBgColor = color; |
||||
hasSetSelectedBgColor = true; |
||||
return this; |
||||
} |
||||
|
||||
public ShapeSelector setFocusedBgColor(@ColorInt int color) { |
||||
mFocusedBgColor = color; |
||||
hasSetPressedBgColor = true; |
||||
return this; |
||||
} |
||||
|
||||
public ShapeSelector setCheckedBgColor(@ColorInt int color) { |
||||
mCheckedBgColor = color; |
||||
hasSetCheckedBgColor = true; |
||||
return this; |
||||
} |
||||
|
||||
public ShapeSelector setStrokeWidth(@Dimension int width) { |
||||
mStrokeWidth = width; |
||||
return this; |
||||
} |
||||
|
||||
public ShapeSelector setDefaultStrokeColor(@ColorInt int color) { |
||||
mDefaultStrokeColor = color; |
||||
if (!hasSetDisabledStrokeColor) |
||||
mDisabledStrokeColor = color; |
||||
if (!hasSetPressedStrokeColor) |
||||
mPressedStrokeColor = color; |
||||
if (!hasSetSelectedStrokeColor) |
||||
mSelectedStrokeColor = color; |
||||
if (!hasSetFocusedStrokeColor) |
||||
mFocusedStrokeColor = color; |
||||
return this; |
||||
} |
||||
|
||||
public ShapeSelector setDisabledStrokeColor(@ColorInt int color) { |
||||
mDisabledStrokeColor = color; |
||||
hasSetDisabledStrokeColor = true; |
||||
return this; |
||||
} |
||||
|
||||
public ShapeSelector setPressedStrokeColor(@ColorInt int color) { |
||||
mPressedStrokeColor = color; |
||||
hasSetPressedStrokeColor = true; |
||||
return this; |
||||
} |
||||
|
||||
public ShapeSelector setSelectedStrokeColor(@ColorInt int color) { |
||||
mSelectedStrokeColor = color; |
||||
hasSetSelectedStrokeColor = true; |
||||
return this; |
||||
} |
||||
|
||||
public ShapeSelector setCheckedStrokeColor(@ColorInt int color) { |
||||
mCheckedStrokeColor = color; |
||||
hasSetCheckedStrokeColor = true; |
||||
return this; |
||||
} |
||||
|
||||
public ShapeSelector setFocusedStrokeColor(@ColorInt int color) { |
||||
mFocusedStrokeColor = color; |
||||
hasSetFocusedStrokeColor = true; |
||||
return this; |
||||
} |
||||
|
||||
public ShapeSelector setCornerRadius(@Dimension int radius) { |
||||
mCornerRadius = radius; |
||||
return this; |
||||
} |
||||
|
||||
public StateListDrawable create() { |
||||
StateListDrawable selector = new StateListDrawable(); |
||||
|
||||
//enabled = false
|
||||
if (hasSetDisabledBgColor || hasSetDisabledStrokeColor) { |
||||
GradientDrawable disabledShape = getItemShape(mShape, mCornerRadius, |
||||
mDisabledBgColor, mStrokeWidth, mDisabledStrokeColor); |
||||
selector.addState(new int[]{-android.R.attr.state_enabled}, disabledShape); |
||||
} |
||||
|
||||
//pressed = true
|
||||
if (hasSetPressedBgColor || hasSetPressedStrokeColor) { |
||||
GradientDrawable pressedShape = getItemShape(mShape, mCornerRadius, |
||||
mPressedBgColor, mStrokeWidth, mPressedStrokeColor); |
||||
selector.addState(new int[]{android.R.attr.state_pressed}, pressedShape); |
||||
} |
||||
|
||||
//selected = true
|
||||
if (hasSetSelectedBgColor || hasSetSelectedStrokeColor) { |
||||
GradientDrawable selectedShape = getItemShape(mShape, mCornerRadius, |
||||
mSelectedBgColor, mStrokeWidth, mSelectedStrokeColor); |
||||
selector.addState(new int[]{android.R.attr.state_selected}, selectedShape); |
||||
} |
||||
|
||||
//focused = true
|
||||
if (hasSetFocusedBgColor || hasSetFocusedStrokeColor) { |
||||
GradientDrawable focusedShape = getItemShape(mShape, mCornerRadius, |
||||
mFocusedBgColor, mStrokeWidth, mFocusedStrokeColor); |
||||
selector.addState(new int[]{android.R.attr.state_focused}, focusedShape); |
||||
} |
||||
|
||||
//checked = true
|
||||
if (hasSetCheckedBgColor || hasSetCheckedStrokeColor) { |
||||
GradientDrawable checkedShape = getItemShape(mShape, mCornerRadius, |
||||
mCheckedBgColor, mStrokeWidth, mCheckedStrokeColor); |
||||
selector.addState(new int[]{android.R.attr.state_checked}, checkedShape); |
||||
} |
||||
|
||||
//default
|
||||
GradientDrawable defaultShape = getItemShape(mShape, mCornerRadius, |
||||
mDefaultBgColor, mStrokeWidth, mDefaultStrokeColor); |
||||
selector.addState(new int[]{}, defaultShape); |
||||
|
||||
return selector; |
||||
} |
||||
|
||||
private GradientDrawable getItemShape(int shape, int cornerRadius, |
||||
int solidColor, int strokeWidth, int strokeColor) { |
||||
GradientDrawable drawable = new GradientDrawable(); |
||||
drawable.setShape(shape); |
||||
drawable.setStroke(strokeWidth, strokeColor); |
||||
drawable.setCornerRadius(cornerRadius); |
||||
drawable.setColor(solidColor); |
||||
return drawable; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 资源DrawableSelector |
||||
* |
||||
* @author hjy |
||||
* created at 2017/12/11 22:34 |
||||
*/ |
||||
public static final class DrawableSelector { |
||||
|
||||
private Drawable mDefaultDrawable; |
||||
private Drawable mDisabledDrawable; |
||||
private Drawable mPressedDrawable; |
||||
private Drawable mSelectedDrawable; |
||||
private Drawable mFocusedDrawable; |
||||
|
||||
private boolean hasSetDisabledDrawable = false; |
||||
private boolean hasSetPressedDrawable = false; |
||||
private boolean hasSetSelectedDrawable = false; |
||||
private boolean hasSetFocusedDrawable = false; |
||||
|
||||
private DrawableSelector() { |
||||
mDefaultDrawable = new ColorDrawable(Color.TRANSPARENT); |
||||
} |
||||
|
||||
public DrawableSelector setDefaultDrawable(Drawable drawable) { |
||||
mDefaultDrawable = drawable; |
||||
if (!hasSetDisabledDrawable) |
||||
mDisabledDrawable = drawable; |
||||
if (!hasSetPressedDrawable) |
||||
mPressedDrawable = drawable; |
||||
if (!hasSetSelectedDrawable) |
||||
mSelectedDrawable = drawable; |
||||
if (!hasSetFocusedDrawable) |
||||
mFocusedDrawable = drawable; |
||||
return this; |
||||
} |
||||
|
||||
public DrawableSelector setDisabledDrawable(Drawable drawable) { |
||||
mDisabledDrawable = drawable; |
||||
hasSetDisabledDrawable = true; |
||||
return this; |
||||
} |
||||
|
||||
public DrawableSelector setPressedDrawable(Drawable drawable) { |
||||
mPressedDrawable = drawable; |
||||
hasSetPressedDrawable = true; |
||||
return this; |
||||
} |
||||
|
||||
public DrawableSelector setSelectedDrawable(Drawable drawable) { |
||||
mSelectedDrawable = drawable; |
||||
hasSetSelectedDrawable = true; |
||||
return this; |
||||
} |
||||
|
||||
public DrawableSelector setFocusedDrawable(Drawable drawable) { |
||||
mFocusedDrawable = drawable; |
||||
hasSetFocusedDrawable = true; |
||||
return this; |
||||
} |
||||
|
||||
public StateListDrawable create() { |
||||
StateListDrawable selector = new StateListDrawable(); |
||||
if (hasSetDisabledDrawable) |
||||
selector.addState(new int[]{-android.R.attr.state_enabled}, mDisabledDrawable); |
||||
if (hasSetPressedDrawable) |
||||
selector.addState(new int[]{android.R.attr.state_pressed}, mPressedDrawable); |
||||
if (hasSetSelectedDrawable) |
||||
selector.addState(new int[]{android.R.attr.state_selected}, mSelectedDrawable); |
||||
if (hasSetFocusedDrawable) |
||||
selector.addState(new int[]{android.R.attr.state_focused}, mFocusedDrawable); |
||||
selector.addState(new int[]{}, mDefaultDrawable); |
||||
return selector; |
||||
} |
||||
|
||||
public DrawableSelector setDefaultDrawable(Context context, @DrawableRes int drawableRes) { |
||||
return setDefaultDrawable(ContextCompat.getDrawable(context, drawableRes)); |
||||
} |
||||
|
||||
public DrawableSelector setDisabledDrawable(Context context, @DrawableRes int drawableRes) { |
||||
return setDisabledDrawable(ContextCompat.getDrawable(context, drawableRes)); |
||||
} |
||||
|
||||
public DrawableSelector setPressedDrawable(Context context, @DrawableRes int drawableRes) { |
||||
return setPressedDrawable(ContextCompat.getDrawable(context, drawableRes)); |
||||
} |
||||
|
||||
public DrawableSelector setSelectedDrawable(Context context, @DrawableRes int drawableRes) { |
||||
return setSelectedDrawable(ContextCompat.getDrawable(context, drawableRes)); |
||||
} |
||||
|
||||
public DrawableSelector setFocusedDrawable(Context context, @DrawableRes int drawableRes) { |
||||
return setFocusedDrawable(ContextCompat.getDrawable(context, drawableRes)); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 颜色ColorSelector |
||||
* |
||||
* @author hjy |
||||
* created at 2017/12/11 22:26 |
||||
*/ |
||||
public static final class ColorSelector { |
||||
|
||||
private int mDefaultColor; |
||||
private int mDisabledColor; |
||||
private int mPressedColor; |
||||
private int mSelectedColor; |
||||
private int mFocusedColor; |
||||
private int mCheckedColor; |
||||
|
||||
private boolean hasSetDisabledColor = false; |
||||
private boolean hasSetPressedColor = false; |
||||
private boolean hasSetSelectedColor = false; |
||||
private boolean hasSetFocusedColor = false; |
||||
private boolean hasSetCheckedColor = false; |
||||
|
||||
private ColorSelector() { |
||||
mDefaultColor = Color.BLACK; |
||||
mDisabledColor = Color.GRAY; |
||||
mPressedColor = Color.BLACK; |
||||
mSelectedColor = Color.BLACK; |
||||
mFocusedColor = Color.BLACK; |
||||
} |
||||
|
||||
public ColorSelector setDefaultColor(@ColorInt int color) { |
||||
mDefaultColor = color; |
||||
if (!hasSetDisabledColor) |
||||
mDisabledColor = color; |
||||
if (!hasSetPressedColor) |
||||
mPressedColor = color; |
||||
if (!hasSetSelectedColor) |
||||
mSelectedColor = color; |
||||
if (!hasSetFocusedColor) |
||||
mFocusedColor = color; |
||||
return this; |
||||
} |
||||
|
||||
public ColorSelector setDisabledColor(@ColorInt int color) { |
||||
mDisabledColor = color; |
||||
hasSetDisabledColor = true; |
||||
return this; |
||||
} |
||||
|
||||
public ColorSelector setPressedColor(@ColorInt int color) { |
||||
mPressedColor = color; |
||||
hasSetPressedColor = true; |
||||
return this; |
||||
} |
||||
|
||||
public ColorSelector setSelectedColor(@ColorInt int color) { |
||||
mSelectedColor = color; |
||||
hasSetSelectedColor = true; |
||||
return this; |
||||
} |
||||
|
||||
public ColorSelector setFocusedColor(@ColorInt int color) { |
||||
mFocusedColor = color; |
||||
hasSetFocusedColor = true; |
||||
return this; |
||||
} |
||||
|
||||
public ColorSelector setCheckedColor(@ColorInt int color) { |
||||
mCheckedColor = color; |
||||
hasSetCheckedColor = true; |
||||
return this; |
||||
} |
||||
|
||||
public ColorStateList create() { |
||||
int[] colors = new int[]{ |
||||
hasSetDisabledColor ? mDisabledColor : mDefaultColor, |
||||
hasSetPressedColor ? mPressedColor : mDefaultColor, |
||||
hasSetSelectedColor ? mSelectedColor : mDefaultColor, |
||||
hasSetFocusedColor ? mFocusedColor : mDefaultColor, |
||||
hasSetCheckedColor ? mCheckedColor : mDefaultColor, |
||||
mDefaultColor |
||||
}; |
||||
int[][] states = new int[6][]; |
||||
states[0] = new int[]{-android.R.attr.state_enabled}; |
||||
states[1] = new int[]{android.R.attr.state_pressed}; |
||||
states[2] = new int[]{android.R.attr.state_selected}; |
||||
states[3] = new int[]{android.R.attr.state_focused}; |
||||
states[4] = new int[]{android.R.attr.state_checked}; |
||||
states[5] = new int[]{}; |
||||
return new ColorStateList(states, colors); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,318 @@ |
||||
package io.legado.app.lib.theme; |
||||
|
||||
import android.annotation.SuppressLint; |
||||
import android.content.Context; |
||||
import android.content.SharedPreferences; |
||||
import android.graphics.Color; |
||||
import androidx.annotation.*; |
||||
import androidx.core.content.ContextCompat; |
||||
import io.legado.app.R; |
||||
|
||||
/** |
||||
* @author Aidan Follestad (afollestad), Karim Abou Zeid (kabouzeid) |
||||
*/ |
||||
public final class ThemeStore implements ThemeStorePrefKeys, ThemeStoreInterface { |
||||
|
||||
private final Context mContext; |
||||
private final SharedPreferences.Editor mEditor; |
||||
|
||||
public static ThemeStore editTheme(@NonNull Context context) { |
||||
return new ThemeStore(context); |
||||
} |
||||
|
||||
@SuppressLint("CommitPrefEdits") |
||||
private ThemeStore(@NonNull Context context) { |
||||
mContext = context; |
||||
mEditor = prefs(context).edit(); |
||||
} |
||||
|
||||
|
||||
@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; |
||||
} |
||||
|
||||
@Override |
||||
public ThemeStore navigationBarColorRes(@ColorRes int colorRes) { |
||||
return navigationBarColor(ContextCompat.getColor(mContext, colorRes)); |
||||
} |
||||
|
||||
@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 backgroundColor(int color) { |
||||
mEditor.putInt(KEY_BACKGROUND_COLOR, color); |
||||
return this; |
||||
} |
||||
|
||||
@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; |
||||
} |
||||
|
||||
// Commit method
|
||||
|
||||
@SuppressWarnings("unchecked") |
||||
@Override |
||||
public void apply() { |
||||
mEditor.putLong(VALUES_CHANGED, System.currentTimeMillis()) |
||||
.putBoolean(IS_CONFIGURED_KEY, true) |
||||
.apply(); |
||||
} |
||||
|
||||
// Static getters
|
||||
|
||||
@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).apply(); |
||||
} |
||||
|
||||
@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 |
||||
@ColorInt |
||||
public static int backgroundColor(@NonNull Context context) { |
||||
return prefs(context).getInt(KEY_BACKGROUND_COLOR, ATHUtil.resolveColor(context, android.R.attr.colorBackground)); |
||||
} |
||||
|
||||
@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).apply(); |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
} |
@ -0,0 +1,92 @@ |
||||
package io.legado.app.lib.theme; |
||||
|
||||
|
||||
import androidx.annotation.AttrRes; |
||||
import androidx.annotation.ColorInt; |
||||
import androidx.annotation.ColorRes; |
||||
|
||||
/** |
||||
* @author Aidan Follestad (afollestad), Karim Abou Zeid (kabouzeid) |
||||
*/ |
||||
interface ThemeStoreInterface { |
||||
|
||||
// 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); |
||||
|
||||
ThemeStore backgroundColor(@ColorInt int color); |
||||
|
||||
// Toggle configurations
|
||||
|
||||
ThemeStore coloredStatusBar(boolean colored); |
||||
|
||||
ThemeStore coloredNavigationBar(boolean applyToNavBar); |
||||
|
||||
// Commit/apply
|
||||
|
||||
void apply(); |
||||
} |
@ -0,0 +1,29 @@ |
||||
package io.legado.app.lib.theme; |
||||
|
||||
/** |
||||
* @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_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_BACKGROUND_COLOR = "backgroundColor"; |
||||
|
||||
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,384 @@ |
||||
package io.legado.app.lib.theme; |
||||
|
||||
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.view.View; |
||||
import android.widget.*; |
||||
import androidx.annotation.CheckResult; |
||||
import androidx.annotation.ColorInt; |
||||
import androidx.annotation.NonNull; |
||||
import androidx.annotation.Nullable; |
||||
import androidx.appcompat.widget.AppCompatEditText; |
||||
import androidx.appcompat.widget.SearchView; |
||||
import androidx.appcompat.widget.SwitchCompat; |
||||
import androidx.core.content.ContextCompat; |
||||
import androidx.core.graphics.drawable.DrawableCompat; |
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton; |
||||
import io.legado.app.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 AppCompatEditText) |
||||
setTint((AppCompatEditText) 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 if (view instanceof SearchView) { |
||||
int iconIdS[] = new int[]{androidx.appcompat.R.id.search_button, androidx.appcompat.R.id.search_close_btn,}; |
||||
for (int iconId : iconIdS) { |
||||
ImageView icon = view.findViewById(iconId); |
||||
if (icon != null) { |
||||
setTint(icon, color); |
||||
} |
||||
} |
||||
|
||||
} 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 { |
||||
Drawable progressDrawable = createTintedDrawable(seekBar.getProgressDrawable(), s1); |
||||
seekBar.setProgressDrawable(progressDrawable); |
||||
Drawable thumbDrawable = createTintedDrawable(seekBar.getThumb(), s1); |
||||
seekBar.setThumb(thumbDrawable); |
||||
} |
||||
} |
||||
|
||||
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 (!skipIndeterminate && progressBar.getIndeterminateDrawable() != null) |
||||
progressBar.getIndeterminateDrawable().setColorFilter(color, mode); |
||||
if (progressBar.getProgressDrawable() != null) |
||||
progressBar.getProgressDrawable().setColorFilter(color, mode); |
||||
} |
||||
} |
||||
|
||||
|
||||
@SuppressLint("RestrictedApi") |
||||
public static void setTint(@NonNull AppCompatEditText 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 |
||||
}); |
||||
editText.setSupportBackgroundTintList(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 ignored) { |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,48 @@ |
||||
package io.legado.app.lib.theme; |
||||
|
||||
import android.graphics.drawable.ColorDrawable; |
||||
import android.graphics.drawable.Drawable; |
||||
import android.graphics.drawable.TransitionDrawable; |
||||
import android.view.View; |
||||
import android.view.ViewTreeObserver; |
||||
import androidx.annotation.ColorInt; |
||||
import androidx.annotation.NonNull; |
||||
import androidx.annotation.Nullable; |
||||
|
||||
/** |
||||
* @author Karim Abou Zeid (kabouzeid) |
||||
*/ |
||||
public final class ViewUtil { |
||||
|
||||
@SuppressWarnings("deprecation") |
||||
public static void removeOnGlobalLayoutListener(View v, ViewTreeObserver.OnGlobalLayoutListener listener) { |
||||
v.getViewTreeObserver().removeOnGlobalLayoutListener(listener); |
||||
} |
||||
|
||||
@SuppressWarnings("deprecation") |
||||
public static void setBackgroundCompat(@NonNull View view, @Nullable Drawable drawable) { |
||||
view.setBackground(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() { |
||||
} |
||||
} |
@ -0,0 +1,6 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" |
||||
android:shape="rectangle"> |
||||
<size android:height="0.5dp" /> |
||||
<solid android:color="@color/divider" /> |
||||
</shape> |
@ -0,0 +1,34 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<resources> |
||||
<color name="background">@color/md_grey_800</color> |
||||
<color name="background_card">#353535</color> |
||||
<color name="background_menu">#282828</color> |
||||
|
||||
<color name="night_mask">#69000000</color> |
||||
|
||||
<color name="colorPrimary">@color/md_grey_800</color> |
||||
<color name="colorPrimaryDark">@color/md_grey_900</color> |
||||
<color name="colorAccent">@color/md_grey_100</color> |
||||
|
||||
<color name="transparent30">#30ffffff</color> |
||||
|
||||
<color name="bg_divider_line">#363636</color> |
||||
<color name="btn_bg_press">#804D4D4D</color> |
||||
<color name="btn_bg_press_2">#80686868</color> |
||||
<color name="btn_bg_press_tp">#88111111</color> |
||||
<color name="darker_gray">#66666666</color> |
||||
|
||||
<color name="tv_btn_normal_black">#737373</color> |
||||
<color name="tv_btn_press_black">#565656</color> |
||||
|
||||
<color name="tv_text_default">#ffffffff</color> |
||||
<color name="tv_text_secondary">#e5ffffff</color> |
||||
<color name="tv_text_summary">#b3ffffff</color> |
||||
<color name="menu_color_default">#b7b7b7</color> |
||||
|
||||
|
||||
<color name="tv_text_button_nor">#303030</color> |
||||
|
||||
<!--statusBarBackground--> |
||||
<color name="navigation_bar_bag">#222222</color> |
||||
</resources> |
@ -0,0 +1,19 @@ |
||||
<resources> |
||||
|
||||
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Dark"> |
||||
<item name="overlapAnchor">false</item> |
||||
<item name="colorAccent">@color/md_grey_100</item> |
||||
</style> |
||||
|
||||
<style name="Style.Shadow.Top" parent="android:Widget"> |
||||
<item name="android:layout_width">match_parent</item> |
||||
<item name="android:layout_height">@dimen/shadow_height</item> |
||||
<item name="android:background">@drawable/bg_shadow_top_night</item> |
||||
</style> |
||||
|
||||
<style name="Style.Shadow.Bottom" parent="android:Widget"> |
||||
<item name="android:layout_width">match_parent</item> |
||||
<item name="android:layout_height">@dimen/shadow_height</item> |
||||
<item name="android:background">@drawable/bg_shadow_bottom_night</item> |
||||
</style> |
||||
</resources> |
@ -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> |
Loading…
Reference in new issue