6.6.2 - Alpha4 - 优化部分控件主题色与背景色对比度过低时的视觉体验

This commit is contained in:
SuperMonster003
2025-03-13 17:48:29 +08:00
parent 5c15917abf
commit 17e202a5b1
17 changed files with 335 additions and 129 deletions

View File

@@ -19,6 +19,7 @@
"打包页面支持 Pinyin 库选项", "打包页面支持 Pinyin 库选项",
"打包应用主活动页面优化状态栏背景及文字颜色", "打包应用主活动页面优化状态栏背景及文字颜色",
"控件的文字及图标根据主题色亮度值自动切换合适的颜色", "控件的文字及图标根据主题色亮度值自动切换合适的颜色",
"部分控件主题色与背景色对比度过低时的视觉体验",
"应用内页面导航栏设置为透明或半透明以增强视觉体验", "应用内页面导航栏设置为透明或半透明以增强视觉体验",
"长按应用主页 \"文件\" 标签可切换浮动按钮可见状态", "长按应用主页 \"文件\" 标签可切换浮动按钮可见状态",
"日志页面浮动按钮可见状态与列表滚动操作联动", "日志页面浮动按钮可见状态与列表滚动操作联动",

View File

@@ -767,7 +767,7 @@ class UI(private val scriptRuntime: ScriptRuntime) : AugmentableProxy(scriptRunt
private fun attrValueConvert(o: Any?): Any? = when (o) { private fun attrValueConvert(o: Any?): Any? = when (o) {
is String -> o is String -> o
is ColorNativeObject -> Colors.toHexRhino(o) is ColorNativeObject -> Colors.toHexRhino(o)
is ThemeColor -> o.getColorPrimary() is ThemeColor -> o.colorPrimary
is NativeWith -> attrValueConvert(o.prototype) is NativeWith -> attrValueConvert(o.prototype)
else -> o else -> o
} }

View File

@@ -17,16 +17,10 @@ import org.autojs.autojs6.R
* Modified by SuperMonster003 as of Mar 30, 2023. * Modified by SuperMonster003 as of Mar 30, 2023.
* Transformed by SuperMonster003 on Mar 30, 2023. * Transformed by SuperMonster003 on Mar 30, 2023.
*/ */
class ThemeColor { class ThemeColor(@JvmField var colorPrimary: Int, @JvmField var colorPrimaryDark: Int, @JvmField var colorAccent: Int) {
@JvmField @JvmOverloads
var colorPrimary = 0 constructor(color: Int = 0) : this(color, color, color)
@JvmField
var colorAccent = 0
@JvmField
var colorPrimaryDark = 0
@ScriptInterface @ScriptInterface
fun getColorPrimary() = colorPrimary fun getColorPrimary() = colorPrimary
@@ -41,16 +35,6 @@ class ThemeColor {
fun isLuminanceDark() = ColorUtils.isLuminanceDark(colorPrimary) fun isLuminanceDark() = ColorUtils.isLuminanceDark(colorPrimary)
constructor()
constructor(color: Int) : this(color, color, color)
constructor(colorPrimary: Int, colorPrimaryDark: Int, colorAccent: Int) {
this.colorPrimary = colorPrimary
this.colorPrimaryDark = colorPrimaryDark
this.colorAccent = colorAccent
}
fun colorPrimary(colorPrimary: Int) = also { this.colorPrimary = colorPrimary } fun colorPrimary(colorPrimary: Int) = also { this.colorPrimary = colorPrimary }
fun colorPrimaryDark(colorPrimaryDark: Int) = also { this.colorPrimaryDark = colorPrimaryDark } fun colorPrimaryDark(colorPrimaryDark: Int) = also { this.colorPrimaryDark = colorPrimaryDark }

View File

@@ -19,6 +19,8 @@ import androidx.appcompat.widget.SwitchCompat;
import androidx.core.graphics.drawable.DrawableCompat; import androidx.core.graphics.drawable.DrawableCompat;
import org.autojs.autojs.theme.internal.ScrollingViewEdgeGlowColorHelper; import org.autojs.autojs.theme.internal.ScrollingViewEdgeGlowColorHelper;
import org.autojs.autojs.util.ColorUtils;
import org.autojs.autojs6.R;
/** /**
* Created by Stardust on Oct 24, 2016. * Created by Stardust on Oct 24, 2016.
@@ -27,8 +29,8 @@ public class ThemeColorHelper {
private static final String TAG = "ThemeColorHelper"; private static final String TAG = "ThemeColorHelper";
private static final int[][] SWITCH_STATES = new int[][]{ private static final int[][] SWITCH_STATES = new int[][]{
new int[]{-android.R.attr.state_checked},
new int[]{android.R.attr.state_checked}, new int[]{android.R.attr.state_checked},
new int[]{-android.R.attr.state_checked},
}; };
private static void setColorPrimary(View v, int themeColor) { private static void setColorPrimary(View v, int themeColor) {
@@ -44,36 +46,67 @@ public class ThemeColorHelper {
} }
private static void setColorPrimary(ViewGroup viewGroup, int themeColor) { private static void setColorPrimary(ViewGroup viewGroup, int themeColor) {
setColorPrimary(viewGroup, themeColor, false);
}
private static void setColorPrimary(ViewGroup viewGroup, int themeColor, boolean contrastMatters) {
if (contrastMatters) themeColor = ColorUtils.adjustColorForContrast(viewGroup.getContext().getColor(R.color.window_background), themeColor, 2.3);
for (int i = 0; i < viewGroup.getChildCount(); i++) { for (int i = 0; i < viewGroup.getChildCount(); i++) {
setColorPrimary(viewGroup.getChildAt(i), themeColor); setColorPrimary(viewGroup.getChildAt(i), themeColor);
} }
} }
public static void setColorPrimary(SwitchCompat switchCompat, int color) { public static void setColorPrimary(SwitchCompat switchCompat, int color) {
setThumbDrawableTintList(switchCompat.getThumbDrawable(), color); setColorPrimary(switchCompat, color, false);
setTrackDrawableTintList(switchCompat.getTrackDrawable(), color); }
public static void setColorPrimary(SwitchCompat switchCompat, int color, boolean contrastMatters) {
int adjustedThumbColor = contrastMatters
? ColorUtils.adjustColorForContrast(switchCompat.getContext().getColor(R.color.window_background), color, 2.3)
: color;
int adjustedTrackColor = contrastMatters
? ColorUtils.adjustColorForContrast(switchCompat.getContext().getColor(R.color.window_background), color, 3.6)
: color;
setThumbDrawableTintList(switchCompat.getThumbDrawable(), adjustedThumbColor);
setTrackDrawableTintList(switchCompat.getTrackDrawable(), adjustedTrackColor, true);
} }
public static void setColorPrimary(Switch sw, int color) { public static void setColorPrimary(Switch sw, int color) {
setThumbDrawableTintList(sw.getThumbDrawable(), color); setColorPrimary(sw, color, false);
setTrackDrawableTintList(sw.getTrackDrawable(), color); }
public static void setColorPrimary(Switch sw, int color, boolean contrastMatters) {
int adjustedThumbColor = contrastMatters
? ColorUtils.adjustColorForContrast(sw.getContext().getColor(R.color.window_background), color, 2.3)
: color;
int adjustedTrackColor = contrastMatters
? ColorUtils.adjustColorForContrast(sw.getContext().getColor(R.color.window_background), color, 3.6)
: color;
setThumbDrawableTintList(sw.getThumbDrawable(), adjustedThumbColor);
setTrackDrawableTintList(sw.getTrackDrawable(), adjustedTrackColor, false);
} }
private static void setThumbDrawableTintList(Drawable drawable, int color) { private static void setThumbDrawableTintList(Drawable drawable, int color) {
int unselectedColor = ColorUtils.isLuminanceLight(color)
? Color.parseColor("#616161") // R.color.md_grey_700
: Color.DKGRAY;
int[] thumbColors = new int[]{ int[] thumbColors = new int[]{
Color.DKGRAY,
color, color,
unselectedColor,
}; };
DrawableCompat.setTintList(DrawableCompat.wrap(drawable), new ColorStateList(SWITCH_STATES, thumbColors)); DrawableCompat.setTintList(DrawableCompat.wrap(drawable), new ColorStateList(SWITCH_STATES, thumbColors));
} }
private static void setTrackDrawableTintList(Drawable drawable, int color) { private static void setTrackDrawableTintList(Drawable drawable, int color, boolean isCompat) {
int alpha = isCompat ? 0x29 : 0x66;
int[] trackColors = new int[]{ int[] trackColors = new int[]{
Color.GRAY, makeAlpha(alpha, color),
makeAlpha(0x66, color) makeAlpha(alpha, Color.BLACK),
}; };
DrawableCompat.setTintList(DrawableCompat.wrap(drawable), new ColorStateList(SWITCH_STATES, trackColors)); DrawableCompat.setTintList(drawable, new ColorStateList(SWITCH_STATES, trackColors));
} }
private static int makeAlpha(int alpha, int color) { private static int makeAlpha(int alpha, int color) {

View File

@@ -10,6 +10,8 @@ import androidx.preference.PreferenceViewHolder
import org.autojs.autojs.theme.ThemeColor import org.autojs.autojs.theme.ThemeColor
import org.autojs.autojs.theme.ThemeColorManager import org.autojs.autojs.theme.ThemeColorManager
import org.autojs.autojs.theme.ThemeColorMutable import org.autojs.autojs.theme.ThemeColorMutable
import org.autojs.autojs.util.ColorUtils
import org.autojs.autojs6.R
/** /**
* Created by Stardust on Aug 8, 2016. * Created by Stardust on Aug 8, 2016.
@@ -35,9 +37,9 @@ class ThemeColorPreferenceCategory : PreferenceCategory, ThemeColorMutable {
fun setTitleTextColor(titleTextColor: Int) = setThemeColor(ThemeColor(titleTextColor)) fun setTitleTextColor(titleTextColor: Int) = setThemeColor(ThemeColor(titleTextColor))
override fun setThemeColor(color: ThemeColor) { override fun setThemeColor(color: ThemeColor) {
color.colorPrimary.let { ColorUtils.adjustColorForContrast(context.getColor(R.color.window_background), color.colorPrimary, 3.2).let { contrastColor ->
mColor = it mColor = contrastColor
mTitleTextView?.setTextColor(it) mTitleTextView?.setTextColor(contrastColor)
} }
} }

View File

@@ -1,5 +1,6 @@
package org.autojs.autojs.theme.preference package org.autojs.autojs.theme.preference
import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.content.res.Resources import android.content.res.Resources
import android.content.res.TypedArray import android.content.res.TypedArray
@@ -32,6 +33,27 @@ class ThemeColorSwitchPreference : SwitchPreference, ThemeColorMutable, LongClic
override var longClickPromptMore: CharSequence? = null override var longClickPromptMore: CharSequence? = null
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) { constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) {
init(context, attrs, defStyleAttr, defStyleRes)
}
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
init(context, attrs, defStyleAttr, 0)
}
@SuppressLint("RestrictedApi")
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
init(context, attrs, 0, 0)
}
constructor(context: Context) : super(context) {
init(context, null, 0, 0)
}
init {
ThemeColorManager.add(this)
}
private fun init(context: Context, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) {
obtainStyledAttrs(context, attrs, R.styleable.MaterialPreference, defStyleAttr, defStyleRes) obtainStyledAttrs(context, attrs, R.styleable.MaterialPreference, defStyleAttr, defStyleRes)
.let { a -> .let { a ->
getAttrString(a, R.styleable.MaterialPreference_longClickPrompt)?.also { longClickPrompt = it } getAttrString(a, R.styleable.MaterialPreference_longClickPrompt)?.also { longClickPrompt = it }
@@ -40,20 +62,6 @@ class ThemeColorSwitchPreference : SwitchPreference, ThemeColorMutable, LongClic
} }
} }
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : this(context, attrs, defStyleAttr, 0)
constructor(context: Context, attrs: AttributeSet?) : this(
context, attrs, TypedArrayUtils.getAttr(
context, androidx.preference.R.attr.switchPreferenceStyle, android.R.attr.switchPreferenceStyle
)
)
constructor(context: Context) : this(context, null)
init {
ThemeColorManager.add(this)
}
override fun onBindViewHolder(holder: PreferenceViewHolder) { override fun onBindViewHolder(holder: PreferenceViewHolder) {
super.onBindViewHolder(holder) super.onBindViewHolder(holder)
mCheckableView = holder.findViewById(Resources.getSystem().getIdentifier("switch_widget", "id", "android")) mCheckableView = holder.findViewById(Resources.getSystem().getIdentifier("switch_widget", "id", "android"))
@@ -70,10 +78,10 @@ class ThemeColorSwitchPreference : SwitchPreference, ThemeColorMutable, LongClic
private fun applyColor() { private fun applyColor() {
if (mCheckableView is Switch) { if (mCheckableView is Switch) {
ThemeColorHelper.setColorPrimary(mCheckableView as Switch?, mColor) ThemeColorHelper.setColorPrimary(mCheckableView as Switch, mColor, true)
} }
if (mCheckableView is SwitchCompat) { if (mCheckableView is SwitchCompat) {
ThemeColorHelper.setColorPrimary(mCheckableView as SwitchCompat?, mColor) ThemeColorHelper.setColorPrimary(mCheckableView as SwitchCompat, mColor, true)
} }
} }
@@ -81,6 +89,7 @@ class ThemeColorSwitchPreference : SwitchPreference, ThemeColorMutable, LongClic
return context.obtainStyledAttributes(set, styleableRes, defStyleAttr, defStyleRes) return context.obtainStyledAttributes(set, styleableRes, defStyleAttr, defStyleRes)
} }
@SuppressLint("RestrictedApi")
private fun getAttrString(a: TypedArray, index: Int): String? = TypedArrayUtils.getString(a, index, index) private fun getAttrString(a: TypedArray, index: Int): String? = TypedArrayUtils.getString(a, index, index)
} }

View File

@@ -39,8 +39,9 @@ public class ThemeColorFloatingActionButton extends FloatingActionButton impleme
@Override @Override
public void setThemeColor(ThemeColor color) { public void setThemeColor(ThemeColor color) {
int colorAccent = color.colorAccent; int colorAccent = color.colorAccent;
setBackgroundTintList(ColorStateList.valueOf(colorAccent)); int colorForContrast = ColorUtils.adjustColorForContrast(getContext().getColor(R.color.window_background), colorAccent, 1.15);
var tintColorRes = ColorUtils.isLuminanceLight(colorAccent) setBackgroundTintList(ColorStateList.valueOf(colorForContrast));
var tintColorRes = ColorUtils.isLuminanceLight(colorForContrast)
? R.color.fab_tint_dark ? R.color.fab_tint_dark
: R.color.fab_tint_light; : R.color.fab_tint_light;
var tintColor = getResources().getColor(tintColorRes, null); var tintColor = getResources().getColor(tintColorRes, null);

View File

@@ -72,8 +72,8 @@ abstract class BaseActivity : AppCompatActivity() {
initThemeColors() initThemeColors()
if (handleStatusBarThemeColorAutomatically && !BuildConfig.isInrt) { if (handleStatusBarThemeColorAutomatically && !BuildConfig.isInrt) {
ThemeColorManager.addActivityStatusBar(this) ThemeColorManager.addActivityStatusBar(this)
setUpStatusBarIconLightByThemeColor()
} }
setUpStatusBarIconLightByThemeColor()
} }
override fun onResume() { override fun onResume() {

View File

@@ -44,6 +44,7 @@ import org.autojs.autojs.model.script.Scripts
import org.autojs.autojs.pio.PFile import org.autojs.autojs.pio.PFile
import org.autojs.autojs.pio.PFiles import org.autojs.autojs.pio.PFiles
import org.autojs.autojs.project.ProjectConfig import org.autojs.autojs.project.ProjectConfig
import org.autojs.autojs.theme.ThemeColorManagerCompat
import org.autojs.autojs.theme.widget.ThemeColorSwipeRefreshLayout import org.autojs.autojs.theme.widget.ThemeColorSwipeRefreshLayout
import org.autojs.autojs.ui.common.ScriptLoopDialog import org.autojs.autojs.ui.common.ScriptLoopDialog
import org.autojs.autojs.ui.common.ScriptOperations import org.autojs.autojs.ui.common.ScriptOperations
@@ -54,6 +55,7 @@ import org.autojs.autojs.ui.project.BuildActivity
import org.autojs.autojs.ui.viewmodel.ExplorerItemManager import org.autojs.autojs.ui.viewmodel.ExplorerItemManager
import org.autojs.autojs.ui.widget.BindableViewHolder import org.autojs.autojs.ui.widget.BindableViewHolder
import org.autojs.autojs.ui.widget.FirstCharView import org.autojs.autojs.ui.widget.FirstCharView
import org.autojs.autojs.util.ColorUtils
import org.autojs.autojs.util.EnvironmentUtils.externalStoragePath import org.autojs.autojs.util.EnvironmentUtils.externalStoragePath
import org.autojs.autojs.util.FileUtils import org.autojs.autojs.util.FileUtils
import org.autojs.autojs.util.IntentUtils import org.autojs.autojs.util.IntentUtils
@@ -715,14 +717,19 @@ open class ExplorerView : ThemeColorSwipeRefreshLayout, SwipeRefreshLayout.OnRef
private fun setFirstChar(item: ExplorerItem) { private fun setFirstChar(item: ExplorerItem) {
mFirstChar.setIcon(ExplorerViewHelper.getIcon(item)) mFirstChar.setIcon(ExplorerViewHelper.getIcon(item))
when (item.type) { when (item.type) {
FileUtils.TYPE.JAVASCRIPT, FileUtils.TYPE.AUTO -> mFirstChar FileUtils.TYPE.JAVASCRIPT, FileUtils.TYPE.AUTO -> {
.setIconTextColorByThemeColorLuminance() val themeColorForContrast = ColorUtils.adjustColorForContrast(context.getColor(R.color.item_background_dark), ThemeColorManagerCompat.getColorPrimary(), 1.15)
.setStrokeThemeColor() mFirstChar
.setFillThemeColor() .setIconTextColorByThemeColorLuminance()
else -> mFirstChar .setStrokeColor(themeColorForContrast)
.setIconTextColorDayNight() .setFillColor(themeColorForContrast)
.setStrokeColorDayNight() }
.setFillTransparent() else -> {
mFirstChar
.setIconTextColorDayNight()
.setStrokeColorDayNight()
.setFillTransparent()
}
} }
} }

View File

@@ -1,13 +1,20 @@
package org.autojs.autojs.ui.filechooser; package org.autojs.autojs.ui.filechooser;
import android.content.Context;
import android.content.res.ColorStateList;
import android.view.View; import android.view.View;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import org.autojs.autojs.core.ui.widget.JsCheckBox;
import org.autojs.autojs.model.explorer.ExplorerItem; import org.autojs.autojs.model.explorer.ExplorerItem;
import org.autojs.autojs.pio.PFile;
import org.autojs.autojs.pio.PFiles; import org.autojs.autojs.pio.PFiles;
import org.autojs.autojs.theme.ThemeColorManagerCompat;
import org.autojs.autojs.ui.explorer.ExplorerViewHelper; import org.autojs.autojs.ui.explorer.ExplorerViewHelper;
import org.autojs.autojs.ui.widget.BindableViewHolder; import org.autojs.autojs.ui.widget.BindableViewHolder;
import org.autojs.autojs.util.ColorUtils;
import org.autojs.autojs6.R;
import org.autojs.autojs6.databinding.ExplorerFirstCharIconBinding; import org.autojs.autojs6.databinding.ExplorerFirstCharIconBinding;
import org.autojs.autojs6.databinding.FileChooseListFileBinding; import org.autojs.autojs6.databinding.FileChooseListFileBinding;
@@ -33,22 +40,39 @@ class ExplorerItemViewHolder extends BindableViewHolder<Object> {
public void bind(Object item, int position) { public void bind(Object item, int position) {
if (!(item instanceof ExplorerItem explorerItem)) return; if (!(item instanceof ExplorerItem explorerItem)) return;
mExplorerItem = explorerItem; mExplorerItem = explorerItem;
listFileBinding.name.setText(ExplorerViewHelper.getDisplayName(fileChooseListView.getContext(), explorerItem));
listFileBinding.item.setOnClickListener(view -> listFileBinding.checkbox.toggle()); Context context = fileChooseListView.getContext();
listFileBinding.checkbox.setOnCheckedChangeListener((buttonView, isChecked) -> { JsCheckBox checkbox = listFileBinding.checkbox;
if (listFileBinding.checkbox.isChecked()) {
int itemBackgroundDarkColor = context.getColor(R.color.item_background_dark);
int themePrimaryColor = ThemeColorManagerCompat.getColorPrimary();
int checkBoxCheckedThemeColorForContrast = ColorUtils.adjustColorForContrast(itemBackgroundDarkColor, themePrimaryColor, 1.9);
int checkBoxUncheckedCheckedThemeColorForContrast = ColorUtils.adjustColorForContrast(itemBackgroundDarkColor, themePrimaryColor, 1.4);
int itemIconThemeColorForContrast = ColorUtils.adjustColorForContrast(itemBackgroundDarkColor, themePrimaryColor, 1.15);
checkbox.setButtonTintList(new ColorStateList(
new int[][]{new int[]{android.R.attr.state_checked}, new int[]{}},
new int[]{checkBoxCheckedThemeColorForContrast, checkBoxUncheckedCheckedThemeColorForContrast}
));
listFileBinding.name.setText(ExplorerViewHelper.getDisplayName(context, explorerItem));
listFileBinding.item.setOnClickListener(view -> checkbox.toggle());
checkbox.setOnCheckedChangeListener((buttonView, isChecked) -> {
if (checkbox.isChecked()) {
fileChooseListView.check(mExplorerItem.toScriptFile(), getAdapterPosition()); fileChooseListView.check(mExplorerItem.toScriptFile(), getAdapterPosition());
} else { } else {
fileChooseListView.getSelectedFiles().remove(mExplorerItem.toScriptFile()); fileChooseListView.getSelectedFiles().remove(mExplorerItem.toScriptFile());
} }
}); });
listFileBinding.scriptFileSize.setText(PFiles.getHumanReadableSize(explorerItem.getSize())); listFileBinding.scriptFileSize.setText(PFiles.getHumanReadableSize(explorerItem.getSize()));
listFileBinding.scriptFileDate.setText(PFile.getFullDateString(explorerItem.lastModified()));
switch (explorerItem.getType()) { switch (explorerItem.getType()) {
case JAVASCRIPT, AUTO -> firstCharIconBinding.firstChar case JAVASCRIPT, AUTO -> firstCharIconBinding.firstChar
.setIconTextColorByThemeColorLuminance() .setIconTextColorByThemeColorLuminance()
.setStrokeThemeColor() .setStrokeColor(itemIconThemeColorForContrast)
.setFillColorDayNight(); .setFillColor(itemIconThemeColorForContrast);
default -> firstCharIconBinding.firstChar default -> firstCharIconBinding.firstChar
.setIconTextColorDayNight() .setIconTextColorDayNight()
.setStrokeColorDayNight() .setStrokeColorDayNight()
@@ -57,7 +81,7 @@ class ExplorerItemViewHolder extends BindableViewHolder<Object> {
firstCharIconBinding.firstChar.setIcon(ExplorerViewHelper.getIcon(explorerItem)); firstCharIconBinding.firstChar.setIcon(ExplorerViewHelper.getIcon(explorerItem));
listFileBinding.checkbox.setChecked(fileChooseListView.getSelectedFiles().containsKey(mExplorerItem.toScriptFile()), false); checkbox.setChecked(fileChooseListView.getSelectedFiles().containsKey(mExplorerItem.toScriptFile()), false);
} }
} }

View File

@@ -25,9 +25,12 @@ import org.autojs.autojs.execution.ScriptExecutionListener;
import org.autojs.autojs.execution.SimpleScriptExecutionListener; import org.autojs.autojs.execution.SimpleScriptExecutionListener;
import org.autojs.autojs.groundwork.WrapContentLinearLayoutManager; import org.autojs.autojs.groundwork.WrapContentLinearLayoutManager;
import org.autojs.autojs.script.AutoFileSource; import org.autojs.autojs.script.AutoFileSource;
import org.autojs.autojs.script.JavaScriptFileSource;
import org.autojs.autojs.storage.database.ModelChange; import org.autojs.autojs.storage.database.ModelChange;
import org.autojs.autojs.theme.ThemeColorManagerCompat;
import org.autojs.autojs.timing.TimedTaskManager; import org.autojs.autojs.timing.TimedTaskManager;
import org.autojs.autojs.ui.timing.TimedTaskSettingActivity; import org.autojs.autojs.ui.timing.TimedTaskSettingActivity;
import org.autojs.autojs.util.ColorUtils;
import org.autojs.autojs.util.FileUtils; import org.autojs.autojs.util.FileUtils;
import org.autojs.autojs6.R; import org.autojs.autojs6.R;
import org.autojs.autojs6.databinding.ExplorerFirstCharIconBinding; import org.autojs.autojs6.databinding.ExplorerFirstCharIconBinding;
@@ -232,10 +235,19 @@ public class TaskListRecyclerView extends ThemeColorRecyclerView {
public void bind(Task task) { public void bind(Task task) {
mTask = task; mTask = task;
int itemIconThemeColorForContrast = ColorUtils.adjustColorForContrast(getContext().getColor(R.color.window_background), ThemeColorManagerCompat.getColorPrimary(), 2.3);
FileUtils.TYPE.Icon icon;
if (JavaScriptFileSource.ENGINE.equals(mTask.getEngineName())) {
icon = FileUtils.TYPE.JAVASCRIPT.icon;
} else if (AutoFileSource.ENGINE.equals(mTask.getEngineName())) {
icon = FileUtils.TYPE.AUTO.icon;
} else {
icon = FileUtils.TYPE.UNKNOWN.icon;
}
firstCharIconBinding.firstChar firstCharIconBinding.firstChar
.setIcon(AutoFileSource.ENGINE.equals(mTask.getEngineName()) ? FileUtils.TYPE.AUTO.icon : FileUtils.TYPE.JAVASCRIPT.icon) .setIcon(icon)
.setIconTextThemeColor() .setIconTextColor(itemIconThemeColorForContrast)
.setStrokeThemeColor() .setStrokeColor(itemIconThemeColorForContrast)
.setFillTransparent(); .setFillTransparent();
itemBinding.name.setText(task.getName()); itemBinding.name.setText(task.getName());
itemBinding.taskListFilePath.setText(task.getDesc()); itemBinding.taskListFilePath.setText(task.getDesc());

View File

@@ -11,6 +11,7 @@ import androidx.annotation.ColorInt
import androidx.annotation.ColorRes import androidx.annotation.ColorRes
import org.autojs.autojs.theme.ThemeColorManager import org.autojs.autojs.theme.ThemeColorManager
import org.autojs.autojs.theme.ThemeColorManagerCompat import org.autojs.autojs.theme.ThemeColorManagerCompat
import org.autojs.autojs.util.ColorUtils
import org.autojs.autojs.util.FileUtils import org.autojs.autojs.util.FileUtils
import org.autojs.autojs6.R import org.autojs.autojs6.R
import kotlin.math.roundToInt import kotlin.math.roundToInt
@@ -50,8 +51,6 @@ class FirstCharView : TextView {
return privateBackground!! return privateBackground!!
} }
private fun convertColorResToInt(@ColorRes colorRes: Int) = context.getColor(colorRes)
fun setIconText(text: CharSequence?) = also { setText(text) } fun setIconText(text: CharSequence?) = also { setText(text) }
fun setIcon(icon: FileUtils.TYPE.Icon): FirstCharView { fun setIcon(icon: FileUtils.TYPE.Icon): FirstCharView {
@@ -70,7 +69,7 @@ class FirstCharView : TextView {
fun setIconTextColor(@ColorInt color: Int) = also { setTextColor(color) } fun setIconTextColor(@ColorInt color: Int) = also { setTextColor(color) }
fun setIconTextColorRes(@ColorRes colorRes: Int) = also { setTextColor(convertColorResToInt(colorRes)) } fun setIconTextColorRes(@ColorRes colorRes: Int) = also { setTextColor(context.getColor(colorRes)) }
fun setIconTextColorByThemeColorLuminance() = also { setIconTextColorRes(ThemeColorManager.getDayOrNightColorResByLuminance()) } fun setIconTextColorByThemeColorLuminance() = also { setIconTextColorRes(ThemeColorManager.getDayOrNightColorResByLuminance()) }
@@ -82,7 +81,7 @@ class FirstCharView : TextView {
fun setStrokeColor(@ColorInt color: Int) = also { background().setStroke(strokeWidth, color) } fun setStrokeColor(@ColorInt color: Int) = also { background().setStroke(strokeWidth, color) }
fun setStrokeColorRes(@ColorRes colorRes: Int): FirstCharView = setStrokeColor(convertColorResToInt(colorRes)) fun setStrokeColorRes(@ColorRes colorRes: Int): FirstCharView = setStrokeColor(context.getColor(colorRes))
fun setStrokeThemeColor() = setStrokeColor(ThemeColorManagerCompat.getColorPrimary()) fun setStrokeThemeColor() = setStrokeColor(ThemeColorManagerCompat.getColorPrimary())
@@ -92,7 +91,7 @@ class FirstCharView : TextView {
fun setFillColor(@ColorInt color: Int) = also { background().setColor(color) } fun setFillColor(@ColorInt color: Int) = also { background().setColor(color) }
fun setFillColorRes(@ColorRes colorRes: Int) = setFillColor(convertColorResToInt(colorRes)) fun setFillColorRes(@ColorRes colorRes: Int) = setFillColor(context.getColor(colorRes))
fun setFillThemeColor() = setFillColor(ThemeColorManagerCompat.getColorPrimary()) fun setFillThemeColor() = setFillColor(ThemeColorManagerCompat.getColorPrimary())

View File

@@ -55,7 +55,7 @@ public class PrefSwitch extends JsSwitch implements SharedPreferences.OnSharedPr
@Override @Override
public void setThemeColor(ThemeColor color) { public void setThemeColor(ThemeColor color) {
ThemeColorHelper.setColorPrimary(this, color.colorPrimary); ThemeColorHelper.setColorPrimary(this, color.colorPrimary, true);
} }
private void readInitialState() { private void readInitialState() {

View File

@@ -632,4 +632,105 @@ object ColorUtils {
@JvmStatic @JvmStatic
fun equals(c1: String?, c2: String?) = equals(parseColor(c1), parseColor(c2)) fun equals(c1: String?, c2: String?) = equals(parseColor(c1), parseColor(c2))
/**
* Adjust the reference color to achieve better contrast on the background color, while remaining as close as possible to the reference color.
*
* zh-CN: 调整参考色, 使其在背景色上具有更好的对比度, 同时尽量接近参考色.
*
* @param background The background color. (zh-CN: 背景颜色.)
* @param reference The reference color. (zh-CN: 参考颜色.)
* @param minimumContrast The minimum contrast ratio, typically between 1.0 and 21.0 (1 being the lowest contrast, 21 being the highest contrast).
* (zh-CN: 最小对比度, 通常值为 1.0 - 21.0 (1 为最低对比度, 21 为最高对比度).)
* - 4.5: Minimum contrast ratio for normal use cases (Standard AA)
* - 7.0: High contrast ratio for better readability (Standard AAA)
* - < 4.5 (e.g. 3.0): Lower contrast ratio (< 4.5, e.g., 3.0) is acceptable for decorative or less significant elements
* - zh-CN:
* - 4.5: 普通场景的最低对比度标准 (AA 标准)
* - 7.0: 高对比度场景标准 (AAA 标准)
* - < 4.5 (如 3.0): 装饰性或次要元素可用的较低标准
* @return The adjusted color. (zh-CN: 调整后的颜色.)
*/
@JvmStatic
fun adjustColorForContrast(
@ColorInt background: Int,
@ColorInt reference: Int,
minimumContrast: Double = 4.5,
): Int {
// 如果已经满足对比度要求, 直接返回参考色
if (calculateContrast(background, reference) >= minimumContrast) {
return reference
}
// 转为 HSL 以便调整亮度
val hsl = FloatArray(3)
ColorUtils.colorToHSL(reference, hsl)
// 提高亮度, 尝试达到目标对比度
val lighterColor = findAdjustableHSLColor(hsl, background, minimumContrast, lighten = true)
if (lighterColor != null) {
return lighterColor
}
// 降低亮度, 尝试达到目标对比度
val darkerColor = findAdjustableHSLColor(hsl, background, minimumContrast, lighten = false)
if (darkerColor != null) {
return darkerColor
}
// 如果两种情况下都无法满足, 返回原始颜色 (极端情况)
return reference
}
/**
* Calculate the contrast ratio between two colors using the W3C WCAG formula.
*
* zh-CN: 计算两种颜色的对比度, 使用 W3C WCAG 公式.
*/
private fun calculateContrast(color1: Int, color2: Int): Double {
return ColorUtils.calculateContrast(color1, color2)
}
/**
* Adjust the lightness of a color in HSL format to meet the minimum contrast ratio.
*
* zh-CN: 调整颜色的亮度, 尝试找到满足最小对比度的颜色.
*
* @param hsl The color value in HSL format, including Hue, Saturation, and Lightness.
* (zh-CN: HSL 格式颜色值, 包括色相 (Hue), 饱和度 (Saturation), 亮度 (Lightness).)
* @param background The background color. (zh-CN: 背景颜色.)
* @param minimumContrast minimum contrast ratio. (zh-CN: 最小对比度值.)
* @param lighten Whether to increase brightness (true) or decrease brightness (false).
* (zh-CN: 是否提高亮度 (true 为提高亮度, false 为降低亮度).)
* @return The adjusted color, or null if no suitable color can be found.
* (zh-CN: 调整后的颜色, 若无法找到满足条件的颜色, 返回 null.)
*/
@ColorInt
private fun findAdjustableHSLColor(
hsl: FloatArray,
@ColorInt background: Int,
minimumContrast: Double,
lighten: Boolean,
): Int? {
val step = 0.02f // 每次调整亮度的步长
val maxSteps = 50 // 最大调整次数 (防止死循环)
val adjustedHSL = hsl.copyOf()
for (i in 0 until maxSteps) {
// 根据 lighten 参数, 增加或减少亮度
adjustedHSL[2] = (adjustedHSL[2] + (if (lighten) step else -step))
.coerceIn(0f, 1f) // 防止超出合法范围 [0, 1]
// 将调整后的 HSL 转回 RGB
val adjustedColor = ColorUtils.HSLToColor(adjustedHSL)
// 重新计算对比度, 如果满足条件即可返回
if (calculateContrast(background, adjustedColor) >= minimumContrast) {
return adjustedColor
}
}
// 无法找到合适的亮度调整
return null
}
} }

View File

@@ -17,13 +17,13 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="@color/item_background_dark" android:background="@color/item_background_dark"
android:baselineAligned="false"
android:clickable="true" android:clickable="true"
android:focusable="true"
android:foreground="?selectableItemBackground" android:foreground="?selectableItemBackground"
android:orientation="horizontal" android:orientation="horizontal"
android:paddingVertical="9dp" android:paddingVertical="9dp"
android:paddingStart="8dp" android:paddingStart="8dp">
android:baselineAligned="false"
android:focusable="true">
<include <include
layout="@layout/explorer_first_char_icon" layout="@layout/explorer_first_char_icon"

View File

@@ -1,77 +1,110 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android" <androidx.appcompat.widget.LinearLayoutCompat
xmlns:tools="http://schemas.android.com/tools" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" xmlns:tools="http://schemas.android.com/tools"
android:layout_height="wrap_content" android:layout_width="match_parent"
android:orientation="vertical"> android:layout_height="wrap_content"
android:orientation="vertical">
<View <View
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="1px" android:layout_height="1px"
android:background="?android:divider" /> android:background="?android:divider" />
<LinearLayout <LinearLayout
android:id="@+id/item" android:id="@+id/item"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:clickable="true" android:background="@color/item_background_dark"
android:foreground="?selectableItemBackground" android:clickable="true"
android:orientation="horizontal" android:focusable="true"
android:padding="8dp"> android:foreground="?selectableItemBackground"
android:orientation="horizontal"
android:paddingVertical="9dp"
android:paddingStart="8dp">
<org.autojs.autojs.core.ui.widget.JsCheckBox <org.autojs.autojs.core.ui.widget.JsCheckBox
android:id="@+id/checkbox" android:id="@+id/checkbox"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:gravity="center" /> android:gravity="center" />
<include <include
layout="@layout/explorer_first_char_icon" layout="@layout/explorer_first_char_icon"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_width="wrap_content"/> android:layout_width="wrap_content" />
<LinearLayout <LinearLayout
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="10dp"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical" android:ellipsize="end"
android:layout_marginStart="10dp" android:gravity="center_vertical"
android:layout_weight="1" android:maxLines="1"
android:orientation="vertical"> android:textColor="?android:textColorPrimary"
android:textSize="14sp"
tools:text="@string/text_sample_name" />
<TextView <LinearLayout
android:id="@+id/name" android:layout_width="match_parent"
android:layout_width="match_parent" android:layout_height="wrap_content"
android:layout_marginTop="4dp">
<TextView
android:id="@+id/script_file_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:ellipsize="end" android:ellipsize="end"
android:gravity="center_vertical"
android:maxLines="1" android:maxLines="1"
android:textColor="?android:textColorPrimary" android:textColor="?android:textColorSecondary"
android:textSize="14sp" android:textSize="11sp"
tools:text="@string/text_sample_name" /> tools:text="@string/text_sample_file_date" />
<TextView <TextView
android:id="@+id/script_file_size" android:paddingHorizontal="3sp"
android:layout_width="match_parent" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical" android:layout_gravity="center"
android:layout_marginTop="4dp" android:gravity="center"
android:ellipsize="middle" android:ellipsize="end"
android:gravity="center_vertical"
android:maxLines="1" android:maxLines="1"
android:textColor="?android:textColorPrimary" android:textColor="?android:textColorSecondary"
android:textSize="11sp" />
<TextView
android:id="@+id/script_file_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:ellipsize="end"
android:maxLines="1"
android:textColor="?android:textColorSecondary"
android:textSize="11sp" android:textSize="11sp"
tools:text="@string/text_sample_file_size" /> tools:text="@string/text_sample_file_size" />
</LinearLayout>
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
<View <View
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="1px" android:layout_height="1px"
android:background="#EDEEEF" /> android:background="#EDEEEF" />
</androidx.appcompat.widget.LinearLayoutCompat> </androidx.appcompat.widget.LinearLayoutCompat>

View File

@@ -1,5 +1,5 @@
#Thu Mar 13 12:06:20 CST 2025 #Thu Mar 13 17:43:40 CST 2025
BUILD_TIME=1741838780961 BUILD_TIME=1741859020501
COMPILE_SDK_VERSION=35 COMPILE_SDK_VERSION=35
JAVA_VERSION=23 JAVA_VERSION=23
JAVA_VERSION_MIN_RADICAL=0 JAVA_VERSION_MIN_RADICAL=0
@@ -17,6 +17,6 @@ RAPID_OCR_OPENCV_MOBILE_LABEL_VERSION=13
RAPID_OCR_OPENCV_MOBILE_VERSION=4.5.3 RAPID_OCR_OPENCV_MOBILE_VERSION=4.5.3
TARGET_SDK_VERSION=35 TARGET_SDK_VERSION=35
TARGET_SDK_VERSION_INRT=29 TARGET_SDK_VERSION_INRT=29
VERSION_BUILD=3023 VERSION_BUILD=3025
VERSION_NAME=6.6.2 Alpha4 VERSION_NAME=6.6.2 Alpha4
VSCODE_EXT_REQUIRED_VERSION=1.0.8 VSCODE_EXT_REQUIRED_VERSION=1.0.8