v9.0.0 设置页/商店页遥控焦点高亮(获得焦点变蓝)+商店手动导航

This commit is contained in:
Hermes Agent committed 2026-10-08 13:31:40 +08:00
1 parent 1798429a2f
commit 6ae217b9cd
3 files changed
+135 -29

No files matched your search

@@ -27,6 +27,29 @@ class SettingsActivity : Activity() {
private lateinit var statusText: TextView
/** 焦点高亮背景:获得焦点→蓝色,普通→深灰 */
private fun focusBg(normal: Int = 0xFF2A2F3A.toInt(), focused: Int = 0xFF1B6EF3.toInt())
: android.graphics.drawable.StateListDrawable {
val sl = android.graphics.drawable.StateListDrawable()
sl.addState(intArrayOf(android.R.attr.state_focused), android.graphics.drawable.ColorDrawable(focused))
sl.addState(intArrayOf(), android.graphics.drawable.ColorDrawable(normal))
return sl
}
/** 可聚焦的操作行(代替固定背景的 Button,保证遥控器上能看到选中) */
private fun mkAction(label: String, onClick: () -> Unit): TextView =
TextView(this).apply {
text = label
textSize = 17f
setTextColor(Color.WHITE)
gravity = Gravity.CENTER
setPadding(24, 26, 24, 26)
isFocusable = true
isFocusableInTouchMode = true
background = focusBg()
setOnClickListener { onClick() }
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
try {
@@ -44,7 +67,12 @@ class SettingsActivity : Activity() {
setBackgroundColor(Color.parseColor("#12141A"))
setPadding(96, 64, 96, 64)
}
setContentView(root)
val scroll = android.widget.ScrollView(this).apply {
setBackgroundColor(Color.parseColor("#12141A"))
isFillViewport = true
}
scroll.addView(root)
setContentView(scroll)
root.addView(TextView(this).apply {
text = "设置"
@@ -88,7 +116,9 @@ class SettingsActivity : Activity() {
isChecked = isBootReceiverEnabled()
val pad = (24 * resources.displayMetrics.density).toInt()
setPadding(pad, pad / 2, pad, pad / 2)
setBackgroundColor(Color.parseColor("#1C2028"))
isFocusable = true
isFocusableInTouchMode = true
background = focusBg(normal = 0xFF1C2028.toInt())
}
bootSwitch.setOnCheckedChangeListener { _, checked ->
val pm = packageManager
@@ -135,20 +165,17 @@ class SettingsActivity : Activity() {
textSize = 16f
setTextColor(Color.WHITE)
setHintTextColor(Color.parseColor("#888888"))
setBackgroundColor(Color.parseColor("#1C2028"))
setPadding(24, 20, 24, 20)
isSingleLine = true
isFocusable = true
isFocusableInTouchMode = true
background = focusBg(normal = 0xFF1C2028.toInt())
inputType = android.text.InputType.TYPE_CLASS_TEXT
}
root.addView(cardInput, LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT).apply { bottomMargin = 12 })
val actBtn = Button(this).apply {
text = "激活"
textSize = 17f
setBackgroundColor(Color.parseColor("#1B6EF3"))
setOnClickListener { doActivate(cardInput.text.toString().trim()) }
}
val actBtn = mkAction("激活") { doActivate(cardInput.text.toString().trim()) }
root.addView(actBtn, LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT).apply { bottomMargin = 40 })
@@ -159,11 +186,8 @@ class SettingsActivity : Activity() {
gravity = Gravity.CENTER; setPadding(0, 24, 0, 24)
})
} else {
val btn = Button(this).apply {
text = "支付成为会员(月/季/年)"
textSize = 17f
setBackgroundColor(Color.parseColor("#1B6EF3"))
setOnClickListener { startActivity(Intent(this@SettingsActivity, ShopActivity::class.java)) }
val btn = mkAction("支付成为会员(月/季/年)") {
startActivity(Intent(this@SettingsActivity, ShopActivity::class.java))
}
root.addView(btn, LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT))
@@ -33,11 +33,44 @@ class ShopActivity : Activity() {
data class Plan(val id: Int, val name: String, val price: String, val days: Int)
private lateinit var list: ListView
private var rowAdapterRef: RowAdapter? = null
private lateinit var alipay: TextView
private lateinit var wxpay: TextView
private var shopZone = 0 // 0=套餐列表 1=支付方式
private lateinit var statusText: TextView
private var payType = "alipay"
private var orderNo = ""
private var machineId = ""
private val handler = Handler(Looper.getMainLooper())
/** 高亮自控的行适配器 */
private inner class RowAdapter(private var items: List<String>) : android.widget.BaseAdapter() {
var selected = 0
set(value) { field = value; notifyDataSetChanged() }
fun setItems(v: List<String>) { items = v; notifyDataSetChanged() }
override fun getCount(): Int = items.size
override fun getItem(position: Int): Any = items[position]
override fun getItemId(position: Int): Long = position.toLong()
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
val tv = (convertView as? TextView) ?: TextView(this@ShopActivity).apply {
textSize = 18f; setPadding(36, 26, 36, 26)
isSingleLine = true
ellipsize = android.text.TextUtils.TruncateAt.END
}
tv.text = items[position]
val on = position == selected
tv.setBackgroundColor(if (on) Color.parseColor("#1B6EF3") else Color.parseColor("#1C1F26"))
tv.setTextColor(Color.WHITE)
return tv
}
}
private fun focusBg(normal: Int, focused: Int): android.graphics.drawable.StateListDrawable {
val sl = android.graphics.drawable.StateListDrawable()
sl.addState(intArrayOf(android.R.attr.state_focused), android.graphics.drawable.ColorDrawable(focused))
sl.addState(intArrayOf(), android.graphics.drawable.ColorDrawable(normal))
return sl
}
private var pollTask: Runnable? = null
private var pollCount = 0
@@ -76,6 +109,10 @@ class ShopActivity : Activity() {
list = ListView(this).apply {
setBackgroundColor(Color.parseColor("#1C1F26"))
setSelector(android.graphics.drawable.ColorDrawable(Color.TRANSPARENT))
isFocusable = false
isFocusableInTouchMode = false
setItemsCanFocus(false)
}
root.addView(list, LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, 0, 1f
@@ -88,15 +125,16 @@ class ShopActivity : Activity() {
root.addView(statusText)
val row = LinearLayout(this).apply { orientation = LinearLayout.HORIZONTAL }
val alipay = Button(this).apply { text = "支付宝"; textSize = 15f }
val wxpay = Button(this).apply { text = "微信"; textSize = 15f }
fun sel(b: Button, t: String) {
val active = payType == t
b.setBackgroundColor(if (active) Color.parseColor("#1B6EF3") else Color.parseColor("#2A2F3A"))
fun mkPay(label: String, t: String) = TextView(this).apply {
text = label; textSize = 16f
setTextColor(Color.WHITE); gravity = Gravity.CENTER
setPadding(24, 26, 24, 26)
isFocusable = true; isFocusableInTouchMode = true
background = focusBg(0xFF2A2F3A.toInt(), 0xFF1B6EF3.toInt())
setOnClickListener { payType = t; refreshPayBtns() }
}
alipay.setOnClickListener { payType = "alipay"; sel(alipay, "alipay"); sel(wxpay, "wxpay") }
wxpay.setOnClickListener { payType = "wxpay"; sel(alipay, "alipay"); sel(wxpay, "wxpay") }
sel(alipay, "alipay"); sel(wxpay, "wxpay")
alipay = mkPay("支付宝", "alipay")
wxpay = mkPay("微信", "wxpay")
row.addView(alipay, LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f).apply { rightMargin = 16 })
row.addView(wxpay, LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f))
root.addView(row)
@@ -104,10 +142,20 @@ class ShopActivity : Activity() {
list.onItemClickListener = AdapterView.OnItemClickListener { _, _, pos, _ ->
if (pos < plans.size) createOrder(plans[pos])
}
refreshPayBtns()
loadPlans()
}
/** 当前支付方式:亮蓝 + 焦点时更亮 */
private fun refreshPayBtns() {
val a = payType == "alipay"
alipay.setBackgroundColor(Color.parseColor(if (a) "#1B6EF3" else "#2A2F3A"))
wxpay.setBackgroundColor(Color.parseColor(if (a) "#2A2F3A" else "#1B6EF3"))
alipay.alpha = if (a) 1f else 0.75f
wxpay.alpha = if (a) 0.75f else 1f
}
@SuppressLint("SetTextI18n")
private fun loadPlans() {
statusText.text = "加载套餐…"
@@ -130,11 +178,13 @@ class ShopActivity : Activity() {
}
runOnUiThread {
plans.sortBy { it.days }
list.adapter = ArrayAdapter(this, android.R.layout.simple_list_item_1, plans.map {
val ra = RowAdapter(plans.map {
val d = it.days
"📱 ${it.name} ¥${it.price} ${if (d >= 999) "永久" else "${d}天"}"
})
statusText.text = "选择套餐后按 OK 购买"
rowAdapterRef = ra
list.adapter = ra
statusText.text = "上下选择套餐,OK 购买;左右可切支付方式"
}
} catch (e: Exception) {
runOnUiThread { statusText.text = "加载失败: ${e.javaClass.simpleName}: ${e.message?.take(150)}" }
@@ -237,9 +287,41 @@ class ShopActivity : Activity() {
}
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
if (keyCode == KeyEvent.KEYCODE_BACK && pollTask != null) {
// 支付轮询中返回 → 取消轮询
handler.removeCallbacks(pollTask!!); pollTask = null
// 支付中:回归普通处理
if (pollTask != null) {
if (keyCode == KeyEvent.KEYCODE_BACK) { handler.removeCallbacks(pollTask!!); pollTask = null }
return super.onKeyDown(keyCode, event)
}
val ra = rowAdapterRef
when (keyCode) {
KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_DPAD_DOWN -> {
val delta = if (keyCode == KeyEvent.KEYCODE_DPAD_UP) -1 else 1
if (shopZone == 0 && ra != null && ra.count > 0) {
val np = ra.selected + delta
if (np < 0) { shopZone = 1; refreshPayBtns(); alipay.requestFocus() }
else { ra.selected = np.coerceAtMost(ra.count - 1); list.setSelection(ra.selected) }
} else if (shopZone == 1) {
if (delta > 0) { } else { shopZone = 0; ra?.let { list.setSelection(it.selected) } }
}
return true
}
KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_DPAD_RIGHT -> {
if (shopZone == 1) { payType = if (payType == "alipay") "wxpay" else "alipay"; refreshPayBtns() }
else if (ra != null && ra.count > 0) {
// 列表里左右也可切支付方式,方便一步到位
payType = if (payType == "alipay") "wxpay" else "alipay"; refreshPayBtns()
}
return true
}
KeyEvent.KEYCODE_DPAD_CENTER, KeyEvent.KEYCODE_ENTER, KeyEvent.KEYCODE_NUMPAD_ENTER -> {
if (shopZone == 1) { payType = if (payType == "alipay") "wxpay" else "alipay"; refreshPayBtns() }
else {
val pos = ra?.selected ?: -1
if (pos in plans.indices) createOrder(plans[pos])
}
return true
}
KeyEvent.KEYCODE_BACK -> { finish(); return true }
}
return super.onKeyDown(keyCode, event)
}