问题描述
例如在 BuyFragment 购买页 支持在输入框 EditText 软键盘输入商品编号加入购物车,同时支持 扫码 自动加入购物车的需求场景,但是焦点在 EditText 时,扫码内容会直接输入 EditText,不符合业务需求。
解决办法
- BuyFragment 购买页初始化时,通过 setOnKeyListener 同时 监听 根 View binding.root 和 手动输入框 EditText binding.etId
- 判断 binding.etId 返回的 keyEvent 的 deviceId 若 > 0 则为硬件设备输入,此时将原本在 EditText 的焦点 转移 根 View binding.root,防止扫码内容输入 EditText
- 再通过 binding.root 的监听处理扫描内容,参考代码如下:
class BuyFragment : Fragment() {
...
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
handleViewScanData(binding.root)
binding.etId.setOnKeyListener { _, _, keyEvent ->
// deviceId > 0 为硬件设备输入
if (keyEvent.deviceId > 0) {
requestViewFocus(binding.root)
true
} else {
false
}
binding.etId.requestFocus()
}
/**
* view 设置焦点
*/
fun requestViewFocus(view: View) {
view.isFocusableInTouchMode = true
view.requestFocus()
}
/**
* view 输入事件处理
*/
fun handleViewScanData(view: View) {
requestViewFocus(view)
view.setOnKeyListener { _, _, keyEvent ->
...
true
}
}
...
可能遇到的问题
根 View binding.root 获得焦点时出现选中框,如下图:
- 解决办法:布局中新增一个 1像素 View 作为 焦点。
<View
android:id="@+id/v_point"
android:layout_width="1dp"
android:layout_height="1dp" />
加入 binding.vPoint 后参考代码如下:
class BuyFragment : Fragment() {
...
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
handleViewScanData(binding.vPoint)
binding.etId.setOnKeyListener { _, _, keyEvent ->
if (keyEvent.deviceId > 0) {
requestViewFocus(binding.vPoint)
true
} else {
false
}
binding.etId.requestFocus()
}
/**
* view 设置焦点
*/
fun requestViewFocus(view: View) {
view.isFocusableInTouchMode = true
view.requestFocus()
}
/**
* view 输入事件处理
*/
fun handleViewScanData(view: View) {
requestViewFocus(view)
view.setOnKeyListener { _, _, keyEvent ->
...
true
}
}
...