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


当前回答

我知道有很多答案,但我想我也可以提供我的实现。(完整的细节可以在我回答的另一个问题中找到)。

所以,要添加一个点击监听器,你的内部ViewHolder类需要实现View.OnClickListener。这是因为你将设置一个OnClickListener到ViewHolder的构造函数的itemView参数。让我来告诉你我的意思:

public class ExampleClickViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

    TextView text1, text2;

    ExampleClickViewHolder(View itemView) {
        super(itemView);

        // we do this because we want to check when an item has been clicked:
        itemView.setOnClickListener(this);

        // now, like before, we assign our View variables
        title = (TextView) itemView.findViewById(R.id.text1);
        subtitle = (TextView) itemView.findViewById(R.id.text2);
    }

    @Override
    public void onClick(View v) {
        // The user may not set a click listener for list items, in which case our listener
        // will be null, so we need to check for this
        if (mOnEntryClickListener != null) {
            mOnEntryClickListener.onEntryClick(v, getLayoutPosition());
        }
    }
}

唯一需要添加的其他东西是适配器的自定义接口和setter方法:

private OnEntryClickListener mOnEntryClickListener;

public interface OnEntryClickListener {
    void onEntryClick(View view, int position);
}

public void setOnEntryClickListener(OnEntryClickListener onEntryClickListener) {
    mOnEntryClickListener = onEntryClickListener;
}

这样,新的支持单击的适配器就完成了。

现在,让我们用它…

    ExampleClickAdapter clickAdapter = new ExampleClickAdapter(yourObjects);
    clickAdapter.setOnEntryClickListener(new ExampleClickAdapter.OnEntryClickListener() {
        @Override
        public void onEntryClick(View view, int position) {
            // stuff that will happen when a list item is clicked
        }
    });

这基本上就是设置普通适配器的方法,除了使用您创建的setter方法来控制当用户单击特定列表项时要做什么。

你也可以看看我在GitHub上做的一组关于Gist的例子:

https://gist.github.com/FarbodSalamat-Zadeh/7646564f48ee708c1582c013e1de4f07

其他回答

我已经为android开发了一个轻量级的库,你可以访问github并遵循这个示例:

RecycleClick.addTo(YOUR_RECYCLE_VIEW).setOnItemClickListener(new RecycleClick.OnItemClickListener() {
    @Override
    public void onItemClicked(RecyclerView recyclerView, int position, View v) {
        // Your code here
    }
});

将类标记为抽象并实现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);
    }
};

同样可以做长时间点击

基于Jacob Tabak的回答(+1),我能够添加onLongClick监听器:

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 {
    public interface OnItemClickListener {
        void onItemClick(View view, int position);

        void onItemLongClick(View view, int position);
    }

    private OnItemClickListener mListener;

    private GestureDetector mGestureDetector;

    public RecyclerItemClickListener(Context context, final RecyclerView recyclerView, OnItemClickListener listener) {
        mListener = listener;

        mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                return true;
            }

            @Override
            public void onLongPress(MotionEvent e) {
                View childView = recyclerView.findChildViewUnder(e.getX(), e.getY());

                if (childView != null && mListener != null) {
                    mListener.onItemLongClick(childView, recyclerView.getChildAdapterPosition(childView));
                }
            }
        });
    }

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

然后你可以这样使用它:

recyclerView.addOnItemTouchListener(new RecyclerItemClickListener(getActivity(), recyclerView, new RecyclerItemClickListener.OnItemClickListener() {
    @Override
    public void onItemClick(View view, int position) {
        // ...
    }

    @Override
    public void onItemLongClick(View view, int position) {
        // ...
    }
}));

在ViewHolder中设置点击监听器,如下所示:

public class MyViewHolder extends RecyclerView.ViewHolder {
    public TextView title, year, genre;

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

        title = (TextView) view.findViewById(R.id.title);
        genre = (TextView) view.findViewById(R.id.genre);
        year = (TextView) view.findViewById(R.id.year);

        view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(context, ""+getAdapterPosition(), Toast.LENGTH_SHORT).show();
            }
        });
    }
}

有更简单的方法。只需要在根视图上应用onBindViewHolder中的click。

考虑这是你对适配器的看法,

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/linearlayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

        <TextView
            android:id="@+id/textview"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="1dp"
            android:textSize="15sp" />
</LinearLayout>

然后在适配器中执行以下操作

//get the layout and make view holder
@Override
public RVAdapter.ViewHolder1 onCreateViewHolder(ViewGroup parent, int viewType) {

    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_layout, null);
    ViewHolder1 viewHolder = new ViewHolder1(view);
    return viewHolder;
}

@Override
public void onBindViewHolder(RVAdapter.ViewHolder1 holder, int position) {

    //apply on click on your root view
    holder.linearlayout.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            //Do on click stuff
        }
    });
}

//make references to views in layout including root view
public class ViewHolder1 extends RecyclerView.ViewHolder {

    protected LinearLayout linearlayout = null
    protected TextView textview = null;

    public CareerLinksViewHolder(View itemView) {
        super(itemView);

        this.linearlayout = (LinearLayout) itemView.findViewById(R.id.linearlayout);
        this.tvCompName = (TextView) itemView.findViewById(R.id.textview);
    }
}