如何在 RecyclerView 上正确突出显示所选项目?

新手上路,请多包涵

我正在尝试使用 RecyclerView 作为水平 ListView 。我想弄清楚如何突出显示所选项目。当我单击其中一个项目时,它会被选中并正确突出显示,但是当我单击另一个项目时,第二个项目会与旧项目一起突出显示。

这是我的 onClick 函数:

 @Override
public void onClick(View view) {

    if(selectedListItem!=null){
        Log.d(TAG, "selectedListItem " + getPosition() + " " + item);
        selectedListItem.setBackgroundColor(Color.RED);
    }
    Log.d(TAG, "onClick " + getPosition() + " " + item);
    viewHolderListener.onIndexChanged(getPosition());
    selectedPosition = getPosition();
    view.setBackgroundColor(Color.CYAN);
    selectedListItem = view;
}

这是 onBindViewHolder

 @Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
    viewHolder.setItem(fruitsData[position]);
    if(selectedPosition == position)
        viewHolder.itemView.setBackgroundColor(Color.CYAN);
    else
        viewHolder.itemView.setBackgroundColor(Color.RED);

}

原文由 user65721 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 428
2 个回答

我编写了一个基本适配器类来使用 RecyclerView 自动处理项目选择。只需从中派生您的适配器并使用带有 state_selected 的可绘制状态列表,就像您对列表视图所做的那样。

我有一篇关于它的 博客文章,但这里是代码:

 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 = getLayoutPosition();
                    notifyItemChanged(focusedItem);
                }
            });
        }
    }
}

原文由 Greg Ennis 发布,翻译遵循 CC BY-SA 3.0 许可协议

这是很简单的方法。

在 RecyclerView Adapter 类中有一个 private int selectedPos = RecyclerView.NO_POSITION; ,并在 onBindViewHolder 方法下尝试:

 @Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
    viewHolder.itemView.setSelected(selectedPos == position);

}

并在您的 OnClick 事件中修改:

 @Override
public void onClick(View view) {
     notifyItemChanged(selectedPos);
     selectedPos = getLayoutPosition();
     notifyItemChanged(selectedPos);
}

就像 Navigtional Drawer 和其他 RecyclerView Item Adapter 的魅力一样。

注意:一定要使用像 @colabug 澄清的选择器在你的布局中使用背景颜色:

 <selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:drawable="@color/pressed_color" android:state_pressed="true"/>
  <item android:drawable="@color/selected_color" android:state_selected="true"/>
  <item android:drawable="@color/focused_color" android:state_focused="true"/>
</selector>

否则 setSelected(..) 什么都不做,使这个解决方案无用。

原文由 zIronManBox 发布,翻译遵循 CC BY-SA 4.0 许可协议

推荐问题