6.7.0 - Alpha19 - 主页抽屉添加开关分隔线以增强视觉体验
This commit is contained in:
@@ -151,7 +151,7 @@
|
|||||||
"崩溃报告页面支持双指缩放调整字体大小并添加常用功能按钮",
|
"崩溃报告页面支持双指缩放调整字体大小并添加常用功能按钮",
|
||||||
"应用启动器图标支持自适应图标特性 _[`issue #405`](http://issues.autojs6.com/405)_",
|
"应用启动器图标支持自适应图标特性 _[`issue #405`](http://issues.autojs6.com/405)_",
|
||||||
"Rhino 引擎在泛型签名解析失败时回退为原始反射类型以增强低版本安卓系统的反射方法可用性",
|
"Rhino 引擎在泛型签名解析失败时回退为原始反射类型以增强低版本安卓系统的反射方法可用性",
|
||||||
"主页抽屉开关类条目支持点击标题文字区域显示详情对话框并按需支持快捷跳转系统设置",
|
"主页抽屉开关类条目添加分隔线, 支持点击标题文字区域显示详情对话框并按需支持快捷跳转系统设置",
|
||||||
"启动或重启 AutoJs6 时支持点击主页抽屉 \"客户端模式\" 标题文字区域中止正在尝试建立的连接",
|
"启动或重启 AutoJs6 时支持点击主页抽屉 \"客户端模式\" 标题文字区域中止正在尝试建立的连接",
|
||||||
"客户端模式连接时支持使用 IPv6 地址及域名地址建立连接",
|
"客户端模式连接时支持使用 IPv6 地址及域名地址建立连接",
|
||||||
"客户端模式连接时支持特殊用途 IPv4 地址 (回环/广播/多播/保留/...) 检测提示",
|
"客户端模式连接时支持特殊用途 IPv4 地址 (回环/广播/多播/保留/...) 检测提示",
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import android.content.Intent
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
import android.view.MotionEvent
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
@@ -726,7 +727,6 @@ open class DrawerFragment : Fragment() {
|
|||||||
drawerStatsDisposables.add(historyDisposable)
|
drawerStatsDisposables.add(historyDisposable)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun configureDrawerWidth() {
|
private fun configureDrawerWidth() {
|
||||||
val screenWidthDp = resources.configuration.screenWidthDp
|
val screenWidthDp = resources.configuration.screenWidthDp
|
||||||
val targetWidthPx = 288f.coerceIn(
|
val targetWidthPx = 288f.coerceIn(
|
||||||
@@ -741,6 +741,40 @@ open class DrawerFragment : Fragment() {
|
|||||||
binding.pluginCenter.setOnClickListener { PluginCenterActivity.startActivity(it.context) }
|
binding.pluginCenter.setOnClickListener { PluginCenterActivity.startActivity(it.context) }
|
||||||
binding.restart.setOnClickListener { restart(mActivity, mActivity::beforeExit) }
|
binding.restart.setOnClickListener { restart(mActivity, mActivity::beforeExit) }
|
||||||
binding.exit.setOnClickListener { exit(mActivity, mActivity::beforeExit) }
|
binding.exit.setOnClickListener { exit(mActivity, mActivity::beforeExit) }
|
||||||
|
|
||||||
|
// Consume touches on drawer blank area to prevent "press state" leaking to RecyclerView items.
|
||||||
|
// zh-CN: 消费抽屉空白区域触摸, 防止按压状态影响 RecyclerView item 的 ripple/pressed 表现.
|
||||||
|
binding.drawerMenuContainer.setOnTouchListener { v, ev ->
|
||||||
|
val rv = binding.drawerMenu
|
||||||
|
val buttonsRow = binding.settings.parent as? View
|
||||||
|
|
||||||
|
fun hitTest(target: View?): Boolean {
|
||||||
|
if (target == null) return false
|
||||||
|
val loc = IntArray(2)
|
||||||
|
target.getLocationOnScreen(loc)
|
||||||
|
val left = loc[0]
|
||||||
|
val top = loc[1]
|
||||||
|
val right = left + target.width
|
||||||
|
val bottom = top + target.height
|
||||||
|
val x = ev.rawX.toInt()
|
||||||
|
val y = ev.rawY.toInt()
|
||||||
|
return x in left until right && y in top until bottom
|
||||||
|
}
|
||||||
|
|
||||||
|
val onRecycler = hitTest(rv)
|
||||||
|
val onButtons = hitTest(buttonsRow)
|
||||||
|
|
||||||
|
if (onRecycler || onButtons) {
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
// Keep container from staying pressed.
|
||||||
|
// zh-CN: 避免容器保持 pressed 状态.
|
||||||
|
if (ev.actionMasked == MotionEvent.ACTION_DOWN) {
|
||||||
|
v.isPressed = false
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import androidx.core.view.isVisible
|
|||||||
import me.zhanghai.android.materialprogressbar.MaterialProgressBar
|
import me.zhanghai.android.materialprogressbar.MaterialProgressBar
|
||||||
import org.autojs.autojs.ui.widget.BindableViewHolder
|
import org.autojs.autojs.ui.widget.BindableViewHolder
|
||||||
import org.autojs.autojs.ui.widget.PrefSwitch
|
import org.autojs.autojs.ui.widget.PrefSwitch
|
||||||
|
import org.autojs.autojs.util.ViewUtils.installFullRowRippleForwarder
|
||||||
import org.autojs.autojs6.databinding.DrawerMenuItemBinding
|
import org.autojs.autojs6.databinding.DrawerMenuItemBinding
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -17,6 +18,7 @@ import org.autojs.autojs6.databinding.DrawerMenuItemBinding
|
|||||||
class DrawerMenuItemViewHolder(itemView: View) : BindableViewHolder<DrawerMenuItem?>(itemView) {
|
class DrawerMenuItemViewHolder(itemView: View) : BindableViewHolder<DrawerMenuItem?>(itemView) {
|
||||||
|
|
||||||
private val mSwitchCompat: PrefSwitch
|
private val mSwitchCompat: PrefSwitch
|
||||||
|
private val mSwitchDivider: View
|
||||||
private val mProgressBar: MaterialProgressBar
|
private val mProgressBar: MaterialProgressBar
|
||||||
private val mIcon: ImageView
|
private val mIcon: ImageView
|
||||||
private val mTitle: TextView
|
private val mTitle: TextView
|
||||||
@@ -30,6 +32,7 @@ class DrawerMenuItemViewHolder(itemView: View) : BindableViewHolder<DrawerMenuIt
|
|||||||
init {
|
init {
|
||||||
val binding = DrawerMenuItemBinding.bind(itemView)
|
val binding = DrawerMenuItemBinding.bind(itemView)
|
||||||
mSwitchCompat = binding.sw
|
mSwitchCompat = binding.sw
|
||||||
|
mSwitchDivider = binding.switchDivider
|
||||||
mProgressBar = binding.progressBar
|
mProgressBar = binding.progressBar
|
||||||
mIcon = binding.icon
|
mIcon = binding.icon
|
||||||
mTitle = binding.title
|
mTitle = binding.title
|
||||||
@@ -38,6 +41,13 @@ class DrawerMenuItemViewHolder(itemView: View) : BindableViewHolder<DrawerMenuIt
|
|||||||
onClick()
|
onClick()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val iconContainer = binding.iconContainer
|
||||||
|
val titleContainer = binding.titleContainer
|
||||||
|
|
||||||
|
// Install full-row ripple forwarding once.
|
||||||
|
// zh-CN: 安装整行 Ripple 转发, 通常只需安装一次.
|
||||||
|
installFullRowRippleForwarder(itemView, iconContainer, titleContainer)
|
||||||
|
|
||||||
val toggleAction = {
|
val toggleAction = {
|
||||||
if (mSwitchCompat.isVisible) {
|
if (mSwitchCompat.isVisible) {
|
||||||
mSwitchCompat.toggle()
|
mSwitchCompat.toggle()
|
||||||
@@ -46,11 +56,11 @@ class DrawerMenuItemViewHolder(itemView: View) : BindableViewHolder<DrawerMenuIt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.iconContainer.setOnClickListener {
|
iconContainer.setOnClickListener {
|
||||||
toggleAction()
|
toggleAction()
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.iconContainer.setOnLongClickListener {
|
iconContainer.setOnLongClickListener {
|
||||||
when (val menuItem = mDrawerMenuItem) {
|
when (val menuItem = mDrawerMenuItem) {
|
||||||
is DrawerMenuToggleableItem -> {
|
is DrawerMenuToggleableItem -> {
|
||||||
menuItem.launchManagerIfPossible()
|
menuItem.launchManagerIfPossible()
|
||||||
@@ -59,7 +69,7 @@ class DrawerMenuItemViewHolder(itemView: View) : BindableViewHolder<DrawerMenuIt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.titleContainer.setOnClickListener {
|
titleContainer.setOnClickListener {
|
||||||
when (val menuItem = mDrawerMenuItem) {
|
when (val menuItem = mDrawerMenuItem) {
|
||||||
is DrawerMenuToggleableItem -> {
|
is DrawerMenuToggleableItem -> {
|
||||||
menuItem.onTitleContainerClick()
|
menuItem.onTitleContainerClick()
|
||||||
@@ -68,7 +78,7 @@ class DrawerMenuItemViewHolder(itemView: View) : BindableViewHolder<DrawerMenuIt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.titleContainer.setOnLongClickListener {
|
titleContainer.setOnLongClickListener {
|
||||||
when (val menuItem = mDrawerMenuItem) {
|
when (val menuItem = mDrawerMenuItem) {
|
||||||
is DrawerMenuToggleableItem -> {
|
is DrawerMenuToggleableItem -> {
|
||||||
menuItem.launchManagerIfPossible()
|
menuItem.launchManagerIfPossible()
|
||||||
@@ -98,9 +108,11 @@ class DrawerMenuItemViewHolder(itemView: View) : BindableViewHolder<DrawerMenuIt
|
|||||||
private fun setSwitch(item: DrawerMenuItem) {
|
private fun setSwitch(item: DrawerMenuItem) {
|
||||||
if (!item.isSwitchEnabled) {
|
if (!item.isSwitchEnabled) {
|
||||||
mSwitchCompat.visibility = View.GONE
|
mSwitchCompat.visibility = View.GONE
|
||||||
|
mSwitchDivider.visibility = View.GONE
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
mSwitchCompat.visibility = View.VISIBLE
|
mSwitchCompat.visibility = View.VISIBLE
|
||||||
|
mSwitchDivider.visibility = View.VISIBLE
|
||||||
val prefKey = item.prefKey
|
val prefKey = item.prefKey
|
||||||
if (prefKey == DrawerMenuItem.DEFAULT_PREFERENCE_KEY) {
|
if (prefKey == DrawerMenuItem.DEFAULT_PREFERENCE_KEY) {
|
||||||
mSwitchCompat.setChecked(item.isChecked, false)
|
mSwitchCompat.setChecked(item.isChecked, false)
|
||||||
|
|||||||
@@ -32,8 +32,10 @@ import android.util.DisplayMetrics
|
|||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
import android.view.Gravity
|
import android.view.Gravity
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
|
import android.view.MotionEvent
|
||||||
import android.view.ScaleGestureDetector
|
import android.view.ScaleGestureDetector
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.view.ViewConfiguration
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
|
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
import android.view.ViewTreeObserver
|
import android.view.ViewTreeObserver
|
||||||
@@ -72,6 +74,7 @@ import org.autojs.autojs.runtime.ScriptRuntime
|
|||||||
import org.autojs.autojs.theme.ThemeColorManager
|
import org.autojs.autojs.theme.ThemeColorManager
|
||||||
import org.autojs.autojs.util.StringUtils.key
|
import org.autojs.autojs.util.StringUtils.key
|
||||||
import org.autojs.autojs6.R
|
import org.autojs.autojs6.R
|
||||||
|
import kotlin.math.abs
|
||||||
import kotlin.math.floor
|
import kotlin.math.floor
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
@@ -846,6 +849,7 @@ object ViewUtils {
|
|||||||
// zh-CN:
|
// zh-CN:
|
||||||
// 如果 view 未 attach 时调用 requestApplyInsets() 会被丢弃.
|
// 如果 view 未 attach 时调用 requestApplyInsets() 会被丢弃.
|
||||||
// 需要等 attach 后再请求一次, 才能稳定触发 insets 分发.
|
// 需要等 attach 后再请求一次, 才能稳定触发 insets 分发.
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
private fun View.requestApplyInsetsWhenAttached() {
|
private fun View.requestApplyInsetsWhenAttached() {
|
||||||
if (ViewCompat.isAttachedToWindow(this)) {
|
if (ViewCompat.isAttachedToWindow(this)) {
|
||||||
ViewCompat.requestApplyInsets(this)
|
ViewCompat.requestApplyInsets(this)
|
||||||
@@ -1405,6 +1409,239 @@ object ViewUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Install a ripple forwarder that makes full-row background react to touches on specific children,
|
||||||
|
* while preserving RecyclerView-like delayed pressed behavior.
|
||||||
|
* zh-CN:
|
||||||
|
* 安装 Ripple 转发器, 让整行背景响应指定子视图的触摸,
|
||||||
|
* 同时尽量模拟 RecyclerView 的延迟 pressed 行为.
|
||||||
|
*/
|
||||||
|
fun installFullRowRippleForwarder(
|
||||||
|
parent: View,
|
||||||
|
vararg touchSources: View,
|
||||||
|
pressDelayMillis: Int = ViewConfiguration.getTapTimeout(),
|
||||||
|
) {
|
||||||
|
// Ensure the parent can show stateful background/foreground.
|
||||||
|
// zh-CN: 确保父视图可以显示带状态的 background/foreground.
|
||||||
|
parent.isClickable = true
|
||||||
|
parent.isFocusable = true
|
||||||
|
|
||||||
|
val vc = ViewConfiguration.get(parent.context)
|
||||||
|
|
||||||
|
// Movement threshold to decide "scrolling" vs "tapping".
|
||||||
|
// zh-CN: 用于区分 "滚动" 与 "点击" 的移动阈值.
|
||||||
|
val touchSlop = vc.scaledTouchSlop
|
||||||
|
|
||||||
|
// Duration used by framework to show a short pressed state for quick taps.
|
||||||
|
// zh-CN: 系统用于 "快速点击" 时短暂显示 pressed 的持续时间.
|
||||||
|
val pressedStateDuration = ViewConfiguration.getPressedStateDuration()
|
||||||
|
|
||||||
|
// Reusable objects to avoid allocations in hot paths.
|
||||||
|
// zh-CN: 复用对象, 避免高频路径分配.
|
||||||
|
val parentLoc = IntArray(2)
|
||||||
|
val childHitRect = Rect()
|
||||||
|
|
||||||
|
touchSources.forEach { child ->
|
||||||
|
child.setOnTouchListener(object : View.OnTouchListener {
|
||||||
|
|
||||||
|
// Track one gesture stream.
|
||||||
|
// zh-CN: 跟踪一次手势流.
|
||||||
|
private var activePointerId: Int = MotionEvent.INVALID_POINTER_ID
|
||||||
|
|
||||||
|
// Down positions in raw (screen) coordinates.
|
||||||
|
// zh-CN: DOWN 时的 raw (屏幕) 坐标.
|
||||||
|
private var downRawX: Float = 0f
|
||||||
|
private var downRawY: Float = 0f
|
||||||
|
|
||||||
|
// Last known raw coordinates for hotspot update.
|
||||||
|
// zh-CN: 用于更新 hotspot 的最近 raw 坐标.
|
||||||
|
private var lastRawX: Float = 0f
|
||||||
|
private var lastRawY: Float = 0f
|
||||||
|
|
||||||
|
// Whether we have applied parent pressed state.
|
||||||
|
// zh-CN: 是否已应用父视图 pressed 状态.
|
||||||
|
private var pressedApplied: Boolean = false
|
||||||
|
|
||||||
|
// Whether we are still waiting to apply pressed (pre-pressed).
|
||||||
|
// zh-CN: 是否仍处于等待 pressed 的 pre-pressed 状态.
|
||||||
|
private var prePressed: Boolean = false
|
||||||
|
|
||||||
|
// Runnable to apply pressed after delay.
|
||||||
|
// zh-CN: 延迟触发 pressed 的 Runnable.
|
||||||
|
private val applyPressedRunnable = Runnable {
|
||||||
|
if (!prePressed) {
|
||||||
|
return@Runnable
|
||||||
|
}
|
||||||
|
if (!isInsideViewWithSlop(child, lastRawX, lastRawY, touchSlop, childHitRect)) {
|
||||||
|
prePressed = false
|
||||||
|
return@Runnable
|
||||||
|
}
|
||||||
|
applyPressedNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTouch(v: View, event: MotionEvent): Boolean {
|
||||||
|
when (event.actionMasked) {
|
||||||
|
MotionEvent.ACTION_DOWN -> {
|
||||||
|
activePointerId = event.getPointerId(0)
|
||||||
|
|
||||||
|
downRawX = event.rawX
|
||||||
|
downRawY = event.rawY
|
||||||
|
lastRawX = event.rawX
|
||||||
|
lastRawY = event.rawY
|
||||||
|
|
||||||
|
pressedApplied = false
|
||||||
|
prePressed = true
|
||||||
|
|
||||||
|
// Delay pressed to mimic scrolling container behavior.
|
||||||
|
// zh-CN: 延迟 pressed, 模拟可滚动容器的行为.
|
||||||
|
parent.removeCallbacks(applyPressedRunnable)
|
||||||
|
parent.postDelayed(applyPressedRunnable, pressDelayMillis.toLong())
|
||||||
|
}
|
||||||
|
|
||||||
|
MotionEvent.ACTION_MOVE -> {
|
||||||
|
val idx = event.findPointerIndex(activePointerId)
|
||||||
|
if (idx < 0) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
lastRawX = event.rawX
|
||||||
|
lastRawY = event.rawY
|
||||||
|
|
||||||
|
// If moved too much, treat as scroll and cancel.
|
||||||
|
// zh-CN: 如果移动过大, 视为滚动并取消.
|
||||||
|
val movedTooMuch =
|
||||||
|
abs(lastRawX - downRawX) > touchSlop || abs(lastRawY - downRawY) > touchSlop
|
||||||
|
|
||||||
|
if (movedTooMuch) {
|
||||||
|
cancelPressed()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// If pressed is already applied, keep hotspot in sync.
|
||||||
|
// zh-CN: 若 pressed 已应用, 持续同步 hotspot.
|
||||||
|
if (pressedApplied) {
|
||||||
|
updateHotspot(lastRawX, lastRawY)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MotionEvent.ACTION_UP -> {
|
||||||
|
val idx = event.findPointerIndex(activePointerId)
|
||||||
|
if (idx < 0) {
|
||||||
|
cancelPressed()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
lastRawX = event.rawX
|
||||||
|
lastRawY = event.rawY
|
||||||
|
|
||||||
|
// If we never applied pressed (quick tap), apply briefly then clear.
|
||||||
|
// zh-CN: 如果尚未应用 pressed (快速点击), 短暂应用后清除.
|
||||||
|
if (prePressed && !pressedApplied) {
|
||||||
|
parent.removeCallbacks(applyPressedRunnable)
|
||||||
|
|
||||||
|
if (isInsideViewWithSlop(child, lastRawX, lastRawY, touchSlop, childHitRect)) {
|
||||||
|
applyPressedNow()
|
||||||
|
parent.postDelayed(
|
||||||
|
{ parent.isPressed = false },
|
||||||
|
pressedStateDuration.toLong(),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
cancelPressed()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Normal end of gesture.
|
||||||
|
// zh-CN: 正常结束手势.
|
||||||
|
parent.removeCallbacks(applyPressedRunnable)
|
||||||
|
// Defer clearing pressed state until after this UP is dispatched to the child view.
|
||||||
|
// zh-CN: 将清除 pressed 的时机延后到本次 UP 分发给子视图之后.
|
||||||
|
parent.post {
|
||||||
|
parent.isPressed = false
|
||||||
|
}
|
||||||
|
prePressed = false
|
||||||
|
pressedApplied = false
|
||||||
|
}
|
||||||
|
|
||||||
|
activePointerId = MotionEvent.INVALID_POINTER_ID
|
||||||
|
}
|
||||||
|
|
||||||
|
MotionEvent.ACTION_CANCEL -> {
|
||||||
|
cancelPressed()
|
||||||
|
activePointerId = MotionEvent.INVALID_POINTER_ID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do not consume, so child's click/long-click keep working.
|
||||||
|
// zh-CN: 不消费事件, 保持子视图 click/long-click 正常工作.
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply pressed immediately and update hotspot.
|
||||||
|
* zh-CN: 立即应用 pressed, 并更新 hotspot.
|
||||||
|
*/
|
||||||
|
private fun applyPressedNow() {
|
||||||
|
pressedApplied = true
|
||||||
|
prePressed = false
|
||||||
|
parent.isPressed = true
|
||||||
|
updateHotspot(lastRawX, lastRawY)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancel any pending pressed state and clear current pressed state.
|
||||||
|
* zh-CN: 取消所有待触发的 pressed, 并清除当前 pressed 状态.
|
||||||
|
*/
|
||||||
|
private fun cancelPressed() {
|
||||||
|
parent.removeCallbacks(applyPressedRunnable)
|
||||||
|
parent.isPressed = false
|
||||||
|
prePressed = false
|
||||||
|
pressedApplied = false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update parent's ripple hotspot based on raw coordinates.
|
||||||
|
* zh-CN: 基于 raw 坐标更新父视图的 Ripple hotspot.
|
||||||
|
*/
|
||||||
|
private fun updateHotspot(rawX: Float, rawY: Float) {
|
||||||
|
parent.getLocationOnScreen(parentLoc)
|
||||||
|
val hx = rawX - parentLoc[0]
|
||||||
|
val hy = rawY - parentLoc[1]
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
|
parent.drawableHotspotChanged(hx, hy)
|
||||||
|
parent.background?.setHotspot(hx, hy)
|
||||||
|
parent.foreground?.setHotspot(hx, hy)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether a raw (screen) coordinate is inside the view bounds with slop tolerance.
|
||||||
|
* zh-CN: 判断 raw (屏幕) 坐标是否在视图边界内, 并允许一定 slop 容差.
|
||||||
|
*/
|
||||||
|
private fun isInsideViewWithSlop(
|
||||||
|
view: View,
|
||||||
|
rawX: Float,
|
||||||
|
rawY: Float,
|
||||||
|
slop: Int,
|
||||||
|
outRect: Rect,
|
||||||
|
): Boolean {
|
||||||
|
val loc = IntArray(2)
|
||||||
|
view.getLocationOnScreen(loc)
|
||||||
|
|
||||||
|
val xInView = rawX - loc[0]
|
||||||
|
val yInView = rawY - loc[1]
|
||||||
|
|
||||||
|
outRect.set(
|
||||||
|
-slop,
|
||||||
|
-slop,
|
||||||
|
view.width + slop,
|
||||||
|
view.height + slop,
|
||||||
|
)
|
||||||
|
return outRect.contains(xInView.toInt(), yInView.toInt())
|
||||||
|
}
|
||||||
|
|
||||||
enum class MODE(val key: String) {
|
enum class MODE(val key: String) {
|
||||||
|
|
||||||
DAY(key(R.string.key_night_mode_always_off)),
|
DAY(key(R.string.key_night_mode_always_off)),
|
||||||
|
|||||||
@@ -5,8 +5,10 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:minHeight="43dp"
|
|
||||||
android:background="?selectableItemBackground"
|
android:background="?selectableItemBackground"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"
|
||||||
|
android:minHeight="43dp"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
@@ -32,7 +34,6 @@
|
|||||||
android:layout_height="15dp"
|
android:layout_height="15dp"
|
||||||
android:backgroundTint="@color/drawer_menu_group_text_color"
|
android:backgroundTint="@color/drawer_menu_group_text_color"
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
@@ -41,7 +42,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:minHeight="43dp"
|
android:minHeight="43dp"
|
||||||
android:layout_toEndOf="@+id/icon_container"
|
android:layout_toEndOf="@+id/icon_container"
|
||||||
android:layout_toStartOf="@id/sw"
|
android:layout_toStartOf="@id/switch_divider"
|
||||||
android:layout_centerVertical="true"
|
android:layout_centerVertical="true"
|
||||||
android:layout_marginEnd="5dp"
|
android:layout_marginEnd="5dp"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
@@ -66,9 +67,20 @@
|
|||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
tools:visibility="gone"
|
tools:visibility="gone"
|
||||||
tools:text="@string/text_sample_string" />
|
tools:text="@string/text_sample_string" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/switch_divider"
|
||||||
|
android:layout_width="1dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_toStartOf="@id/sw"
|
||||||
|
android:layout_marginStart="2dp"
|
||||||
|
android:layout_marginEnd="6dp"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:background="@color/day_night_alpha_20"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
<org.autojs.autojs.ui.widget.PrefSwitch
|
<org.autojs.autojs.ui.widget.PrefSwitch
|
||||||
android:id="@+id/sw"
|
android:id="@+id/sw"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
@@ -79,5 +91,4 @@
|
|||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
tools:checked="true"
|
tools:checked="true"
|
||||||
tools:visibility="visible" />
|
tools:visibility="visible" />
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
@@ -29,16 +29,16 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_horizontal"
|
android:layout_gravity="center_horizontal"
|
||||||
android:layout_marginVertical="2dp"
|
android:paddingVertical="2dp"
|
||||||
android:baselineAligned="false">
|
android:baselineAligned="false">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/settings"
|
android:id="@+id/settings"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:background="?selectableItemBackground"
|
android:background="?selectableItemBackground"
|
||||||
android:layout_gravity="center|bottom"
|
android:gravity="center|bottom"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
@@ -65,10 +65,10 @@
|
|||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/plugin_center"
|
android:id="@+id/plugin_center"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:background="?selectableItemBackground"
|
android:background="?selectableItemBackground"
|
||||||
android:layout_gravity="center|bottom"
|
android:gravity="center|bottom"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
@@ -95,10 +95,10 @@
|
|||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/restart"
|
android:id="@+id/restart"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:background="?selectableItemBackground"
|
android:background="?selectableItemBackground"
|
||||||
android:layout_gravity="center|bottom"
|
android:gravity="center|bottom"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
@@ -125,10 +125,10 @@
|
|||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/exit"
|
android:id="@+id/exit"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:background="?selectableItemBackground"
|
android:background="?selectableItemBackground"
|
||||||
android:layout_gravity="center|bottom"
|
android:gravity="center|bottom"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
|
|||||||
Reference in New Issue
Block a user