首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

收放自如的软键盘SoftKeyboard

  • 24-12-16 12:05
  • 3668
  • 7482
juejin.cn

监听点击SoftKeyboard外部区域来收起输入法的实现方法

在Android应用中,当用户点击屏幕上的非EditText区域时,通常希望自动隐藏软键盘以提供更好的用户体验。以下是几种常见的实现方式及其详细说明和代码示例。

方法1:使用OnTouchListener监听触摸事件

这种方法通过设置一个全局的OnTouchListener来监听整个窗口的触摸事件,并在检测到点击发生在当前焦点视图(通常是EditText)之外时隐藏输入法。

代码示例 (Kotlin):
kotlin
代码解读
复制代码
class MainActivity : AppCompatActivity() { private lateinit var binding: ActivityMainBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) // 设置触摸监听器给根布局 findViewById(android.R.id.content).setOnTouchListener { _, event -> if (event.action == MotionEvent.ACTION_DOWN) { val currentFocus = currentFocus if (currentFocus is EditText && !isTouchInsideView(event, currentFocus)) { hideSoftKeyboard(this, currentFocus) return@setOnTouchListener true // 拦截事件 } } false } // 示例:点击按钮打开软键盘 binding.openKeyboardButton.setOnClickListener { openSoftKeyboard(binding.etInputData) } } /** * 判断点击是否在指定视图内。 */ private fun isTouchInsideView(event: MotionEvent, view: View): Boolean { val location = IntArray(2) view.getLocationOnScreen(location) val left = location[0] val top = location[1] val right = left + view.width val bottom = top + view.height return event.rawX >= left && event.rawX <= right && event.rawY >= top && event.rawY <= bottom } /** * 隐藏软键盘的方法。 */ private fun hideSoftKeyboard(activity: Activity, view: View) { val imm = activity.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager imm.hideSoftInputFromWindow(view.windowToken, 0) } /** * 打开软键盘的方法。 */ private fun openSoftKeyboard(view: View) { view.requestFocus() val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT) } }

方法2:重写dispatchTouchEvent

这个方法是在Activity中重写dispatchTouchEvent方法,捕捉所有传入的触摸事件,并判断点击是否发生在EditText以外的区域。如果点击发生在EditText外,则隐藏输入法。

代码示例 (Kotlin):
kotlin
代码解读
复制代码
class KeyboardExampleActivity : AppCompatActivity() { private lateinit var binding: ActivityKeyboardExampleBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityKeyboardExampleBinding.inflate(layoutInflater) setContentView(binding.root) // 其他初始化代码... } override fun dispatchTouchEvent(ev: MotionEvent): Boolean { if (ev.action == MotionEvent.ACTION_DOWN) { val currentFocusView = currentFocus if (currentFocusView is EditText && !isTouchTargetView(ev, currentFocusView)) { // 如果点击不是在当前获得焦点的EditText上,则隐藏软键盘 hideKeyboard(currentFocusView) } } return super.dispatchTouchEvent(ev) } /** * 判断手指落点是否位于输入框控件区域内。 */ private fun isTouchTargetView(event: MotionEvent?, view: View?): Boolean { if (event == null || view == null) return false val location = IntArray(2) view.getLocationOnScreen(location) val left = location[0] val top = location[1] val right = left + view.width val bottom = top + view.height return event.rawX >= left && event.rawX <= right && event.rawY >= top && event.rawY <= bottom } /** * 隐藏软键盘的方法。 */ private fun hideKeyboard(view: View) { val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager imm.hideSoftInputFromWindow(view.windowToken, 0) } /** * 打开软键盘的方法。 */ private fun openKeyboard(view: View) { view.requestFocus() val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT) } }

方法3:使用TouchDelegate

TouchDelegate主要用于扩大某个子View的触摸范围,而不是直接用来处理输入法的收起。它允许你指定一个父容器和一个代理区域,使得用户点击代理区域内的任何位置都会触发子View的点击事件。这在某些特定场景下有用,但并不是处理点击外部区域隐藏输入法的最常用方法。

使用场景与代码示例 (Kotlin):
kotlin
代码解读
复制代码
// 找到需要扩大的子View以及其所在的父容器 val parent = findViewById(R.id.parent_layout) val smallButton = findViewById(R.id.small_button) // 创建一个矩形作为扩展后的触摸区域 val bounds = Rect() smallButton.getHitRect(bounds) bounds.top -= 50 // 向上扩展 bounds.left -= 50 // 向左扩展 bounds.bottom += 50 // 向下扩展 bounds.right += 50 // 向右扩展 // 创建并应用TouchDelegate parent.touchDelegate = TouchDelegate(bounds, smallButton)

方法4:结合dispatchTouchEvent和isTouchTargetView

这是方法2的一个具体实现,它通过重写dispatchTouchEvent方法来检查手指落点是否位于输入框控件区域内,如果不是的话则隐藏软键盘。落在软键盘上的点击会被软键盘消耗掉,不会调用Activity的dispatchTouchEvent方法。

代码示例 (Kotlin):
kotlin
代码解读
复制代码
class KeyboardActivity : AppCompatActivity() { private lateinit var binding: ActivityKeyboardBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityKeyboardBinding.inflate(layoutInflater) setContentView(binding.root) // 示例:点击按钮打开软键盘 binding.openKeyboardButton.setOnClickListener { openKeyboard(binding.etInputData) } } override fun dispatchTouchEvent(ev: MotionEvent): Boolean { if (ev.action == MotionEvent.ACTION_DOWN) { if (!isTouchTargetView(ev, binding.etInputData)) { // 判断不是触摸输入框的位置则隐藏软键盘 currentFocus?.let { hideKeyboard(it) } } } return super.dispatchTouchEvent(ev) } /** * 判断手指落点是否位于输入框控件区域内。 */ private fun isTouchTargetView(event: MotionEvent?, view: View?): Boolean { if (event == null || view == null) return false val location = IntArray(2) view.getLocationOnScreen(location) val left = location[0] val top = location[1] val right = left + view.width val bottom = top + view.height return event.rawX >= left && event.rawX <= right && event.rawY >= top && event.rawY <= bottom } /** * 隐藏软键盘的方法。 */ private fun hideKeyboard(view: View) { val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager imm.hideSoftInputFromWindow(view.windowToken, 0) } /** * 打开软键盘的方法。 */ private fun openKeyboard(view: View) { view.requestFocus() val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT) } }

以上就是几种常见的方式及其实现代码。

注:本文转载自juejin.cn的望佑的文章"https://juejin.cn/post/7447873068976537626"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

140
Android
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top