6.6.2 - Alpha4 - 优化部分控件主题色与背景色对比度过低时的视觉体验
This commit is contained in:
@@ -767,7 +767,7 @@ class UI(private val scriptRuntime: ScriptRuntime) : AugmentableProxy(scriptRunt
|
||||
private fun attrValueConvert(o: Any?): Any? = when (o) {
|
||||
is String -> o
|
||||
is ColorNativeObject -> Colors.toHexRhino(o)
|
||||
is ThemeColor -> o.getColorPrimary()
|
||||
is ThemeColor -> o.colorPrimary
|
||||
is NativeWith -> attrValueConvert(o.prototype)
|
||||
else -> o
|
||||
}
|
||||
|
||||
@@ -17,16 +17,10 @@ import org.autojs.autojs6.R
|
||||
* Modified by SuperMonster003 as of 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
|
||||
var colorPrimary = 0
|
||||
|
||||
@JvmField
|
||||
var colorAccent = 0
|
||||
|
||||
@JvmField
|
||||
var colorPrimaryDark = 0
|
||||
@JvmOverloads
|
||||
constructor(color: Int = 0) : this(color, color, color)
|
||||
|
||||
@ScriptInterface
|
||||
fun getColorPrimary() = colorPrimary
|
||||
@@ -41,16 +35,6 @@ class ThemeColor {
|
||||
|
||||
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 colorPrimaryDark(colorPrimaryDark: Int) = also { this.colorPrimaryDark = colorPrimaryDark }
|
||||
|
||||
@@ -19,6 +19,8 @@ import androidx.appcompat.widget.SwitchCompat;
|
||||
import androidx.core.graphics.drawable.DrawableCompat;
|
||||
|
||||
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.
|
||||
@@ -27,8 +29,8 @@ public class ThemeColorHelper {
|
||||
|
||||
private static final String TAG = "ThemeColorHelper";
|
||||
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},
|
||||
};
|
||||
|
||||
private static void setColorPrimary(View v, int themeColor) {
|
||||
@@ -44,36 +46,67 @@ public class ThemeColorHelper {
|
||||
}
|
||||
|
||||
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++) {
|
||||
setColorPrimary(viewGroup.getChildAt(i), themeColor);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setColorPrimary(SwitchCompat switchCompat, int color) {
|
||||
setThumbDrawableTintList(switchCompat.getThumbDrawable(), color);
|
||||
setTrackDrawableTintList(switchCompat.getTrackDrawable(), color);
|
||||
setColorPrimary(switchCompat, color, false);
|
||||
}
|
||||
|
||||
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) {
|
||||
setThumbDrawableTintList(sw.getThumbDrawable(), color);
|
||||
setTrackDrawableTintList(sw.getTrackDrawable(), color);
|
||||
setColorPrimary(sw, color, false);
|
||||
}
|
||||
|
||||
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) {
|
||||
int unselectedColor = ColorUtils.isLuminanceLight(color)
|
||||
? Color.parseColor("#616161") // R.color.md_grey_700
|
||||
: Color.DKGRAY;
|
||||
int[] thumbColors = new int[]{
|
||||
Color.DKGRAY,
|
||||
color,
|
||||
unselectedColor,
|
||||
};
|
||||
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[]{
|
||||
Color.GRAY,
|
||||
makeAlpha(0x66, color)
|
||||
makeAlpha(alpha, 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) {
|
||||
|
||||
@@ -10,6 +10,8 @@ import androidx.preference.PreferenceViewHolder
|
||||
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 8, 2016.
|
||||
@@ -35,9 +37,9 @@ class ThemeColorPreferenceCategory : PreferenceCategory, ThemeColorMutable {
|
||||
fun setTitleTextColor(titleTextColor: Int) = setThemeColor(ThemeColor(titleTextColor))
|
||||
|
||||
override fun setThemeColor(color: ThemeColor) {
|
||||
color.colorPrimary.let {
|
||||
mColor = it
|
||||
mTitleTextView?.setTextColor(it)
|
||||
ColorUtils.adjustColorForContrast(context.getColor(R.color.window_background), color.colorPrimary, 3.2).let { contrastColor ->
|
||||
mColor = contrastColor
|
||||
mTitleTextView?.setTextColor(contrastColor)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.autojs.autojs.theme.preference
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.res.Resources
|
||||
import android.content.res.TypedArray
|
||||
@@ -32,6 +33,27 @@ class ThemeColorSwitchPreference : SwitchPreference, ThemeColorMutable, LongClic
|
||||
override var longClickPromptMore: CharSequence? = null
|
||||
|
||||
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)
|
||||
.let { a ->
|
||||
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) {
|
||||
super.onBindViewHolder(holder)
|
||||
mCheckableView = holder.findViewById(Resources.getSystem().getIdentifier("switch_widget", "id", "android"))
|
||||
@@ -70,10 +78,10 @@ class ThemeColorSwitchPreference : SwitchPreference, ThemeColorMutable, LongClic
|
||||
|
||||
private fun applyColor() {
|
||||
if (mCheckableView is Switch) {
|
||||
ThemeColorHelper.setColorPrimary(mCheckableView as Switch?, mColor)
|
||||
ThemeColorHelper.setColorPrimary(mCheckableView as Switch, mColor, true)
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
||||
@SuppressLint("RestrictedApi")
|
||||
private fun getAttrString(a: TypedArray, index: Int): String? = TypedArrayUtils.getString(a, index, index)
|
||||
|
||||
}
|
||||
@@ -39,8 +39,9 @@ public class ThemeColorFloatingActionButton extends FloatingActionButton impleme
|
||||
@Override
|
||||
public void setThemeColor(ThemeColor color) {
|
||||
int colorAccent = color.colorAccent;
|
||||
setBackgroundTintList(ColorStateList.valueOf(colorAccent));
|
||||
var tintColorRes = ColorUtils.isLuminanceLight(colorAccent)
|
||||
int colorForContrast = ColorUtils.adjustColorForContrast(getContext().getColor(R.color.window_background), colorAccent, 1.15);
|
||||
setBackgroundTintList(ColorStateList.valueOf(colorForContrast));
|
||||
var tintColorRes = ColorUtils.isLuminanceLight(colorForContrast)
|
||||
? R.color.fab_tint_dark
|
||||
: R.color.fab_tint_light;
|
||||
var tintColor = getResources().getColor(tintColorRes, null);
|
||||
|
||||
@@ -72,8 +72,8 @@ abstract class BaseActivity : AppCompatActivity() {
|
||||
initThemeColors()
|
||||
if (handleStatusBarThemeColorAutomatically && !BuildConfig.isInrt) {
|
||||
ThemeColorManager.addActivityStatusBar(this)
|
||||
setUpStatusBarIconLightByThemeColor()
|
||||
}
|
||||
setUpStatusBarIconLightByThemeColor()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
|
||||
@@ -44,6 +44,7 @@ import org.autojs.autojs.model.script.Scripts
|
||||
import org.autojs.autojs.pio.PFile
|
||||
import org.autojs.autojs.pio.PFiles
|
||||
import org.autojs.autojs.project.ProjectConfig
|
||||
import org.autojs.autojs.theme.ThemeColorManagerCompat
|
||||
import org.autojs.autojs.theme.widget.ThemeColorSwipeRefreshLayout
|
||||
import org.autojs.autojs.ui.common.ScriptLoopDialog
|
||||
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.widget.BindableViewHolder
|
||||
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.FileUtils
|
||||
import org.autojs.autojs.util.IntentUtils
|
||||
@@ -715,14 +717,19 @@ open class ExplorerView : ThemeColorSwipeRefreshLayout, SwipeRefreshLayout.OnRef
|
||||
private fun setFirstChar(item: ExplorerItem) {
|
||||
mFirstChar.setIcon(ExplorerViewHelper.getIcon(item))
|
||||
when (item.type) {
|
||||
FileUtils.TYPE.JAVASCRIPT, FileUtils.TYPE.AUTO -> mFirstChar
|
||||
.setIconTextColorByThemeColorLuminance()
|
||||
.setStrokeThemeColor()
|
||||
.setFillThemeColor()
|
||||
else -> mFirstChar
|
||||
.setIconTextColorDayNight()
|
||||
.setStrokeColorDayNight()
|
||||
.setFillTransparent()
|
||||
FileUtils.TYPE.JAVASCRIPT, FileUtils.TYPE.AUTO -> {
|
||||
val themeColorForContrast = ColorUtils.adjustColorForContrast(context.getColor(R.color.item_background_dark), ThemeColorManagerCompat.getColorPrimary(), 1.15)
|
||||
mFirstChar
|
||||
.setIconTextColorByThemeColorLuminance()
|
||||
.setStrokeColor(themeColorForContrast)
|
||||
.setFillColor(themeColorForContrast)
|
||||
}
|
||||
else -> {
|
||||
mFirstChar
|
||||
.setIconTextColorDayNight()
|
||||
.setStrokeColorDayNight()
|
||||
.setFillTransparent()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
package org.autojs.autojs.ui.filechooser;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.autojs.autojs.core.ui.widget.JsCheckBox;
|
||||
import org.autojs.autojs.model.explorer.ExplorerItem;
|
||||
import org.autojs.autojs.pio.PFile;
|
||||
import org.autojs.autojs.pio.PFiles;
|
||||
import org.autojs.autojs.theme.ThemeColorManagerCompat;
|
||||
import org.autojs.autojs.ui.explorer.ExplorerViewHelper;
|
||||
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.FileChooseListFileBinding;
|
||||
|
||||
@@ -33,22 +40,39 @@ class ExplorerItemViewHolder extends BindableViewHolder<Object> {
|
||||
public void bind(Object item, int position) {
|
||||
if (!(item instanceof ExplorerItem explorerItem)) return;
|
||||
mExplorerItem = explorerItem;
|
||||
listFileBinding.name.setText(ExplorerViewHelper.getDisplayName(fileChooseListView.getContext(), explorerItem));
|
||||
listFileBinding.item.setOnClickListener(view -> listFileBinding.checkbox.toggle());
|
||||
listFileBinding.checkbox.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
||||
if (listFileBinding.checkbox.isChecked()) {
|
||||
|
||||
Context context = fileChooseListView.getContext();
|
||||
JsCheckBox checkbox = listFileBinding.checkbox;
|
||||
|
||||
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());
|
||||
} else {
|
||||
fileChooseListView.getSelectedFiles().remove(mExplorerItem.toScriptFile());
|
||||
}
|
||||
});
|
||||
listFileBinding.scriptFileSize.setText(PFiles.getHumanReadableSize(explorerItem.getSize()));
|
||||
listFileBinding.scriptFileDate.setText(PFile.getFullDateString(explorerItem.lastModified()));
|
||||
|
||||
switch (explorerItem.getType()) {
|
||||
case JAVASCRIPT, AUTO -> firstCharIconBinding.firstChar
|
||||
.setIconTextColorByThemeColorLuminance()
|
||||
.setStrokeThemeColor()
|
||||
.setFillColorDayNight();
|
||||
.setStrokeColor(itemIconThemeColorForContrast)
|
||||
.setFillColor(itemIconThemeColorForContrast);
|
||||
default -> firstCharIconBinding.firstChar
|
||||
.setIconTextColorDayNight()
|
||||
.setStrokeColorDayNight()
|
||||
@@ -57,7 +81,7 @@ class ExplorerItemViewHolder extends BindableViewHolder<Object> {
|
||||
|
||||
firstCharIconBinding.firstChar.setIcon(ExplorerViewHelper.getIcon(explorerItem));
|
||||
|
||||
listFileBinding.checkbox.setChecked(fileChooseListView.getSelectedFiles().containsKey(mExplorerItem.toScriptFile()), false);
|
||||
checkbox.setChecked(fileChooseListView.getSelectedFiles().containsKey(mExplorerItem.toScriptFile()), false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,9 +25,12 @@ import org.autojs.autojs.execution.ScriptExecutionListener;
|
||||
import org.autojs.autojs.execution.SimpleScriptExecutionListener;
|
||||
import org.autojs.autojs.groundwork.WrapContentLinearLayoutManager;
|
||||
import org.autojs.autojs.script.AutoFileSource;
|
||||
import org.autojs.autojs.script.JavaScriptFileSource;
|
||||
import org.autojs.autojs.storage.database.ModelChange;
|
||||
import org.autojs.autojs.theme.ThemeColorManagerCompat;
|
||||
import org.autojs.autojs.timing.TimedTaskManager;
|
||||
import org.autojs.autojs.ui.timing.TimedTaskSettingActivity;
|
||||
import org.autojs.autojs.util.ColorUtils;
|
||||
import org.autojs.autojs.util.FileUtils;
|
||||
import org.autojs.autojs6.R;
|
||||
import org.autojs.autojs6.databinding.ExplorerFirstCharIconBinding;
|
||||
@@ -232,10 +235,19 @@ public class TaskListRecyclerView extends ThemeColorRecyclerView {
|
||||
|
||||
public void bind(Task 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
|
||||
.setIcon(AutoFileSource.ENGINE.equals(mTask.getEngineName()) ? FileUtils.TYPE.AUTO.icon : FileUtils.TYPE.JAVASCRIPT.icon)
|
||||
.setIconTextThemeColor()
|
||||
.setStrokeThemeColor()
|
||||
.setIcon(icon)
|
||||
.setIconTextColor(itemIconThemeColorForContrast)
|
||||
.setStrokeColor(itemIconThemeColorForContrast)
|
||||
.setFillTransparent();
|
||||
itemBinding.name.setText(task.getName());
|
||||
itemBinding.taskListFilePath.setText(task.getDesc());
|
||||
|
||||
@@ -11,6 +11,7 @@ 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.ColorUtils
|
||||
import org.autojs.autojs.util.FileUtils
|
||||
import org.autojs.autojs6.R
|
||||
import kotlin.math.roundToInt
|
||||
@@ -50,8 +51,6 @@ class FirstCharView : TextView {
|
||||
return privateBackground!!
|
||||
}
|
||||
|
||||
private fun convertColorResToInt(@ColorRes colorRes: Int) = context.getColor(colorRes)
|
||||
|
||||
fun setIconText(text: CharSequence?) = also { setText(text) }
|
||||
|
||||
fun setIcon(icon: FileUtils.TYPE.Icon): FirstCharView {
|
||||
@@ -70,7 +69,7 @@ class FirstCharView : TextView {
|
||||
|
||||
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()) }
|
||||
|
||||
@@ -82,7 +81,7 @@ class FirstCharView : TextView {
|
||||
|
||||
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())
|
||||
|
||||
@@ -92,7 +91,7 @@ class FirstCharView : TextView {
|
||||
|
||||
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())
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ public class PrefSwitch extends JsSwitch implements SharedPreferences.OnSharedPr
|
||||
|
||||
@Override
|
||||
public void setThemeColor(ThemeColor color) {
|
||||
ThemeColorHelper.setColorPrimary(this, color.colorPrimary);
|
||||
ThemeColorHelper.setColorPrimary(this, color.colorPrimary, true);
|
||||
}
|
||||
|
||||
private void readInitialState() {
|
||||
|
||||
@@ -632,4 +632,105 @@ object ColorUtils {
|
||||
@JvmStatic
|
||||
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
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,13 +17,13 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/item_background_dark"
|
||||
android:baselineAligned="false"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:foreground="?selectableItemBackground"
|
||||
android:orientation="horizontal"
|
||||
android:paddingVertical="9dp"
|
||||
android:paddingStart="8dp"
|
||||
android:baselineAligned="false"
|
||||
android:focusable="true">
|
||||
android:paddingStart="8dp">
|
||||
|
||||
<include
|
||||
layout="@layout/explorer_first_char_icon"
|
||||
|
||||
@@ -1,77 +1,110 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
<androidx.appcompat.widget.LinearLayoutCompat
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1px"
|
||||
android:background="?android:divider" />
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1px"
|
||||
android:background="?android:divider" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/item"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clickable="true"
|
||||
android:foreground="?selectableItemBackground"
|
||||
android:orientation="horizontal"
|
||||
android:padding="8dp">
|
||||
android:id="@+id/item"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/item_background_dark"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:foreground="?selectableItemBackground"
|
||||
android:orientation="horizontal"
|
||||
android:paddingVertical="9dp"
|
||||
android:paddingStart="8dp">
|
||||
|
||||
<org.autojs.autojs.core.ui.widget.JsCheckBox
|
||||
android:id="@+id/checkbox"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:gravity="center" />
|
||||
android:id="@+id/checkbox"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:gravity="center" />
|
||||
|
||||
<include
|
||||
layout="@layout/explorer_first_char_icon"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"/>
|
||||
layout="@layout/explorer_first_char_icon"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content" />
|
||||
|
||||
<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_gravity="center_vertical"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
android:ellipsize="end"
|
||||
android:gravity="center_vertical"
|
||||
android:maxLines="1"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="14sp"
|
||||
tools:text="@string/text_sample_name" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/name"
|
||||
android:layout_width="match_parent"
|
||||
<LinearLayout
|
||||
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_gravity="center"
|
||||
android:gravity="center"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center_vertical"
|
||||
android:maxLines="1"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="14sp"
|
||||
tools:text="@string/text_sample_name" />
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:textSize="11sp"
|
||||
tools:text="@string/text_sample_file_date" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/script_file_size"
|
||||
android:layout_width="match_parent"
|
||||
<TextView
|
||||
android:paddingHorizontal="3sp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginTop="4dp"
|
||||
android:ellipsize="middle"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:ellipsize="end"
|
||||
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"
|
||||
tools:text="@string/text_sample_file_size" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1px"
|
||||
android:background="#EDEEEF" />
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1px"
|
||||
android:background="#EDEEEF" />
|
||||
|
||||
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user