有人使用RecyclerView找到了一种方法来设置一个onClickListener的项目在RecyclerView? 我想设置一个监听器为每个项目的布局,但这似乎有点太麻烦了 我确信有一种方法让RecyclerView监听onClick事件,但我不能完全弄清楚。


当前回答

在适配器类中添加接口。

public interface SelectedUser{

    void selectedUser(UserModel userModel);

}

在mainactivity中实现你的接口并覆盖selectedUser方法。

@Override
public void selectedUser(UserModel userModel) {

    startActivity(new Intent(MainActivity.this, SelectedUserActivity.class).putExtra("data",userModel));

}

完整的教程在这里加上源代码。 Recyclerview与clicklistener和searchview

其他回答

通常你在CardView中有多个元素,所以你需要一个布局视图来包装和组织它们。你可以添加一个OnClickListener到那个布局视图。1. 添加一个id到你的布局。在这个例子中是线性布局

<android.support.v7.widget.CardView
 .....>

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/card_view_linearLayout">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="name"
            android:id="@+id/card_view_name" />

        ...

    </LinearLayout>

</android.support.v7.widget.CardView>

2美元。在你的内部ViewHolder类中获取布局视图。

public static class ViewHolder extends RecyclerView.ViewHolder{
    private TextView nameView;
    ...
    private LinearLayout linearLayout;
    public ViewHolder(View itemView) {
        super(itemView);
        nameView = (TextView)itemView.findViewById(R.id.card_view_name);
        ...
        linearLayout = (LinearLayout)itemView.findViewById(R.id.card_view_linearLayout);
    }
}

3美元。将监听器添加到onBindViewHolder中的布局中,并使用回调将数据发送到活动或片段(未测试)。

@Override
public void onBindViewHolder(TrackAdapter.ViewHolder holder, final int position) {
    String str = mStringList.get(position);

    holder.nameView.setText(str);
    ...
    holder.linearLayout.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            callback.itemCallback(mStringList.get(position));
        }
    });
}

如何使用回调是另一个故事

将类标记为抽象并实现OnClick方法

public abstract class MainGridAdapter extends
    RecyclerView.Adapter<MainGridAdapter.ViewHolder> {
private List<MainListItem> mDataset;

// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public class ViewHolder extends RecyclerView.ViewHolder {
    // each data item is just a string in this case
    public TextView txtHeader;
    public TextView txtFooter;

    public ViewHolder(View v) {
        super(v);
        txtHeader = (TextView) v.findViewById(R.id.firstLine);
        txtFooter = (TextView) v.findViewById(R.id.secondLine);
    }
}

public void add(int position, MainListItem item) {
    mDataset.add(position, item);
    notifyItemInserted(position);
}

public void remove(MainListItem item) {
    int position = mDataset.indexOf(item);
    mDataset.remove(position);
    notifyItemRemoved(position);
}

// Provide a suitable constructor (depends on the kind of dataset)
public MainGridAdapter(List<MainListItem> myDataset) {
    mDataset = myDataset;
}

// Create new views (invoked by the layout manager)
@Override
public MainGridAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
        int viewType) {
    // create a new view
    View v = LayoutInflater.from(parent.getContext()).inflate(
            R.layout.list_item_grid_line, parent, false);
    // set the view's size, margins, paddings and layout parameters
    ViewHolder vh = new ViewHolder(v);
    return vh;
}

// Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
    // - get element from your dataset at this position
    // - replace the contents of the view with that element     
    OnClickListener clickListener = new OnClickListener() {
        @Override
        public void onClick(View v) {
            onItemClicked(position);
        }
    };
    holder.itemView.setOnClickListener(clickListener);
    holder.txtHeader.setOnClickListener(clickListener);
    holder.txtFooter.setOnClickListener(clickListener);
    final MainListItem item = mDataset.get(position);
    holder.txtHeader.setText(item.getTitle());
    if (TextUtils.isEmpty(item.getDescription())) {
        holder.txtFooter.setVisibility(View.GONE);
    } else {
        holder.txtFooter.setVisibility(View.VISIBLE);
        holder.txtFooter.setText(item.getDescription());
    }
}

// Return the size of your dataset (invoked by the layout manager)
@Override
public int getItemCount() {
    return mDataset.size();
}

public abstract void onItemClicked(int position);

}

在绑定事件中实现单击处理程序,使其只有一个事件实现

执行此:

mAdapter = new MainGridAdapter(listItems) {         
    @Override
    public void onItemClicked(int position) {
        showToast("Item Clicked: " + position, ToastPlus.STYLE_INFO);
    }
};

同样可以做长时间点击

我们可以使用Java弱引用来实现这一点。 从语义上讲,视图持有者应该响应click事件或将其委托给正确的响应器。

我们的目标:

Viewholder应该对响应事件的类一无所知,除非它实现了某个接口。 点击处理程序应该得到被点击的视图在RecyclerView中的位置。 我们应该能够辨别视图持有人中单击了哪个视图。 保持所有组件之间的松散耦合,不要造成任何保留周期。

步骤:

Create an interface to handle click responses. Implement this interface in the Activity that will handle the click. Add a member variable in the RecyclerView Adapter to hold the Weak Reference and a constructor that sets it. Do the same in the RecyclerView ViewHolder and add a member variable to keep track of position. Set your on click listeners on any view you'd like in the ViewHolder, then callback to the responder to handle them. Change your onBindViewHolder method to set the position when binding. Pass the responder down to the ViewHolder. In the responder, you can now use getId() on the view to figure out which view was clicked.

这里是一个要点,这样你就可以看到它们是如何组合在一起的: RecyclerView点击处理

这对我来说很难在活动中有一个项目点击监听器,也有一个项目的单一视图的点击监听器,不会触发项目点击监听器。在玩了Jacob Tabak的回答后,我尊重他的回答,如果项目内没有其他触摸操作,就点击项目。

我有一个自定义OnClickListener接口,有一个项目点击事件,它持有从适配器点击的项目的视图和项目的位置。我在构造函数(或者它可以是setter)中呈现它的一个实例,并将它附加到视图持有者容器click listener。

我也有其他的点击监听器在适配器(可以在视图持有人),这将处理当前的视图点击从容器。

 public class MyRecyclerAdapter extends RecyclerView.Adapter<MyViewHolder> {

private ArrayList<String> mData;
private OnItemClickListener mOnItemClickListener;

public interface OnItemClickListener {
    public void onItemClick(View view, int position);
}

public MyRecyclerAdapter(ArrayList<String> itemsData,
        OnItemClickListener onItemClickListener) {
    mOnItemClickListener = onItemClickListener;
    this.mData = itemsData;
}

@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent,
        int viewType) {

    View layoutView = LayoutInflater.from(mContext).inflate(
            R.layout.list_item, parent, false);

    final MyViewHolder viewHolder = new MyViewHolder(layoutView);

    viewHolder.container.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            mOnItemClickListener.onItemClick(v, viewHolder.getAdapterPosition());
        }
    });

    viewHоlder.button.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            //do button click work here with
            // mData.get( viewHolder.getAdapterPosition() );
        }
    });

    return viewHolder;
}

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

在活动中,您需要通过传递OnItemClickListener实例来初始化适配器

public class FeedActivity extends ActionBarActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    ...

    RecyclerView recyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);

    .....

    MyRecyclerAdapter adapter = new MyRecyclerAdapter(new ArrayList<String>(), new OnItemClickListener() {

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

            ///list item was clicked
        }
    });

    recyclerView.setLayoutManager(new LinearLayoutManager(this));
    recyclerView.setAdapter(mFeedsAdapter);
}

还有我的ViewHolder

public class MyViewHolder extends RecyclerView.ViewHolder {

public Button button;
public View container;

public MyViewHolder(View itemLayoutView) {
    super(itemLayoutView);

    container = itemLayoutView;
    button = (Button) itemLayoutView.findViewById(R.id.button);
}}

From most of the answers above, they seem to be setting their onclicklisteners to individual items. However, the solution am about to offer is very simple but yet not intuitive to many. Many are forgetting that the other components are always in a parent component which is used to display items in the List or Recycler views. This solution is just about setting a single onclick listener to this parent view and the turn is played. The solution also includes a way to pass the position of the item being clicked on from the list or recycler view. Here, our main rootview is a CardView from the android support library. Here is sample code

public class ListAdapter extends RecyclerView.Adapter<ListAdapter.ViewHolder> {

public static final String LOG_TAG = ListAdapter.class.getSimpleName();
private Cursor mDataset;
private Context mContext;
private ViewHolder mViewHolder;

// Provide a suitable constructor (depends on the kind of dataset)
public ListAdapter(Context context, Cursor Dataset) {
    mDataset = Dataset;
    mContext = context;
}

// Create new views (invoked by the layout manager)
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

    // create a new view
    View v = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.list_business_view, parent, false);

    mViewHolder = new ViewHolder(v);
    return mViewHolder;
}

public void setData(Cursor newdata) {
    this.mDataset = newdata;
}

// Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
//Bind data to other items here. To save time, i have ommited that.
           //here is where we attach a click listerner for an item in the recycler list rather than for each element of a given item.
            holder.card.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(mContext, " Just cliked item at position " + itemPosition, Toast.LENGTH_LONG).show();

            }
        });

    }
}

// Return the size of your dataset (invoked by the layout manager)
@Override
public int getItemCount() {
    if (null != mDataset) {
        return mDataset.getCount();
    }
    return 0;

}


// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public static class ViewHolder extends RecyclerView.ViewHolder{
    // each data item is just a string in this case
    public final TextView mBusinesssName; // View for the business name
    public final TextView mBusinessCategory; //View for the category name
    public final ImageView businessImage; // View for the business category image Image
    public final TextView mBusinessDistance; // View for the distance
    public final CardView card;

    public ViewHolder(View view) {
        super(view);
        mBusinesssName = (TextView) view.findViewById(R.id.list_item_name_textview);
        mBusinessCategory = (TextView) view.findViewById(R.id.list_item_category_textview);
        mBusinessDistance = (TextView) view.findViewById(R.id.list_item_dist_textview);
        businessImage = (ImageView) view.findViewById(R.id.list_item_icon);
        card = (CardView) view.findViewById(R.id.card_view);

    }
}
}