6.6.2 - Alpha4 - 新增 ui.statusBarAppearanceLight/statusBarAppearanceLightBy/navigationBarColor 等方法

This commit is contained in:
SuperMonster003
2025-03-15 18:16:09 +08:00
parent aab0e7e254
commit 05bde0f7a3
15 changed files with 173 additions and 47 deletions

View File

@@ -1,6 +1,7 @@
package org.autojs.autojs.runtime.api.augment.ui
import android.graphics.drawable.ColorDrawable
import android.os.Build
import android.view.ContextThemeWrapper
import android.view.View
import android.view.ViewGroup
@@ -33,6 +34,7 @@ import org.autojs.autojs.runtime.api.augment.colors.Colors
import org.autojs.autojs.runtime.api.augment.jsox.Numberx
import org.autojs.autojs.runtime.exception.WrappedIllegalArgumentException
import org.autojs.autojs.theme.ThemeColor
import org.autojs.autojs.util.ColorUtils
import org.autojs.autojs.util.RhinoUtils
import org.autojs.autojs.util.RhinoUtils.NOT_CONSTRUCTABLE
import org.autojs.autojs.util.RhinoUtils.UNDEFINED
@@ -107,7 +109,12 @@ class UI(private val scriptRuntime: ScriptRuntime) : AugmentableProxy(scriptRunt
::registerWidget.name,
::setContentView.name,
::statusBarColor.name,
::statusBarAppearanceLight.name,
::statusBarAppearanceLightBy.name,
::backgroundColor.name,
::navigationBarColor.name,
::navigationBarAppearanceLight.name,
::navigationBarAppearanceLightBy.name,
::findById.name,
::findByStringId.name,
::findView.name,
@@ -516,6 +523,29 @@ class UI(private val scriptRuntime: ScriptRuntime) : AugmentableProxy(scriptRunt
UNDEFINED
}
@JvmStatic
@RhinoRuntimeFunctionInterface
fun statusBarAppearanceLight(scriptRuntime: ScriptRuntime, args: Array<out Any?>): Undefined = ensureArgumentsAtMost(args, 1) { argList ->
val (isLight) = argList
ensureActivity(scriptRuntime) { activity ->
runRhinoRuntime(scriptRuntime, newBaseFunction("action", {
ViewUtils.setStatusBarAppearanceLight(activity, coerceBoolean(isLight, true))
}, NOT_CONSTRUCTABLE))
}
UNDEFINED
}
@JvmStatic
@RhinoRuntimeFunctionInterface
fun statusBarAppearanceLightBy(scriptRuntime: ScriptRuntime, args: Array<out Any?>): Undefined = ensureArgumentsOnlyOne(args) { refColor ->
ensureActivity(scriptRuntime) { activity ->
runRhinoRuntime(scriptRuntime, newBaseFunction("action", {
Colors.toIntRhino(refColor).also { ViewUtils.setStatusBarAppearanceLight(activity, ColorUtils.isLuminanceDark(it)) }
}, NOT_CONSTRUCTABLE))
}
UNDEFINED
}
@JvmStatic
@RhinoRuntimeFunctionInterface
fun backgroundColor(scriptRuntime: ScriptRuntime, args: Array<out Any?>): Undefined = ensureArgumentsOnlyOne(args) { color ->
@@ -529,6 +559,50 @@ class UI(private val scriptRuntime: ScriptRuntime) : AugmentableProxy(scriptRunt
UNDEFINED
}
@JvmStatic
@RhinoRuntimeFunctionInterface
fun navigationBarColor(scriptRuntime: ScriptRuntime, args: Array<out Any?>): Undefined = ensureArgumentsOnlyOne(args) { color ->
ensureActivity(scriptRuntime) { activity ->
runRhinoRuntime(scriptRuntime, newBaseFunction("action", {
Colors.toIntRhino(color).also { ViewUtils.setNavigationBarBackgroundColor(activity, it) }
}, NOT_CONSTRUCTABLE))
}
UNDEFINED
}
@JvmStatic
@RhinoRuntimeFunctionInterface
fun navigationBarAppearanceLight(scriptRuntime: ScriptRuntime, args: Array<out Any?>): Undefined = ensureArgumentsAtMost(args, 1) { argList ->
val (isLight) = argList
ensureActivity(scriptRuntime) { activity ->
runRhinoRuntime(scriptRuntime, newBaseFunction("action", {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
ScriptRuntime.requiresApi(Build.VERSION_CODES.O)
} else {
ViewUtils.setNavigationBarAppearanceLight(activity, coerceBoolean(isLight, true))
}
}, NOT_CONSTRUCTABLE))
}
UNDEFINED
}
@JvmStatic
@RhinoRuntimeFunctionInterface
fun navigationBarAppearanceLightBy(scriptRuntime: ScriptRuntime, args: Array<out Any?>): Undefined = ensureArgumentsOnlyOne(args) { refColor ->
ensureActivity(scriptRuntime) { activity ->
runRhinoRuntime(scriptRuntime, newBaseFunction("action", {
Colors.toIntRhino(refColor).also {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
ScriptRuntime.requiresApi(Build.VERSION_CODES.O)
} else {
ViewUtils.setNavigationBarAppearanceLight(activity, ColorUtils.isLuminanceDark(it))
}
}
}, NOT_CONSTRUCTABLE))
}
UNDEFINED
}
@JvmStatic
@RhinoRuntimeFunctionInterface
fun findById(scriptRuntime: ScriptRuntime, args: Array<out Any?>): Any? = ensureArgumentsOnlyOne(args) { id ->

View File

@@ -96,7 +96,7 @@ class ColorSelectActivity : BaseActivity() {
override fun initThemeColors() {
super.initThemeColors()
setUpToolbarColors()
setUpStatusBarIconLight()
setUpStatusBarAppearanceLight()
}
private fun setUpToolbarColors() {
@@ -112,8 +112,8 @@ class ColorSelectActivity : BaseActivity() {
}
}
private fun setUpStatusBarIconLight() {
ViewUtils.setStatusBarIconLight(this, ColorUtils.isLuminanceDark(mCurrentColor))
private fun setUpStatusBarAppearanceLight() {
ViewUtils.setStatusBarAppearanceLight(this, ColorUtils.isLuminanceDark(mCurrentColor))
}
private fun setColorWithAnimation(view: View, colorTo: Int) {

View File

@@ -39,6 +39,7 @@ abstract class BaseActivity : AppCompatActivity() {
if (handleNavigationBarContrastEnforcedAutomatically) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
@Suppress("DEPRECATION")
window.navigationBarColor = getColor(R.color.black_alpha_44)
}
}
@@ -72,7 +73,7 @@ abstract class BaseActivity : AppCompatActivity() {
initThemeColors()
if (handleStatusBarThemeColorAutomatically && !BuildConfig.isInrt) {
ThemeColorManager.addActivityStatusBar(this)
setUpStatusBarIconLightByThemeColor()
setUpStatusBarAppearanceLightByThemeColor()
}
}
@@ -89,12 +90,12 @@ abstract class BaseActivity : AppCompatActivity() {
fun setToolbarAsBack(title: String?) = ViewUtils.setToolbarAsBack(this, title)
protected fun setUpStatusBarIconLightByNightMode() {
ViewUtils.setStatusBarIconLight(this, ViewUtils.isNightModeEnabled)
protected fun setUpStatusBarAppearanceLightByNightMode() {
ViewUtils.setStatusBarAppearanceLight(this, ViewUtils.isNightModeEnabled)
}
protected fun setUpStatusBarIconLightByThemeColor() {
ViewUtils.setStatusBarIconLight(this, ThemeColorManager.isThemeColorLuminanceDark())
protected fun setUpStatusBarAppearanceLightByThemeColor() {
ViewUtils.setStatusBarAppearanceLight(this, ThemeColorManager.isThemeColorLuminanceDark())
}
}

View File

@@ -5,6 +5,7 @@ import android.os.Bundle
import android.webkit.WebView
import org.autojs.autojs.ui.BaseActivity
import org.autojs.autojs.util.DocsUtils.getUrl
import org.autojs.autojs.util.ViewUtils
import org.autojs.autojs.util.WebViewUtils
import org.autojs.autojs6.databinding.ActivityDocumentationBinding
@@ -26,7 +27,10 @@ class DocumentationActivity : BaseActivity() {
binding.ewebView.also { ewebView ->
ewebView.webView.also { webView ->
mWebView = webView
WebViewUtils.adaptDarkMode(this@DocumentationActivity, webView)
webView.settings.setSupportMultipleWindows(true)
if (ViewUtils.isNightModeYes(this)) {
WebViewUtils.adaptDarkMode(webView)
}
WebViewUtils.excludeWebViewFromStatusBarAndNavigationBar(ewebView)
webView.loadUrl(intent.getStringExtra(EXTRA_URL) ?: getUrl("index.html"))
}
@@ -36,7 +40,7 @@ class DocumentationActivity : BaseActivity() {
override fun onStart() {
super.onStart()
setUpStatusBarIconLightByNightMode()
setUpStatusBarAppearanceLightByNightMode()
}
@SuppressLint("MissingSuperCall")

View File

@@ -15,6 +15,7 @@ import org.autojs.autojs.ui.main.QueryEvent
import org.autojs.autojs.ui.main.ViewPagerFragment
import org.autojs.autojs.ui.main.ViewStatesManageable
import org.autojs.autojs.util.DocsUtils.getUrl
import org.autojs.autojs.util.ViewUtils
import org.autojs.autojs.util.WebViewUtils
import org.autojs.autojs6.R
import org.autojs.autojs6.databinding.FragmentOnlineDocsBinding
@@ -54,7 +55,10 @@ open class DocumentationFragment : ViewPagerFragment(ROTATION_GONE), BackPressed
binding.ewebView.also { ewebView ->
ewebView.webView.also { webView ->
mWebView = webView
WebViewUtils.adaptDarkMode(requireContext(), webView)
webView.settings.setSupportMultipleWindows(true)
if (ViewUtils.isNightModeYes(requireContext())) {
WebViewUtils.adaptDarkMode(webView)
}
WebViewUtils.excludeWebViewFromNavigationBar(ewebView)
}
}

View File

@@ -201,8 +201,8 @@ class MainActivity : BaseActivity(), DelegateHost, HostActivity {
override fun onDrawerSlide(drawerView: View, slideOffset: Float) {
super.onDrawerSlide(drawerView, slideOffset)
when {
slideOffset > 0.5 -> setUpStatusBarIconLightByNightMode()
else -> setUpStatusBarIconLightByThemeColor()
slideOffset > 0.5 -> setUpStatusBarAppearanceLightByNightMode()
else -> setUpStatusBarAppearanceLightByThemeColor()
}
}
@@ -260,13 +260,13 @@ class MainActivity : BaseActivity(), DelegateHost, HostActivity {
super.initThemeColors()
setUpToolbarColors()
setUpTabLayoutColors()
setUpStatusBarIconLight()
setUpStatusBarAppearanceLight()
}
override fun onWindowFocusChanged(hasFocus: Boolean) {
super.onWindowFocusChanged(hasFocus)
if (hasFocus) {
setUpStatusBarIconLight()
setUpStatusBarAppearanceLight()
}
}
@@ -295,12 +295,12 @@ class MainActivity : BaseActivity(), DelegateHost, HostActivity {
mTab.setSelectedTabIndicatorColor(tabSelectedIndicatorColor)
}
private fun setUpStatusBarIconLight() {
private fun setUpStatusBarAppearanceLight() {
Handler(Looper.getMainLooper()).post {
if (sIsActionBarDrawerOpened) {
setUpStatusBarIconLightByNightMode()
setUpStatusBarAppearanceLightByNightMode()
} else {
setUpStatusBarIconLightByThemeColor()
setUpStatusBarAppearanceLightByThemeColor()
}
}
}

View File

@@ -147,12 +147,12 @@ abstract class BaseDisplayContentActivity : BaseActivity() {
internalFabView.backgroundTintList = ColorStateList.valueOf(themeColorNight)
internalFabView.imageTintList = ColorStateList.valueOf(if (ColorUtils.isLuminanceDark(themeColorNight)) getColor(R.color.night) else getColor(R.color.day))
ViewUtils.setStatusBarBackgroundColor(this, themeColorNight)
ViewUtils.setStatusBarIconLight(this, ColorUtils.isLuminanceDark(themeColorNight))
ViewUtils.setStatusBarAppearanceLight(this, ColorUtils.isLuminanceDark(themeColorNight))
} else {
internalFabView.backgroundTintList = ColorStateList.valueOf(themeColorDay)
internalFabView.imageTintList = ColorStateList.valueOf(if (ColorUtils.isLuminanceDark(themeColorDay)) getColor(R.color.night) else getColor(R.color.day))
ViewUtils.setStatusBarBackgroundColor(this, themeColorDay)
ViewUtils.setStatusBarIconLight(this, ColorUtils.isLuminanceDark(themeColorDay))
ViewUtils.setStatusBarAppearanceLight(this, ColorUtils.isLuminanceDark(themeColorDay))
}
}

View File

@@ -18,6 +18,7 @@ import org.autojs.autojs6.databinding.ActivitySplashBinding
class SplashActivity : BaseActivity() {
override val handleStatusBarThemeColorAutomatically = false
override val handleNavigationBarContrastEnforcedAutomatically = false
private var mAlreadyEnterNextActivity = false
private var mPaused = false

View File

@@ -9,6 +9,7 @@ import android.graphics.Color
import android.view.View
import androidx.annotation.ColorInt
import androidx.annotation.ColorRes
import androidx.annotation.FloatRange
import androidx.core.graphics.ColorUtils
import org.autojs.autojs.app.GlobalAppContext
import org.autojs.autojs.core.image.ColorTable
@@ -579,6 +580,7 @@ object ColorUtils {
* @see <a href="https://www.w3.org/TR/WCAG20/#relativeluminancedef">W3C Recommendation</a>
*/
@JvmStatic
@FloatRange(0.0, 1.0)
fun luminance(@ColorInt color: Int): Double {
// @Hint by SuperMonster003 on Jan 21, 2023.
// ! Compatibility solution.

View File

@@ -26,6 +26,7 @@ import android.view.WindowManager
import android.widget.FrameLayout
import android.widget.Toast
import androidx.annotation.IdRes
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import androidx.appcompat.widget.Toolbar
@@ -167,20 +168,20 @@ object ViewUtils {
}
@JvmStatic
fun isStatusBarIconLight(activity: Activity): Boolean {
return !isStatusBarIconDark(activity)
fun isStatusBarAppearanceLight(activity: Activity): Boolean {
return !isStatusBarAppearanceDark(activity)
}
@JvmStatic
fun isStatusBarIconDark(activity: Activity): Boolean {
fun isStatusBarAppearanceDark(activity: Activity): Boolean {
@Suppress("DEPRECATION")
return hasSystemUiVisibility(activity, View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR)
}
fun setStatusBarIconLight(activity: Activity, isLight: Boolean) {
fun setStatusBarAppearanceLight(activity: Activity, isLight: Boolean) {
@Suppress("DEPRECATION")
when {
isStatusBarIconLight(activity) == isLight -> return
isStatusBarAppearanceLight(activity) == isLight -> return
isLight -> removeSystemUiVisibility(activity, View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR)
else -> appendSystemUiVisibility(activity, View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR)
}
@@ -210,6 +211,29 @@ object ViewUtils {
}
}
@RequiresApi(Build.VERSION_CODES.O)
@JvmStatic
fun isNavigationBarAppearanceLight(activity: Activity): Boolean {
return !isNavigationBarAppearanceDark(activity)
}
@RequiresApi(Build.VERSION_CODES.O)
@JvmStatic
fun isNavigationBarAppearanceDark(activity: Activity): Boolean {
@Suppress("DEPRECATION")
return hasSystemUiVisibility(activity, View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR)
}
@RequiresApi(Build.VERSION_CODES.O)
fun setNavigationBarAppearanceLight(activity: Activity, isLight: Boolean) {
@Suppress("DEPRECATION")
when {
isNavigationBarAppearanceLight(activity) == isLight -> return
isLight -> removeSystemUiVisibility(activity, View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR)
else -> appendSystemUiVisibility(activity, View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR)
}
}
fun setNavigationBarBackgroundColor(activity: Activity, color: Int) {
val window = activity.window
val decorView = window.decorView

View File

@@ -1,8 +1,5 @@
package org.autojs.autojs.util
import android.content.Context
import android.os.Build.VERSION.SDK_INT
import android.os.Build.VERSION_CODES.TIRAMISU
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.core.graphics.Insets
@@ -37,25 +34,39 @@ class WebViewUtils {
// ! - 安卓系统 WebView或类似 Google Chrome 浏览器)版本 >= 105
// ! 参阅: https://stackoverflow.com/questions/57449900/letting-webview-on-android-work-with-prefers-color-scheme-dark
@JvmStatic
fun adaptDarkMode(context: Context, webView: WebView) {
if (isFeatureSupported(FORCE_DARK) && SDK_INT < TIRAMISU) {
webView.settings.let { webSettings ->
webSettings.setSupportMultipleWindows(true)
// @Comment by SuperMonster003 on Aug 14, 2023.
// # @Suppress("DEPRECATION")
// # WebSettingsCompat.setForceDark(
// # webSettings, when (ViewUtils.isNightModeYes(context)) {
// # true -> FORCE_DARK_ON
// # else -> FORCE_DARK_OFF
// # }
// # )
if (isFeatureSupported(ALGORITHMIC_DARKENING)) {
WebSettingsCompat.setAlgorithmicDarkeningAllowed(webSettings, ViewUtils.isNightModeYes(context))
}
fun adaptDarkMode(webView: WebView) {
val settings = webView.settings
when {
isFeatureSupported(ALGORITHMIC_DARKENING) -> {
WebSettingsCompat.setAlgorithmicDarkeningAllowed(settings, true)
}
isFeatureSupported(FORCE_DARK) -> {
@Suppress("DEPRECATION")
WebSettingsCompat.setForceDark(settings, WebSettingsCompat.FORCE_DARK_ON)
}
// FIXME by SuperMonster003 on Mar 14, 2025.
// ! Not working.
// ! zh-CN: 不起作用.
// else -> injectDarkModeCSS(webView)
}
}
private fun injectDarkModeCSS(webView: WebView) {
val darkModeCSS = """
(function() {
let style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = `
html { filter: invert(1) hue-rotate(180deg); }
img, video { filter: invert(1) hue-rotate(180deg); }
`;
document.head.appendChild(style);
})();
""".trimIndent()
webView.evaluateJavascript(darkModeCSS, null)
}
fun excludeWebViewFromNavigationBar(ewebView: EWebView) {
excludeWebViewFromSystemBars(ewebView, excludeStatusBar = false, excludeNavigationBar = true)
}

View File

@@ -52,6 +52,6 @@
android:id="@+id/script_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fafafa" />
android:background="@color/window_background" />
</LinearLayout>

View File

@@ -17,6 +17,8 @@
<color name="night_day">@color/night</color>
<color name="night_day_full">@color/night_full</color>
<color name="window_background">#FFFFFF</color>
<color name="window_background_light">#FFFFFF</color>
<color name="window_background_night">@color/day_full</color>
<color name="window_background_selected">#E5E5E5</color>
<color name="text_color_primary">@color/day_night</color>
<color name="text_color_primary_full">@color/day_night_full</color>