Android 扫码枪输入时屏蔽软键盘和顶部状态栏
这是个扫码枪回车输入扫码内容的界面,常用于收银收款等场景
前期踩了很多坑,网上的资料也因为 Android 历史版本不同有各种兼容问题,最后总结了下
在无霸屏设置的 android 设备上使用如下方案可有效避免界面弹出软键盘和显示顶部状态栏问题,环境为 Android 7.1.2
屏蔽软键盘:自动聚焦
隐藏顶部状态:方案一 hideStatusBar
必须在 setContentView
之前,方案二在 styles 中设置 NoActionBar
具体可自行搜索
- AndroidManifest.xml
<activity
android:name=".MyActivity"
android:windowSoftInputMode="stateHidden"
android:exported="false" />
- activity_my.xml
<EditText
android:id="@+id/scanInput"
android:layout_width="0dp"
android:layout_height="0dp"
android:focusable="true"
android:focusableInTouchMode="true"
android:focusedByDefault="true"
android:importantForAutofill="no"
android:inputType="none" />
- MyActivity.kt
class MyActivity : AppCompatActivity() {
private lateinit var binding: ActivityMyBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMyBinding.inflate(layoutInflater)
hideStatusBar()
setContentView(binding.root)
hideSoftKeyboard()
initListener()
}
override fun onResume() {
super.onResume()
hideSoftKeyboard()
hideActionBar()
}
private fun hideSoftKeyboard() {
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN)
this.currentFocus?.let { view ->
val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager
imm?.hideSoftInputFromWindow(view.windowToken, InputMethodManager.RESULT_HIDDEN)
}
}
private fun hideStatusBar() {
requestWindowFeature(Window.FEATURE_NO_TITLE);
window.setFlags(
WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN
)
}
private fun hideActionBar() {
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN
actionBar?.hide()
}
private fun initListener() {
binding.scanInput.requestFocus()
binding.scanInput.setOnKeyListener { _, keyCode, keyEvent ->
if (keyCode == KeyEvent.KEYCODE_ENTER && keyEvent.action == KeyEvent.ACTION_UP) {
val code = binding.scanInput.text.toString()
// to do with code
binding.scanInput.text = null
return@setOnKeyListener true
}
false
}
}
}
如果是 Jetpack Compose 布局或者不想用 EditText 获取输入,那么可以在 Activity 内用 dispatchKeyEvent 事件获取,
需要注意的是 KeyEvent 并不能直接转为我们想要的字符,所以需要用 KeyListener 和 Editable 组合输入,并最终获取类似输入框中的字符串
class MyActivity : ComponentActivity() {
private val tag = "MainActivity"
private var isFocus = false
private val tkl: KeyListener = TextKeyListener(Capitalize.NONE, false)
private val et: Editable = Editable.Factory.getInstance().newEditable("")
override fun onWindowFocusChanged(hasFocus: Boolean) {
super.onWindowFocusChanged(hasFocus)
isFocus = hasFocus
Log.i(tag, "hasFocus: $hasFocus")
}
private fun onKey(event: KeyEvent): Boolean {
return when (event.action) {
KeyEvent.ACTION_DOWN -> {
tkl.onKeyDown(null, et, event.keyCode, event)
}
KeyEvent.ACTION_UP -> {
tkl.onKeyUp(null, et, event.keyCode, event)
}
else -> {
tkl.onKeyOther(null, et, event)
}
}
}
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
if (isFocus) {
if (event.action == KeyEvent.ACTION_UP && event.keyCode == KeyEvent.KEYCODE_ENTER) {
Log.i(tag, "[dispatchKeyEvent] enter: ${et}")
et.clear()
return true
} else if (onKey(event)) {
return true
}
}
return super.dispatchKeyEvent(event)
}
}
如有问题或建议,欢迎大家评论区讨论指正!