Android中调用bringToFront()后如何将视图还原至原有层级?
Android 长按缩放图片后还原视图层级的解决方案
问题核心原理
调用bringToFront()的本质是将目标View从父容器的子View列表中移动到末尾位置,Android渲染子View时会按照列表顺序从先到后绘制,列表末尾的View会显示在最上层,因此系统没有提供直接的反向API,我们可以通过以下几种方案实现层级还原。
方案1:使用Z轴属性控制层级(推荐,兼容API 21+)
该方案无需调整父容器的子View顺序,通过动态修改Z轴高度实现层级变化,实现成本最低:
- 放大时先记录ImageView和TextView原本的Z轴数值,再将其Z值调高即可显示在最上层
- 缩小后将Z值还原为记录的初始值即可恢复原有层级
修改后的示例代码:
// 用于存储原始Z值的变量,可放在Activity成员变量位置,也可以用View的tag存储 private var ivOriginalZ = 0f private var tvOriginalZ = 0f fun Activity.zoomInOut(iv: ImageView, tv: TextView, isZoomedIn: Boolean): Boolean { val isZoomed: Boolean val parent = iv.parent as ViewGroup if (isZoomedIn) { val animZoomOut = AnimationUtils.loadAnimation( applicationContext, R.anim.zoom_out ) // 动画结束后还原Z值 animZoomOut.setAnimationListener(object : Animation.AnimationListener { override fun onAnimationStart(animation: Animation?) {} override fun onAnimationRepeat(animation: Animation?) {} override fun onAnimationEnd(animation: Animation?) { iv.z = ivOriginalZ tv.z = tvOriginalZ } }) iv.startAnimation(animZoomOut) tv.startAnimation(animZoomOut) isZoomed = false } else { // 放大前先记录原始Z值 ivOriginalZ = iv.z tvOriginalZ = tv.z val animZoomIn = AnimationUtils.loadAnimation( applicationContext, R.anim.zoom_in ) animZoomIn.setAnimationListener(object : Animation.AnimationListener { override fun onAnimationStart(animation: Animation?) {} override fun onAnimationRepeat(animation: Animation?) {} override fun onAnimationEnd(animation: Animation?) { // 调高Z值,值越大越靠上层 iv.z = parent.maxZ + 1f tv.z = parent.maxZ + 1f } }) iv.startAnimation(animZoomIn) tv.startAnimation(animZoomIn) isZoomed = true } return isZoomed }
方案2:记录原始索引位置(兼容所有API版本)
如果需要兼容API 21以下的设备,可以通过记录View在父容器中的原始索引实现还原:
- 调用
bringToFront()之前,先获取ImageView和TextView在父容器子View列表中的索引位置并存储 - 缩小动画结束后,调用父容器的
addView(View, index)方法将两个View插回原来的索引位置,即可恢复原有层级
示例代码片段:
// 存储原始索引的成员变量 private var ivOriginalIndex = 0 private var tvOriginalIndex = 0 // 放大时的逻辑 ivOriginalIndex = parent.indexOfChild(iv) tvOriginalIndex = parent.indexOfChild(tv) iv.bringToFront() tv.bringToFront() // 缩小时的逻辑 parent.addView(iv, ivOriginalIndex) parent.addView(tv, tvOriginalIndex)
注意事项
所有层级调整操作建议放在动画结束的回调中执行,避免动画过程中出现层级闪烁的问题。
内容的提问来源于stack exchange,提问作者LastCard1440
相关产品推荐
相关产品推荐

