Adding a colored background with text/icon under swiped row when using Android's RecyclerView

前端 未结 7 505
遥遥无期
遥遥无期 2020-12-02 07:37

EDIT: The real problem was that my LinearLayout was wrapped in another layout, which caused the incorrect behavior. The accepted answer by Sanvywell has

相关标签:
7条回答
  • 2020-12-02 08:05

    Here's how I do it without 3rd party library.

    The foreground view will be always visible in the recycler view, and when swipe is performed the background will be visible staying in a static position.

    Create your custom RecyclerView item and add your custom icon, text and background color to the background layout of item. Notice that I put an id to RelativeLayout with id=foreground and id=background.

    Here's mine recylerview_item.xml.

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:orientation="vertical">
    
        <RelativeLayout
            android:id="@+id/background"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@color/colorPrimary"> <!--Add your background color here-->
    
            <ImageView
                android:id="@+id/delete_icon"
                android:layout_width="30dp"
                android:layout_height="30dp"
                android:layout_alignParentRight="true"
                android:layout_centerVertical="true"
                android:layout_marginRight="10dp"
                app:srcCompat="@drawable/ic_delete"/>
    
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_marginRight="10dp"
                android:layout_toLeftOf="@id/delete_icon"
                android:text="Swipe to delete"
                android:textColor="#fff"
                android:textSize="13dp" />
        </RelativeLayout>
    
        <RelativeLayout
            android:padding="20dp"
            android:id="@+id/foreground"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/colorWhite">
    
                <TextView
                    android:id="@+id/textView"
                    android:text="HelloWorld"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content" />
    
        </RelativeLayout>
    </FrameLayout>
    

    and from your ViewHolder define your RelativeLayout foreground and background view and make it public. Also create a method that will remove the item. In my case my ViewHolder is under my RecyclerViewAdapter.class, so...

    public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {
    
        List<Object> listItem;
    
        public RecyclerViewAdapter(...) {
            ...
        } 
    
        @Override
        public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = mInflater.inflate(R.layout.recyclerview_item, parent, false);
            return new ViewHolder(view);
        }
    
        @Override
        public void onBindViewHolder(final ViewHolder holder, int position) {
            ....
        }
    
        @Override
        public int getItemCount() {
            ...
        }
    
        public class ViewHolder extends RecyclerView.ViewHolder{
    
            public RelativeLayout foreground, background;
    
            public ViewHolder(View itemView) {
                super(itemView);
    
                /** define your foreground and background **/
    
                foreground = itemView.findViewById(R.id.foreground);
                background = itemView.findViewById(R.id.background);
    
            }
    
        }
    
        /**Call this later to remove the item on swipe**/
        public void removeItem(int position){
            //remove the item here
            listItem.remove(position);
            notifyItemRemoved(position);
        }
    }
    

    And create a class and name it RecyclerItemTouchHelper.class, this is where swipe thing will happen.

    public class RecyclerItemTouchHelper extends ItemTouchHelper.SimpleCallback {
    
        private RecyclerItemTouchHelperListener listener;
    
        public RecyclerItemTouchHelper(int dragDirs, int swipeDirs, RecyclerItemTouchHelperListener listener) {
            super(dragDirs, swipeDirs);
            this.listener = listener;
        }
    
        @Override
        public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
            return true;
        }
    
        @Override
        public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
            if (viewHolder != null) {
                final View foregroundView = ((RecyclerViewAdapter.ViewHolder) viewHolder).foreground;
                getDefaultUIUtil().onSelected(foregroundView);
            }
        }
    
        @Override
        public void onChildDrawOver(Canvas c, RecyclerView recyclerView,
                                    RecyclerView.ViewHolder viewHolder, float dX, float dY,
                                    int actionState, boolean isCurrentlyActive) {
            final View foregroundView = ((RecyclerViewAdapter.ViewHolder) viewHolder).foreground;
            getDefaultUIUtil().onDrawOver(c, recyclerView, foregroundView, dX, dY,
                    actionState, isCurrentlyActive);
        }
    
        @Override
        public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
            final View foregroundView = ((RecyclerViewAdapter.ViewHolder) viewHolder).foreground;
            getDefaultUIUtil().clearView(foregroundView);
        }
    
        @Override
        public void onChildDraw(Canvas c, RecyclerView recyclerView,
                                RecyclerView.ViewHolder viewHolder, float dX, float dY,
                                int actionState, boolean isCurrentlyActive) {
            final View foregroundView = ((RecyclerViewAdapter.ViewHolder) viewHolder).foreground;
    
            getDefaultUIUtil().onDraw(c, recyclerView, foregroundView, dX, dY,
                    actionState, isCurrentlyActive);
        }
    
        @Override
        public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
            listener.onSwiped(viewHolder, direction, viewHolder.getAdapterPosition());
        }
    
        @Override
        public int convertToAbsoluteDirection(int flags, int layoutDirection) {
            return super.convertToAbsoluteDirection(flags, layoutDirection);
        }
    
        public interface RecyclerItemTouchHelperListener {
            void onSwiped(RecyclerView.ViewHolder viewHolder, int direction, int position);
        }
    }
    

    Now, from your MainActivity.class or wherever your RecyclerView is, attach the RecyclerItemTouchHelper into it. In my case the RecyclerView is in MainActivity.class so I implemented RecyclerItemTouchHelper.RecyclerItemTouchHelperListener into it and override the method onSwiped()...

    public class MainActivity extends AppCompatActivity implements RecyclerItemTouchHelper.RecyclerItemTouchHelperListener {
    
        RecyclerView recyclerView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Toolbar toolbar = findViewById(R.id.toolbar);
            setSupportActionBar(toolbar);
    
            //Configure RecyclerView
    
            recyclerView = (RecyclerView) findViewById(R.id.recyclerView);  
            RecyclerView.LayoutManager mLyoutManager = new LinearLayoutManager(getApplicationContext());
            recyclerView.setLayoutManager(mLyoutManager);
            recyclerView.setItemAnimator(new DefaultItemAnimator());
            adapter = new RecyclerViewAdapter(this);
            adapter.setClickListener(this);
            recyclerView.setAdapter(adapter);
            recyclerView.addItemDecoration(new DividerItemDecoration(recyclerView.getContext(), DividerItemDecoration.VERTICAL));
    
            //Attached the ItemTouchHelper
            ItemTouchHelper.SimpleCallback itemTouchHelperCallback = new RecyclerItemTouchHelper(0, ItemTouchHelper.LEFT, this);
            new ItemTouchHelper(itemTouchHelperCallback).attachToRecyclerView(recyclerView);
        }
    
        //define the method onSwiped()
        @Override
        public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction, int position) {
            if (viewHolder instanceof RecyclerViewAdapter.ViewHolder) {
                adapter.removeItem(viewHolder.getAdapterPosition()); //remove the item from the adapter
            }
        }
    
    }
    

    For more information and clarification here is the blog for it.

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