530 lines
20 KiB
Kotlin
530 lines
20 KiB
Kotlin
|
/*
|
||
|
* Twidere - Twitter client for Android
|
||
|
*
|
||
|
* Copyright (C) 2012-2017 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||
|
*
|
||
|
* This program is free software: you can redistribute it and/or modify
|
||
|
* it under the terms of the GNU General Public License as published by
|
||
|
* the Free Software Foundation, either version 3 of the License, or
|
||
|
* (at your option) any later version.
|
||
|
*
|
||
|
* This program is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
* GNU General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU General Public License
|
||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
|
||
|
package org.mariotaku.twidere.util
|
||
|
|
||
|
import android.content.Context
|
||
|
import android.content.SharedPreferences
|
||
|
import android.content.res.Resources
|
||
|
import android.graphics.Color
|
||
|
import android.graphics.PorterDuff
|
||
|
import android.graphics.drawable.ColorDrawable
|
||
|
import android.graphics.drawable.Drawable
|
||
|
import android.os.Build
|
||
|
import android.support.annotation.ColorInt
|
||
|
import android.support.annotation.FloatRange
|
||
|
import android.support.annotation.StyleRes
|
||
|
import android.support.v4.content.ContextCompat
|
||
|
import android.support.v4.graphics.ColorUtils
|
||
|
import android.support.v7.app.TwilightManagerAccessor
|
||
|
import android.support.v7.view.menu.ActionMenuItemView
|
||
|
import android.support.v7.widget.ActionMenuView
|
||
|
import android.support.v7.widget.TintTypedArray
|
||
|
import android.support.v7.widget.Toolbar
|
||
|
import android.support.v7.widget.TwidereToolbar
|
||
|
import android.util.TypedValue
|
||
|
import android.view.*
|
||
|
import android.widget.FrameLayout
|
||
|
import org.mariotaku.chameleon.Chameleon
|
||
|
import org.mariotaku.chameleon.ChameleonUtils
|
||
|
import org.mariotaku.kpreferences.get
|
||
|
import org.mariotaku.twidere.R
|
||
|
import org.mariotaku.twidere.TwidereConstants
|
||
|
import org.mariotaku.twidere.constant.SharedPreferenceConstants.VALUE_THEME_BACKGROUND_SOLID
|
||
|
import org.mariotaku.twidere.constant.SharedPreferenceConstants.VALUE_THEME_BACKGROUND_TRANSPARENT
|
||
|
import org.mariotaku.twidere.constant.themeBackgroundAlphaKey
|
||
|
import org.mariotaku.twidere.constant.themeBackgroundOptionKey
|
||
|
import org.mariotaku.twidere.constant.themeColorKey
|
||
|
import org.mariotaku.twidere.graphic.ActionIconDrawable
|
||
|
import org.mariotaku.twidere.graphic.WindowBackgroundDrawable
|
||
|
import org.mariotaku.twidere.graphic.iface.DoNotWrapDrawable
|
||
|
import org.mariotaku.twidere.preference.ThemeBackgroundPreference.MAX_ALPHA
|
||
|
import org.mariotaku.twidere.preference.ThemeBackgroundPreference.MIN_ALPHA
|
||
|
import org.mariotaku.twidere.util.menu.TwidereMenuInfo
|
||
|
import org.mariotaku.twidere.util.support.ViewSupport
|
||
|
|
||
|
/**
|
||
|
* Created by mariotaku on 2017/4/15.
|
||
|
*/
|
||
|
|
||
|
object ThemeUtils {
|
||
|
const val ACCENT_COLOR_THRESHOLD = 192
|
||
|
const val DARK_COLOR_THRESHOLD = 128
|
||
|
|
||
|
fun getUserTheme(context: Context, preferences: SharedPreferences): Chameleon.Theme {
|
||
|
val theme = Chameleon.Theme.from(context)
|
||
|
val userColor = getUserAccentColor(context, preferences)
|
||
|
theme.colorAccent = userColor
|
||
|
theme.colorPrimary = userColor
|
||
|
val backgroundOption = preferences[themeBackgroundOptionKey]
|
||
|
if (theme.isToolbarColored) {
|
||
|
theme.colorToolbar = theme.colorPrimary
|
||
|
} else if (backgroundOption == TwidereConstants.VALUE_THEME_BACKGROUND_SOLID) {
|
||
|
theme.colorToolbar = if (ThemeUtils.isLightTheme(context)) {
|
||
|
Color.WHITE
|
||
|
} else {
|
||
|
Color.BLACK
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (isTransparentBackground(backgroundOption)) {
|
||
|
theme.colorToolbar = ColorUtils.setAlphaComponent(theme.colorToolbar,
|
||
|
ThemeUtils.getActionBarAlpha(preferences[themeBackgroundAlphaKey]))
|
||
|
}
|
||
|
theme.statusBarColor = ChameleonUtils.darkenColor(theme.colorToolbar)
|
||
|
theme.lightStatusBarMode = Chameleon.Theme.LightStatusBarMode.AUTO
|
||
|
theme.textColorLink = ThemeUtils.getOptimalAccentColor(theme.colorAccent, theme.colorForeground)
|
||
|
|
||
|
return theme
|
||
|
}
|
||
|
|
||
|
@StyleRes
|
||
|
fun getCurrentThemeResource(context: Context, @StyleRes lightTheme: Int, @StyleRes darkTheme: Int): Int {
|
||
|
if (TwilightManagerAccessor.isNight(context)) return darkTheme
|
||
|
return lightTheme
|
||
|
}
|
||
|
|
||
|
fun getTextColorPrimary(context: Context): Int {
|
||
|
return getColorFromAttribute(context, android.R.attr.textColorPrimary, 0)
|
||
|
}
|
||
|
|
||
|
fun getTextColorSecondary(context: Context): Int {
|
||
|
return getColorFromAttribute(context, android.R.attr.textColorSecondary, 0)
|
||
|
}
|
||
|
|
||
|
fun getCardBackgroundColor(context: Context, backgroundOption: String, themeAlpha: Int): Int {
|
||
|
val a = context.obtainStyledAttributes(intArrayOf(R.attr.cardItemBackgroundColor))
|
||
|
val color = a.getColor(0, Color.TRANSPARENT)
|
||
|
a.recycle()
|
||
|
if (isTransparentBackground(backgroundOption)) {
|
||
|
return themeAlpha shl 24 or (0x00FFFFFF and color)
|
||
|
} else if (isSolidBackground(backgroundOption)) {
|
||
|
return TwidereColorUtils.getContrastYIQ(color, Color.WHITE, Color.BLACK)
|
||
|
} else {
|
||
|
return color
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fun getColorBackground(context: Context): Int {
|
||
|
val a = context.obtainStyledAttributes(intArrayOf(android.R.attr.colorBackground))
|
||
|
try {
|
||
|
return a.getColor(0, Color.TRANSPARENT)
|
||
|
} finally {
|
||
|
a.recycle()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fun computeDarkColor(color: Int): Int {
|
||
|
return shiftColor(color, 0.9f)
|
||
|
}
|
||
|
|
||
|
fun isLightColor(color: Int): Boolean {
|
||
|
return ChameleonUtils.isColorLight(color)
|
||
|
}
|
||
|
|
||
|
|
||
|
fun getColorDependent(color: Int): Int {
|
||
|
return ChameleonUtils.getColorDependent(color)
|
||
|
}
|
||
|
|
||
|
fun isSolidBackground(option: String): Boolean {
|
||
|
return VALUE_THEME_BACKGROUND_SOLID == option
|
||
|
}
|
||
|
|
||
|
fun isWindowFloating(context: Context): Boolean {
|
||
|
val a = context.obtainStyledAttributes(intArrayOf(android.R.attr.windowIsFloating))
|
||
|
try {
|
||
|
return a.getBoolean(0, false)
|
||
|
} finally {
|
||
|
a.recycle()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fun isTransparentBackground(option: String): Boolean {
|
||
|
return VALUE_THEME_BACKGROUND_TRANSPARENT == option
|
||
|
}
|
||
|
|
||
|
fun getThemeBackgroundColor(context: Context, backgroundOption: String, alpha: Int): Int {
|
||
|
if (isWindowFloating(context)) {
|
||
|
return getThemeBackgroundColor(context)
|
||
|
} else if (backgroundOption == VALUE_THEME_BACKGROUND_TRANSPARENT) {
|
||
|
return ColorUtils.setAlphaComponent(getThemeBackgroundColor(context), alpha)
|
||
|
} else if (backgroundOption == VALUE_THEME_BACKGROUND_SOLID) {
|
||
|
return if (isLightTheme(context)) Color.WHITE else Color.BLACK
|
||
|
} else {
|
||
|
return getThemeBackgroundColor(context)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
fun getThemeBackgroundColor(context: Context): Int {
|
||
|
val a = context.obtainStyledAttributes(intArrayOf(android.R.attr.colorBackground))
|
||
|
try {
|
||
|
return a.getColor(0, 0)
|
||
|
} finally {
|
||
|
a.recycle()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fun getThemeBackgroundColor(context: Context, themeRes: Int): Int {
|
||
|
if (themeRes == 0) {
|
||
|
return getThemeBackgroundColor(context)
|
||
|
}
|
||
|
val a = context.obtainStyledAttributes(null, intArrayOf(android.R.attr.colorBackground),
|
||
|
0, themeRes)
|
||
|
try {
|
||
|
return a.getColor(0, 0)
|
||
|
} finally {
|
||
|
a.recycle()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fun applyWindowBackground(context: Context, window: Window, backgroundOption: String, alpha: Int) {
|
||
|
if (isWindowFloating(context)) {
|
||
|
window.setBackgroundDrawable(getWindowBackground(context))
|
||
|
} else if (VALUE_THEME_BACKGROUND_TRANSPARENT == backgroundOption) {
|
||
|
window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER)
|
||
|
window.setBackgroundDrawable(getWindowBackgroundFromThemeApplyAlpha(context, alpha))
|
||
|
} else if (VALUE_THEME_BACKGROUND_SOLID == backgroundOption) {
|
||
|
window.setBackgroundDrawable(ColorDrawable(if (isLightTheme(context)) Color.WHITE else Color.BLACK))
|
||
|
} else {
|
||
|
window.setBackgroundDrawable(getWindowBackground(context))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fun getDrawableFromThemeAttribute(context: Context, attr: Int): Drawable {
|
||
|
val a = TintTypedArray.obtainStyledAttributes(context, null, intArrayOf(attr))
|
||
|
try {
|
||
|
return a.getDrawable(0)
|
||
|
} finally {
|
||
|
a.recycle()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fun wrapMenuIcon(menu: Menu, itemColor: Int, subItemColor: Int, vararg excludeGroups: Int) {
|
||
|
for (i in 0 until menu.size()) {
|
||
|
val item = menu.getItem(i)
|
||
|
wrapMenuItemIcon(item, itemColor, *excludeGroups)
|
||
|
if (item.hasSubMenu()) {
|
||
|
wrapMenuIcon(item.subMenu, subItemColor, subItemColor, *excludeGroups)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fun wrapMenuIcon(view: ActionMenuView,
|
||
|
colorDark: Int = ContextCompat.getColor(view.context, R.color.action_icon_dark),
|
||
|
colorLight: Int = ContextCompat.getColor(view.context, R.color.action_icon_light),
|
||
|
vararg excludeGroups: Int) {
|
||
|
val context = view.context
|
||
|
val itemBackgroundColor = ThemeUtils.getThemeBackgroundColor(context)
|
||
|
val popupItemBackgroundColor = ThemeUtils.getThemeBackgroundColor(context, view.popupTheme)
|
||
|
val itemColor = TwidereColorUtils.getContrastYIQ(itemBackgroundColor, colorDark, colorLight)
|
||
|
val popupItemColor = TwidereColorUtils.getContrastYIQ(popupItemBackgroundColor, colorDark, colorLight)
|
||
|
val menu = view.menu
|
||
|
val childCount = view.childCount
|
||
|
var k = 0
|
||
|
for (i in 0 until menu.size()) {
|
||
|
val item = menu.getItem(i)
|
||
|
wrapMenuItemIcon(item, itemColor, *excludeGroups)
|
||
|
if (item.hasSubMenu()) {
|
||
|
wrapMenuIcon(item.subMenu, popupItemColor, popupItemColor, *excludeGroups)
|
||
|
}
|
||
|
if (item.isVisible) {
|
||
|
k++
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
fun wrapToolbarMenuIcon(view: ActionMenuView?, itemColor: Int, popupItemColor: Int, vararg excludeGroups: Int) {
|
||
|
if (view == null) return
|
||
|
val menu = view.menu
|
||
|
val childCount = view.childCount
|
||
|
var k = 0
|
||
|
for (i in 0 until menu.size()) {
|
||
|
val item = menu.getItem(i)
|
||
|
wrapMenuItemIcon(item, itemColor, *excludeGroups)
|
||
|
if (item.hasSubMenu()) {
|
||
|
wrapMenuIcon(item.subMenu, popupItemColor, popupItemColor, *excludeGroups)
|
||
|
}
|
||
|
if (item.isVisible) {
|
||
|
k++
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fun wrapMenuItemIcon(item: MenuItem, itemColor: Int, vararg excludeGroups: Int) {
|
||
|
if (item.groupId in excludeGroups) return
|
||
|
val icon = item.icon?.takeUnless { it is DoNotWrapDrawable } ?: return
|
||
|
if (icon is ActionIconDrawable) {
|
||
|
icon.defaultColor = itemColor
|
||
|
item.icon = icon
|
||
|
return
|
||
|
}
|
||
|
icon.mutate()
|
||
|
val callback = icon.callback
|
||
|
val newIcon = ActionIconDrawable(icon, itemColor)
|
||
|
newIcon.callback = callback
|
||
|
item.icon = newIcon
|
||
|
}
|
||
|
|
||
|
fun getColorFromAttribute(context: Context, attr: Int, def: Int = 0): Int {
|
||
|
val a = context.obtainStyledAttributes(intArrayOf(attr))
|
||
|
try {
|
||
|
return a.getColor(0, def)
|
||
|
} finally {
|
||
|
a.recycle()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fun getActionIconColor(context: Context): Int {
|
||
|
val itemBackgroundColor = ThemeUtils.getThemeBackgroundColor(context)
|
||
|
return getActionIconColor(context, itemBackgroundColor)
|
||
|
}
|
||
|
|
||
|
fun getActionIconColor(context: Context, backgroundColor: Int): Int {
|
||
|
val colorDark = ContextCompat.getColor(context, R.color.action_icon_dark)
|
||
|
val colorLight = ContextCompat.getColor(context, R.color.action_icon_light)
|
||
|
return if (ThemeUtils.isLightColor(backgroundColor)) colorDark else colorLight
|
||
|
}
|
||
|
|
||
|
fun getContrastActionBarItemColor(context: Context): Int {
|
||
|
return ThemeUtils.getColorFromAttribute(context, android.R.attr.colorForeground, 0)
|
||
|
}
|
||
|
|
||
|
fun getSelectableItemBackgroundDrawable(context: Context): Drawable? {
|
||
|
return getDrawableFromThemeAttribute(context, android.R.attr.selectableItemBackground)
|
||
|
}
|
||
|
|
||
|
fun getImageHighlightDrawable(context: Context): Drawable? {
|
||
|
return getSelectableItemBackgroundDrawable(context)?.apply {
|
||
|
alpha = 0x80
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fun isLightTheme(context: Context): Boolean {
|
||
|
val a = context.obtainStyledAttributes(intArrayOf(R.attr.isLightTheme))
|
||
|
try {
|
||
|
return a.getBoolean(0, false)
|
||
|
} finally {
|
||
|
a.recycle()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fun getWindowBackgroundFromThemeApplyAlpha(context: Context, alpha: Int): Drawable {
|
||
|
var backgroundColor: Int
|
||
|
val d = getWindowBackground(context)
|
||
|
if (d is ColorDrawable) {
|
||
|
backgroundColor = d.color
|
||
|
} else {
|
||
|
backgroundColor = getColorBackground(context)
|
||
|
}
|
||
|
backgroundColor = backgroundColor and 0x00FFFFFF
|
||
|
backgroundColor = ColorUtils.setAlphaComponent(backgroundColor,
|
||
|
alpha.coerceIn(MIN_ALPHA..MAX_ALPHA))
|
||
|
return WindowBackgroundDrawable(backgroundColor)
|
||
|
}
|
||
|
|
||
|
fun getWindowBackground(context: Context): Drawable? {
|
||
|
val a = context.obtainStyledAttributes(intArrayOf(android.R.attr.windowBackground))
|
||
|
try {
|
||
|
return a.getDrawable(0)
|
||
|
} finally {
|
||
|
a.recycle()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fun getThemeForegroundColor(context: Context): Int {
|
||
|
return getThemeForegroundColor(context, 0)
|
||
|
}
|
||
|
|
||
|
fun getThemeForegroundColor(context: Context, themeRes: Int): Int {
|
||
|
val value = TypedValue()
|
||
|
val theme: Resources.Theme
|
||
|
if (themeRes != 0) {
|
||
|
theme = context.resources.newTheme()
|
||
|
theme.applyStyle(themeRes, false)
|
||
|
} else {
|
||
|
theme = context.theme
|
||
|
}
|
||
|
if (!theme.resolveAttribute(android.R.attr.colorForeground, value, true)) {
|
||
|
return 0
|
||
|
}
|
||
|
if (value.type in TypedValue.TYPE_FIRST_COLOR_INT..TypedValue.TYPE_LAST_COLOR_INT) {
|
||
|
// windowBackground is a color
|
||
|
return value.data
|
||
|
}
|
||
|
return 0
|
||
|
}
|
||
|
|
||
|
|
||
|
fun getActionBarAlpha(alpha: Int): Int {
|
||
|
val normalizedAlpha = alpha.coerceIn(0, 0xFF)
|
||
|
val delta = MAX_ALPHA - normalizedAlpha
|
||
|
return (MAX_ALPHA - delta / 2).coerceIn(MIN_ALPHA, MAX_ALPHA)
|
||
|
}
|
||
|
|
||
|
fun getActionBarHeight(context: Context): Int {
|
||
|
val tv = TypedValue()
|
||
|
val theme = context.theme
|
||
|
val attr = R.attr.actionBarSize
|
||
|
if (theme.resolveAttribute(attr, tv, true)) {
|
||
|
return TypedValue.complexToDimensionPixelSize(tv.data, context.resources.displayMetrics)
|
||
|
}
|
||
|
return 0
|
||
|
}
|
||
|
|
||
|
fun getContrastColor(color: Int, darkColor: Int, lightColor: Int): Int {
|
||
|
if (TwidereColorUtils.getYIQLuminance(color) <= ACCENT_COLOR_THRESHOLD) {
|
||
|
//return light text color
|
||
|
return lightColor
|
||
|
}
|
||
|
//return dark text color
|
||
|
return darkColor
|
||
|
}
|
||
|
|
||
|
fun resetCheatSheet(menuView: ActionMenuView) {
|
||
|
val listener = View.OnLongClickListener { v ->
|
||
|
if ((v as ActionMenuItemView).hasText()) return@OnLongClickListener false
|
||
|
val menuItem = v.itemData
|
||
|
Utils.showMenuItemToast(v, menuItem.title, true)
|
||
|
return@OnLongClickListener true
|
||
|
}
|
||
|
(0 until menuView.childCount).forEach { i ->
|
||
|
val child = menuView.getChildAt(i) as? ActionMenuItemView ?: return@forEach
|
||
|
if (child.itemData.hasSubMenu()) return@forEach
|
||
|
child.setOnLongClickListener(listener)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fun getOptimalAccentColor(accentColor: Int, foregroundColor: Int): Int {
|
||
|
val yiq = IntArray(3)
|
||
|
TwidereColorUtils.colorToYIQ(foregroundColor, yiq)
|
||
|
val foregroundColorY = yiq[0]
|
||
|
TwidereColorUtils.colorToYIQ(accentColor, yiq)
|
||
|
if (foregroundColorY < DARK_COLOR_THRESHOLD && yiq[0] <= ACCENT_COLOR_THRESHOLD) {
|
||
|
return accentColor
|
||
|
} else if (foregroundColorY > ACCENT_COLOR_THRESHOLD && yiq[0] > DARK_COLOR_THRESHOLD) {
|
||
|
return accentColor
|
||
|
}
|
||
|
yiq[0] = yiq[0] + (foregroundColorY - yiq[0]) / 2
|
||
|
return TwidereColorUtils.YIQToColor(Color.alpha(accentColor), yiq)
|
||
|
}
|
||
|
|
||
|
fun setCompatContentViewOverlay(window: Window, overlay: Drawable?) {
|
||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) return
|
||
|
val contentLayout = window.findViewById(android.support.v7.appcompat.R.id.action_bar_activity_content)
|
||
|
?: window.findViewById(android.R.id.content) as? FrameLayout ?: return
|
||
|
ViewSupport.setForeground(contentLayout, overlay)
|
||
|
}
|
||
|
|
||
|
fun getSupportActionBarElevation(context: Context): Float {
|
||
|
val a = context.obtainStyledAttributes(null, intArrayOf(R.attr.elevation), R.attr.actionBarStyle, 0)
|
||
|
try {
|
||
|
return a.getDimension(0, 0f)
|
||
|
} finally {
|
||
|
a.recycle()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fun setActionBarOverflowColor(toolbar: Toolbar, itemColor: Int) {
|
||
|
if (toolbar is TwidereToolbar) {
|
||
|
toolbar.setItemColor(itemColor)
|
||
|
}
|
||
|
val overflowIcon = toolbar.overflowIcon
|
||
|
if (overflowIcon != null) {
|
||
|
overflowIcon.setColorFilter(itemColor, PorterDuff.Mode.SRC_ATOP)
|
||
|
toolbar.overflowIcon = overflowIcon
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fun applyColorFilterToMenuIcon(menu: Menu, @ColorInt color: Int,
|
||
|
@ColorInt popupColor: Int, @ColorInt highlightColor: Int, mode: PorterDuff.Mode,
|
||
|
vararg excludedGroups: Int) {
|
||
|
var i = 0
|
||
|
val j = menu.size()
|
||
|
while (i < j) {
|
||
|
val item = menu.getItem(i)
|
||
|
val icon = item.icon
|
||
|
val info = item.menuInfo
|
||
|
if (icon != null && item.groupId !in excludedGroups) {
|
||
|
icon.mutate()
|
||
|
if (info is TwidereMenuInfo) {
|
||
|
val sInfo = info
|
||
|
val stateColor = if (sInfo.isHighlight) sInfo.getHighlightColor(highlightColor) else color
|
||
|
if (stateColor != 0) {
|
||
|
icon.setColorFilter(stateColor, mode)
|
||
|
}
|
||
|
} else if (color != 0) {
|
||
|
icon.setColorFilter(color, mode)
|
||
|
}
|
||
|
}
|
||
|
if (item.hasSubMenu()) {
|
||
|
// SubMenu item is always in popup
|
||
|
applyColorFilterToMenuIcon(item.subMenu, popupColor, popupColor, highlightColor, mode, *excludedGroups)
|
||
|
}
|
||
|
i++
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fun applyToolbarItemColor(context: Context, toolbar: Toolbar, toolbarColor: Int) {
|
||
|
val contrastForegroundColor = ThemeUtils.getColorDependent(toolbarColor)
|
||
|
toolbar.setTitleTextColor(contrastForegroundColor)
|
||
|
toolbar.setSubtitleTextColor(contrastForegroundColor)
|
||
|
val popupItemColor: Int
|
||
|
val popupTheme = toolbar.popupTheme
|
||
|
if (popupTheme != 0) {
|
||
|
popupItemColor = getThemeForegroundColor(context, popupTheme)
|
||
|
} else {
|
||
|
popupItemColor = getThemeForegroundColor(context)
|
||
|
}
|
||
|
val navigationIcon = toolbar.navigationIcon
|
||
|
if (navigationIcon != null) {
|
||
|
navigationIcon.setColorFilter(contrastForegroundColor, PorterDuff.Mode.SRC_ATOP)
|
||
|
toolbar.navigationIcon = navigationIcon
|
||
|
}
|
||
|
getThemeForegroundColor(context)
|
||
|
setActionBarOverflowColor(toolbar, contrastForegroundColor)
|
||
|
wrapToolbarMenuIcon(ViewSupport.findViewByType(toolbar, ActionMenuView::class.java),
|
||
|
contrastForegroundColor, popupItemColor)
|
||
|
if (toolbar is TwidereToolbar) {
|
||
|
toolbar.setItemColor(contrastForegroundColor)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@ColorInt
|
||
|
private fun shiftColor(@ColorInt color: Int, @FloatRange(from = 0.0, to = 2.0) by: Float): Int {
|
||
|
if (by == 1.0f) {
|
||
|
return color
|
||
|
} else {
|
||
|
val hsv = FloatArray(3)
|
||
|
Color.colorToHSV(color, hsv)
|
||
|
hsv[2] *= by
|
||
|
return Color.HSVToColor(hsv)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private fun getUserAccentColor(context: Context, preferences: SharedPreferences): Int {
|
||
|
val color = preferences[themeColorKey]
|
||
|
if (color == 0) return ContextCompat.getColor(context, R.color.branding_color)
|
||
|
return color
|
||
|
}
|
||
|
|
||
|
}
|