Получить щелкнутый элемент и его положение в RecyclerView
я заменяю мой ListView с RecyclerView, список показывает ок, но я хотел бы знать, как получить элемент и его позицию, похож на метод OnItemClickListener.onItemClick(AdapterView parent, View v, int position, long id) мы используем в ListView.
Спасибо за идеи!
17 ответов:
на основе ссылки:почему RecyclerView не имеет onItemClickListener ()? и чем RecyclerView отличается от Listview?, а также общая идея @Duncan, я даю свое решение здесь:
определить один интерфейс
RecyclerViewClickListenerдля передачи сообщения от адаптера кActivity/Fragment:public interface RecyclerViewClickListener { public void recyclerViewListClicked(View v, int position); }на
Activity/Fragmentреализует интерфейс, а также передать слушателю адаптер:@Override public void recyclerViewListClicked(View v, int position){... ...} //set up adapter and pass clicked listener this myAdapter = new MyRecyclerViewAdapter(context, this);на
AdapterиViewHolder:public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.ItemViewHolder> { ... ... private Context context; private static RecyclerViewClickListener itemListener; public MyRecyclerViewAdapter(Context context, RecyclerViewClickListener itemListener) { this.context = context; this.itemListener = itemListener; ... ... } //ViewHolder class implement OnClickListener, //set clicklistener to itemView and, //send message back to Activity/Fragment public static class ItemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{ ... ... public ItemViewHolder(View convertView) { super(convertView); ... ... convertView.setOnClickListener(this); } @Override public void onClick(View v) { itemListener.recyclerViewListClicked(v, this.getPosition()); } } }после тестирования, он работает нормально.
[обновление]начиная с API 22,
RecyclerView.ViewHoler.getPosition()устарел, так что вместо этого сgetLayoutPosition().
public class MyRvAdapter extends RecyclerView.Adapter<MyRvAdapter.MyViewHolder>{ public Context context; public ArrayList<RvDataItem> dataItems; ... constructor overrides ... class MyViewHolder extends RecyclerView.ViewHolder{ public TextView textView; public Context context; public MyViewHolder(View itemView, Context context) { super(itemView); this.context = context; this.textView = (TextView)itemView.findViewById(R.id.textView); // on item click itemView.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v) { // get position int pos = getAdapterPosition(); // check if item still exists if(pos != RecyclerView.NO_POSITION){ RvDataItem clickedDataItem = dataItems.get(pos); Toast.makeText(v.getContext(), "You clicked " + clickedDataItem.getName(), Toast.LENGTH_SHORT).show(); } } }); } } }
вот пример установки прослушивателя щелчков.
Adapter extends RecyclerView.Adapter<MessageAdapter.MessageViewHolder> { ... } public static class MessageViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { public TextView tv_msg; public TextView tv_date; public TextView tv_sendTime; public ImageView sharedFile; public ProgressBar sendingProgressBar; public MessageViewHolder(View v) { super(v); tv_msg = (TextView) v.findViewById(R.id.tv_msg); tv_date = (TextView) v.findViewById(R.id.tv_date); tv_sendTime = (TextView) v.findViewById(R.id.tv_sendTime); sendingProgressBar = (ProgressBar) v.findViewById(R.id.sendingProgressBar); sharedFile = (ImageView) v.findViewById(R.id.sharedFile); sharedFile.setOnClickListener(this); } @Override public void onClick(View view) { int position = getAdapterPosition(); switch (view.getId()){ case R.id.sharedFile: Log.w("", "Selected"+position); break; } } }
поместите этот код, где вы определяете представление recycler в activity.
rv_list.addOnItemTouchListener( new RecyclerItemClickListener(activity, new RecyclerItemClickListener.OnItemClickListener() { @Override public void onItemClick(View v, int position) { Toast.makeText(activity, "" + position, Toast.LENGTH_SHORT).show(); } }) );затем сделайте отдельный класс и поместите этот код:
import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.View; public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener { private OnItemClickListener mListener; public interface OnItemClickListener { public void onItemClick(View view, int position); } GestureDetector mGestureDetector; public RecyclerItemClickListener(Context context, OnItemClickListener listener) { mListener = listener; mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { @Override public boolean onSingleTapUp(MotionEvent e) { return true; } }); } @Override public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) { View childView = view.findChildViewUnder(e.getX(), e.getY()); if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) { mListener.onItemClick(childView, view.getChildAdapterPosition(childView)); } return false; } @Override public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) { } @Override public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { } }
Если вы хотите щелкнуть событие recycle-View из activity / fragment вместо adapter, вы также можете использовать следующий короткий путь.
recyclerView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { final TextView txtStatusChange = (TextView)v.findViewById(R.id.txt_key_status); txtStatusChange.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Log.e(TAG, "hello text " + txtStatusChange.getText().toString() + " TAG " + txtStatusChange.getTag().toString()); Util.showToast(CampaignLiveActivity.this,"hello"); } }); return false; } });вы также можете использовать другие длинные способы, такие как использование интерфейса
recyclerViewObject.addOnItemTouchListener( new RecyclerItemClickListener( getContext(), recyclerViewObject, new RecyclerItemClickListener.OnItemClickListener() { @Override public void onItemClick(View view, int position) { // view is the clicked view (the one you wanted // position is its position in the adapter } @Override public void onLongItemClick(View view, int position) { } } ) );
использовать ниже код:-
public class SergejAdapter extends RecyclerView.Adapter<SergejAdapter.MyViewHolder>{ ... class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{ @Override public void onClick(View v) { // here you use position int position = getAdapterPosition(); ... } } }
RecyclerView не предоставляет такой метод.
для управления событиями щелчка на RecyclerView я закончил реализацию onClickListener в моем адаптере, при привязке ViewHolder: в моем ViewHolder я сохраняю ссылку на корневое представление (как вы можете сделать с вашими ImageViews, TextViews и т. д...) и при привязке viewHolder я устанавливаю тег на нем с информацией, которую мне нужно обработать click (например, position) и clicklistener
//Create below methods into the Activity which contains RecyclerView. private void createRecyclerView() { final RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recyclerView); recyclerView.setLayoutManager(new LinearLayoutManager(this)); MyAdapter myAdapter=new MyAdapter(dataAray,MianActivity.this); recyclerView.setAdapter(myAdapter); recyclerView.setItemAnimator(new DefaultItemAnimator()); setRecyclerViewClickListner(recyclerView); } private void setRecyclerViewClickListner(RecyclerView recyclerView){ final GestureDetector gestureDetector = new GestureDetector(MainActivity.this,new GestureDetector.SimpleOnGestureListener() { @Override public boolean onSingleTapUp(MotionEvent e) { return true; } }); recyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() { @Override public boolean onInterceptTouchEvent(RecyclerView recyclerView, MotionEvent motionEvent) { View child =recyclerView.findChildViewUnder(motionEvent.getX(),motionEvent.getY()); if(child!=null && gestureDetector.onTouchEvent(motionEvent)){ int position=recyclerView.getChildLayoutPosition(child); String name=itemArray.get(position).name; return true; } @Override public void onTouchEvent(RecyclerView recyclerView, MotionEvent motionEvent) { } @Override public void onRequestDisallowInterceptTouchEvent(boolean b) { } }); }
попробуйте таким образом
класс адаптера :
public class ContentAdapter extends RecyclerView.Adapter<ContentAdapter.ViewHolder> { public interface OnItemClickListener { void onItemClick(ContentItem item); } private final List<ContentItem> items; private final OnItemClickListener listener; public ContentAdapter(List<ContentItem> items, OnItemClickListener listener) { this.items = items; this.listener = listener; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_item, parent, false); return new ViewHolder(v); } @Override public void onBindViewHolder(ViewHolder holder, int position) { holder.bind(items.get(position), listener); } @Override public int getItemCount() { return items.size(); } static class ViewHolder extends RecyclerView.ViewHolder { private TextView name; private ImageView image; public ViewHolder(View itemView) { super(itemView); name = (TextView) itemView.findViewById(R.id.name); image = (ImageView) itemView.findViewById(R.id.image); } public void bind(final ContentItem item, final OnItemClickListener listener) { name.setText(item.name); itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { listener.onItemClick(item); } }); } }}
в вашей деятельности или фрагмент :
ContentAdapter adapter = new ContentAdapter(itemList, this);Примечание : реализовать OnItemClickListener на основе контекста, который вы указали в деятельности или фрагмент и переопределению методов.
каждый раз, когда я использую другой подход. Люди, похоже, хранят или получают позицию в представлении, а не сохраняют ссылку на объект, отображаемый ViewHolder.
вместо этого я использую этот подход и просто сохраняю его в ViewHolder при вызове onBindViewHolder() и устанавливаю ссылку на null в onViewRecycled().
каждый раз, когда ViewHolder становится невидимым, он не знает. Так что это не влияет на большое потребление памяти.
@Override public void onBindViewHolder(final ItemViewHolder holder, int position) { ... holder.displayedItem = adapterItemsList.get(i); ... } @Override public void onViewRecycled(ItemViewHolder holder) { ... holder.displayedItem = null; ... } class ItemViewHolder extends RecyclerView.ViewHolder { ... MySuperItemObject displayedItem = null; ... }
короткое расширение для Котлин
Метод возвращает абсолютное положение всех элементов (не только положение видимых элементов).fun RecyclerView.getChildPositionAt(x: Float, y: Float): Int { return getChildAdapterPosition(findChildViewUnder(x, y)) }и использование
val position = recyclerView.getChildPositionAt(event.x, event.y)
вот самый простой и легкий способ найти положение нажатого элемента:
Я также столкнулся с той же проблемой.
Я хотел найти позицию нажатого / выбранного элемента RecyclerView () и выполнить некоторые конкретные операции над этим конкретным элементом.
getAdapterPosition () метод работает как шарм для такого рода вещей. Я нашел этот способ после долгих исследований и после попытки многих других методы.
int position = getAdapterPosition(); Toast.makeText(this, "Position is: "+position, Toast.LENGTH_SHORT).show();вы не должны использовать какой-либо дополнительный метод. Просто создайте глобальную переменную с именем 'position' и инициализируйте ее с помощью getAdapterPosition() в любом из основных методов адаптера (класса или аналогичного).
вот краткая документация из этого ссылке.
getAdapterPosition добавлено в версии 22.1.0 int getAdapterPosition () Возвращает положение адаптера элемента, представленного этим держателем вида. Заметить что это может отличаться от getLayoutPosition (), если есть ожидающие обновления адаптера, но новый проход макета еще не произошел. RecyclerView не обрабатывает обновления адаптера до следующего обхода макета. Это может привести к временному несоответствию между тем, что пользователь видит на экране, и содержимым адаптера. Это несоответствие не важно, так как оно будет меньше 16 мс, но это может быть проблемой, если вы хотите использовать позицию ViewHolder для доступа к адаптеру. Иногда, возможно, вам потребуется получить точное положение адаптера, чтобы выполнить некоторые действия в ответ на события пользователя. В этом случае, вы должны использовать этот метод, который будет вычислять положение адаптера ViewHolder.
рады вам помочь. Не стесняйтесь задавать вопросы.
используйте getLayoutPosition () в своем методе java пользовательского интерфейса. Это вернет выбранную позицию элемента, проверьте полную информацию на
https://becody.com/get-clicked-item-and-its-position-in-recyclerview/
из конструктора, вы можете установить
onClickсвойство listItem к методу, определенному с помощью одного параметра. У меня есть пример метода, определенного ниже. В getAdapterPosition способ даст вам индекс выбранного listitem элемент.public void exampleOnClickMethod(View view){ myRecyclerView.getChildViewHolder(view).getAdapterPosition()); }для получения информации о настройке RecyclerView см. документацию здесь:https://developer.android.com/guide/topics/ui/layout/recyclerview
просто добавьте прослушиватель касания элемента на свой объект RecyclerView.
recyclerView.addOnItemTouchListener( new RecyclerItemClickListener(context, new RecyclerItemClickListener.OnItemClickListener() { @Override public void onItemClick(View view, int position) { // TODO Handle item click } }));
в onViewHolder установите onClickListiner в любое представление и в боковом щелчке используйте этот код:
тосты.makeText (Drawer_bar.это, "позиция" + позиция, тост.LENGTH_SHORT).показать();
заменить
Drawer_Barс вашим именем деятельности.
Comments