Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

bringToFront does not work in RecyclerView

I want to make an animation in RecyclerView which requires a child to have a bigger z-index than another child. However, when I used the bringToFront method in ViewGroup it did not work.

Is there any way to bring a child to front in RecyclerView?

like image 832
Juude Avatar asked Nov 10 '14 12:11

Juude


2 Answers

Indeed, bringToFront() does not help; it just changes the order of children in its parent's children array but it doesn't change the order in which children are rendered.

If you are using API-21 or higher you can just change the Z value of the view (view.setZ(..)) to bring it to the front.

Below API-21 there is a callback you can use: RecyclerView.ChildDrawingOrderCallback. With it you can define the order children should be rendered in. (You can also use this with API-21+ in case you don't like the extra shadow you get by changing the Z value.)

Example:

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();

Basically, onGetChildDrawingOrder(...) will be called childCount times and in each iteration we can specify which child to render (by returning its index).

like image 138
Zsolt Safrany Avatar answered Nov 06 '22 22:11

Zsolt Safrany


Order of children is controlled by the LayoutManager. Built in LayoutManagers have their own strict child order for performance reasons.

Current implementation of bringToFront simply moves the child to the end of children list which won't play nice with existing LayoutManagers.

If you are targeting Lollipop, you can use setElevation method. To target older platforms, you'll need a custom LayoutManager that does not rely on order of children.

like image 31
yigit Avatar answered Nov 06 '22 23:11

yigit