Android中如何监听View可见性变化并触发对应事件
检测布局可见性的实现方案
根据你使用的布局显隐控制方式,可以选择以下对应方案:
场景1:通过属性动画控制前一个布局消失
这是最常用的场景,直接绑定动画结束回调即可,此时前一个布局已经完全完成消失动画,不会出现内容残留:
// Kotlin示例 prevView.animate() .alpha(0f) // 这里可以换成你实际用的动画属性,比如translationX .setDuration(300) .withEndAction { // 动画结束后先把前一个布局设置为不可见 prevView.visibility = View.GONE // 再显示目标View targetView.visibility = View.VISIBLE } .start()
// Java示例 prevView.animate() .alpha(0f) .setDuration(300) .withEndAction(() -> { prevView.setVisibility(View.GONE); targetView.setVisibility(View.VISIBLE); }) .start();
场景2:无动画,由其他逻辑控制布局显隐
如果你的布局显隐没有动画,直接通过setVisibility方法修改状态,可用可见性变化监听器实现:
// API 24及以上可用直接用内置可见性监听器 prevView.setOnVisibilityChangeListener { view, newVisibility -> if (newVisibility == View.GONE || newVisibility == View.INVISIBLE) { // 用完移除监听器避免重复触发 view.setOnVisibilityChangeListener(null) targetView.visibility = View.VISIBLE } }
如果需要兼容API 24以下系统,使用全局布局监听器实现:
prevView.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener { override fun onGlobalLayout() { if (prevView.visibility == View.GONE || prevView.visibility == View.INVISIBLE) { // 移除监听器避免重复回调 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { prevView.viewTreeObserver.removeOnGlobalLayoutListener(this) } else { @Suppress("DEPRECATION") prevView.viewTreeObserver.removeGlobalOnLayoutListener(this) } targetView.visibility = View.VISIBLE } } })
场景3:使用Transition框架控制布局过渡
如果是用系统Transition框架做的布局切换,直接绑定过渡结束回调即可:
val outTransition = Fade(Fade.OUT) outTransition.addListener(object : Transition.TransitionListener { override fun onTransitionEnd(transition: Transition) { targetView.visibility = View.VISIBLE transition.removeListener(this) } // 其余未用到的回调方法可留空实现 }) TransitionManager.beginDelayedTransition(parentLayout, outTransition) prevView.visibility = View.GONE
优先推荐使用动画/过渡结束回调的方案,比全局布局监听器性能更高,也不会出现提前触发的问题
内容的提问来源于stack exchange,提问作者Adam Lee
相关产品推荐
相关产品推荐

