6.6.2 - Alpha3 - 控件文字图标根据主题色亮度值自动切换颜色

This commit is contained in:
SuperMonster003
2025-03-08 23:16:49 +08:00
parent ce4f990046
commit b1c17f1222
35 changed files with 853 additions and 436 deletions

View File

@@ -92,7 +92,7 @@ class App : MultiDexApplication() {
val crashHandler = CrashHandler(ErrorReportActivity::class.java)
val strategy = CrashReport.UserStrategy(applicationContext)
strategy.crashHandleCallback = crashHandler
strategy.setCrashHandleCallback(crashHandler)
CrashReport.initCrashReport(applicationContext, BUGLY_APP_ID, false, strategy)
@@ -115,7 +115,6 @@ class App : MultiDexApplication() {
else -> ViewUtils.MODE.DAY
}
}
else -> ViewUtils.MODE.NULL
}
)
@@ -221,7 +220,7 @@ class App : MultiDexApplication() {
}
override fun onConfigurationChanged(newConfig: Configuration) {
ViewUtils.onConfigurationChanged(newConfig)
ViewUtils.onConfigurationChangedForNightMode(newConfig)
EventBus.getDefault().post(newConfig)
FloatyWindowManger.getCircularMenu()?.savePosition(newConfig)
super.onConfigurationChanged(newConfig)

View File

@@ -1,72 +1,56 @@
package org.autojs.autojs.core.image;
package org.autojs.autojs.core.image
import android.graphics.Color;
import androidx.annotation.ColorInt;
import org.autojs.autojs.util.ColorUtils;
import androidx.annotation.ColorInt
import org.autojs.autojs.annotation.ScriptInterface
import org.autojs.autojs.util.ColorUtils
/**
* Created by Stardust on Dec 31, 2017.
* Transformed by SuperMonster003 on Mar 8, 2025.
*/
public class Colors {
@Suppress("FunctionName")
class Colors {
public int rgb(int red, int green, int blue) {
return Color.rgb(red, green, blue);
}
@ScriptInterface
fun rgb(red: Int, green: Int, blue: Int) = ColorUtils.rgb(red, green, blue)
public int argb(int alpha, int red, int green, int blue) {
return Color.argb(alpha, red, green, blue);
}
@ScriptInterface
fun argb(alpha: Int, red: Int, green: Int, blue: Int) = ColorUtils.argb(alpha, red, green, blue)
/**
* @see <a href="https://www.w3.org/TR/WCAG20/#relativeluminancedef">W3C Recommendation</a>
* @see ColorUtils.luminance
*/
public double luminance(@ColorInt int color) {
// return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
// ? Color.luminance(Color.pack(color))
// : Color.luminance(color);
return androidx.core.graphics.ColorUtils.calculateLuminance(color);
}
@ScriptInterface
fun luminance(@ColorInt color: Int) = ColorUtils.luminance(color)
public int parseColor(String colorString) {
return Color.parseColor(colorString);
}
@ScriptInterface
fun parseColor(colorString: String?) = ColorUtils.parseColor(colorString)
public String toString(int color) {
return ColorUtils.toString(color);
}
@ScriptInterface
fun toString(color: Int) = ColorUtils.toString(color)
public void RGBToHSV(int red, int green, int blue, float[] hsv) {
Color.RGBToHSV(red, green, blue, hsv);
}
@ScriptInterface
fun RGBToHSV(red: Int, green: Int, blue: Int, hsv: FloatArray?) = ColorUtils.RGBToHSV(red, green, blue, hsv)
public void colorToHSV(int color, float[] hsv) {
Color.colorToHSV(color, hsv);
}
@ScriptInterface
fun colorToHSV(color: Int, hsv: FloatArray?) = ColorUtils.colorToHSV(color, hsv)
public int HSVToColor(float[] hsv) {
return Color.HSVToColor(hsv);
}
@ScriptInterface
fun HSVToColor(hsv: FloatArray?) = ColorUtils.HSVToColor(hsv)
public int HSVToColor(int alpha, float[] hsv) {
return Color.HSVToColor(alpha, hsv);
}
@ScriptInterface
fun HSVToColor(alpha: Int, hsv: FloatArray?) = ColorUtils.HSVToColor(alpha, hsv)
public boolean equals(int c1, int c2) {
return (c1 & 0xffffff) == (c2 & 0xffffff);
}
@ScriptInterface
fun equals(c1: Int, c2: Int) = ColorUtils.equals(c1, c2)
public boolean equals(int c1, String c2) {
return equals(c1, parseColor(c2));
}
@ScriptInterface
fun equals(c1: Int, c2: String?) = ColorUtils.equals(c1, c2)
public boolean equals(String c1, int c2) {
return equals(parseColor(c1), c2);
}
@ScriptInterface
fun equals(c1: String?, c2: Int) = ColorUtils.equals(c1, c2)
public boolean equals(String c1, String c2) {
return equals(parseColor(c1), parseColor(c2));
}
@ScriptInterface
fun equals(c1: String?, c2: String?) = ColorUtils.equals(c1, c2)
}

View File

@@ -9,6 +9,7 @@ import org.autojs.autojs.core.pref.Pref.getInt
import org.autojs.autojs.core.pref.Pref.putInt
import org.autojs.autojs.extension.ArrayExtensions.toHashCode
import org.autojs.autojs.theme.ThemeColorManager.defaultThemeColor
import org.autojs.autojs.util.ColorUtils
import org.autojs.autojs6.R
/**
@@ -36,6 +37,10 @@ class ThemeColor {
@ScriptInterface
fun getColorPrimaryDark() = colorPrimaryDark
fun isLuminanceLight() = ColorUtils.isLuminanceLight(colorPrimary)
fun isLuminanceDark() = ColorUtils.isLuminanceDark(colorPrimary)
constructor()
constructor(color: Int) : this(color, color, color)

View File

@@ -6,8 +6,7 @@ import android.view.View
import org.autojs.autojs.util.ColorUtils
import org.autojs.autojs6.R
import java.lang.ref.WeakReference
import java.util.LinkedList
import java.util.Vector
import java.util.*
/**
* Created by Stardust on May 10, 2016.
@@ -28,6 +27,12 @@ object ThemeColorManager {
ThemeColor.fromPreferences()?.let { currentThemeColor = it } ?: setThemeColor(defaultThemeColor)
}
@JvmStatic
fun isThemeColorLuminanceLight() = currentThemeColor.isLuminanceLight()
@JvmStatic
fun isThemeColorLuminanceDark() = currentThemeColor.isLuminanceDark()
@JvmStatic
fun add(colorMutable: ThemeColorMutable) = ThemeColorMutableManager.add(colorMutable)

View File

@@ -0,0 +1,16 @@
package org.autojs.autojs.theme
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
object ThemeChangeNotifier {
private val _themeChanged = MutableLiveData<Unit>()
val themeChanged: LiveData<Unit> get() = _themeChanged
fun notifyThemeChanged() {
_themeChanged.postValue(Unit)
}
}

View File

@@ -1,37 +1,23 @@
package org.autojs.autojs.theme.app
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.content.res.ColorStateList
import android.graphics.PorterDuff
import android.graphics.PorterDuffColorFilter
import android.os.Bundle
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.view.View.OnClickListener
import android.view.ViewAnimationUtils
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.annotation.ColorInt
import androidx.appcompat.widget.Toolbar
import androidx.fragment.app.FragmentActivity
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.ThemeColorRecyclerView
import com.google.android.material.appbar.AppBarLayout
import com.jaredrummler.android.colorpicker.ColorPickerDialog
import com.jaredrummler.android.colorpicker.ColorPickerDialogListener
import org.autojs.autojs.core.pref.Pref
import org.autojs.autojs.theme.ThemeChangeNotifier
import org.autojs.autojs.theme.ThemeColor
import org.autojs.autojs.theme.ThemeColorHelper
import org.autojs.autojs.theme.ThemeColorManager
import org.autojs.autojs.ui.BaseActivity
import org.autojs.autojs.util.ColorUtils
import org.autojs.autojs.util.StringUtils.key
import org.autojs.autojs.util.ViewUtils.appendSystemUiVisibility
import org.autojs.autojs.util.ViewUtils
import org.autojs.autojs6.R
import org.autojs.autojs6.databinding.MtActivityColorSelectBinding
import kotlin.math.hypot
/**
@@ -41,6 +27,10 @@ import kotlin.math.hypot
*/
class ColorSelectActivity : BaseActivity() {
override val handleStatusBarThemeColorAutomatically = false
private var binding: MtActivityColorSelectBinding? = null
private lateinit var mAppBarLayout: AppBarLayout
private lateinit var mTitle: String
private lateinit var mColorSettingRecyclerView: ColorSettingRecyclerView
@@ -55,28 +45,33 @@ class ColorSelectActivity : BaseActivity() {
}
}
@Suppress("DEPRECATION")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
handleIntent()
setUpUI()
appendSystemUiVisibility(this, View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_STABLE)
binding = MtActivityColorSelectBinding.inflate(layoutInflater).also {
setUpUI(it)
}
}
override fun onDestroy() {
super.onDestroy()
binding = null
}
private fun handleIntent() {
mTitle = intent.getStringExtra("title") ?: getString(R.string.mt_color_picker_title)
}
private fun setUpUI() {
setContentView(R.layout.mt_activity_color_select)
private fun setUpUI(binding: MtActivityColorSelectBinding) {
setContentView(binding.root)
mCurrentColor = ThemeColorManager.colorPrimary
mAppBarLayout = findViewById<AppBarLayout?>(R.id.appBar).apply { setBackgroundColor(mCurrentColor) }
setUpToolbar()
setUpColorSettingRecyclerView()
mAppBarLayout = binding.appBar.apply { setBackgroundColor(mCurrentColor) }
setUpToolbar(binding)
setUpColorSettingRecyclerView(binding)
}
private fun setUpToolbar() {
findViewById<Toolbar>(R.id.toolbar).also { toolbar ->
private fun setUpToolbar(binding: MtActivityColorSelectBinding) {
binding.toolbar.also { toolbar ->
toolbar.title = mTitle
setSupportActionBar(toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
@@ -84,26 +79,53 @@ class ColorSelectActivity : BaseActivity() {
}
}
private fun setUpColorSettingRecyclerView() {
mColorSettingRecyclerView = findViewById<ColorSettingRecyclerView?>(R.id.color_setting_recycler_view)
.apply {
setCustomColor()
setSelectedColor(mCurrentColor)
setOnItemClickListener(mOnItemClickListener)
}
private fun setUpColorSettingRecyclerView(binding: MtActivityColorSelectBinding) {
mColorSettingRecyclerView = binding.colorSettingRecyclerView.apply {
setCustomColor()
setSelectedColor(mCurrentColor)
setOnItemClickListener(mOnItemClickListener)
}
}
override fun finish() {
mColorSettingRecyclerView.selectedThemeColor?.let {
ThemeColorManager.setThemeColor(it.colorPrimary)
Pref.putString(key(R.string.key_theme_color), getColorString(this))
ThemeChangeNotifier.notifyThemeChanged()
}
super.finish()
}
override fun initThemeColors() {
super.initThemeColors()
setUpToolbarColors()
setUpStatusBarIconLight()
}
private fun setUpToolbarColors() {
val toolbar = binding!!.toolbar
val aimColor = when {
ColorUtils.isLuminanceLight(mCurrentColor) -> getColor(R.color.day)
else -> getColor(R.color.night)
}
toolbar.setTitleTextColor(aimColor)
toolbar.setSubtitleTextColor(aimColor)
toolbar.navigationIcon?.let { navigationIcon ->
navigationIcon.colorFilter = PorterDuffColorFilter(aimColor, PorterDuff.Mode.SRC_IN)
}
}
private fun setUpStatusBarIconLight() {
ViewUtils.setStatusBarIconLight(this, ColorUtils.isLuminanceDark(mCurrentColor))
}
private fun setColorWithAnimation(view: View, colorTo: Int) {
findViewById<View>(R.id.appBarContainer).setBackgroundColor(mCurrentColor)
binding!!.appBarContainer.setBackgroundColor(mCurrentColor)
view.setBackgroundColor(colorTo)
mCurrentColor = colorTo
initThemeColors()
ViewAnimationUtils.createCircularReveal(
/* view = */ view,
/* centerX = */ view.left,
@@ -111,13 +133,12 @@ class ColorSelectActivity : BaseActivity() {
/* startRadius = */ 0f,
/* endRadius = */ hypot(view.width.toDouble(), view.height.toDouble()).toFloat()
).apply {
duration = 500
duration = 500L
start()
}
mCurrentColor = colorTo
}
private class ColorItem(var name: String, var themeColor: ThemeColor) {
class ColorItem(var name: String, var themeColor: ThemeColor) {
constructor(name: String, color: Int) : this(name, ThemeColor(color))
}
@@ -152,7 +173,7 @@ class ColorSelectActivity : BaseActivity() {
return "${colorItem.name} [${ColorUtils.toString(colorItem.themeColor.colorPrimary).uppercase()}]"
}
private fun getColorItems(context: Context): List<ColorItem> = ArrayList<Pair</* nameRes */ Int, /* colorInt */ Int>>()
internal fun getColorItems(context: Context): List<ColorItem> = ArrayList<Pair</* nameRes */ Int, /* colorInt */ Int>>()
.apply {
add(customColorPosition, Pair(Pref.getInt(KEY_CUSTOM_COLOR, context.getColor(R.color.md_blue_grey_800)), R.string.mt_custom))
add(defaultColorPosition, Pair(context.getColor(R.color.theme_color_default), R.string.theme_color_default))
@@ -160,147 +181,6 @@ class ColorSelectActivity : BaseActivity() {
}
.map { (colorInt, nameRes) -> ColorItem(context.getString(nameRes), colorInt) }
class ColorSettingRecyclerView : ThemeColorRecyclerView {
private var mOnItemClickListener: OnItemClickListener? = null
private var mSelectedPosition = SELECT_NONE
val selectedThemeColor: ThemeColor?
get() = getColorItems(context)[mSelectedPosition].themeColor.takeUnless { mSelectedPosition < 0 }
private val customColor: Int
get() = Pref.getInt(KEY_CUSTOM_COLOR, context.getColor(R.color.md_blue_grey_800))
private val mActualOnItemClickListener = OnClickListener { v ->
getChildViewHolder(v)?.let { holder ->
val pos = holder.bindingAdapterPosition
if (pos == customColorPosition) {
showColorPicker(v)
} else {
setSelectedPosition(pos)
mOnItemClickListener?.onItemClick(v, pos)
}
}
}
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyle: Int) : super(context, attrs, defStyle)
init {
adapter = Adapter()
layoutManager = LinearLayoutManager(context)
addItemDecoration(DividerItemDecoration(context, VERTICAL))
}
@SuppressLint("NotifyDataSetChanged")
fun setSelectedPosition(currentPosition: Int) {
if (mSelectedPosition != SELECT_NONE) {
adapter!!.notifyItemChanged(mSelectedPosition)
mSelectedPosition = currentPosition
adapter!!.notifyItemChanged(currentPosition)
} else {
mSelectedPosition = currentPosition
adapter!!.notifyDataSetChanged()
}
Pref.putInt(KEY_SELECTED_COLOR_INDEX, mSelectedPosition)
}
fun setSelectedColor(colorPrimary: Int) {
for ((i, colorItem) in getColorItems(context).withIndex()) {
if (colorItem.themeColor.colorPrimary == colorPrimary) {
return Unit.also { setSelectedPosition(i) }
}
}
mSelectedPosition = SELECT_NONE
}
private fun setCustomColor(color: Int) {
getColorItems(context)[customColorPosition].themeColor.colorPrimary = color
}
fun setCustomColor() {
setCustomColor(customColor)
}
private fun showColorPicker(v: View) {
ColorPickerDialog.newBuilder()
.setAllowCustom(true)
.setAllowPresets(false)
.setDialogType(ColorPickerDialog.TYPE_CUSTOM)
.setShowAlphaSlider(false)
.setDialogTitle(R.string.mt_color_picker_title)
.setColor(customColor)
.create()
.apply {
setColorPickerDialogListener(object : ColorPickerDialogListener {
override fun onColorSelected(dialogId: Int, @ColorInt color: Int) {
val c = color or -0x1000000
Pref.putInt(KEY_CUSTOM_COLOR, c)
setCustomColor(c)
setSelectedPosition(customColorPosition)
mOnItemClickListener?.onItemClick(v, customColorPosition)
}
override fun onDialogDismissed(dialogId: Int) {}
})
}
.show((context as FragmentActivity).supportFragmentManager, "Tag")
}
fun setOnItemClickListener(onItemClickListener: OnItemClickListener?) {
mOnItemClickListener = onItemClickListener
}
private inner class Adapter : RecyclerView.Adapter<ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(LayoutInflater.from(context).inflate(R.layout.mt_color_setting_recycler_view_item, parent, false))
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = getColorItems(context)[position]
holder.apply {
setColor(item.themeColor.colorPrimary)
name.text = item.name
name.setTextColor(context.getColor(R.color.color_selector_item_text))
setChecked(mSelectedPosition == position)
}
}
override fun getItemCount() = getColorItems(context).size
}
private inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var color: ImageView
var name: TextView
init {
itemView.setOnClickListener(mActualOnItemClickListener)
color = itemView.findViewById(R.id.color)
name = itemView.findViewById(R.id.name)
}
fun setChecked(checked: Boolean) {
if (checked) {
color.setImageResource(R.drawable.mt_ic_check_white_36dp)
color.imageTintList = ColorStateList.valueOf(context.getColor(R.color.night_day))
} else {
color.setImageDrawable(null)
}
}
fun setColor(c: Int) = ThemeColorHelper.setBackgroundColor(color, c)
}
}
}
}

View File

@@ -0,0 +1,170 @@
package org.autojs.autojs.theme.app
import android.annotation.SuppressLint
import android.content.Context
import android.content.res.ColorStateList
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.view.View.OnClickListener
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.annotation.ColorInt
import androidx.fragment.app.FragmentActivity
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.ThemeColorRecyclerView
import com.jaredrummler.android.colorpicker.ColorPickerDialog
import com.jaredrummler.android.colorpicker.ColorPickerDialogListener
import org.autojs.autojs.core.pref.Pref
import org.autojs.autojs.theme.ThemeColor
import org.autojs.autojs.theme.ThemeColorHelper
import org.autojs.autojs.util.ColorUtils
import org.autojs.autojs6.R
class ColorSettingRecyclerView : ThemeColorRecyclerView {
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyle: Int) : super(context, attrs, defStyle)
private var mOnItemClickListener: ColorSelectActivity.OnItemClickListener? = null
private var mSelectedPosition = ColorSelectActivity.SELECT_NONE
val selectedThemeColor: ThemeColor?
get() = ColorSelectActivity.getColorItems(context)[mSelectedPosition].themeColor.takeUnless { mSelectedPosition < 0 }
private val customColor: Int
get() = Pref.getInt(ColorSelectActivity.KEY_CUSTOM_COLOR, context.getColor(R.color.md_blue_grey_800))
private val mActualOnItemClickListener = OnClickListener { v ->
getChildViewHolder(v)?.let { holder ->
val pos = holder.bindingAdapterPosition
if (pos == ColorSelectActivity.customColorPosition) {
showColorPicker(v)
} else {
setSelectedPosition(pos)
mOnItemClickListener?.onItemClick(v, pos)
}
}
}
init {
adapter = Adapter()
layoutManager = LinearLayoutManager(context)
addItemDecoration(DividerItemDecoration(context, VERTICAL))
}
@SuppressLint("NotifyDataSetChanged")
fun setSelectedPosition(currentPosition: Int) {
if (mSelectedPosition != ColorSelectActivity.SELECT_NONE) {
adapter!!.notifyItemChanged(mSelectedPosition)
mSelectedPosition = currentPosition
adapter!!.notifyItemChanged(currentPosition)
} else {
mSelectedPosition = currentPosition
adapter!!.notifyDataSetChanged()
}
Pref.putInt(ColorSelectActivity.KEY_SELECTED_COLOR_INDEX, mSelectedPosition)
}
fun setSelectedColor(colorPrimary: Int) {
for ((i, colorItem) in ColorSelectActivity.getColorItems(context).withIndex()) {
if (colorItem.themeColor.colorPrimary == colorPrimary) {
setSelectedPosition(i)
return
}
}
mSelectedPosition = ColorSelectActivity.SELECT_NONE
}
private fun setCustomColor(color: Int) {
ColorSelectActivity.getColorItems(context)[ColorSelectActivity.customColorPosition].themeColor.colorPrimary = color
}
fun setCustomColor() {
setCustomColor(customColor)
}
private fun showColorPicker(v: View) {
ColorPickerDialog.newBuilder()
.setAllowCustom(true)
.setAllowPresets(false)
.setDialogType(ColorPickerDialog.TYPE_CUSTOM)
.setShowAlphaSlider(false)
.setDialogTitle(R.string.mt_color_picker_title)
.setColor(customColor)
.create()
.apply {
setColorPickerDialogListener(object : ColorPickerDialogListener {
override fun onColorSelected(dialogId: Int, @ColorInt color: Int) {
val c = color or -0x1000000
Pref.putInt(ColorSelectActivity.KEY_CUSTOM_COLOR, c)
setCustomColor(c)
setSelectedPosition(ColorSelectActivity.customColorPosition)
mOnItemClickListener?.onItemClick(v, ColorSelectActivity.customColorPosition)
}
override fun onDialogDismissed(dialogId: Int) {}
})
}
.show((context as FragmentActivity).supportFragmentManager, "Tag")
}
fun setOnItemClickListener(onItemClickListener: ColorSelectActivity.OnItemClickListener?) {
mOnItemClickListener = onItemClickListener
}
private inner class Adapter : RecyclerView.Adapter<ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(LayoutInflater.from(context).inflate(R.layout.mt_color_setting_recycler_view_item, parent, false))
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = ColorSelectActivity.getColorItems(context)[position]
holder.apply {
setColor(item.themeColor.colorPrimary)
nameView.text = item.name
nameView.setTextColor(context.getColor(R.color.color_selector_item_text))
setChecked(mSelectedPosition == position)
}
}
override fun getItemCount() = ColorSelectActivity.getColorItems(context).size
}
private inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var colorView: ImageView
var nameView: TextView
init {
itemView.setOnClickListener(mActualOnItemClickListener)
colorView = itemView.findViewById(R.id.color)
nameView = itemView.findViewById(R.id.name)
}
fun setChecked(checked: Boolean) {
if (checked) {
colorView.setImageResource(R.drawable.mt_ic_check_white_36dp)
val selectedThemeColorRes = selectedThemeColor?.colorPrimary?.let {
if (ColorUtils.isLuminanceLight(it)) R.color.day else R.color.night
} ?: R.color.night_day
colorView.imageTintList = ColorStateList.valueOf(context.getColor(selectedThemeColorRes))
} else {
colorView.setImageDrawable(null)
}
}
fun setColor(c: Int) = ThemeColorHelper.setBackgroundColor(colorView, c)
}
}

View File

@@ -9,6 +9,8 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton;
import org.autojs.autojs.theme.ThemeColor;
import org.autojs.autojs.theme.ThemeColorManager;
import org.autojs.autojs.theme.ThemeColorMutable;
import org.autojs.autojs.util.ColorUtils;
import org.autojs.autojs6.R;
/**
* Created by Stardust on Aug 16, 2016.
@@ -35,7 +37,13 @@ public class ThemeColorFloatingActionButton extends FloatingActionButton impleme
@Override
public void setThemeColor(ThemeColor color) {
setBackgroundTintList(ColorStateList.valueOf(color.colorAccent));
int colorAccent = color.colorAccent;
setBackgroundTintList(ColorStateList.valueOf(colorAccent));
var tintColorRes = ColorUtils.isLuminanceLight(colorAccent)
? R.color.fab_tint_dark
: R.color.fab_tint_light;
var tintColor = getResources().getColor(tintColorRes, null);
setImageTintList(ColorStateList.valueOf(tintColor));
}
}

View File

@@ -1,11 +1,13 @@
package org.autojs.autojs.theme.widget;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.Toolbar;
import org.autojs.autojs.theme.ThemeColor;
import org.autojs.autojs.theme.ThemeColorManager;
import org.autojs.autojs.theme.ThemeColorMutable;
@@ -40,7 +42,43 @@ public class ThemeColorToolbar extends Toolbar implements ThemeColorMutable {
@Override
public void setThemeColor(ThemeColor color) {
setBackgroundColor(color.colorPrimary);
getViewTreeObserver().addOnGlobalLayoutListener(() -> applyThemeColor(color));
}
private void applyThemeColor(ThemeColor color) {
int colorPrimary = color.colorPrimary;
setBackgroundColor(colorPrimary);
int aimColor;
int popupTheme;
if (ThemeColorManager.isThemeColorLuminanceLight()) {
aimColor = getResources().getColor(R.color.day, null);
popupTheme = R.style.PopupMenuThemeLight;
} else {
aimColor = getResources().getColor(R.color.night, null);
popupTheme = R.style.PopupMenuThemeDark;
}
setTitleTextColor(aimColor);
setSubtitleTextColor(aimColor);
Drawable navigationIcon = getNavigationIcon();
if (navigationIcon != null) {
navigationIcon.setColorFilter(new PorterDuffColorFilter(aimColor, PorterDuff.Mode.SRC_IN));
setNavigationIcon(navigationIcon);
}
Drawable collapseIcon = getCollapseIcon();
if (collapseIcon != null) {
collapseIcon.setColorFilter(new PorterDuffColorFilter(aimColor, PorterDuff.Mode.SRC_IN));
setCollapseIcon(collapseIcon);
}
Drawable overflowIcon = getOverflowIcon();
if (overflowIcon != null) {
overflowIcon.setColorFilter(new PorterDuffColorFilter(aimColor, PorterDuff.Mode.SRC_IN));
setOverflowIcon(overflowIcon);
}
setPopupTheme(popupTheme);
}
}

View File

@@ -5,11 +5,15 @@ package org.autojs.autojs.ui
import android.content.Context
import android.os.Build
import android.os.Bundle
import android.view.View
import android.view.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
import android.view.View.SYSTEM_UI_FLAG_LAYOUT_STABLE
import android.view.WindowManager
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import org.autojs.autojs.core.accessibility.AccessibilityTool
import org.autojs.autojs.core.pref.Language
import org.autojs.autojs.theme.ThemeChangeNotifier
import org.autojs.autojs.theme.ThemeColorManager
import org.autojs.autojs.util.LocaleUtils
import org.autojs.autojs.util.ViewUtils
@@ -21,27 +25,22 @@ import org.autojs.autojs6.BuildConfig
*/
abstract class BaseActivity : AppCompatActivity() {
open val handleStatusBarThemeColorAutomatically = true
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (ViewUtils.isAutoNightModeEnabled) {
val isNightModeYes = ViewUtils.isNightModeYes(this)
if (ViewUtils.isNightModeEnabled != isNightModeYes) {
ViewUtils.isNightModeEnabled = isNightModeYes
val mode = when (isNightModeYes) {
true -> ViewUtils.MODE.NIGHT
else -> ViewUtils.MODE.DAY
}
ViewUtils.setDefaultNightMode(mode)
}
}
@Suppress("DEPRECATION")
ViewUtils.appendSystemUiVisibility(this, SYSTEM_UI_FLAG_LAYOUT_STABLE or SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)
if (!BuildConfig.isInrt) {
ViewUtils.makeBarsAdaptToNightMode(this)
}
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
setApplicationLocale(this)
ThemeChangeNotifier.themeChanged.observe(this) {
initThemeColors()
}
// @Dubious by SuperMonster003 on Oct 28, 2024.
// ! Is it property to start a11y service automatically here?
// ! zh-CN: 无障碍服务自启动放在这里是否合适?
@@ -62,11 +61,11 @@ abstract class BaseActivity : AppCompatActivity() {
override fun onStart() {
super.onStart()
if (!BuildConfig.isInrt) {
if (window.decorView.systemUiVisibility and SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN == 0) {
ThemeColorManager.addActivityStatusBar(this)
}
initThemeColors()
if (handleStatusBarThemeColorAutomatically && !BuildConfig.isInrt) {
ThemeColorManager.addActivityStatusBar(this)
}
setUpStatusBarIconLightByThemeColor()
}
override fun onResume() {
@@ -74,8 +73,20 @@ abstract class BaseActivity : AppCompatActivity() {
LocaleUtils.syncPrefWithCurrentStateIfNeeded(this)
}
open fun initThemeColors() {
/* Empty body. */
}
fun setToolbarAsBack(titleRes: Int) = ViewUtils.setToolbarAsBack(this, titleRes)
fun setToolbarAsBack(title: String?) = ViewUtils.setToolbarAsBack(this, title)
protected fun setUpStatusBarIconLightByNightMode() {
ViewUtils.setStatusBarIconLight(this, ViewUtils.isNightModeEnabled)
}
protected fun setUpStatusBarIconLightByThemeColor() {
ViewUtils.setStatusBarIconLight(this, ThemeColorManager.isThemeColorLuminanceDark())
}
}

View File

@@ -717,7 +717,7 @@ open class ExplorerView : ThemeColorSwipeRefreshLayout, SwipeRefreshLayout.OnRef
mFirstChar.setIcon(ExplorerViewHelper.getIcon(item))
when (item.type) {
FileUtils.TYPE.JAVASCRIPT, FileUtils.TYPE.AUTO -> mFirstChar
.setIconTextColorNightDay()
.setIconTextByThemeColorLuminance()
.setStrokeThemeColor()
.setFillThemeColor()
else -> mFirstChar

View File

@@ -46,7 +46,7 @@ class ExplorerItemViewHolder extends BindableViewHolder<Object> {
switch (explorerItem.getType()) {
case JAVASCRIPT, AUTO -> firstCharIconBinding.firstChar
.setIconTextColorNightDay()
.setIconTextByThemeColorLuminance()
.setStrokeThemeColor()
.setFillColorDayNight();
default -> firstCharIconBinding.firstChar

View File

@@ -5,7 +5,12 @@ import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.content.res.ColorStateList
import android.graphics.PorterDuff
import android.graphics.PorterDuffColorFilter
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.os.Process
import android.util.Log
import android.view.Gravity
@@ -14,11 +19,13 @@ import android.view.MenuItem
import android.view.View
import androidx.activity.result.contract.ActivityResultContracts.RequestMultiplePermissions
import androidx.appcompat.app.ActionBarDrawerToggle
import androidx.core.view.forEach
import androidx.drawerlayout.widget.DrawerLayout
import androidx.fragment.app.Fragment
import androidx.viewpager.widget.ViewPager
import androidx.viewpager.widget.ViewPager.SimpleOnPageChangeListener
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.android.material.tabs.TabLayout
import com.huaban.analysis.jieba.CharsDictionaryDatabase
import com.huaban.analysis.jieba.PhrasesDictionaryDatabase
import com.huaban.analysis.jieba.WordDictionaryDatabase
@@ -40,7 +47,9 @@ import org.autojs.autojs.permission.ManageAllFilesPermission
import org.autojs.autojs.permission.PostNotificationPermission
import org.autojs.autojs.runtime.api.WrappedShizuku
import org.autojs.autojs.service.ForegroundService
import org.autojs.autojs.theme.ThemeColorManager
import org.autojs.autojs.theme.ThemeColorManager.addViewBackground
import org.autojs.autojs.theme.widget.ThemeColorToolbar
import org.autojs.autojs.ui.BaseActivity
import org.autojs.autojs.ui.doc.DocumentationFragment
import org.autojs.autojs.ui.enhancedfloaty.FloatyService
@@ -54,6 +63,7 @@ import org.autojs.autojs.ui.main.task.TaskManagerFragment
import org.autojs.autojs.ui.settings.PreferencesActivity
import org.autojs.autojs.ui.widget.DrawerAutoClose
import org.autojs.autojs.ui.widget.SearchViewItem
import org.autojs.autojs.util.StringUtils.key
import org.autojs.autojs.util.UpdateUtils
import org.autojs.autojs.util.ViewUtils
import org.autojs.autojs.util.WorkingDirectoryUtils
@@ -67,12 +77,18 @@ import org.greenrobot.eventbus.EventBus
*/
class MainActivity : BaseActivity(), DelegateHost, HostActivity {
override val handleStatusBarThemeColorAutomatically = false
private var binding: ActivityMainBinding? = null
private lateinit var mViewPager: ViewPager
private lateinit var mFab: FloatingActionButton
private lateinit var mTab: TabLayout
private lateinit var mToolbar: ThemeColorToolbar
private lateinit var mPagerAdapter: StoredFragmentPagerAdapter
private lateinit var mLogMenuItem: MenuItem
private lateinit var mSearchMenuItem: MenuItem
private lateinit var mActionBarDrawerToggle: ActionBarDrawerToggle
private val mActivityResultMediator = OnActivityResultDelegate.Mediator()
private val mRequestPermissionCallbacks = RequestPermissionCallbacks()
@@ -119,14 +135,19 @@ class MainActivity : BaseActivity(), DelegateHost, HostActivity {
setContentView(it.root)
mViewPager = it.viewpager
mFab = it.fab
mTab = it.tab
mToolbar = it.toolbar
addViewBackground(it.appBar)
setUpToolbar(it, drawerLayout)
setUpToolbar(drawerLayout)
setUpTabViewPager(it)
registerBackPressHandlers(drawerLayout)
}
@Suppress("DEPRECATION")
ViewUtils.appendSystemUiVisibility(this, View.SYSTEM_UI_FLAG_LAYOUT_STABLE)
ViewUtils.registerOnSharedPreferenceChangeListener(this)
Pref.registerOnSharedPreferenceChangeListener { _, key ->
if (key == key(R.string.key_keep_screen_on_when_in_foreground)) {
ViewUtils.configKeepScreenOnWhenInForeground(this)
}
}
WorkingDirectoryUtils.determineIfNeeded()
ExplorerView.clearViewStates()
@@ -162,27 +183,37 @@ class MainActivity : BaseActivity(), DelegateHost, HostActivity {
mBackPressObserver.registerHandler(DoublePressExit(this, R.string.text_press_again_to_exit))
}
private fun setUpToolbar(binding: ActivityMainBinding, drawerLayout: DrawerLayout) {
val toolbar = binding.toolbar.also {
private fun setUpToolbar(drawerLayout: DrawerLayout) {
val toolbar = mToolbar.also {
setSupportActionBar(it)
it.setTitle(R.string.app_name)
it.setOnLongClickListener { true.also { PreferencesActivity.launch(this) } }
}
object : ActionBarDrawerToggle(
mActionBarDrawerToggle = object : ActionBarDrawerToggle(
this,
drawerLayout,
toolbar,
R.string.text_drawer_open,
R.string.text_drawer_close
) {
override fun onDrawerSlide(drawerView: View, slideOffset: Float) {
super.onDrawerSlide(drawerView, slideOffset)
when {
slideOffset > 0.5 -> setUpStatusBarIconLightByNightMode()
else -> setUpStatusBarIconLightByThemeColor()
}
}
override fun onDrawerOpened(drawerView: View) {
super.onDrawerOpened(drawerView)
sIsActionBarDrawerOpened = true
EventBus.getDefault().post(object : OnDrawerOpened {})
}
override fun onDrawerClosed(drawerView: View) {
super.onDrawerClosed(drawerView)
sIsActionBarDrawerOpened = false
EventBus.getDefault().post(object : OnDrawerClosed {})
}
}.also {
@@ -224,6 +255,67 @@ class MainActivity : BaseActivity(), DelegateHost, HostActivity {
}
}
override fun initThemeColors() {
super.initThemeColors()
setUpToolbarColors()
setUpTabLayoutColors()
setUpStatusBarIconLight()
}
override fun onWindowFocusChanged(hasFocus: Boolean) {
super.onWindowFocusChanged(hasFocus)
if (hasFocus) {
setUpStatusBarIconLight()
}
}
private fun setUpToolbarColors() {
val aimColor = when {
ThemeColorManager.isThemeColorLuminanceLight() -> getColor(R.color.day)
else -> getColor(R.color.night)
}
mToolbar.menu.forEach { menuItem ->
menuItem.icon?.colorFilter = PorterDuffColorFilter(aimColor, PorterDuff.Mode.SRC_IN)
}
mSearchViewItem?.initThemeColors()
}
private fun setUpTabLayoutColors() {
val tabNormalColor: Int
val tabSelectedColor: Int
val tabSelectedIndicatorColor: Int
when {
ThemeColorManager.isThemeColorLuminanceLight() -> {
tabNormalColor = getColor(R.color.tab_text_dark)
tabSelectedColor = getColor(R.color.tab_selected_text_dark)
tabSelectedIndicatorColor = getColor(R.color.tab_indicator_dark)
}
else -> {
tabNormalColor = getColor(R.color.tab_text_light)
tabSelectedColor = getColor(R.color.tab_selected_text_light)
tabSelectedIndicatorColor = getColor(R.color.tab_indicator_light)
}
}
mTab.setTabTextColors(tabNormalColor, tabSelectedColor)
mTab.setSelectedTabIndicatorColor(tabSelectedIndicatorColor)
}
private fun setUpStatusBarIconLight() {
if (shouldChangeStatusBarIconLight()) {
Handler(Looper.getMainLooper()).post {
if (sIsActionBarDrawerOpened) {
setUpStatusBarIconLightByNightMode()
} else {
setUpStatusBarIconLightByThemeColor()
}
}
}
}
private fun shouldChangeStatusBarIconLight(): Boolean {
return ViewUtils.isNightModeEnabled == ViewUtils.isStatusBarIconDark(this)
}
fun rebirth() {
packageManager.getLaunchIntentForPackage(packageName)?.let {
startActivity(Intent.makeRestartActivityTask(it.component))
@@ -290,7 +382,9 @@ class MainActivity : BaseActivity(), DelegateHost, HostActivity {
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.menu_main, menu)
mLogMenuItem = menu.findItem(R.id.action_log)
setUpSearchMenuItem(menu.findItem(R.id.action_search))
mSearchMenuItem = menu.findItem(R.id.action_search)
setUpSearchMenuItem(mSearchMenuItem)
setUpToolbarColors()
return true
}
@@ -309,6 +403,7 @@ class MainActivity : BaseActivity(), DelegateHost, HostActivity {
private fun setUpSearchMenuItem(searchMenuItem: MenuItem) {
mSearchViewItem = object : SearchViewItem(this, searchMenuItem) {
override fun onMenuItemActionExpand(item: MenuItem): Boolean {
setUpToolbarCollapseIconColor()
if (isCurrentPageDocs) {
mDocsSearchItemExpanded = true
mLogMenuItem.setIcon(R.drawable.ic_ali_up)
@@ -340,6 +435,18 @@ class MainActivity : BaseActivity(), DelegateHost, HostActivity {
}
}
private fun setUpToolbarCollapseIconColor() {
val collapseIcon = mToolbar.collapseIcon
if (collapseIcon != null) {
val isThemeColorLuminanceLight = ThemeColorManager.isThemeColorLuminanceLight()
val fullColor = getColor(if (isThemeColorLuminanceLight) R.color.day_full else R.color.night_full)
collapseIcon.setTintList(ColorStateList.valueOf(fullColor))
collapseIcon.setTint(fullColor)
collapseIcon.colorFilter = PorterDuffColorFilter(fullColor, PorterDuff.Mode.SRC_IN)
mToolbar.collapseIcon = collapseIcon
}
}
private fun submitForwardQuery() {
val event = QueryEvent.FIND_FORWARD
EventBus.getDefault().post(event)
@@ -354,12 +461,12 @@ class MainActivity : BaseActivity(), DelegateHost, HostActivity {
super.onDestroy()
binding = null
mSearchViewItem = null
EventBus.getDefault().unregister(this)
}
companion object {
private val TAG = MainActivity::class.java.simpleName
private var sIsActionBarDrawerOpened = false
var shouldRecreateMainActivity = false

View File

@@ -38,7 +38,6 @@ import org.autojs.autojs.ui.settings.PreferencesActivity
import org.autojs.autojs.util.NetworkUtils
import org.autojs.autojs.util.ViewUtils
import org.autojs.autojs.util.ViewUtils.MODE
import org.autojs.autojs.util.ViewUtils.isNightModeYes
import org.autojs.autojs6.BuildConfig
import org.autojs.autojs6.R
import org.autojs.autojs6.databinding.FragmentDrawerBinding
@@ -273,7 +272,7 @@ open class DrawerFragment : Fragment() {
object : DrawerMenuItemCustomHelper(mContext) {
override fun toggle(): Boolean = runCatching {
val isTurningOn = !isActive
val isNightModeYes = isNightModeYes(resources.configuration)
val isNightModeYes = ViewUtils.isNightModeYes(resources.configuration)
val mode = when {
isTurningOn -> MODE.FOLLOW
isNightModeYes -> MODE.NIGHT
@@ -281,7 +280,7 @@ open class DrawerFragment : Fragment() {
}
ViewUtils.setDefaultNightMode(mode)
if (isTurningOn) {
ViewUtils.isNightModeEnabled = isNightModeYes
ViewUtils.isNightModeEnabled = ViewUtils.isSystemDarkModeEnabled(mContext)
Pref.putString(R.string.key_night_mode, MODE.FOLLOW.key)
} else {
when (isNightModeYes) {

View File

@@ -3,7 +3,9 @@ package org.autojs.autojs.ui.settings
import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.core.content.ContextCompat
import org.autojs.autojs.app.GlobalAppContext
import org.autojs.autojs.theme.ThemeColorManager
import org.autojs.autojs.ui.BaseActivity
import org.autojs.autojs6.R
import org.autojs.autojs6.databinding.ActivityPreferencesBinding
@@ -14,7 +16,7 @@ import org.autojs.autojs6.databinding.ActivityPreferencesBinding
*/
open class PreferencesActivity : BaseActivity() {
private lateinit var binding: ActivityPreferencesBinding
private var binding: ActivityPreferencesBinding? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -34,6 +36,22 @@ open class PreferencesActivity : BaseActivity() {
.commit()
}
override fun onStart() {
super.onStart()
binding!!.toolbar.navigationIcon?.let {
val aimColor = when {
ThemeColorManager.isThemeColorLuminanceLight() -> ContextCompat.getColor(this, R.color.day)
else -> ContextCompat.getColor(this, R.color.night)
}
it.setTint(aimColor)
}
}
override fun onDestroy() {
super.onDestroy()
binding = null
}
companion object {
@JvmStatic

View File

@@ -17,12 +17,15 @@ import org.autojs.autojs6.R
@SuppressLint("CustomSplashScreen")
class SplashActivity : BaseActivity() {
override val handleStatusBarThemeColorAutomatically = false
private var mAlreadyEnterNextActivity = false
private var mPaused = false
private lateinit var mHandler: Handler
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_splash)
@Suppress("DEPRECATION")
@@ -30,7 +33,6 @@ class SplashActivity : BaseActivity() {
mHandler.postDelayed({ enterNextActivity() }, INIT_TIMEOUT)
FloatyWindowManger.hideCircularMenuIfNeeded()
super.onCreate(savedInstanceState)
}
override fun onPause() {

View File

@@ -9,6 +9,7 @@ import android.view.Gravity
import android.widget.TextView
import androidx.annotation.ColorInt
import androidx.annotation.ColorRes
import org.autojs.autojs.theme.ThemeColorManager
import org.autojs.autojs.theme.ThemeColorManagerCompat
import org.autojs.autojs.util.FileUtils
import org.autojs.autojs6.R
@@ -71,6 +72,13 @@ class FirstCharView : TextView {
fun setIconTextColorRes(@ColorRes colorRes: Int) = also { setTextColor(convertColorResToInt(colorRes)) }
fun setIconTextByThemeColorLuminance() = also {
when {
ThemeColorManager.isThemeColorLuminanceLight() -> setIconTextColorRes(R.color.day)
else -> setIconTextColorRes(R.color.night)
}
}
fun setIconTextThemeColor() = setIconTextColor(ThemeColorManagerCompat.getColorPrimary())
fun setIconTextColorDayNight() = setIconTextColorRes(COLOR_RES_DAY_NIGHT)

View File

@@ -5,10 +5,10 @@ import android.app.SearchManager;
import android.content.Context;
import android.view.MenuItem;
import android.widget.EditText;
import android.widget.ImageView;
import androidx.appcompat.widget.SearchView;
import androidx.core.view.MenuItemCompat;
import org.autojs.autojs.theme.ThemeColorManager;
import org.autojs.autojs6.R;
/**
@@ -22,8 +22,12 @@ public class SearchViewItem implements MenuItemCompat.OnActionExpandListener, Se
private QueryCallback mQueryCallback;
private final MenuItem mSearchMenuItem;
private final Activity mActivity;
private EditText mTextview;
private ImageView mCloseButtonView;
public SearchViewItem(Activity activity, MenuItem searchMenuItem) {
mActivity = activity;
mSearchMenuItem = searchMenuItem;
SearchManager searchManager = (SearchManager) activity.getSystemService(Context.SEARCH_SERVICE);
SearchView searchView = (SearchView) searchMenuItem.getActionView();
@@ -31,14 +35,27 @@ public class SearchViewItem implements MenuItemCompat.OnActionExpandListener, Se
return;
}
searchView.setSearchableInfo(searchManager.getSearchableInfo(activity.getComponentName()));
EditText textview = searchView.findViewById(androidx.appcompat.R.id.search_src_text);
if (textview != null) {
textview.setHintTextColor(activity.getColor(R.color.night_day));
}
mTextview = searchView.findViewById(androidx.appcompat.R.id.search_src_text);
mCloseButtonView = searchView.findViewById(androidx.appcompat.R.id.search_close_btn);
initThemeColors();
MenuItemCompat.setOnActionExpandListener(searchMenuItem, this);
searchView.setOnQueryTextListener(this);
}
public void initThemeColors() {
boolean isThemeColorLuminanceLight = ThemeColorManager.isThemeColorLuminanceLight();
int fullColor = mActivity.getColor(isThemeColorLuminanceLight ? R.color.day_full : R.color.night_full);
int hintColor = mActivity.getColor(isThemeColorLuminanceLight ? R.color.day : R.color.night);
if (mTextview != null) {
mTextview.setTextColor(fullColor);
mTextview.setHintTextColor(hintColor);
}
if (mCloseButtonView != null) {
mCloseButtonView.setColorFilter(fullColor);
}
}
public void setQueryCallback(QueryCallback queryCallback) {
mQueryCallback = queryCallback;
}

View File

@@ -9,6 +9,7 @@ import android.graphics.Color
import android.view.View
import androidx.annotation.ColorInt
import androidx.annotation.ColorRes
import androidx.core.graphics.ColorUtils
import org.autojs.autojs.app.GlobalAppContext
import org.autojs.autojs.core.image.ColorTable
import org.autojs.autojs.theme.ThemeColor
@@ -17,6 +18,7 @@ import kotlin.math.pow
import kotlin.math.roundToInt
import kotlin.text.RegexOption.IGNORE_CASE
@Suppress("FunctionName")
object ColorUtils {
@JvmField
@@ -514,12 +516,120 @@ object ColorUtils {
return tmp.toInt()
}
fun toColorStateList(color: String): ColorStateList {
return ColorStateList.valueOf(toInt(color))
fun toColorStateList(color: String) = ColorStateList.valueOf(toInt(color))
fun toColorStateList(view: View, color: String) = ColorStateList.valueOf(parse(view, color))
@JvmStatic
fun rgb(red: Int, green: Int, blue: Int): Int = Color.rgb(red, green, blue)
@JvmStatic
fun argb(alpha: Int, red: Int, green: Int, blue: Int): Int = Color.argb(alpha, red, green, blue)
/**
* Calculates the relative luminance of a color based on the W3C WCAG 2.0 definition.
* This method employs a perceptual brightness calculation, which considers how human eyes perceive light
* and visibly similar changes in brightness. It differs from a simple brightness calculation by employing
* gamma correction and converting RGB color information to the CIE XYZ color space.
*
* zh-CN:
*
* 计算颜色相对亮度 (luminance), 基于 W3C WCAG 2.0 的定义.
* 本方法采用了一种符合人眼感知的亮度计算方式, 考虑到人眼对不同颜色的光敏感性的非线性特性以及视网膜对亮度变化的感知效果.
* 与简单的线性明度计算不同, 本方法通过加入伽马矫正 (Gamma Correction) 和将 RGB 颜色转化到 CIE XYZ 色彩空间来实现更真实的感官亮度评估.
*
* Differences from basic brightness calculation:
* 1. Gamma Correction: Adjusts the linear RGB color channels to account for human vision's non-linear
* response to light intensity. This step improves the representation of perceptual brightness.
* 2. CIE XYZ Color Space: To better model human color perception, color information is converted
* from RGB to the XYZ color space, which defines brightness, chromaticity, and hue more accurately.
*
* zh-CN:
*
* 与基本明度计算的区别:
* 1. 伽马矫正 (Gamma Correction): 对 RGB 通道值进行非线性调整, 以匹配人眼对亮度强度的非线性响应. 此步骤可提高感知亮度的准确性.
* 2. CIE XYZ 色彩空间: 将颜色从 RGB 转换到 XYZ 色彩空间, 该空间定义了更符合人类视觉感知的 [亮度/色度/色调] 信息.
*
* Usage:
* This method adheres to the W3C Web Content Accessibility Guidelines (WCAG 2.0) definition of relative
* luminance, suitable for evaluating color contrast ratios to ensure text readability and accessibility.
* For example, it is commonly used in validating color combinations for web accessibility or UI design.
*
* zh-CN:
*
* 用法:
* 本方法遵循 W3C <<网络内容无障碍指南2.0>> (WCAG 2.0) 中定义的 "相对亮度" 概念,
* 适用于评估颜色对比度, 从而确保文本可读性和无障碍性设计.
* 例如, 在验证网页颜色组合或 UI 设计中的颜色对比是否满足无障碍标准中, 广泛使用此方法.
*
* Implementation notes:
* Internally, this method uses [androidx.core.graphics.ColorUtils.calculateLuminance], which follows
* the WCAG standard. On `Android O` or higher, alternative system solutions such as [Color.luminance]
* may also be used.
*
* zh-CN:
*
* 实现说明:
* 此方法对内调用了 [androidx.core.graphics.ColorUtils.calculateLuminance], 其实现遵循 WCAG 标准.
* 对于 `Android O` 及其以上版本, 也可以替代性地使用系统方法如 [Color.luminance].
*
* @param color The input color, in ARGB format. (zh-CN: 输入颜色, 以 ARGB 格式表示).
* @return The relative luminance of the color, following WCAG 2.0 standards. (zh-CN: 返回该颜色的相对亮度, 符合 WCAG 2.0 标准).
*
* @see <a href="https://www.w3.org/TR/WCAG20/#relativeluminancedef">W3C Recommendation</a>
*/
@JvmStatic
fun luminance(@ColorInt color: Int): Double {
// @Hint by SuperMonster003 on Jan 21, 2023.
// ! Compatibility solution.
// ! zh-CN: 兼容方案.
// # return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
// # ? Color.luminance(Color.pack(color))
// # : Color.luminance(color);
return ColorUtils.calculateLuminance(color)
}
fun toColorStateList(view: View, color: String): ColorStateList {
return ColorStateList.valueOf(parse(view, color))
/**
* @see <a href=https://stackoverflow.com/
* questions/3942878/how-to-decide-font-color-in-white-or-black-depending-on-background-color>
* How to decide font color in white or black depending on background color?
* </a>
*/
@JvmStatic
fun isLuminanceLight(@ColorInt color: Int) = luminance(color) > 0.179
@JvmStatic
fun isLuminanceDark(@ColorInt color: Int) = !isLuminanceLight(color)
@JvmStatic
fun parseColor(colorString: String?): Int = Color.parseColor(colorString)
@JvmStatic
fun RGBToHSV(red: Int, green: Int, blue: Int, hsv: FloatArray?) {
Color.RGBToHSV(red, green, blue, hsv)
}
@JvmStatic
fun colorToHSV(color: Int, hsv: FloatArray?) {
Color.colorToHSV(color, hsv)
}
@JvmStatic
fun HSVToColor(hsv: FloatArray?) = Color.HSVToColor(hsv)
@JvmStatic
fun HSVToColor(alpha: Int, hsv: FloatArray?) = Color.HSVToColor(alpha, hsv)
@JvmStatic
fun equals(c1: Int, c2: Int) = (c1 and 0xffffff) == (c2 and 0xffffff)
@JvmStatic
fun equals(c1: Int, c2: String?) = equals(c1, parseColor(c2))
@JvmStatic
fun equals(c1: String?, c2: Int) = equals(parseColor(c1), c2)
@JvmStatic
fun equals(c1: String?, c2: String?) = equals(parseColor(c1), parseColor(c2))
}

View File

@@ -2,13 +2,17 @@
package org.autojs.autojs.util
import android.annotation.SuppressLint
import android.app.Activity
import android.app.UiModeManager
import android.content.Context
import android.content.ContextWrapper
import android.content.res.Configuration
import android.content.res.Configuration.UI_MODE_NIGHT_MASK
import android.content.res.Configuration.UI_MODE_NIGHT_YES
import android.graphics.Color
import android.graphics.PorterDuff
import android.graphics.PorterDuffColorFilter
import android.graphics.Rect
import android.os.Build
import android.os.Looper
@@ -26,6 +30,7 @@ import androidx.core.view.WindowInsetsControllerCompat
import com.google.android.material.snackbar.Snackbar
import org.autojs.autojs.app.GlobalAppContext
import org.autojs.autojs.core.pref.Pref
import org.autojs.autojs.theme.ThemeColorManager
import org.autojs.autojs.util.StringUtils.key
import org.autojs.autojs6.R
@@ -79,6 +84,7 @@ object ViewUtils {
// ! zh-CN (translated by SuperMonster003 on Jul 29, 2024):
// ! 在一些设备上无法正常获取结果.
// ! 参阅: https://github.com/hyb1996/Auto.js/issues/268
@SuppressLint("InternalInsetResource", "DiscouragedApi")
fun getStatusBarHeightLegacy(context: Context): Int {
return context.resources.getIdentifier("status_bar_height", "dimen", "android").let { resourceId ->
when (resourceId > 0) {
@@ -141,6 +147,32 @@ object ViewUtils {
}
}
@JvmStatic
fun hasSystemUiVisibility(activity: Activity, flags: Int): Boolean {
@Suppress("DEPRECATION")
return activity.window.decorView.systemUiVisibility and flags == flags
}
@JvmStatic
fun isStatusBarIconLight(activity: Activity): Boolean {
return !isStatusBarIconDark(activity)
}
@JvmStatic
fun isStatusBarIconDark(activity: Activity): Boolean {
@Suppress("DEPRECATION")
return hasSystemUiVisibility(activity, View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR)
}
@Suppress("DEPRECATION")
fun setStatusBarIconLight(activity: Activity, isLight: Boolean) {
when {
isStatusBarIconLight(activity) == isLight -> return
isLight -> removeSystemUiVisibility(activity, View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR)
else -> appendSystemUiVisibility(activity, View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR)
}
}
private fun appendWindowFlags(activity: Activity, flags: Int) {
activity.window.addFlags(flags)
}
@@ -161,21 +193,14 @@ object ViewUtils {
val isConfigTakenAsLight = !isConfigDark
getWindowInsetsController(activity).apply {
isAppearanceLightStatusBars = isConfigDark
isAppearanceLightStatusBars = isConfigTakenAsLight
isAppearanceLightNavigationBars = isConfigTakenAsLight
}
}
activity.window.navigationBarColor = when {
Build.VERSION.SDK_INT < Build.VERSION_CODES.O && isConfigTakenAsLight -> {
// @Hint by SuperMonster003 on Sep 9, 2022.
// ! On devices running with Android 7.x and with dark theme disabled,
// ! navigation bar would be white background with white buttons.
// ! zh-CN:
// ! 在安卓 7.x 设备, 暗色主题禁用时, 导航栏背景是白色, 上面的按钮也是白色.
activity.getColor(R.color.navigation_bar_background_before_android_o)
}
else -> Color.TRANSPARENT
}
fun isSystemDarkModeEnabled(context: Context): Boolean {
val uiModeManager = context.getSystemService(Context.UI_MODE_SERVICE) as UiModeManager
return uiModeManager.nightMode == UiModeManager.MODE_NIGHT_YES
}
@JvmStatic
@@ -197,7 +222,7 @@ object ViewUtils {
else -> null
}
fun onConfigurationChanged(configuration: Configuration) {
fun onConfigurationChangedForNightMode(configuration: Configuration) {
if (isAutoNightModeEnabled) {
val isNightModeYes = isNightModeYes(configuration)
if (isNightModeEnabled != isNightModeYes) {
@@ -213,15 +238,19 @@ object ViewUtils {
@JvmStatic
fun setToolbarAsBack(activity: AppCompatActivity, title: String?) {
activity.apply {
findViewById<Toolbar>(R.id.toolbar).let { toolbar ->
toolbar.title = title
setSupportActionBar(toolbar)
supportActionBar?.let { actionBar ->
toolbar.setNavigationOnClickListener { finish() }
actionBar.setDisplayHomeAsUpEnabled(true)
}
}
val toolbar = activity.findViewById<Toolbar>(R.id.toolbar)
toolbar.title = title
activity.setSupportActionBar(toolbar)
activity.supportActionBar?.let { actionBar ->
toolbar.setNavigationOnClickListener { activity.finish() }
actionBar.setDisplayHomeAsUpEnabled(true)
}
toolbar.navigationIcon?.let { navigationIcon ->
val navigationIconColor = when {
ThemeColorManager.isThemeColorLuminanceLight() -> R.color.day
else -> R.color.night
}.let { activity.resources.getColor(it, null) }
navigationIcon.colorFilter = PorterDuffColorFilter(navigationIconColor, PorterDuff.Mode.SRC_IN)
}
}
@@ -297,14 +326,6 @@ object ViewUtils {
isKeepScreenOnWhenInForegroundEnabled = true
}
fun registerOnSharedPreferenceChangeListener(activity: Activity) {
Pref.registerOnSharedPreferenceChangeListener { _, key ->
if (key == key(R.string.key_keep_screen_on_when_in_foreground)) {
configKeepScreenOnWhenInForeground(activity)
}
}
}
fun configKeepScreenOnWhenInForeground(activity: Activity) {
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON.let { flags ->
if (isKeepScreenOnWhenInForegroundEnabled) {