Android 如何在RecyclerView中选择职位?

Android 如何在RecyclerView中选择职位?,android,android-support-library,android-recyclerview,android-cardview,Android,Android Support Library,Android Recyclerview,Android Cardview,我正在试验支持库的recyclerview和cards。我有一堆卡片。每张卡的右上角都有一个“x”图标,可以将其移除: 卡片xml,list\u 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="ma

我正在试验支持库的recyclerview和cards。我有一堆卡片。每张卡的右上角都有一个“x”图标,可以将其移除:

卡片xml,
list\u 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>

这不起作用,因为您不能设置标记,我也不能从
onClick访问适配器。

onClickListener
s设置在
onBindViewHolder()
上,您可以从那里访问位置。如果在
ViewHolder
中设置它们,则除非将位置传递到
ViewHolder

编辑

正如
pskink
所指出的
ViewHolder
有一个
getPosition()
所以您最初的操作方式是正确的

单击视图时,您可以在
视图夹中使用
getPosition()
,它将返回位置

更新

    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);
    }
String[] values = {"Hello","World"};
RecyclerAdapter recyclerAdapter = new RecyclerAdapter(values, new RecyclerAdapter.ClickCallback() {
    @Override
    public void onItemClick(int position) {
         // Do anything with the item position
    }
});
getPosition()
现在已被弃用,并替换为
getAdapterPosition()

更新2020

getAdapterPosition()
现在已被弃用,并替换为
getAbsoluteAdapterPosition()
getBindingAdapterPosition()

Kotlin代码:

覆盖BindViewHolder(holder:MyHolder,position:Int){
//-在此位置从数据集中获取元素
val item=myDataset.get(holder.absoluteAdapterPosition)
}

补充@tyczj答案:

通用适配器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);

}
适配器用法:

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 class CategoriesAdapter扩展了GenericRecycleAdapter{
公共类别适配器(列表、上下文){
超级(列表、上下文);
}
@凌驾
虚无主义(类别){
}
@凌驾
公共int getLayout(){
返回R.layout.categories\u行;
}
@凌驾
公共无效开始(类别项,holder.TextImageHolder){
}
}

另一种方法-使用View类的setTag()getTag()方法

  • 在适配器的onBindViewHolder方法中使用setTag()

    @Override
    public void onBindViewHolder(myViewHolder viewHolder, int position) {
        viewHolder.mCardView.setTag(position);
    }
    
    其中,在myViewHolder类中定义了mCardView

    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();
    }
    
  • 有关更多详细信息,请参见

    我是通过这种方式解决的

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

    获得焦点子对象,并使用它在适配器中获得位置

    mRecyclerView.getChildAdapterPosition(mRecyclerView.getFocusedChild())
    

    我认为获得项目位置的最正确方法是

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

    因为是视图,所以您并不总是单击行布局的根视图。若视图不是根视图(例如按钮),您将得到类强制转换异常。因此,首先我们需要找到视图,它是视图的直接子视图。然后,使用recyclerView.getChildAdapterPosition(视图)查找位置

    就我个人而言,我发现的最简单的方法是:

    在“RecycleAdapter”类(子类)内创建接口。

    在构造函数中添加接口变量作为参数。

    private String[] items;
    private ClickCallback callback;
    
    public RecyclerAdapter(String[] items, ClickCallback clickCallback) {
        this.items = items;
        this.callback = clickCallback;
    }
    
    在ViewHolder(另一个子类)中设置单击侦听器,并通过界面将“位置”传递给

        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);
        }
    
    String[] values = {"Hello","World"};
    RecyclerAdapter recyclerAdapter = new RecyclerAdapter(values, new RecyclerAdapter.ClickCallback() {
        @Override
        public void onItemClick(int position) {
             // Do anything with the item position
        }
    });
    
    现在,在活动/片段中初始化回收器适配器时,只需创建一个新的“ClickCallback”(界面)


    对我来说就是这样。:)

    无需让您的ViewHolder实现View.OnClickListener。通过在RecyclerView的onCreateViewHolder方法中设置click侦听器,可以直接获得单击的位置。以下是代码示例:

    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();
        }
    
    }
    
    公共类ItemListAdapterRecycler扩展了RecyclerView.Adapter
    {
    私人最终清单项目;
    public ItemListAdapterRecycler(列表项)
    {
    这个项目=项目;
    }
    @凌驾
    public ItemViewHolder onCreateViewHolder(最终视图组父级,int-viewType)
    {
    View=LayoutFlater.from(parent.getContext()).flate(R.layout.item_行,parent,false);
    view.setOnClickListener(新的view.OnClickListener()
    {
    @凌驾
    公共void onClick(视图)
    {
    int currentPosition=getClickedPosition(视图);
    Log.d(“调试”,“当前位置”);
    }
    });
    返回新的ItemViewHolder(视图);
    }
    @凌驾
    BindViewHolder上的公共无效(ItemViewHolder ItemViewHolder,int位置)
    {
    ...
    }
    @凌驾
    public int getItemCount()
    {
    返回items.size();
    }
    私有int getClickedPosition(视图clickedView)
    {
    RecycleView RecycleView=(RecycleView)clickedView.getParent();
    ItemViewHolder currentViewHolder=(ItemViewHolder)recyclerView.getChildViewHolder(clickedView);
    返回currentViewHolder.getAdapterPosition();
    }
    }
    
    1。创建类名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

    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) {
    
        }
    }));
    
    onBindViewHolder()是为每个项目调用的,当您可以在ViewHolder构造函数中调用一次时,在onBindVieHolder()中设置click侦听器是不必要的重复选项

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

    简单地说,在使用数据绑定时,在
    ViewHolder

    上,您需要从项目的单击侦听器内部了解RecyclerView单击位置:

    科特林

        val recyclerView = view.parent as RecyclerView
        val position = recyclerView.getChildAdapterPosition(view)
    

    你能展示一些代码吗?如果taskViewHolder没有setOnClickListener方法,我如何执行此操作?您可以在中使用viewholder中的视图there@tyczj不,更好的方法是在ViewHolder中设置侦听器,观众知道他们自己的观点positions@pskink如果不将位置传递给构造函数,您如何知道位置?@tyczj ViewHolder.getPosition(),顺便说一句,当您创建一个不知道位置的ViewHolder时,位置是在onbindviewholder中设置的
    @Override
    public void onClick(View v) {
         int pos = getAdapterPosition();
    }
    
        val recyclerView = view.parent as RecyclerView
        val position = recyclerView.getChildAdapterPosition(view)