如何获得在RecyclerView中select的位置?
我正在试验支持库的recyclerview和卡片。 我有一个卡的recyclerview。 每张卡片的右上angular都有一个“x”图标可以将其删除:
卡xml, list_item.xml
:
<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="5dp"> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/taskDesc" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:textSize="40sp" android:text="hi"/> <ImageView android:id="@+id/xImg" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_alignParentRight="true" android:src="@drawable/ic_remove"/> </RelativeLayout> </android.support.v7.widget.CardView>
我试图用我将在notifyItemRemoved(position)
中的notifyItemRemoved(position)
中使用的位置来标记行:
public class TaskAdapter extends RecyclerView.Adapter<TaskAdapter.TaskViewHolder> { private List<Task> taskList; private TaskAdapter thisAdapter = this; // cache of views to reduce number of findViewById calls public static class TaskViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { protected TextView taskTV; protected ImageView closeBtn; public TaskViewHolder(View v) { super(v); taskTV = (TextView)v.findViewById(R.id.taskDesc); } @Override public void onClick(View v) { int position = v.getTag(); adapter.notifyItemRemoved(position); } } public TaskAdapter(List<Task> tasks) { if(tasks == null) throw new IllegalArgumentException("tasks cannot be null"); taskList = tasks; } // onBindViewHolder binds a model to a viewholder @Override public void onBindViewHolder(TaskViewHolder taskViewHolder, int pos) { final int position = pos; Task currTask = taskList.get(pos); taskViewHolder.taskTV.setText(currTask.getDescription()); taskViewHolder.closeBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { thisAdapter.notifyItemRemoved(position); } }); } @Override public int getItemCount() { return taskList.size(); } // inflates row to create a viewHolder @Override public TaskViewHolder onCreateViewHolder(ViewGroup parent, int pos) { View itemView = LayoutInflater.from(parent.getContext()). inflate(R.layout.list_item, parent, false); return new TaskViewHolder(itemView); } }
这将无法正常工作,因为您无法设置标签,也无法从onClick.
访问适配器onClick.
在onBindViewHolder
上设置你的onClick监听onBindViewHolder
,你可以从那里访问位置。 如果将它们设置在ViewHolder中,除非将该位置传递给ViewHolder,否则不会知道被点击的位置
编辑
正如pskink
指出,ViewHolder有一个getPosition
所以你原来的做法是正确的。
当点击视图时,可以在ViewHolder中使用getPosition
并返回该位置
更新
getPosition()
现在被弃用,并用getAdapterPosition()
一个不同的方法 – 使用View类的setTag()和getTag()方法。
-
在适配器的onBindViewHolder方法中使用setTag()
@Override public void onBindViewHolder(myViewHolder viewHolder, int position) { viewHolder.mCardView.setTag(position); }
mCardView是在myViewHolder类中定义的
private class myViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { public View mCardView; public myViewHolder(View view) { super(view); mCardView = (CardView) view.findViewById(R.id.card_view); mCardView.setOnClickListener(this); } }
-
在OnClickListener实现中使用getTag()
@Override public void onClick(View view) { int position = (int) view.getTag(); //display toast with position of cardview in recyclerview list upon click Toast.makeText(view.getContext(),Integer.toString(position),Toast.LENGTH_SHORT).show(); }
有关更多详细信息,请参阅https://stackoverflow.com/a/33027953/4658957
补充@tyczj回答:
generics适配器Pseido代码:
public abstract class GenericRecycleAdapter<T, K extends RecyclerView.ViewHolder> extends RecyclerView.Adapter{ private List<T> mList; //default implementation code public abstract int getLayout(); @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()) .inflate(getLayout(), parent, false); return getCustomHolder(v); } public Holders.TextImageHolder getCustomHolder(View v) { return new Holders.TextImageHolder(v){ @Override public void onClick(View v) { onItem(mList.get(this.getAdapterPosition())); } }; } abstract void onItem(T t); @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { onSet(mList.get(position), (K) holder); } public abstract void onSet(T item, K holder); }
ViewHolder:
public class Holders { public static class TextImageHolder extends RecyclerView.ViewHolder implements View.OnClickListener{ public TextView text; public TextImageHolder(View itemView) { super(itemView); text = (TextView) itemView.findViewById(R.id.text); text.setOnClickListener(this); } @Override public void onClick(View v) { } } }
适配器用法:
public class CategoriesAdapter extends GenericRecycleAdapter<Category, Holders.TextImageHolder> { public CategoriesAdapter(List<Category> list, Context context) { super(list, context); } @Override void onItem(Category category) { } @Override public int getLayout() { return R.layout.categories_row; } @Override public void onSet(Category item, Holders.TextImageHolder holder) { } }
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { FrameLayout root; public ViewHolder(View itemView) { super(itemView); root = (FrameLayout) itemView.findViewById(R.id.root); root.setOnClickListener(this); } @Override public void onClick(View v) { LogUtils.errorLog("POS_CLICKED: ",""+getAdapterPosition()); } }
获得专注的孩子,并使用它来获得适配器的位置。
mRecyclerView.getChildAdapterPosition(mRecyclerView.getFocusedChild())
就我个人而言,我发现和为我工作的最简单的方法如下:
在“RecycleAdapter”类(子类)中创build一个接口
public interface ClickCallback { void onItemClick(int position); }
在构造函数中添加一个接口的variables作为参数。
private String[] items; private ClickCallback callback; public RecyclerAdapter(String[] items, ClickCallback clickCallback) { this.items = items; this.callback = clickCallback; }
在ViewHolder(另一个子类)中设置一个Click监听器,并通过接口传递'position'
AwesomeViewHolder(View itemView) { super(itemView); itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { callback.onItemClick(getAdapterPosition()); } }); mTextView = (TextView) itemView.findViewById(R.id.mTextView); }
现在,当在活动/片段中初始化回收站适配器时,只需创build一个新的“ClickCallback”(接口)
String[] values = {"Hello","World"}; RecyclerAdapter recyclerAdapter = new RecyclerAdapter(values, new RecyclerAdapter.ClickCallback() { @Override public void onItemClick(int position) { // Do anything with the item position } });
这就是我的。 🙂
我解决了这个问题
class MyOnClickListener implements View.OnClickListener { @Override public void onClick(View v) { int itemPosition = mRecyclerView.getChildAdapterPosition(v); myResult = results.get(itemPosition); } }
并在适配器中
@Override public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_wifi, parent, false); v.setOnClickListener(new MyOnClickListener()); ViewHolder vh = new ViewHolder(v); return vh; }
我认为最正确的方式来获得项目的立场是
View.OnClickListener onClickListener = new View.OnClickListener() { @Override public void onClick(View v) { View view = v; View parent = (View) v.getParent(); while (!(parent instanceof RecyclerView)){ view=parent; parent = (View) parent.getParent(); } int position = recyclerView.getChildAdapterPosition(view); }
因为查看,您不总是点击您的行布局的根视图。 如果视图不是一个根(例如button),你会得到类转换exception。 因此,首先我们需要find这个视图,这是您reciclerview的一个直截了当的孩子。 然后,使用recyclerView.getChildAdapterPosition(view)查找位置;