Android中如何设置子子视图的Z轴层级?如何在运行时将Button置于FrameLayout 1上方?
问题1:如何为嵌套结构中的子子视图设置Z轴层级?
在Android开发里,要给嵌套得很深的子子视图调Z轴层级,其实有几种实用的办法,得看你的API版本和具体布局情况来选:
用
elevation和translationZ(API 21及以上)
这是Android 5.0之后官方推荐的方式,属于Material Design的特性。elevation是视图的基础Z轴高度,translationZ是动态的偏移量(比如按钮点击时的抬升效果)。不管视图嵌套多少层,直接给目标子子视图设置这两个属性就行,系统会自动根据整体Z值来决定渲染顺序。
举个代码例子:// Kotlin 代码,记得自己实现dp转px的工具方法 childChildView.elevation = 10.dpToPx() childChildView.translationZ = 5.dpToPx()// Java 代码 childChildView.setElevation(dpToPx(10)); childChildView.setTranslationZ(dpToPx(5));小提醒:如果两个视图的
elevation值相同,那它们的绘制顺序(也就是添加到父布局的先后)就决定了层级,后添加的会在上层。调用
bringChildToFront()方法
这个方法能让目标视图成为它直接父布局的最上层子视图,但要注意它的作用范围仅限直接父布局。比如你的结构是根布局 -> 父布局 -> 子子视图,直接调用子子视图.bringChildToFront()只会让它在父布局的子视图里排第一;如果想让它超过根布局里的其他视图,要么把父布局也调到上层,要么把子子视图移到根布局里再调用根布局的bringChildToFront()。
示例代码:// 先让子子视图在直接父布局内排最前 val directParent = childChildView.parent as ViewGroup directParent.bringChildToFront(childChildView) // 如果要让它在更上层的布局里突出,再调父布局的层级 val grandParent = directParent.parent as ViewGroup grandParent.bringChildToFront(directParent)调整布局添加顺序
在XML布局里,后写的视图会被绘制在前面的视图之上;如果是动态添加视图,先加的在下层,后加的在上层。所以你可以调整子子视图在其父布局里的添加顺序,或者调整其父布局在更上层布局里的顺序,来间接实现层级调整。
问题2:将Button置于FrameLayout 1的上方如何实现?
首先我默认你的布局结构大概是这样:根布局是LinearLayout,里面包含FrameLayout 1和RelativeLayout 3;FrameLayout 1内部有RelativeLayout 2,RelativeLayout 2里有ImageView和Button。现在要让Button显示在FrameLayout 1的所有内容之上,有这几个靠谱的办法:
方法1:用elevation直接提升Button层级
这是最简单的办法,只要给Button设置比FrameLayout 1更高的elevation值,不管它嵌套多少层,都会被渲染在FrameLayout 1之上:
// Kotlin 代码 button.elevation = frameLayout1.elevation + 10.dpToPx()
// Java 代码 button.setElevation(frameLayout1.getElevation() + dpToPx(10));
这个方法适合API 21及以上的设备。
方法2:把Button移到FrameLayout 1的直接子层级
如果你的布局允许,可以把Button从原来的RelativeLayout 2里移除,添加到FrameLayout 1中,再调整它的位置和原来一致,最后调用bringChildToFront()让它成为FrameLayout 1的最上层子视图:
// Kotlin 代码 // 先从原来的父布局移除Button (button.parent as ViewGroup).removeView(button) // 设置FrameLayout的布局参数,保证位置和原来一样 val layoutParams = FrameLayout.LayoutParams(button.width, button.height) layoutParams.leftMargin = button.left layoutParams.topMargin = button.top // 添加到FrameLayout 1 frameLayout1.addView(button, layoutParams) // 调到最上层 frameLayout1.bringChildToFront(button)
方法3:提升RelativeLayout 2的层级
如果Button不需要脱离RelativeLayout 2,你可以直接提升RelativeLayout 2的elevation,让它整个布局在FrameLayout 1的其他子视图之上,这样里面的Button自然也会在上层:
// Kotlin 代码 relativeLayout2.elevation = frameLayout1.elevation + 5.dpToPx()
另外补充个小技巧:FrameLayout的子视图绘制顺序是按添加顺序来的,后添加的在上层,所以如果是XML布局,你可以把包含Button的RelativeLayout 2写在FrameLayout 1的最后面,默认就会在上层啦。
内容的提问来源于stack exchange,提问作者Nidhi Savaliya

