6.7.0 - Alpha10 - 新增 ui.navigationBarHeight 属性 (getter), 用于获取导航栏高度 (issue #456)
This commit is contained in:
@@ -12,6 +12,7 @@
|
|||||||
"s13n.bytes 方法, 用于标准化字节数据 (参阅 项目文档 > [标准化](https://docs.autojs6.com/#/s13n))",
|
"s13n.bytes 方法, 用于标准化字节数据 (参阅 项目文档 > [标准化](https://docs.autojs6.com/#/s13n))",
|
||||||
"UiObject#isShifted 方法, 用于检测控件位置变化",
|
"UiObject#isShifted 方法, 用于检测控件位置变化",
|
||||||
"device.getSharedDeviceId 方法, 用于跨应用获取统一共享设备 ID _[`issue #455`](http://issues.autojs6.com/455)_",
|
"device.getSharedDeviceId 方法, 用于跨应用获取统一共享设备 ID _[`issue #455`](http://issues.autojs6.com/455)_",
|
||||||
|
"ui.navigationBarHeight 属性 (getter), 用于获取导航栏高度 _[`issue #456`](http://issues.autojs6.com/456)_",
|
||||||
"http 模块请求相关方法获取的 body 对象增加 stream/saveToFile/close 方法 _[`issue #452`](http://issues.autojs6.com/452)_",
|
"http 模块请求相关方法获取的 body 对象增加 stream/saveToFile/close 方法 _[`issue #452`](http://issues.autojs6.com/452)_",
|
||||||
"http 模块请求相关方法支持缓存控制选项参数 (cacheBody/bodyCacheThresholdBytes)",
|
"http 模块请求相关方法支持缓存控制选项参数 (cacheBody/bodyCacheThresholdBytes)",
|
||||||
"http 模块请求相关方法支持不安全选项参数 (isInsecure/insecure), 用于忽略证书相关异常 _[`issue #417`](http://issues.autojs6.com/417)_",
|
"http 模块请求相关方法支持不安全选项参数 (isInsecure/insecure), 用于忽略证书相关异常 _[`issue #417`](http://issues.autojs6.com/417)_",
|
||||||
@@ -51,6 +52,7 @@
|
|||||||
"构建工具启用 isCleanup[Paddle/Rapid]Ocr 配置选项时无法正常完成 Rebuild Project 任务的问题"
|
"构建工具启用 isCleanup[Paddle/Rapid]Ocr 配置选项时无法正常完成 Rebuild Project 任务的问题"
|
||||||
],
|
],
|
||||||
"improvement": [
|
"improvement": [
|
||||||
|
"ui.statusBarHeight 属性 (getter) 增强一定程度的兼容性",
|
||||||
"console.log 等方法打印全局对象 (images, app, ocr 等) 时支持显示详细信息",
|
"console.log 等方法打印全局对象 (images, app, ocr 等) 时支持显示详细信息",
|
||||||
"android.graphics.Paint#setColor 支持正常解析 ColorInt/ColorHex/ColorName 等颜色参数",
|
"android.graphics.Paint#setColor 支持正常解析 ColorInt/ColorHex/ColorName 等颜色参数",
|
||||||
"内置模块相关方法实参类型的异常消息增加类型摘要信息",
|
"内置模块相关方法实参类型的异常消息增加类型摘要信息",
|
||||||
|
|||||||
@@ -135,8 +135,11 @@ class UI(private val scriptRuntime: ScriptRuntime) : AugmentableProxy(scriptRunt
|
|||||||
(activity as? ScriptExecuteActivity)?.eventEmitter
|
(activity as? ScriptExecuteActivity)?.eventEmitter
|
||||||
},
|
},
|
||||||
"statusBarHeight" to Supplier {
|
"statusBarHeight" to Supplier {
|
||||||
ViewUtils.getStatusBarHeightByDimen(globalContext)
|
ViewUtils.getStatusBarHeight(globalContext)
|
||||||
},
|
},
|
||||||
|
"navigationBarHeight" to Supplier {
|
||||||
|
ViewUtils.getNavigationBarHeight(globalContext)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ open class LayoutBoundsView : View {
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
this.setWillNotDraw(false)
|
this.setWillNotDraw(false)
|
||||||
statusBarHeight = ViewUtils.getStatusBarHeightByWindow(context)
|
statusBarHeight = ViewUtils.getStatusBarHeight(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setOnNodeInfoSelectListener(onNodeInfoSelectListener: OnNodeInfoSelectListener?) {
|
fun setOnNodeInfoSelectListener(onNodeInfoSelectListener: OnNodeInfoSelectListener?) {
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ public class LayoutHierarchyView extends MultiLevelListView {
|
|||||||
mPaint.setStyle(Paint.Style.STROKE);
|
mPaint.setStyle(Paint.Style.STROKE);
|
||||||
mPaint.setAntiAlias(true);
|
mPaint.setAntiAlias(true);
|
||||||
mPaint.setStrokeWidth(3);
|
mPaint.setStrokeWidth(3);
|
||||||
mStatusBarHeight = ViewUtils.getStatusBarHeightByWindow(getContext());
|
mStatusBarHeight = ViewUtils.getStatusBarHeight(getContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Paint getBoundsPaint() {
|
public Paint getBoundsPaint() {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import android.content.ContextWrapper
|
|||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.content.res.Configuration.UI_MODE_NIGHT_MASK
|
import android.content.res.Configuration.UI_MODE_NIGHT_MASK
|
||||||
import android.content.res.Configuration.UI_MODE_NIGHT_YES
|
import android.content.res.Configuration.UI_MODE_NIGHT_YES
|
||||||
|
import android.content.res.Resources
|
||||||
import android.graphics.ColorFilter
|
import android.graphics.ColorFilter
|
||||||
import android.graphics.PorterDuff
|
import android.graphics.PorterDuff
|
||||||
import android.graphics.PorterDuffColorFilter
|
import android.graphics.PorterDuffColorFilter
|
||||||
@@ -64,14 +65,6 @@ import kotlin.math.roundToInt
|
|||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
object ViewUtils {
|
object ViewUtils {
|
||||||
|
|
||||||
enum class MODE(val key: String) {
|
|
||||||
DAY(key(R.string.key_night_mode_always_off)),
|
|
||||||
NIGHT(key(R.string.key_night_mode_always_on)),
|
|
||||||
FOLLOW(key(R.string.key_night_mode_follow_system)),
|
|
||||||
NULL(key(R.string.key_night_mode_null)),
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
private const val TAG_STATUS_BAR_SCRIM = "status_bar_scrim"
|
private const val TAG_STATUS_BAR_SCRIM = "status_bar_scrim"
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@@ -103,47 +96,78 @@ object ViewUtils {
|
|||||||
return view.findViewById(resId)
|
return view.findViewById(resId)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME by Stardust on Jan 23, 2018.
|
|
||||||
// ! Not working in some devices.
|
|
||||||
// ! https://github.com/hyb1996/Auto.js/issues/268
|
|
||||||
// ! zh-CN (translated by SuperMonster003 on Jul 29, 2024):
|
|
||||||
// ! 在一些设备上无法正常获取结果.
|
|
||||||
// ! 参阅: https://github.com/hyb1996/Auto.js/issues/268
|
|
||||||
@SuppressLint("InternalInsetResource", "DiscouragedApi")
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
fun getStatusBarHeightByDimen(context: Context, withFallback: Boolean = true): Int {
|
fun getStatusBarHeight(context: Context, withFallback: Boolean = true): Int {
|
||||||
val resourceId = context.resources.getIdentifier("status_bar_height", "dimen", "android")
|
val window = getWindowForContext(context)
|
||||||
val dimenStatusBarHeight = when (resourceId > 0) {
|
|
||||||
true -> context.resources.getDimensionPixelSize(resourceId)
|
// [1] Status bar height solution based on WindowInsets, compatible with display cutout.
|
||||||
else -> 0
|
// zh-CN: 基于 WindowInsets 的状态栏高度方案, 兼容刘海 (display cutout).
|
||||||
}
|
|
||||||
return when {
|
val insetsTop = window?.decorView?.let { decor ->
|
||||||
dimenStatusBarHeight > 0 -> dimenStatusBarHeight
|
ViewCompat.getRootWindowInsets(decor)?.let { insets ->
|
||||||
withFallback -> TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 24f, context.resources.displayMetrics).toInt()
|
val statusTop = insets.getInsets(WindowInsetsCompat.Type.statusBars()).top
|
||||||
else -> 0
|
val cutoutTop = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||||
}
|
insets.displayCutout?.safeInsetTop ?: 0
|
||||||
|
} else 0
|
||||||
|
maxOf(statusTop, cutoutTop)
|
||||||
|
}
|
||||||
|
} ?: 0
|
||||||
|
if (insetsTop > 0) return insetsTop
|
||||||
|
|
||||||
|
// [2] Visible area top solution, may be 0 in some fullscreen/immersive modes.
|
||||||
|
// zh-CN: 可见区域 top 方案, 在某些全屏/沉浸式下可能为 0.
|
||||||
|
|
||||||
|
val rectTop = window?.decorView?.let { decor ->
|
||||||
|
Rect().also { rect -> decor.getWindowVisibleDisplayFrame(rect) }.top
|
||||||
|
} ?: 0
|
||||||
|
if (rectTop > 0) return rectTop
|
||||||
|
|
||||||
|
// [3] Internal dimen solution, only as an estimate.
|
||||||
|
// zh-CN: 内部 dimen 方案, 仅作为估值.
|
||||||
|
|
||||||
|
if (withFallback) return getStatusBarHeightByDimen(context)
|
||||||
|
|
||||||
|
// [4] Finally return 0, no constant forced.
|
||||||
|
// zh-CN: 最终返回 0, 不强制指定常量.
|
||||||
|
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
fun getStatusBarHeightByWindow(context: Context, withFallback: Boolean = true): Int {
|
fun getNavigationBarHeight(context: Context, withFallback: Boolean = true): Int {
|
||||||
val windowStatusBarHeight = getWindowForContext(context)?.decorView?.let { decorView ->
|
val window = getWindowForContext(context)
|
||||||
Rect().also { rect ->
|
|
||||||
decorView.getWindowVisibleDisplayFrame(rect)
|
// [1] Status bar height solution based on WindowInsets.
|
||||||
}.top
|
// zh-CN: 基于 WindowInsets 的状态栏高度方案.
|
||||||
|
|
||||||
|
val maxInsets = window?.decorView?.let { decor ->
|
||||||
|
ViewCompat.getRootWindowInsets(decor)
|
||||||
|
?.getInsets(WindowInsetsCompat.Type.navigationBars())
|
||||||
|
?.let { insets ->
|
||||||
|
// Compatible with horizontal screen navigation bars: take the maximum value of bottom/left/right.
|
||||||
|
// zh-CN: 兼容横屏左右侧导航栏: 取 bottom/left/right 最大值.
|
||||||
|
maxOf(insets.bottom, insets.left, insets.right)
|
||||||
|
}
|
||||||
} ?: 0
|
} ?: 0
|
||||||
return when {
|
if (maxInsets > 0) return maxInsets
|
||||||
windowStatusBarHeight > 0 -> windowStatusBarHeight
|
|
||||||
withFallback -> TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 24f, context.resources.displayMetrics).toInt()
|
// [2] Internal dimen solution, only as an estimate.
|
||||||
else -> 0
|
// zh-CN: 内部 dimen 方案, 仅作为估值.
|
||||||
}
|
|
||||||
|
if (withFallback) return getNavigationBarHeightByDimen(context)
|
||||||
|
|
||||||
|
// [3] Finally return 0, no constant forced.
|
||||||
|
// zh-CN: 最终返回 0, 不强制指定常量.
|
||||||
|
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getTitleBarHeight(context: Context): Int {
|
fun getTitleBarHeight(context: Context): Int {
|
||||||
val window = getWindowForContext(context)
|
val window = getWindowForContext(context)
|
||||||
val contentViewTop = window?.findViewById<View>(Window.ID_ANDROID_CONTENT)?.top ?: 0
|
val contentViewTop = window?.findViewById<View>(Window.ID_ANDROID_CONTENT)?.top ?: 0
|
||||||
return contentViewTop - getStatusBarHeightByWindow(context)
|
return contentViewTop - getStatusBarHeight(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getScreenHeight(activity: Activity) = DisplayMetrics().let { metrics ->
|
fun getScreenHeight(activity: Activity) = DisplayMetrics().let { metrics ->
|
||||||
@@ -307,7 +331,7 @@ object ViewUtils {
|
|||||||
val navBarOverlay = View(activity).apply {
|
val navBarOverlay = View(activity).apply {
|
||||||
layoutParams = FrameLayout.LayoutParams(
|
layoutParams = FrameLayout.LayoutParams(
|
||||||
MATCH_PARENT,
|
MATCH_PARENT,
|
||||||
navBarInsets.bottom, // 导航栏高度
|
navBarInsets.bottom, // Navigation bar height. (zh-CN: 导航栏高度.)
|
||||||
).apply { gravity = Gravity.BOTTOM }
|
).apply { gravity = Gravity.BOTTOM }
|
||||||
setBackgroundColor(color)
|
setBackgroundColor(color)
|
||||||
}
|
}
|
||||||
@@ -652,10 +676,12 @@ object ViewUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 显示软键盘.
|
* Show soft keyboard. (zh-CN: 显示软键盘.)
|
||||||
*
|
*
|
||||||
* @param target 需要获取输入的视图 (如 EditText)
|
* @param target The view that needs input (like EditText).
|
||||||
* @param useForced 是否使用 SHOW_FORCED 方式强制弹出, 默认 false, 代表由系统自行判断
|
* zh-CN: @param target 需要获取输入的视图 (如 EditText).
|
||||||
|
* @param useForced Whether to use SHOW_FORCED to force showing, default false, let system decide.
|
||||||
|
* zh-CN: @param useForced 是否使用 SHOW_FORCED 方式强制弹出, 默认 false, 代表由系统自行判断.
|
||||||
*/
|
*/
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
@@ -675,9 +701,10 @@ object ViewUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 隐藏软键盘.
|
* Hide soft keyboard. (zh-CN: 隐藏软键盘.)
|
||||||
*
|
*
|
||||||
* @param target 当前持有输入焦点的视图, 也可以是任意位于同一窗口的 View
|
* @param target The view currently holding input focus, or any view in the same window.
|
||||||
|
* zh-CN: @param target 当前持有输入焦点的视图, 也可以是任意位于同一窗口的 View.
|
||||||
*/
|
*/
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun hideSoftInput(target: View) {
|
fun hideSoftInput(target: View) {
|
||||||
@@ -685,6 +712,154 @@ object ViewUtils {
|
|||||||
imm.hideSoftInputFromWindow(target.windowToken, 0)
|
imm.hideSoftInputFromWindow(target.windowToken, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @Comment by SuperMonster003 on Oct 29, 2025.
|
||||||
|
// ! Replaced with getStatusBarHeightByWindow and improved getStatusBarHeightByDimen methods.
|
||||||
|
// ! zh-CN: 已替换为 getStatusBarHeightByWindow 和已改进的 getStatusBarHeightByDimen 方法.
|
||||||
|
// FIXME by Stardust on Jan 23, 2018.
|
||||||
|
// ! Not working in some devices.
|
||||||
|
// ! https://github.com/hyb1996/Auto.js/issues/268
|
||||||
|
// ! zh-CN (translated by SuperMonster003 on Jul 29, 2024):
|
||||||
|
// ! 在一些设备上无法正常获取结果.
|
||||||
|
// ! 参阅: https://github.com/hyb1996/Auto.js/issues/268
|
||||||
|
// # @SuppressLint("InternalInsetResource", "DiscouragedApi")
|
||||||
|
// # @JvmStatic
|
||||||
|
// # @JvmOverloads
|
||||||
|
// # fun getStatusBarHeightByDimen(context: Context, withFallback: Boolean = true): Int {
|
||||||
|
// # val resourceId = context.resources.getIdentifier("status_bar_height", "dimen", "android")
|
||||||
|
// # val dimenStatusBarHeight = when (resourceId > 0) {
|
||||||
|
// # true -> context.resources.getDimensionPixelSize(resourceId)
|
||||||
|
// # else -> 0
|
||||||
|
// # }
|
||||||
|
// # return when {
|
||||||
|
// # dimenStatusBarHeight > 0 -> dimenStatusBarHeight
|
||||||
|
// # withFallback -> TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 24f, context.resources.displayMetrics).toInt()
|
||||||
|
// # else -> 0
|
||||||
|
// # }
|
||||||
|
// # }
|
||||||
|
private fun getStatusBarHeightByDimen(context: Context, withComputedOnPreR: Boolean = true): Int {
|
||||||
|
val res = context.resources
|
||||||
|
|
||||||
|
// [1] Priority read from internal dimen to try to cover portrait/landscape differences.
|
||||||
|
// zh-CN: 优先从内部 dimen 读取, 尽量覆盖横竖屏差异.
|
||||||
|
|
||||||
|
val isLandscape = res.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
|
||||||
|
val dimenNameCandidates = when (isLandscape) {
|
||||||
|
true -> listOf("status_bar_height_landscape", "status_bar_height", "status_bar_height_default", "status_bar_height_portrait")
|
||||||
|
else -> listOf("status_bar_height_portrait", "status_bar_height", "status_bar_height_default", "status_bar_height_landscape")
|
||||||
|
}
|
||||||
|
|
||||||
|
val dimenHeight = dimenNameCandidates.asSequence().map { res.queryDimen(it) }.firstOrNull { it > 0 } ?: 0
|
||||||
|
if (dimenHeight > 0) return dimenHeight
|
||||||
|
|
||||||
|
// [2] Try to estimate using DisplayMetrics on pre-Android R.
|
||||||
|
// zh-CN: 在 Android R 以下, 尝试用 DisplayMetrics 估算.
|
||||||
|
|
||||||
|
if (!withComputedOnPreR) return 0
|
||||||
|
val (_, systemUiHeightInset) = getSystemUiInsetsOnPreR(context) ?: return 0
|
||||||
|
|
||||||
|
// Navigation bar estimated value.
|
||||||
|
// zh-CN: 导航栏估算值.
|
||||||
|
val navBar = getNavigationBarHeightByDimen(context, false).coerceAtLeast(0)
|
||||||
|
|
||||||
|
// "Status bar height" is approximately "vertical system area height" minus "navigation bar height".
|
||||||
|
// zh-CN: "状态栏高度" 近似视为 "垂直系统区域高度" 减去 "导航栏高度".
|
||||||
|
val statusGuess = (systemUiHeightInset - navBar).coerceAtLeast(0)
|
||||||
|
|
||||||
|
// Prevent abnormal values (status bar usually not exceeding 48dp).
|
||||||
|
// zh-CN: 防止异常值 (状态栏通常不超过 48dp).
|
||||||
|
val maxReasonable = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 48f, res.displayMetrics).toInt()
|
||||||
|
|
||||||
|
if (statusGuess in 1..maxReasonable) return statusGuess
|
||||||
|
|
||||||
|
// [3] Finally return 0, no constant forced.
|
||||||
|
// zh-CN: 最终返回 0, 仅依赖 context 且不强制指定常量.
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("InternalInsetResource", "DiscouragedApi")
|
||||||
|
private fun getNavigationBarHeightByDimen(context: Context, withComputedOnPreR: Boolean = true): Int {
|
||||||
|
val res = context.resources
|
||||||
|
|
||||||
|
// [1] If system declares not to show navigation bar, return 0 early (non-public resource, may be inaccurate).
|
||||||
|
// zh-CN: 如果系统声明不显示导航栏, 尽早返回 0 (非公开资源, 可能不准确).
|
||||||
|
|
||||||
|
val showNavResId = res.getIdentifier("config_showNavigationBar", "bool", "android")
|
||||||
|
if (showNavResId > 0) runCatching {
|
||||||
|
if (!res.getBoolean(showNavResId)) return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// [2] Priority read from internal dimen to try to cover portrait/landscape differences.
|
||||||
|
// zh-CN: 优先从内部 dimen 读取, 尽量覆盖横竖屏差异.
|
||||||
|
|
||||||
|
val isLandscape = res.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
|
||||||
|
val dimenNameCandidates = when (isLandscape) {
|
||||||
|
true -> listOf("navigation_bar_height_landscape", "navigation_bar_height", "navigation_bar_height_portrait")
|
||||||
|
else -> listOf("navigation_bar_height_portrait", "navigation_bar_height", "navigation_bar_height_landscape")
|
||||||
|
}
|
||||||
|
|
||||||
|
val dimenHeight = dimenNameCandidates.asSequence().map { res.queryDimen(it) }.firstOrNull { it > 0 } ?: 0
|
||||||
|
if (dimenHeight > 0) return dimenHeight
|
||||||
|
|
||||||
|
// [3] Try to estimate using DisplayMetrics on pre-Android R.
|
||||||
|
// zh-CN: 在 Android R 以下, 尝试用 DisplayMetrics 估算.
|
||||||
|
|
||||||
|
if (!withComputedOnPreR) return 0
|
||||||
|
val (systemUiWidthInset, systemUiHeightInset) = getSystemUiInsetsOnPreR(context) ?: return 0
|
||||||
|
|
||||||
|
// Status bar estimated value.
|
||||||
|
// zh-CN: 状态栏估算值.
|
||||||
|
val statusBar = getStatusBarHeightByDimen(context, false)
|
||||||
|
|
||||||
|
val bottomNavGuess = (systemUiHeightInset - statusBar).coerceAtLeast(0)
|
||||||
|
val sideNavGuess = systemUiWidthInset.coerceAtLeast(0)
|
||||||
|
|
||||||
|
// A navigation bar will be more likely on the side in landscape, and more likely on the bottom in portrait.
|
||||||
|
// zh-CN: 导航栏横屏更可能在侧边, 竖屏更可能在底部.
|
||||||
|
val computed = maxOf(bottomNavGuess, sideNavGuess)
|
||||||
|
|
||||||
|
// Prevent abnormal values (navigation bar usually not exceeding 96dp).
|
||||||
|
// zh-CN: 防止异常值 (导航栏通常不超过 96dp).
|
||||||
|
val maxReasonable = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 96f, res.displayMetrics).toInt()
|
||||||
|
|
||||||
|
if (computed in 1..maxReasonable) return computed
|
||||||
|
|
||||||
|
// [4] Finally return 0, no constant forced.
|
||||||
|
// zh-CN: 最终返回 0, 仅依赖 context 且不强制指定常量.
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("InternalInsetResource", "DiscouragedApi")
|
||||||
|
private fun Resources.queryDimen(name: String, def: (() -> Number)? = null): Int = runCatching {
|
||||||
|
val id = this.getIdentifier(name, "dimen", "android")
|
||||||
|
return if (id > 0) this.getDimensionPixelSize(id) else 0
|
||||||
|
}.getOrDefault(def?.invoke()?.toInt() ?: 0)
|
||||||
|
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
private fun getSystemUiInsetsOnPreR(context: Context): Pair<Int, Int>? {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) return null
|
||||||
|
val wm = context.getSystemService(Context.WINDOW_SERVICE) as? WindowManager ?: return null
|
||||||
|
val display = wm.defaultDisplay ?: return null
|
||||||
|
|
||||||
|
val real = DisplayMetrics().also { display.getRealMetrics(it) }
|
||||||
|
val usable = DisplayMetrics().also { display.getMetrics(it) }
|
||||||
|
|
||||||
|
val systemUiWidthInset = (real.widthPixels - usable.widthPixels).coerceAtLeast(0)
|
||||||
|
val systemUiHeightInset = (real.heightPixels - usable.heightPixels).coerceAtLeast(0)
|
||||||
|
|
||||||
|
return Pair(systemUiWidthInset, systemUiHeightInset)
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class MODE(val key: String) {
|
||||||
|
|
||||||
|
DAY(key(R.string.key_night_mode_always_off)),
|
||||||
|
NIGHT(key(R.string.key_night_mode_always_on)),
|
||||||
|
FOLLOW(key(R.string.key_night_mode_follow_system)),
|
||||||
|
NULL(key(R.string.key_night_mode_null)),
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
class AutoNightMode {
|
class AutoNightMode {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@@ -704,7 +879,7 @@ object ViewUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("ClickableViewAccessibility")
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
class TextSizeScaleDetector(context: Context, textView: TextView) :ScaleGestureDetector(context, TextSizeScaleListener(textView)) {
|
class TextSizeScaleDetector(context: Context, textView: TextView) : ScaleGestureDetector(context, TextSizeScaleListener(textView)) {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
textView.apply {
|
textView.apply {
|
||||||
@@ -726,7 +901,6 @@ object ViewUtils {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scaling & Text Size Handling
|
|
||||||
private class TextSizeScaleListener(private val textView: TextView) : ScaleGestureDetector.SimpleOnScaleGestureListener() {
|
private class TextSizeScaleListener(private val textView: TextView) : ScaleGestureDetector.SimpleOnScaleGestureListener() {
|
||||||
|
|
||||||
private val mMinTextSize = 4.0f
|
private val mMinTextSize = 4.0f
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#Wed Oct 29 12:59:31 CST 2025
|
#Wed Oct 29 20:13:49 CST 2025
|
||||||
BUILD_TIME=1761713971603
|
BUILD_TIME=1761740029614
|
||||||
COMPILE_SDK_VERSION=36
|
COMPILE_SDK_VERSION=36
|
||||||
IMAGE_QUANT_CMAKE_VERSION=3.22.1
|
IMAGE_QUANT_CMAKE_VERSION=3.22.1
|
||||||
IMAGE_QUANT_NDK_VERSION=26.1.10909125
|
IMAGE_QUANT_NDK_VERSION=26.1.10909125
|
||||||
@@ -27,6 +27,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=36
|
TARGET_SDK_VERSION=36
|
||||||
TARGET_SDK_VERSION_INRT=29
|
TARGET_SDK_VERSION_INRT=29
|
||||||
VERSION_BUILD=3451
|
VERSION_BUILD=3452
|
||||||
VERSION_NAME=6.7.0 Alpha10
|
VERSION_NAME=6.7.0 Alpha10
|
||||||
VSCODE_EXT_REQUIRED_VERSION=1.0.8
|
VSCODE_EXT_REQUIRED_VERSION=1.0.8
|
||||||
|
|||||||
Reference in New Issue
Block a user