wake-up-neo.com

Wie kann ich die Position in einem RecyclerView auswählen?

Ich experimentiere mit der Recyclingübersicht und den Karten der Support-Bibliothek. Ich habe eine Recyclingübersicht von Karten. Jede Karte hat ein "x" -Symbol in der oberen rechten Ecke, um sie zu entfernen:

Die Karten-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>

Ich habe versucht, die Zeile mit der Position zu markieren, die ich in notifyItemRemoved(position) in TaskAdapter.Java verwenden würde:

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);
}
}

Dies funktioniert nicht, weil Sie weder einen Tag festlegen noch auf den Adapter von onClick. zugreifen können.

47
HukeLau_DABA

Stellen Sie Ihre onClickListeners auf onBindViewHolder() und Sie können von dort auf die Position zugreifen. Wenn Sie sie in Ihrer ViewHolder setzen, wissen Sie nicht, auf welche Position Sie geklickt haben, es sei denn, Sie übergeben die Position auch in die ViewHolder.

EDIT

Wie pskink darauf hingewiesen hat ViewHolder eine getPosition(), so war die Art und Weise, wie Sie sie ursprünglich gemacht haben, korrekt.

Wenn Sie auf die Ansicht klicken, können Sie getPosition() in Ihrer ViewHolder verwenden, und die Position wird zurückgegeben

Update

getPosition() ist nun veraltet und wird durch getAdapterPosition() ersetzt.

91
tyczj

Eine andere Methode - mit den Methoden setTag () und getTag () der View-Klasse.

  1. verwenden Sie setTag () in der onBindViewHolder-Methode Ihres Adapters

    @Override
    public void onBindViewHolder(myViewHolder viewHolder, int position) {
        viewHolder.mCardView.setTag(position);
    }
    

    dabei ist mCardView in der myViewHolder-Klasse definiert

    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);
               }
           }
    
  2. verwenden Sie getTag () in Ihrer OnClickListener-Implementierung

    @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();
    }
    

weitere Informationen erhalten Sie unter https://stackoverflow.com/a/33027953/4658957

15
bastien

Um die Antwort von @tyczj zu ergänzen:

Generischer Adapter Pseido-Code:

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) {

        }
    }


}

Verwendung des Adapters:

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) {

    }



}
8
Mikelis Kaneps
 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());
    }
}
5
notdrone

Die einfachste Art und Weise, die ich für mich gefunden habe und die für mich großartig ist, ist folgende:

Erstellen Sie eine Schnittstelle in Ihrer Klasse "RecycleAdapter" (Unterklasse)

public interface ClickCallback {
    void onItemClick(int position);
}

Fügen Sie im Constructor eine Variable der Schnittstelle als Parameter hinzu.

private String[] items;
private ClickCallback callback;

public RecyclerAdapter(String[] items, ClickCallback clickCallback) {
    this.items = items;
    this.callback = clickCallback;
}

Setzen Sie einen Click-Listener im ViewHolder (einer anderen Unterklasse) und übergeben Sie die 'Position' an die Schnittstelle.

    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);
    }

Wenn Sie nun den Recycler-Adapter in einer Aktivität/einem Fragment initialisieren, erstellen Sie einfach einen neuen 'ClickCallback' (Interface).

String[] values = {"Hello","World"};
RecyclerAdapter recyclerAdapter = new RecyclerAdapter(values, new RecyclerAdapter.ClickCallback() {
    @Override
    public void onItemClick(int position) {
         // Do anything with the item position
    }
});

Das ist es für mich. :)

3
Yusuph wickama

Ich habe diesen Weg gelöst

class MyOnClickListener implements View.OnClickListener {
        @Override
        public void onClick(View v) {

            int itemPosition = mRecyclerView.getChildAdapterPosition(v);

            myResult = results.get(itemPosition);


        }
    }

Und im Adapter

@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;
        }
2
gerzalez

Erhalten Sie ein fokussiertes Kind und verwenden Sie es, um sich im Adapter zu positionieren.

mRecyclerView.getChildAdapterPosition(mRecyclerView.getFocusedChild())
2
Quacker

1. Erstellen Sie die Klasse Name RecyclerTouchListener.Java

import Android.content.Context;
import Android.support.v7.widget.RecyclerView;
import Android.view.GestureDetector;
import Android.view.MotionEvent;
import Android.view.View;

public class RecyclerTouchListener implements RecyclerView.OnItemTouchListener 
{

private GestureDetector gestureDetector;
private ClickListener clickListener;

public RecyclerTouchListener(Context context, final RecyclerView recyclerView, final ClickListener clickListener) {
    this.clickListener = clickListener;
    gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            return true;
        }

        @Override
        public void onLongPress(MotionEvent e) {
            View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
            if (child != null && clickListener != null) {
                clickListener.onLongClick(child, recyclerView.getChildAdapterPosition(child));
            }
        }
    });
}

@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {

    View child = rv.findChildViewUnder(e.getX(), e.getY());
    if (child != null && clickListener != null && gestureDetector.onTouchEvent(e)) {
        clickListener.onClick(child, rv.getChildAdapterPosition(child));
    }
    return false;
}

@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}

@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

}

public interface ClickListener {
    void onClick(View view, int position);

    void onLongClick(View view, int position);
}
}

2. RecyclerTouchListener anrufen

recycleView.addOnItemTouchListener(new RecyclerTouchListener(this, recycleView, 
new RecyclerTouchListener.ClickListener() {
    @Override
    public void onClick(View view, int position) {
        Toast.makeText(MainActivity.this,Integer.toString(position),Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onLongClick(View view, int position) {

    }
}));

Ich denke, der beste Weg, um die Position eines Artikels zu erhalten, ist

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);
}

Da Ansicht, klicken Sie nicht immer auf die Stammansicht Ihres Zeilenlayouts. Wenn view keine Root-Ansicht ist (z. B. Schaltflächen), wird eine Klassenumwandlungsausnahme angezeigt. Zuerst müssen wir also die Ansicht finden, die das direkte Kind Ihres Reciclerview ist. Suchen Sie dann die Position mithilfe von recyclerView.getChildAdapterPosition (view);

1
Yarh
@Override
public void onClick(View v) {
     int pos = getAdapterPosition();
}

Einfach so, auf ViewHolder

onBindViewHolder () wird für jedes Element aufgerufen. Das Festlegen des Klicklisteners in onBindVieHolder () ist eine unnötige Option, die wiederholt werden muss, wenn Sie sie einmal in Ihrem ViewHolder-Konstruktor aufrufen können.

public class MyViewHolder extends RecyclerView.ViewHolder 
      implements View.OnClickListener{
   public final TextView textView; 

   public MyViewHolder(View view){
      textView = (TextView) view.findViewById(R.id.text_view);
      view.setOnClickListener(this);
      // getAdapterPosition() retrieves the position here.
   } 

   @Override
   public void onClick(View v){
      // Clicked on item 
      Toast.makeText(mContext, "Clicked on position: " + getAdapterPosition(), Toast.LENGTH_SHORT).show();
   }
}
0
oiyio

Es ist nicht erforderlich, dass ViewHolder View.OnClickListener implementiert. Sie können die angeklickte Position direkt abrufen, indem Sie in der Methode onCreateViewHolder of RecyclerView einen Click-Listener festlegen.

public class ItemListAdapterRecycler extends RecyclerView.Adapter<ItemViewHolder>
{

    private final List<Item> items;

    public ItemListAdapterRecycler(List<Item> items)
    {
        this.items = items;
    }

    @Override
    public ItemViewHolder onCreateViewHolder(final ViewGroup parent, int viewType)
    {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_row, parent, false);

        view.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View view)
            {
                int currentPosition = getClickedPosition(view);
                Log.d("DEBUG", "" + currentPosition);
            }
        });

        return new ItemViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ItemViewHolder itemViewHolder, int position)
    {
        ...
    }

    @Override
    public int getItemCount()
    {
        return items.size();
    }

    private int getClickedPosition(View clickedView)
    {
        RecyclerView recyclerView = (RecyclerView) clickedView.getParent();
        ItemViewHolder currentViewHolder = (ItemViewHolder) recyclerView.getChildViewHolder(clickedView);
        return currentViewHolder.getAdapterPosition();
    }

}
0
Mouss