Scale up Item in RecyclerView to overlaps 2 adjacent items Android

前端 未结 4 2212
离开以前
离开以前 2020-12-14 20:58

I\'m using RecyclerView with GridLayoutManager. The goal I want to achieve is when I click on an item, It\'ll scale up and overlaps the adjacent items. Just like the picture

相关标签:
4条回答
  • 2020-12-14 21:22

    According aga's answer, i use ViewCompat.setElevation(View view, float elevation) to support API prior to 21, It works like a charming.

    static class ViewHolder extends RecyclerView.ViewHolder {
    
      public ViewHolder(View root) {
        // bind views
        // ...
    
        // bind focus listener
        root.setOnFocusChangeListener(new View.OnFocusChangeListener() {
          @Override
            public void onFocusChange(View v, boolean hasFocus) {
              if (hasFocus) {
                // run scale animation and make it bigger
    
                ViewCompat.setElevation(root, 1);
              } else {
                // run scale animation and make it smaller
    
                ViewCompat.setElevation(root, 0);
              }
            }
         });
      }
    }
    

    The item layout file is very simple like below:

    <?xml version="1.0" encoding="utf-8"?>
    <TextView
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:focusable="true"
        android:focusableInTouchMode="true"
        android:background="@drawable/sl_live_item" />
    
    0 讨论(0)
  • 2020-12-14 21:34

    Try to invoke v.bringToFront() before running the animation.
    If it doesn't work another variant is to use View#setElevation(float val) where val > 0. The drawback is that you'll need to set elevation back to 0 when you're deselecting the item.

    0 讨论(0)
  • 2020-12-14 21:39

    1.Override the getChildDrawingOrder method.

    @Override
    protected int getChildDrawingOrder(int childCount, int i) {
        View view = getLayoutManager().getFocusedChild();
        if (null == view) {
            return super.getChildDrawingOrder(childCount, i);
        }
        int position = indexOfChild(view);
    
        if (position < 0) {
            return super.getChildDrawingOrder(childCount, i);
        }
        if (i == childCount - 1) {
            return position;
        }
        if (i == position) {
            return childCount - 1;
        }
        return super.getChildDrawingOrder(childCount, i);
    }
    

    2.RecyclerView setChildrenDrawingOrderEnabled is true.

    setChildrenDrawingOrderEnabled(true);
    

    3.When item view has focus, invalidate its parent.

    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if (hasFocus) {
            v.setScaleX(1.5f);
            v.setScaleY(1.5f);
            mRecyclerView.invalidate();
        } else {
            v.setScaleX(1.0f);
            v.setScaleY(1.0f);
        }
    }
    
    0 讨论(0)
  • 2020-12-14 21:40

    You need to do it the old way you do with normal ViewGroups, overriding the draw order of children. This example forces the first view to always be drawn last - you need to customize for your use case.

    public TopForcingRecyclerView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        setChildrenDrawingOrderEnabled(true);
    }
    
    @Override protected int getChildDrawingOrder(int childCount, int i) {
        if (i >= childCount - 1) return 0; 
        //when asked for the last view to draw, answer ZERO
        else return i + 1;
        //when asked for the i-th view to draw, answer "the next one"
    }
    

    Pay attention to off by one errors.

    0 讨论(0)
提交回复
热议问题