我想在RecyclerView
制作动画,要求孩子拥有比其他孩子更大的z指数。但是,当我在bringToFront
中使用ViewGroup
方法时,它无效。
有没有办法让孩子站在RecyclerView
?
答案 0 :(得分:8)
确实,bringToFront()
没有帮助;它只是更改其父级子数组中子项的顺序,但它不会更改子项的呈现顺序。
如果您使用的是API-21或更高版本,则只需更改视图的Z
值(view.setZ(..)
)即可将其置于最前面。
在API-21下面有一个可以使用的回调:RecyclerView.ChildDrawingOrderCallback
。有了它,您可以定义子项应该呈现的顺序。(如果您不喜欢通过更改Z
值获得的额外阴影,也可以使用API-21 +。)
示例:
final int indexOfFrontChild = rv.indexOfChild(desiredFrontView);
rv.setChildDrawingOrderCallback(new RecyclerView.ChildDrawingOrderCallback() {
private int nextChildIndexToRender;
@Override
public int onGetChildDrawingOrder(int childCount, int iteration) {
if (iteration == childCount - 1) {
// in the last iteration return the index of the child
// we want to bring to front (and reset nextChildIndexToRender)
nextChildIndexToRender = 0;
return indexOfFrontChild;
} else {
if (nextChildIndexToRender == indexOfFrontChild) {
// skip this index; we will render it during last iteration
nextChildIndexToRender++;
}
return nextChildIndexToRender++;
}
}
});
rv.invalidate();
基本上,onGetChildDrawingOrder(...)
将被称为childCount
次,并且在每个iteration
中我们可以指定要呈现的子项(通过返回其索引)。
答案 1 :(得分:5)
子项的顺序由LayoutManager控制。由于性能原因,内置的LayoutManagers有自己严格的子命令。
bringToFront的当前实现只是将孩子移动到子列表的末尾,这对于现有的LayoutManagers来说不会很好。
如果您定位Lollipop,则可以使用setElevation方法。 要定位较旧的平台,您需要一个不依赖于子级顺序的自定义LayoutManager。
答案 2 :(得分:0)
@Zsolt上面的回答Safrany基于假设回调总是从迭代0调用,而我测试的不是真的。
这里我发布的工作实现不会在外部计数器上传递。
//index of item you want to be displayed on top
private int indexOfFrontChild = 2;
@Override
public int onGetChildDrawingOrder(int childCount, int iteration) {
int childPos = iteration;
//index must be in at least smaller than all children's
if (indexOfFrontChild < childCount) {
//in the last iteration we return view we want to have on top
if (iteration == childCount - 1) {
childPos = indexOfFrontChild;
}else if (iteration >= indexOfFrontChild) {
childPos = iteration + 1;
}
}
return childPos;
}
在我的情况下,物品能够改变它们的高度,因此1个项目可以占据整个屏幕。因此,检查indexOfFrontChild项是否可显示是很好的
if (indexOfFrontChild < childCount)