Background Selector in RecyclerView Item

前端 未结 10 1058
无人共我
无人共我 2020-12-13 17:42

I\'m using the RecyclerView like below:



        
相关标签:
10条回答
  • 2020-12-13 18:08

    Unfortunately using focusable views to simulate item selection is not a good solution because:

    • Focus is lost when notifyDataSetChanged is called
    • Focus is problematic when child views are focusable

    I wrote a base adapter class to automatically handle item selection with a RecyclerView. Just derive your adapter from it and use drawable state lists with state_selected, like you would do with a list view.

    I have a Blog Post Here about it, but here is the code:

    public abstract class TrackSelectionAdapter<VH extends TrackSelectionAdapter.ViewHolder> extends RecyclerView.Adapter<VH> {
        // Start with first item selected
        private int focusedItem = 0;
    
        @Override
        public void onAttachedToRecyclerView(final RecyclerView recyclerView) {
            super.onAttachedToRecyclerView(recyclerView);
    
            // Handle key up and key down and attempt to move selection
            recyclerView.setOnKeyListener(new View.OnKeyListener() {
                @Override
                public boolean onKey(View v, int keyCode, KeyEvent event) {
                    RecyclerView.LayoutManager lm = recyclerView.getLayoutManager();
    
                    // Return false if scrolled to the bounds and allow focus to move off the list
                    if (event.getAction() == KeyEvent.ACTION_DOWN) {
                        if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
                            return tryMoveSelection(lm, 1);
                        } else if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
                            return tryMoveSelection(lm, -1);
                        }
                    }
    
                    return false;
                }
            });
        }
    
        private boolean tryMoveSelection(RecyclerView.LayoutManager lm, int direction) {
            int tryFocusItem = focusedItem + direction;
    
            // If still within valid bounds, move the selection, notify to redraw, and scroll
            if (tryFocusItem >= 0 && tryFocusItem < getItemCount()) {
                notifyItemChanged(focusedItem);
                focusedItem = tryFocusItem;
                notifyItemChanged(focusedItem);
                lm.scrollToPosition(focusedItem);
                return true;
            }
    
            return false;
        }
    
        @Override
        public void onBindViewHolder(VH viewHolder, int i) {
            // Set selected state; use a state list drawable to style the view
            viewHolder.itemView.setSelected(focusedItem == i);
        }
    
        public class ViewHolder extends RecyclerView.ViewHolder {
            public ViewHolder(View itemView) {
                super(itemView);
    
                // Handle item click and set the selection
                itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        // Redraw the old selection and the new
                        notifyItemChanged(focusedItem);
                        focusedItem = mRecyclerView.getChildPosition(v);
                        notifyItemChanged(focusedItem);
                    }
                });
            }
        }
    } 
    
    0 讨论(0)
  • 2020-12-13 18:12
        viewHolder.mRlPrince.setOnTouchListener(new View.OnTouchListener() {
            @Override public boolean onTouch(View v, MotionEvent event) {
    
                if (event.getAction()==MotionEvent.ACTION_DOWN){
                    viewHolder.mRlPrince.setBackgroundColor(Color.parseColor("#f8f8f8"));
                }if (event.getAction()==MotionEvent.ACTION_UP){
                    viewHolder.mRlPrince.setBackgroundColor(Color.WHITE);
                }
    
                return false;
            }
        });
    
    0 讨论(0)
  • 2020-12-13 18:15

    Add :

    android:background="?android:attr/selectableItemBackground"
    

    in item.xml

    0 讨论(0)
  • 2020-12-13 18:16

    Adding android:background="?android:attr/selectableItemBackground" to my_list_item.xml's root layout seems to work for me (assuming you want the default selection colour).

    Also make sure the root layout's android:layout_width is match_parent rather than wrap_content to ensure that the whole row is selectable.

    0 讨论(0)
  • 2020-12-13 18:19

    Set clickable, focusable, focusableInTouchMode to true in all elements of RecyclerView "list".

    0 讨论(0)
  • 2020-12-13 18:19

    If nothing of this works for you, like it didn't for me, use this code:

    android:foreground="?android:attr/selectableItemBackground"
    

    The trick is in android:foreground attribute...

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