use*_*721 131 android recycler-adapter android-recyclerview
我正在尝试使用a 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;
}
Run Code Online (Sandbox Code Playgroud)
这是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);
}
Run Code Online (Sandbox Code Playgroud)
zIr*_*Box 143
这是一种非常简单的方法.
private int selectedPos = RecyclerView.NO_POSITION;在RecyclerView Adapter类中有一个,并在onBindViewHolder方法下尝试:
@Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
viewHolder.itemView.setSelected(selectedPos == position);
}
Run Code Online (Sandbox Code Playgroud)
并在您的OnClick事件中修改:
@Override
public void onClick(View view) {
notifyItemChanged(selectedPos);
selectedPos = getLayoutPosition();
notifyItemChanged(selectedPos);
}
Run Code Online (Sandbox Code Playgroud)
就像Navigtional Drawer和其他RecyclerView物品适配器的魅力一样.
注意:务必使用像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>
Run Code Online (Sandbox Code Playgroud)
否则setSelected(..)将不执行任何操作,使此解决方案无效.
Mee*_*eet 119
正如Pawan在评论中提到的关于不使用该固定位置的IDE警告,我刚刚修改了我的代码如下.点击监听器被移动到
ViewHolder,在那里我得到位置使用getAdapterPosition()方法
int selected_position = 0; // You have to set this globally in the Adapter class
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Item item = items.get(position);
// Here I am just highlighting the background
holder.itemView.setBackgroundColor(selected_position == position ? Color.GREEN : Color.TRANSPARENT);
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public ViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
}
@Override
public void onClick(View v) {
// Below line is just like a safety check, because sometimes holder could be null,
// in that case, getAdapterPosition() will return RecyclerView.NO_POSITION
if (getAdapterPosition() == RecyclerView.NO_POSITION) return;
// Updating old as well as new positions
notifyItemChanged(selected_position);
selected_position = getAdapterPosition();
notifyItemChanged(selected_position);
// Do your another stuff for your onClick
}
}
Run Code Online (Sandbox Code Playgroud)
希望这会有所帮助.
Gre*_*nis 57
我写了一个基础适配器类来自动处理使用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);
}
});
}
}
}
Run Code Online (Sandbox Code Playgroud)
小智 13
如果您将内容滚出视图然后返回视图,则您的实现可能会有效.当我提出你的问题时,我遇到了类似的问题.
以下文件片段对我有用.我的实现是针对多种选择,但我在那里投入了一个强制单一选择.(*1)
// an array of selected items (Integer indices)
private final ArrayList<Integer> selected = new ArrayList<>();
// items coming into view
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
// each time an item comes into view, its position is checked
// against "selected" indices
if (!selected.contains(position)){
// view not selected
holder.parent.setBackgroundColor(Color.LTGRAY);
}
else
// view is selected
holder.parent.setBackgroundColor(Color.CYAN);
}
// selecting items
@Override
public boolean onLongClick(View v) {
// set color immediately.
v.setBackgroundColor(Color.CYAN);
// (*1)
// forcing single selection here
if (selected.isEmpty()){
selected.add(position);
}else {
int oldSelected = selected.get(0);
selected.clear();
selected.add(position);
// we do not notify that an item has been selected
// because that work is done here. we instead send
// notifications for items to be deselected
notifyItemChanged(oldSelected);
}
return false;
}
Run Code Online (Sandbox Code Playgroud)
正如指出的在这个链接的问题,为viewHolders设置听众应该onCreateViewHolder完成.我以前忘了提这个.
看看我的解决方案.我想你应该在持有人中设置选定的位置并将其作为标记传递.应该在onCreateViewHolder(...)方法中设置视图.还有正确的位置来设置侦听器的视图,如OnClickListener或LongClickListener.
请查看下面的示例并阅读代码注释.
public class MyListAdapter extends RecyclerView.Adapter<MyListAdapter.ViewHolder> {
//Here is current selection position
private int mSelectedPosition = 0;
private OnMyListItemClick mOnMainMenuClickListener = OnMyListItemClick.NULL;
...
// constructor, method which allow to set list yourObjectList
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//here you prepare your view
// inflate it
// set listener for it
final ViewHolder result = new ViewHolder(view);
final View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.your_view_layout, parent, false);
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//here you set your current position from holder of clicked view
mSelectedPosition = result.getAdapterPosition();
//here you pass object from your list - item value which you clicked
mOnMainMenuClickListener.onMyListItemClick(yourObjectList.get(mSelectedPosition));
//here you inform view that something was change - view will be invalidated
notifyDataSetChanged();
}
});
return result;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
final YourObject yourObject = yourObjectList.get(position);
holder.bind(yourObject);
if(mSelectedPosition == position)
holder.itemView.setBackgroundColor(Color.CYAN);
else
holder.itemView.setBackgroundColor(Color.RED);
}
// you can create your own listener which you set for adapter
public void setOnMainMenuClickListener(OnMyListItemClick onMyListItemClick) {
mOnMainMenuClickListener = onMyListItemClick == null ? OnMyListItemClick.NULL : onMyListItemClick;
}
static class ViewHolder extends RecyclerView.ViewHolder {
ViewHolder(View view) {
super(view);
}
private void bind(YourObject object){
//bind view with yourObject
}
}
public interface OnMyListItemClick {
OnMyListItemClick NULL = new OnMyListItemClick() {
@Override
public void onMyListItemClick(YourObject item) {
}
};
void onMyListItemClick(YourObject item);
}
}
Run Code Online (Sandbox Code Playgroud)
我想,我已经找到了关于如何使用RecyclerView以及我们需要的所有基本功能的最佳教程(单选+多选,高亮,涟漪,点击和删除多选等等).
这是 - > http://enoent.fr/blog/2015/01/18/recyclerview-basics/
基于此,我能够创建一个库"FlexibleAdapter",它扩展了SelectableAdapter.我认为这必须是Adapter的责任,实际上你不需要每次都重写Adapter的基本功能,让库来做,所以你可以重用相同的实现.
这个适配器非常快,它开箱即用(你不需要扩展它); 您可以为所需的每种视图类型自定义项目; ViewHolder是预定义的:已经实现了常见事件:单击和长击; 它在旋转后保持状态,并且更多.
请在您的项目中实现它.
https://github.com/davideas/FlexibleAdapter
Wiki也可用.
| 归档时间: |
|
| 查看次数: |
170819 次 |
| 最近记录: |