RecyclerView
を使っている人は誰でもonClickListener
をRecyclerView
内の項目に設定する方法を見つけましたか?各項目のそれぞれのレイアウトにリスナーを設定することを考えましたが、それは少し面倒ですRecyclerView
がonClick
イベントをリッスンする方法はあると確信していますが、それを理解することはできません。
APIが根本的に変わったので、あなたがそれぞれのアイテムのためにOnClickListener
を作成することになっていてもそれは私を驚かせないでしょう。それほど面倒なことではありません。 RecyclerView.Adapter<MyViewHolder>
の実装では、次のものが必要です。
private final OnClickListener mOnClickListener = new MyOnClickListener();
@Override
public MyViewHolder onCreateViewHolder(final ViewGroup parent, final int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.myview, parent, false);
view.setOnClickListener(mOnClickListener);
return new MyViewHolder(view);
}
onClick
メソッド
@Override
public void onClick(final View view) {
int itemPosition = mRecyclerView.getChildLayoutPosition(view);
String item = mList.get(itemPosition);
Toast.makeText(mContext, item, Toast.LENGTH_LONG).show();
}
これはOnClickListener
に対してRecyclerView
を実装するためのより良い、そしてより密接に結び付けられていない方法です。
使用の抜粋:
RecyclerView recyclerView = findViewById(R.id.recycler);
recyclerView.addOnItemTouchListener(
new RecyclerItemClickListener(context, recyclerView ,new RecyclerItemClickListener.OnItemClickListener() {
@Override public void onItemClick(View view, int position) {
// do whatever
}
@Override public void onLongItemClick(View view, int position) {
// do whatever
}
})
);
RecyclerItemClickListener
の実装:
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);
public void onLongItemClick(View view, int position);
}
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 child = recyclerView.findChildViewUnder(e.getX(), e.getY());
if (child != null && mListener != null) {
mListener.onLongItemClick(child, recyclerView.getChildAdapterPosition(child));
}
}
});
}
@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 true;
}
return false;
}
@Override public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) { }
@Override
public void onRequestDisallowInterceptTouchEvent (boolean disallowIntercept){}
}
私はこのようにして、過度のクラスやディテクタなどを使わずにそれを行います。アダプタ内の単純なコード以前に提示されたよりlongClickのための特により良い解決策。
public class PasswordAdapter extends RecyclerView.Adapter<PasswordAdapter.ViewHolder> {
private static ClickListener clickListener;
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
TextView name;
public ViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
itemView.setOnLongClickListener(this);
name = (TextView) itemView.findViewById(R.id.card_name);
}
@Override
public void onClick(View v) {
clickListener.onItemClick(getAdapterPosition(), v);
}
@Override
public boolean onLongClick(View v) {
clickListener.onItemLongClick(getAdapterPosition(), v);
return false;
}
}
public void setOnItemClickListener(ClickListener clickListener) {
PasswordAdapter.clickListener = clickListener;
}
public interface ClickListener {
void onItemClick(int position, View v);
void onItemLongClick(int position, View v);
}
}
それからフラグメントまたはアクティビティの中で、ただ打つだけ:
PasswordAdapter mAdapter = ...;
mAdapter.setOnItemClickListener(new PasswordAdapter.ClickListener() {
@Override
public void onItemClick(int position, View v) {
Log.d(TAG, "onItemClick position: " + position);
}
@Override
public void onItemLongClick(int position, View v) {
Log.d(TAG, "onItemLongClick pos = " + position);
}
});
同様の question@ CommonsWareのコメントリンクをチェックしてください this は、OnClickListener
インターフェイスを実装していますviewHolder
。
以下はViewHolder
の簡単な例です。
TextView textView;//declare global with in adapter class
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private ViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
textView = (TextView)view.findViewById(Android.R.id.text1);
}
@Override
public void onClick(View view) {
Toast.makeText(view.getContext(), "position = " + getLayoutPosition(), Toast.LENGTH_SHORT).show();
//go through each item if you have few items within recycler view
if(getLayoutPosition()==0){
//Do whatever you want here
}else if(getLayoutPosition()==1){
//Do whatever you want here
}else if(getLayoutPosition()==2){
}else if(getLayoutPosition()==3){
}else if(getLayoutPosition()==4){
}else if(getLayoutPosition()==5){
}
//or you can use For loop if you have long list of items. Use its length or size of the list as
for(int i = 0; i<exampleList.size(); i++){
}
}
}
Adapter
は次のようになります。
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view =LayoutInflater.from(parent.getContext()).inflate(Android.R.layout.simple_list_item_1, parent, false);
return new ViewHolder(view);
}
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) {
// ...
}
}));
これは私のために働いたものです。 OnClickListener
をonBindView
に添付します。これがパフォーマンスに影響を与えるかどうかはわかりませんが、小さなコードでもうまくいくようです。
public void onBindViewHolder(ViewHolder holder, final int position) {
holder.view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(context, "Recycle Click" + position, Toast.LENGTH_SHORT).show();
}
});
}
これは私がアクティビティ内のアイテムクリックリスナーを持つこと、そしてアイテムクリックリスナーでトリガーされないアイテムの単一のビューのためのクリックリスナーを持つことも非常に困難でした。 Jacob Tabakの答えで遊んだ後、アイテム内に他のタッチ操作が表示されていない場合は、アイテムのクリックに対する彼の答えを尊重します。
クリックされたアイテムのビューとアダプタからのアイテムの位置を保持するitem clickイベントを持つカスタムのOnClickListener
インターフェースがあります。私はそれのインスタンスをコンストラクタに提示し(またはそれはsetterを使用することもできます)、それをビューホルダーコンテナクリックリスナーにアタッチします。
私はまた、コンテナからの現在のビュークリックを処理する他のクリックリスナーをアダプタ内に持っています(ビューホルダーに入れることができます)。
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);
MyViewHolder viewHolder = new MyViewHolder(layoutView);
return viewHolder;
}
@Override
public void onBindViewHolder(MyViewHolder viewHolder,
final int position) {
viewHolder.container.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mOnItemClickListener.onItemClick(v, position);
}
});
viewHilder.button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//do button click work here
}
});
}
@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);
}}
これは私が必要としたものです。
public static class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(View item) {
super(item);
item.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Log.d("RecyclerView", "onClick:" + getAdapterPosition());
}
});
}
}
ソース: http://blog.csdn.net/jwzhangjie/article/details/36868515
私はRecyclerView
のonItemClickListener
のためのアイテムとサブアイテムのための素晴らしい解決策を持っています
ステップ1 - インターフェイスを作成する
public interface OnRecyclerViewItemClickListener
{
/**
* Called when any item with in recyclerview or any item with in item
* clicked
*
* @param position
* The position of the item
* @param id
* The id of the view which is clicked with in the item or
* -1 if the item itself clicked
*/
public void onRecyclerViewItemClicked(int position, int id);
}
ステップ2- それからそれを次のようにアダプタのonBindViewHolder
メソッドで使います
/**
* Custom created method for Setting the item click listener for the items and items with in items
* @param listener OnRecyclerViewItemClickListener
*/
public void setOnItemClickListener(OnRecyclerViewItemClickListener listener)
{
this.listener = listener;
}
@Override
public void onBindViewHolder(ViewHolder viewHolder, final int position)
{
// viewHolder.albumBg.setBackgroundResource(_itemData[position]
// .getImageUrl());
viewHolder.albumName.setText(arrayList.get(position).getName());
viewHolder.artistName.setText(arrayList.get(position).getArtistName());
String imgUrl = arrayList.get(position).getThumbImageUrl();
makeImageRequest(imgUrl, viewHolder);
viewHolder.parentView.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
listener.onRecyclerViewItemClicked(position, -1);
}
});
viewHolder.settingButton.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
listener.onRecyclerViewItemClicked(position, v.getId());
}
});
}
// class to hold a reference to each item of RecyclerView
public static class ViewHolder extends RecyclerView.ViewHolder
{
public TextView albumName, artistName;
public ImageView albumIcon, settingButton;
public LinearLayout parentView;
public ViewHolder(View itemLayoutView)
{
super(itemLayoutView);
// albumBg = (LinearLayout) itemLayoutView
// .findViewById(R.id.albumDlbg);
albumName = (TextView) itemLayoutView.findViewById(R.id.albumName);
artistName = (TextView) itemLayoutView
.findViewById(R.id.artistName);
albumIcon = (ImageView) itemLayoutView.findViewById(R.id.albumIcon);
parentView = (LinearLayout) itemLayoutView
.findViewById(R.id.albumDlbg);
settingButton = (ImageView) itemLayoutView
.findViewById(R.id.settingBtn);
}
}
ステップ3- あなたがこれを使用しているところでアクティビティまたはフラグメント内のリサイクラビューを見つけて設定する
recyclerView = (RecyclerView) rootview.findViewById(R.id.vmtopsongs);
lm = new LinearLayoutManager(mActivity);
lm.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(lm);
recyclerView.addItemDecoration(
new HorizontalDividerItemDecoration.Builder(getActivity())
.Paint(Utils.getPaint()).build());
PopularSongsadapter mAdapter = new PopularSongsadapter(gallery,
mActivity, true);
// set adapter
recyclerView.setAdapter(mAdapter);
mAdapter.setOnItemClickListener(this);
// set item animator to DefaultAnimator
recyclerView.setItemAnimator(new DefaultItemAnimator());
ステップ4 /最後に、リサイクルビューを使用している場所でアクティビティまたはフラグメントにインタフェースを実装します。
@Override
public void onRecyclerViewItemClicked(int position, int id)
{
if(id==-1){
Toast.makeText(mActivity, "complete item clicked", Toast.LENGTH_LONG).show();
}else{
Toast.makeText(mActivity, "setting button clicked", Toast.LENGTH_LONG).show();
}
}
これが私がしたことです。このソリューションは、RecyclerView ItemsとViewsの両方でonClickとonLongClickの両方をサポートし、RecyclerView Items(内部ビュー)をサポートします。
選択したビューにviewHolderというタグを付けます。
public RecyclerViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_item, null);
ViewHolder viewHolder = new ViewHolder(itemView);
itemView.setOnClickListener( this);
itemView.setOnLongClickListener(this);
viewHolder.imageIV.setOnClickListener(this);
viewHolder.imageIV.setOnLongClickListener(this);
viewHolder.imageIV.setTag(viewHolder);
itemView.setTag(viewHolder);
return viewHolder;
}
そして、私はonClick()メソッドで位置を取得するためにholder.getPosition()を使います(onLongClickも同様です):
public void onClick(View view) {
ViewHolder holder = (ViewHolder) view.getTag();
int position = holder.getPosition();
if (view.getId() == holder.imageIV.getId()){
Toast.makeText(context, "imageIV onClick at" + position, Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(context, "RecyclerView Item onClick at " + position, Toast.LENGTH_SHORT).show();
}
}
GetChildPositionを使用したバリアントも機能します。内部ビューについては、onClick()で以下を使用してください。
int position = recyclerView.getChildPosition((View)view.getParent());
私の考えでは、このソリューションの利点は、画像をクリックしたときにはonclick()画像リスナーだけが呼び出されるのに対し、RecyclerView Itemビューに対するJacobのソリューションと内部ビューに対する私のソリューションを組み合わせると)も呼ばれます(画像をクリックすると)。
もっと簡単な方法があります。ルートビューのonBindViewHolder
をクリックするだけで適用できます。
これがアダプタに対するあなたの見解であると考えてください。
<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);
}
}
clickListener
をAdapter
に渡すことができます。
あなたのActivity
で:
private View.OnClickListener mItemClick = new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = null;
int position = list.getChildPosition(v);
switch (position) {
case 0:
intent = new Intent(MainActivity.this, LeakCanaryActivity.class);
break;
case 1:
intent = new Intent(MainActivity.this, ButterKnifeFragmentActivity.class);
break;
}
if (intent != null) {
MainActivity.this.startActivity(intent);
}
}
};
それをAdapter
に渡します。
MainAdapter mainAdapter = new MainAdapter(this, mItemClick);
Adapter
のonCreateViewHolder
において:
@Override
public MainAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int position) {
View itemView = activity.getLayoutInflater().inflate(R.layout.main_adapter_item, viewGroup, false);
ViewHolder holder = new ViewHolder(itemView);
itemView.setOnClickListener(mItemClick);
return holder;
}
私はAndroid用の軽量ライブラリを開発しました、あなたは https://github.com/ChathuraHettiarachchi/RecycleClick を訪問することができます
そして次のサンプルのために続きなさい
RecycleClick.addTo(YOUR_RECYCLEVIEW).setOnItemClickListener(new RecycleClick.OnItemClickListener() {
@Override
public void onItemClicked(RecyclerView recyclerView, int position, View v) {
// YOUR CODE
}
});
あなたのViewHolderクラスにOnClickListenerを実装することができます
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public Item item
@InjectView(R.id.tv_title)
public TextView tvTitle;
@InjectView(R.id.rl_row)
public RelativeLayout rlRow;
public ViewHolder(View v) {
super(v);
ButterKnife.inject(this, v);
v.setOnClickListener(this);
}
@Override
public void onClick(View view) {
Log.e("item title",item.getTitle());
}
}
OnBindViewHolderはビューホルダーのアイテムを設定します
public void onBindViewHolder(ViewHolder holder, int position) {
holder.tvTitle.setText(objects.get(position).getTitle());
holder.item = objects.get(position);
}
あまりにも単純で効果的な方法。
ビューホルダーの中にView.OnClickListener
インターフェースを実装するか、あなたの活動の中でインターフェースを作成してインターフェースを実装する代わりに - 私はこのコードを単純なOnClickListener
実装に使いました。
public static class SimpleStringRecyclerViewAdapter
extends RecyclerView.Adapter<SimpleStringRecyclerViewAdapter.ViewHolder> {
// Your initializations goes here...
private List<String> mValues;
public static class ViewHolder extends RecyclerView.ViewHolder {
//create a variable mView
public final View mView;
/*All your row widgets goes here
public final ImageView mImageView;
public final TextView mTextView;*/
public ViewHolder(View view) {
super(view);
//Initialize it here
mView = view;
/* your row widgets initializations goes here
mImageView = (ImageView) view.findViewById(R.id.avatar);
mTextView = (TextView) view.findViewById(Android.R.id.text1);*/
}
}
public String getValueAt(int position) {
return mValues.get(position);
}
public SimpleStringRecyclerViewAdapter(Context context, List<String> items) {
mBackground = mTypedValue.resourceId;
mValues = items;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item, parent, false);
view.setBackgroundResource(mBackground);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.mBoundString = mValues.get(position);
holder.mTextView.setText(mValues.get(position));
//Here it is simply write onItemClick listener here
holder.mView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Context context = v.getContext();
Intent intent = new Intent(context, ExampleActivity.class);
context.startActivity(intent);
}
});
}
@Override
public int getItemCount() {
return mValues.size();
}
}
これまでに投稿したすべての回答は優れた解決策ですが、あまりにも多くの実装の詳細を扱わずに、ListViewと同じように機能させたい場合は、TwoWay-Viewの使用をお勧めします。
https://github.com/lucasr/twoway-view
この実装では、アイテムの長押し、および押された状態のサポートもサポートされています(これは、この質問に対する他の解決策が欠けている点で重要です)。
ライブラリ全体を使いたくない場合は、 ClickItemTouchListener クラスを見てください。これは、必要に応じてスタンドアロンとして使用できます。私が現時点でそれで見つけた唯一の問題は長押し+スクロールにあります、それは不正確なふるまいを持っているようです。
個別イベントのクリックイベントをキャッチしたい場合は、OnClickListener
クラスにViewHolder
を実装してから、個別のビューまたは全体のitemView
にクリックリスナーを設定します。
次の例は同じことを示しています
public class ContactViewHolder extends RecyclerView.ViewHolder implements OnClickListener
{
TextView txt_title,txt_name,txt_email;
public ContactViewHolder(View itemView)
{
super(itemView);
txt_title = (TextView)itemView.findViewById(R.id.txt_title);
txt_name = (TextView)itemView.findViewById(R.id.txt_name);
txt_email = (TextView)itemView.findViewById(R.id.txt_email);
txt_name.setOnClickListener(this);
txt_email.setOnClickListener(this);
itemView.setOnClickListener(this);
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(v == itemView)
{
Toast.makeText(RecyclerDemoActivity.this, "Visiting Card Clicked is ==>"+txt_name.getText(), Toast.LENGTH_SHORT).show();
}
if(v == txt_name)
{
Toast.makeText(RecyclerDemoActivity.this, "Name ==>"+txt_name.getText(), Toast.LENGTH_SHORT).show();
}
if(v == txt_email)
{
Toast.makeText(RecyclerDemoActivity.this, "Email ==>"+txt_email.getText(), Toast.LENGTH_SHORT).show();
}
}
}
}
ここに私がしたことがあります 続きを読む&ここに要旨をダウンロード
ここに同じものを追加する
CustomItemClickListener.Java
public interface CustomItemClickListener {
public void onItemClick(View v, int position);
}
ItemsListAdapter.Java
public class ItemsListAdapter extends RecyclerView.Adapter<ItemsListAdapter.ViewHolder> {
ArrayList<ItemListSingleItem> data;
Context mContext;
CustomItemClickListener listener;
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View mView = LayoutInflater.from(parent.getContext()).inflate(R.layout.items_list_single_item, parent, false);
final ViewHolder mViewHolder = new ViewHolder(mView);
mView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
listener.onItemClick(v, mViewHolder.getAdapterPosition());
}
});
return mViewHolder;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.itemTitle.setText(Html.fromHtml(data.get(position).getTitle()));
if (!TextUtils.isEmpty(data.get(position).getThumbnailURL())) {
// I Love picasso library :) http://square.github.io/picasso/
Picasso.with(mContext).load(data.get(position).getThumbnailURL()).error(R.drawable.ic_no_image).
placeholder(R.drawable.ic_no_image).
transform(new RoundedCornersTransformation(5, 0)).
into(holder.thumbnailImage);
} else {
holder.thumbnailImage.setImageResource(R.drawable.ic_no_image);
}
}
@Override
public int getItemCount() {
return data.size();
}
public ItemsListAdapter(Context mContext, ArrayList<ItemsListSingleItem> data, CustomItemClickListener listener) {
this.data = data;
this.mContext = mContext;
this.listener = listener;
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView itemTitle;
public ImageView thumbnailImage;
ViewHolder(View v) {
super(v);
itemTitle = (TextView) v
.findViewById(R.id.post_title);
thumbnailImage = (ImageView) v.findViewById(R.id.post_thumb_image);
}
}
}
RecyclerView
はOnClickListener
を持たず、それを自分で実装する必要があります。
OnItemClickListener
からアイテムビューをクリックしたときに呼び出されるAdapter
メソッドを使ってonClick
にViewHolder
インターフェースを追加するのが好きです。したがって、アイテムのクリックを管理する責任はViewHolder
とAdapter
の外側にあります。何をすべきかを決定するアクティビティまたはフラグメント
リスナーとリスナーオブジェクトにインターフェイスを追加します。
public class ItemsAdapter extends RecyclerView.Adapter<ItemsAdapter.ViewHolder> {
...
private static OnItemClickListener onItemClickListener;
...
public static interface OnItemClickListener {
public void onItemClick(View view, int position);
}
...
}
アイテムのルートビューのクリックと、コールバックがトリガーされたときのアダプタ上のonClick
リスナー呼び出しをキャプチャします。
public class ItemsAdapter extends RecyclerView.Adapter<ItemsAdapter.ViewHolder> {
...
private static OnItemClickListener onItemClickListener;
...
public static interface OnItemClickListener {
public void onItemClick(View view, int position);
}
...
public static class ViewHolder extends RecyclerView.ViewHolder {
public ImageView imageView;
public ViewHolder(View itemRootView) {
super(itemRootView);
imageView = (ImageView) itemRootView.findViewById(R.id.itemImage);
itemRootView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int position = ViewHolder.super.getAdapterPosition();
onItemClickListener.onItemClick(view,position);
}
});
}
}
}
アクティビティまたはフラグメント、この例ではフラグメントなので、リスナーをアダプタとonClickコールバックに割り当てます。選択したアイテムを位置別に取得し、アイテムの詳細なアクティビティを開きます。
public class ItemsFragment extends Fragment {
...
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
...
((ItemsAdapter) adapter).setOnItemClickListener(new ItemsAdapter.OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
//Do something when an item has been clicked
}
});
...
}
...
}
残念ながらRecyclerView
にはListView
に組み込まれていた機能がいくつか欠けています。例えば、アイテムがクリックされたときにトリガーされるOnItemClickListener
を追加する機能。 RecyclerView
はあなたのアダプタにOnClickListener
を設定することを可能にします、しかしあなたの呼び出しコードからそのクリックリスナをアダプタとViewHolder
に渡すことはaを捕らえるために複雑です簡単なアイテムクリック.
public class ItemClickSupport {
private final RecyclerView mRecyclerView;
private OnItemClickListener mOnItemClickListener;
private OnItemLongClickListener mOnItemLongClickListener;
private View.OnClickListener mOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mOnItemClickListener != null) {
RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(v);
mOnItemClickListener.onItemClicked(mRecyclerView, holder.getAdapterPosition(), v);
}
}
};
private View.OnLongClickListener mOnLongClickListener = new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
if (mOnItemLongClickListener != null) {
RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(v);
return mOnItemLongClickListener.onItemLongClicked(mRecyclerView, holder.getAdapterPosition(), v);
}
return false;
}
};
private RecyclerView.OnChildAttachStateChangeListener mAttachListener
= new RecyclerView.OnChildAttachStateChangeListener() {
@Override
public void onChildViewAttachedToWindow(View view) {
if (mOnItemClickListener != null) {
view.setOnClickListener(mOnClickListener);
}
if (mOnItemLongClickListener != null) {
view.setOnLongClickListener(mOnLongClickListener);
}
}
@Override
public void onChildViewDetachedFromWindow(View view) {
}
};
private ItemClickSupport(RecyclerView recyclerView) {
mRecyclerView = recyclerView;
mRecyclerView.setTag(R.id.item_click_support, this);
mRecyclerView.addOnChildAttachStateChangeListener(mAttachListener);
}
public static ItemClickSupport addTo(RecyclerView view) {
ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support);
if (support == null) {
support = new ItemClickSupport(view);
}
return support;
}
public static ItemClickSupport removeFrom(RecyclerView view) {
ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support);
if (support != null) {
support.detach(view);
}
return support;
}
public ItemClickSupport setOnItemClickListener(OnItemClickListener listener) {
mOnItemClickListener = listener;
return this;
}
public ItemClickSupport setOnItemLongClickListener(OnItemLongClickListener listener) {
mOnItemLongClickListener = listener;
return this;
}
private void detach(RecyclerView view) {
view.removeOnChildAttachStateChangeListener(mAttachListener);
view.setTag(R.id.item_click_support, null);
}
public interface OnItemClickListener {
void onItemClicked(RecyclerView recyclerView, int position, View v);
}
public interface OnItemLongClickListener {
boolean onItemLongClicked(RecyclerView recyclerView, int position, View v);
}
}
Ids.xmlを使用してR.id.item_click_support
を定義する必要もあります。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="item_click_support" type="id" />
</resources>
結果のコードクリックリスナーは、次のようになります。
ItemClickSupport.addTo(mRecyclerView).setOnItemClickListener(new ItemClickSupport.OnItemClickListener() {
@Override
public void onItemClicked(RecyclerView recyclerView, int position, View v) {
// do it
}
});
Recyclerviewのクリックについての簡単な説明については、これを見てください littlerobots_blog
私にとっては、これが最良の方法です。
class YourRecyclerAdapter extends RecyclerView.Adapter<ContactViewHolder> implements View.OnClickListener {
...
@Override
public void onClick(View view) {
int itemPosition = vRecycle.getChildPosition(view);
//And use itemPosition to get the item from your collection. This way you dont restrain the ViewHolder with a OnClick callback
}
...
}
次のようにViewHolderクラスで setOnClickListener を簡単に定義できます。
public class ViewHolder extends RecyclerView.ViewHolder {
TextView product_name;
ViewHolder(View itemView) {
super(itemView);
product_name = (TextView) itemView.findViewById(R.id.product_name);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int itemPosition = getLayoutPosition();
Toast.makeText(getApplicationContext(), itemPosition + ":" + String.valueOf(product_name.getText()), Toast.LENGTH_SHORT).show();
}
});
}
}
上記の答えのほとんどから、彼らは彼らのonclicklistenersを個々のアイテムに設定しているようです。しかし、提供しようとしている解決策は非常に単純ですが、まだ多くの人にとって直感的ではありません。多くの人は、他のコンポーネントが常にリストまたはリサイクルビューでアイテムを表示するために使用される親コンポーネントにあることを忘れています。この解決策は、単一のオンクリックリスナーをこの親ビューに設定するだけで、順番が再生されます。このソリューションには、リストまたはリサイクラービューからクリックされているアイテムの位置を渡す方法も含まれています。ここで、私たちの主なルートビューは、AndroidサポートライブラリのCardViewです。これがサンプルコードです
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);
}
}
}
mRecyclerView.addOnItemTouchListener(object : RecyclerItemClickListener(this, mRecyclerView,object :RecyclerItemClickListener.OnItemClickListener{
override fun onItemClick(view: View, position: Int) {
}
override fun onLongItemClick(view: View?, position: Int) {
}
}){})
RecyclerItemClickListener.Java:
import Android.content.Context
import Android.support.v7.widget.RecyclerView
import Android.view.GestureDetector
import Android.view.MotionEvent
import Android.view.View
open class RecyclerItemClickListener(context: Context, recyclerView: RecyclerView, private val mListener: OnItemClickListener?) : RecyclerView.OnItemTouchListener {
private var mGestureDetector: GestureDetector
interface OnItemClickListener {
fun onItemClick(view: View, position: Int)
fun onLongItemClick(view: View?, position: Int)
}
init {
mGestureDetector = GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() {
override fun onSingleTapUp(e: MotionEvent): Boolean {
return true
}
override fun onLongPress(e: MotionEvent) {
val child = recyclerView.findChildViewUnder(e.x, e.y)
if (child != null && mListener != null) {
mListener.onLongItemClick(child, recyclerView.getChildAdapterPosition(child))
}
}
})
}
override fun onInterceptTouchEvent(view: RecyclerView, e: MotionEvent): Boolean {
val childView = view.findChildViewUnder(e.x, e.y)
if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
mListener.onItemClick(childView, view.getChildAdapterPosition(childView))
return true
}
return false
}
override fun onTouchEvent(view: RecyclerView, motionEvent: MotionEvent) {}
override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {}
}
これは私のカスタムアダプタのための完全なコードです。このコードは "list_item"という名前のxmlファイルで定義されたリストアイテムで行を膨らませますそれはそれぞれの位置ですべてのリストアイテム行でクリックイベントも実行します。
public class MyCustomAdapter extends RecyclerView.Adapter`<`AdapterMyCustomAdapter.ViewHolder> {
public static class ViewHolder extends RecyclerView.ViewHolder implements OnClickListener {
public onItemClickListener mListener;
public ViewHolder(View v, onItemClickListener listener) {
super(v);
mListener =listener;
v.setOnClickListener(this);
}
@Override
public void onClick(View v) {
mListener.onRecyclerItemClick(v, getPosition());
}
public static interface onItemClickListener {
public void onRecyclerItemClick(View view , int position);
}
}
@Override
public int getItemCount() {
return 5;
}
@Override
public void onBindViewHolder(ViewHolder holder, int pos) {
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int position) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item, parent, false);
/* here list_item is an xml file we want to inflate ...it is same as we do in case of listview for customization.*/
MyCustomAdapter.ViewHolder vh = new ViewHolder(v, new MyCustomAdapter.ViewHolder.onItemClickListener() {
@Override
public void onRecyclerItemClick(View view, int position) {
System.out.println("clicked on list item at position " +position);
}
});
return vh;
}
}
私にとってそれをするためのきれいな方法はこれです。
アダプタコンストラクタ
private class EnvironmentTypeRecyclerViewAdapter extends RecyclerView.Adapter<EnvironmentTypeRecyclerViewAdapter.ViewHolder>
{
private final EnvironmentTypeRecyclerViewAdapterListener mEnvironmentTypeRecyclerViewAdapterListener;
private List<Environment> mEnvironmentsData;
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener
{
public ViewHolder(View v)
{
super(v);
v.setOnClickListener(this);
}
@Override
public void onClick(View v)
{
Environment environment = mEnvironmentsData.get(getAdapterPosition());
if (mEnvironmentTypeRecyclerViewAdapterListener != null && environment != null) {
mEnvironmentTypeRecyclerViewAdapterListener.onListItemSelected(environment);
}
}
public EnvironmentTypeRecyclerViewAdapter(List<SmallCellEnvironment> environments, EnvironmentTypeRecyclerViewAdapterListener environmentTypeRecyclerViewAdapterListener)
{
mEnvironmentTypeRecyclerViewAdapterListener = environmentTypeRecyclerViewAdapterListener;
mEnvironmentsData = environments;
}
}
リンクされたインタフェース
private interface EnvironmentTypeRecyclerViewAdapterListener
{
void onListItemSelected(Environment environment);
}
私は多くの答えがあることを知っています、しかし私は私もそれの私の実装を提供するだけかもしれないと思いました。 (詳細は 私が回答した別の質問 でご覧になれます)。
そのため、クリックリスナーを追加するには、内部のViewHolder
クラスにView.OnClickListener
を実装する必要があります。これは、OnClickListener
をitemView
のコンストラクタのViewHolder
パラメータに設定するためです。私が何を言っているのかあなたに見せましょう:
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());
}
}
}
あなたが追加する必要がある他の唯一のものはあなたのAdapter
とセッターメソッドのためのカスタムインターフェースです:
private OnEntryClickListener mOnEntryClickListener;
public interface OnEntryClickListener {
void onEntryClick(View view, int position);
}
public void setOnEntryClickListener(OnEntryClickListener onEntryClickListener) {
mOnEntryClickListener = onEntryClickListener;
}
だから、あなたの新しい、クリック支援のAdapter
は完成です。
それでは、それを使ってみましょう...
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
}
});
基本的には通常のAdapter
を設定する方法ですが、ユーザーが特定のリスト項目をクリックしたときの動作を制御するために作成したsetterメソッドを使用します。
また、このGitHubの要旨に基づいて作成した一連の例を見ることもできます。
https://Gist.github.com/FarbodSalamat-Zadeh/7646564f48ee708c1582c013e1de4f07
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();
}
});
}
}
これがOnClickListener
を再利用するために私がしていることです
public class TestAdapter extends RecyclerView.Adapter<TestAdapter.MyviewHolder>
implements View.OnClickListener
viewHoderでitemlayoutの親を取ります
public class MyviewHolder extends RecyclerView.ViewHolder {
LinearLayout linearLayout_item;
public MyviewHolder(View itemView) {
super(itemView);
linearLayout_item=itemView.findViewById(R.id.linearLayout_item);
}
}
onBindViewHolder内でタグを位置として設定
@Override
public void onBindViewHolder(MyviewHolder holder, int position) {
holder.linearLayout_item.setTag(position);
holder.linearLayout_item.setOnClickListener(this);
}
そしてOnclickで
@Override
public void onClick(View v) {
int position = (int) v.getTag();
switch (v.getId()) {
case R.id.linearLayout_item:
// do some thing with position
break;
}
}
コンストラクタを実装したkotlin内
以下のようにRecyclerviewコンストラクタを初期化します
class ListAdapter(
c: Context,
private var list: List<Project>,
private val itemClick: (Project) -> Unit
) : RecyclerView.Adapter<ListAdapter.ViewHolder>()
あなたのonCreateViewHolderのitemClickで返す
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int):ProjectViewHolder {
val view = inflater.inflate(R.layout.list_item, parent, false)
return ViewHolder(view, itemClick)
}
あなたのonBindViewHolder
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bindProject(list[position])
}
それからviewHolderクラスでbindProject関数を作成します。
class ViewHolder(
view: View,
private val itemClick: (Project) -> Unit
) : RecyclerView.ViewHolder(view) {
private val clientTextCount = 7
val titleTextView: TextView = view.projectTitleTextView
fun bindProject(project: Project) {
with(project) {
titleTextView.text = name
itemView.setOnClickListener { itemClick(this) }
}
}
}
最後にあなたの活動の中でlazyを使ってアダプタを初期化します
private val adapter: ListAdapter by lazy {
ListAdapter(this, projectList, {
// Here you can implement your onClick function.
})
}
リサイクルリストに新しいリストを追加するには、アダプタのメソッドを以下に初期化します
fun setProjects(projects: List<Project>) {
projectList = projects
notifyDataSetChanged()
}
アクティビティ内の任意の場所でsetProjectsメソッドを呼び出します。
adapter.setProjects(projects)
それでおしまい。
私は全ての答えを酷く見たが、それほど満足のいくものではなかった。私はずっと簡単で速い解決策を見つけました。将来の読者のために共有したいと思いました。
View
を選択してください。 View
の親を取得します(ViewGroup
が適切な人にキャストされていることを確認してください)onClickListener
をこの親に設定してください。 サンプルコード(onBindViewHolder
のadapter
メソッド内に記述されています):
@Override
public void onBindViewHolder(@NonNull final ViewHolder holder, final int position) {
ConstraintLayout parent = (ConstraintLayout) holder.title.getParent();
parent.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(context, "Clicked recycler view item at position " + position, Toast.LENGTH_SHORT).show();
}
});
}
これが私のコードスニペットです
v.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v)
{
int newposition = MainActivity.mRecyclerView.getChildAdapterPosition(v);
Intent cardViewIntent = new Intent(c, in.itechvalley.cardviewexample.MainActivityCards.class);
cardViewIntent.putExtra("Position", newposition);
c.startActivity(cardViewIntent);
}
});
v
は 表示 onCreateViewHolder
から
c
は コンテキスト
Jetpack/AndroidXでこれを実装する方法を見てみましょう
このようなviewmodelクラスでオブザーバブルを作成する必要があります
private MutableLiveData<Integer> adapterItem = new MutableLiveData<>();
public MutableLiveData<Integer> getAdapterItem() {
return adapterItem;
}
public void setAdapterItem(int adapterItem) {
this.getAdapterItem().setValue(adapterItem);
}
次に、adapterクラスで、コンストラクターのパラメーターとしてviewmodel参照を渡すことを確認してから、ビューホルダーにclicklistenerを実装します
public MyViewHolder(@NonNull View itemView) {
super(itemView);
if(itemView != null){
itemView.setOnClickListener(v -> {
int adapterPosition = getAdapterPosition();
viewModel.setAdapterItem(adapterPosition);
});
};
}
次に、activityクラスから変更を観察します
viewModel.getAdapterItem().observe(this, position -> {
Log.w(TAG, "clicked: " + ridesArray.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);
}
イベントを1つだけ実装するようにバインディングイベントにクリックハンドラを実装します
これの実装:
mAdapter = new MainGridAdapter(listItems) {
@Override
public void onItemClicked(int position) {
showToast("Item Clicked: " + position, ToastPlus.STYLE_INFO);
}
};
ロングクリックでも同じことができます
Javaの弱参照を使用してこれを行うことができます。意味的には、ビューホルダーはclickイベントに応答するか、正しいレスポンダに委任するものです。
私たちの目標:
ステップ:
クリック応答を処理するためのインターフェースを作成します。
クリックを処理するActivityにこのインタフェースを実装します。
弱い参照とそれを設定するコンストラクタを保持するためにRecyclerViewアダプタにメンバ変数を追加します。
RecyclerView ViewHolderで同じことを行い、位置を追跡するためにメンバー変数を追加します。
ViewHolderで好きなビューにクリックリスナーを設定してから、レスポンダにコールバックしてそれらを処理します。
バインド時の位置を設定するようにonBindViewHolderメソッドを変更します。
レスポンダをViewHolderに渡します。
レスポンダでは、ビューでgetId()を使用して、どのビューがクリックされたのかを判断できます。
そしてここに要旨があるのであなたはそれがすべて一緒にフィットする方法を見ることができる: RecyclerViewクリック処理
これは、リスナーをListView
レベルまたはActivity
レベルの代わりにFragment
レベルまたはAdapter
レベルで定義できるという点で、ViewHolder
実装に似た結果をもたらす戦略です。また、アダプタとホルダーの定型的な作業の多くを引き受ける抽象クラスも定義します。
まず、RecyclerView.ViewHolder
を拡張し、データをビューにバインドするために使用される汎用データ型Holder
を定義する抽象T
を定義します。 bindViews
メソッドはサブクラスによって実装され、データをビューにマップします。
public abstract class Holder<T> extends RecyclerView.ViewHolder {
T data;
public Holder(View itemView) {
super(itemView);
}
public void bindData(T data){
this.data = data;
bindViews(data);
}
abstract protected void bindViews(T data);
}
また、RecyclerView.Adapter<Holder<T>>
を拡張する抽象Adapter
を作成します。これは3つのインタフェースメソッドのうちの2つを定義し、サブクラスは最後のonViewHolderCreated
メソッドを実装する必要があります。
public abstract class Adapter<T> extends RecyclerView.Adapter<Holder<T>> {
List<T> list = new ArrayList<>();
@Override
public void onBindViewHolder(Holder<T> holder, int position) {
holder.bindData(list.get(position));
}
@Override
public int getItemCount() {
return list.size();
}
public T getItem(int adapterPosition){
return list.get(adapterPosition);
}
}
Holder
を拡張する新しい具象クラスを作成しましょう。このメソッドは、ビューを定義してバインディングを処理するだけです。ここでは ButterKnifeライブラリ を使っていますが、代わりにitemView.findViewById(...)
メソッドを使ってください。
public class PersonHolder extends Holder<Person>{
@Bind(R.id.firstname) TextView firstname;
@Bind(R.id.lastname) TextView lastname;
public PersonHolder(View view){
super(view);
ButterKnife.bind(this, view);
}
@Override
protected void bindViews(Person person) {
firstname.setText(person.firstname);
lastname.setText(person.lastname);
}
}
最後に、Activity
を保持するFragment
クラスまたはRecyclerView
クラスに、次のコードがあります。
// Create adapter, this happens in parent Activity or Fragment of RecyclerView
adapter = new Adapter<Person>(){
@Override
public PersonHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.layout_person_view, parent, false);
PersonHolder holder = new PersonHolder(v);
v.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
int itemPos = holder.getAdapterPosition();
Person person = getItem(itemPos);
// do something with person
EventBus.getDefault().postSticky(new PersonClickedEvent(itemPos, person));
}
});
return holder;
}
};
非常に単純です、このクラスを追加してください:
public class OnItemClickListener implements View.OnClickListener {
private int position;
private OnItemClickCallback onItemClickCallback;
public OnItemClickListener(int position, OnItemClickCallback onItemClickCallback) {
this.position = position;
this.onItemClickCallback = onItemClickCallback;
}
@Override
public void onClick(View view) {
onItemClickCallback.onItemClicked(view, position);
}
public interface OnItemClickCallback {
void onItemClicked(View view, int position);
}
}
'OnItemClickCallback'インターフェースのインスタンスを取得し、それをあなたのアクティビティまたはフラグメントに入れます。
private OnItemClickListener.OnItemClickCallback onItemClickCallback = new OnItemClickListener.OnItemClickCallback() {
@Override
public void onItemClicked(View view, int position) {
}
};
次に、そのコールバックをrecyclerViewに渡します。
recyclerView.setAdapter(new SimpleStringRecyclerViewAdapter(Arrays.asList("1", "2", "3"), onItemClickCallback));
最後に、これはあなたのアダプタになります:
public class SimpleStringRecyclerViewAdapter extends RecyclerView.Adapter<SimpleStringRecyclerViewAdapter.ViewHolder> {
private List<String> mValues;
private OnItemClickListener.OnItemClickCallback onItemClickCallback;
public SimpleStringRecyclerViewAdapter(List<String> items, OnItemClickListener.OnItemClickCallback onItemClickCallback) {
mValues = items;
this.onItemClickCallback = onItemClickCallback;
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public final TextView mTextView;
public ViewHolder(View view) {
super(view);
mTextView = (TextView) view.findViewById(R.id.txt_title);
}
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
holder.mTextView.setText(mValues.get(position));
holder.mTextView.setOnClickListener(new OnItemClickListener(position, onItemClickCallback));
}
@Override
public int getItemCount() {
return mValues.size();
}
}
ステップ1)クリックインターフェイスを書く
RecyclerViewClickListener.Java という名前のインターフェースを作成し、以下のコードを追加します。ここでは、アイテムのクリックとロングクリックをそれぞれ識別するために2つのメソッドonClickとonLongClickを宣言します。
package com.androidtutorialshub.recyclerviewtutorial.Helper;
import Android.view.View;
public interface RecyclerViewClickListener {
void onClick(View view, int position);
void onLongClick(View view, int position);
}
ステップ2)アイテムのタッチクラスを書く
RecyclerViewTouchListener.Java という名前のクラスを作成し、以下のコードを追加します。ここでは、リサイクル業者のビューアイテムのクリックと長押しを検出するロジックを作成します。
package com.androidtutorialshub.recyclerviewtutorial.Helper;
import Android.content.Context;
import Android.support.v7.widget.RecyclerView;
import Android.view.GestureDetector;
import Android.view.MotionEvent;
import Android.view.View;
public class RecyclerViewTouchListener implements RecyclerView.OnItemTouchListener{
private GestureDetector gestureDetector;
private RecyclerViewClickListener clickListener;
public RecyclerViewTouchListener(Context context, final RecyclerView recyclerView, final RecyclerViewClickListener 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.getChildPosition(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.getChildPosition(child));
}
return false;
}
@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
}
ステップ3)クリックリスナーの定義
MainActivity.Java を開き、以下の変更を更新します。ここでonClick()メソッドはアイテムのクリックを検出し、onLongClickはアイテムのロングクリックを検出します。
recyclerView.addOnItemTouchListener(new RecyclerViewTouchListener(getApplicationContext(), recyclerView, new RecyclerViewClickListener() {
@Override
public void onClick(View view, int position) {
Toast.makeText(getApplicationContext(), bookList.get(position).getTitle() + " is clicked!", Toast.LENGTH_SHORT).show();
}
@Override
public void onLongClick(View view, int position) {
Toast.makeText(getApplicationContext(), bookList.get(position).getTitle() + " is long pressed!", Toast.LENGTH_SHORT).show();
}
}));
詳細情報またはソースコードのダウンロード: - http://www.androidtutorialshub.com/Android-recyclerview-click-listener-tutorial/
これを試してください。わたしにはできる。ところで、私はsetOnClickListener
はリサイクル業者の見解には効果がないことがわかりました。
recycler.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
// anything todo
}
return true;
}
});
Kotlinで同じ答え
inner class MyViewHolder(v: View, myOnClickListener: MyOnClickListener) : RecyclerView.ViewHolder(v) {
init {
v.setOnClickListener { v -> myOnClickListener.onClick(v, adapterPosition) }
}
}
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): MyViewHolder {
val view = LayoutInflater.from(viewGroup.context).inflate(R.layout.myview, viewGroup, false)
return MyViewHolder(view, mOnClickListener)
}
inner class MyOnClickListener {
fun onClick(view: View, position: Int) {
val item = mList[position]
Toast.makeText(view.context, item, Toast.LENGTH_LONG).show()
}
}
Kotlinハンドルについては、Jacobs anserに基づくrecyclerview anserをクリックしてください。
1)CREATE CLASS RecyclerItemClickListener
class RecyclerItemClickListener(context: Context, recyclerView: RecyclerView, listner: OnItemClickListener) : RecyclerView.OnItemTouchListener {
var mGestureDetector: GestureDetector
var mListner: OnItemClickListener
interface OnItemClickListener {
fun onItemClick(view: View, position: Int)
fun onLongItemClick(view: View, position: Int)
}
init {
this.mListner = listner
mGestureDetector = GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() {
override fun onSingleTapUp(e: MotionEvent?): Boolean {
return true
}
override fun onLongPress(e: MotionEvent?) {
val child: View? = recyclerView.findChildViewUnder(e!!.getX(), e.getY())
if (child != null && mListner != null) {
mListner.onLongItemClick(child, recyclerView.getChildAdapterPosition(child))
}
}
})
}
override fun onTouchEvent(rv: RecyclerView, e: MotionEvent) {
}
override fun onInterceptTouchEvent(view: RecyclerView, e: MotionEvent): Boolean {
val childView: View? = view.findChildViewUnder(e!!.getX(), e.getY())
if (childView != null && mListner != null && mGestureDetector.onTouchEvent(e)) {
mListner.onItemClick(childView, view.getChildAdapterPosition(childView))
return true
}
return false
}
override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {
}
}
2)任意のリサイクルビュー(アクティビティ/フラグメント)をクリックします
recyclerView.addOnItemTouchListener(
RecyclerItemClickListener(
this, recyclerView, object : RecyclerItemClickListener.OnItemClickListener {
override fun onItemClick(view: View, position: Int) {
}
override fun onLongItemClick(view: View, position: Int) {
}
})
)
これがシンプルで明確な方法です。ReacyclerView
ViewHolder
public static class MyViewholder extends RecyclerView.ViewHolder {
public MyViewholder(View itemView) {
super(itemView);
itemView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Log.d("Tag", "onClick:" + getAdapterPosition());
}
});
}
}
getAdapterPosition()
は現在クリックされているアイテムの位置を返します
通常CardView
には複数の要素があるので、それらをラップして整理するにはレイアウトビューが必要です。
そのレイアウトビューにOnClickListener
を追加できます。
1.レイアウトにIDを追加します。この場合LinearLayout
<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
のレイアウトにリスナーを追加し、コールバックを使用してデータをActivity
またはFragment
に送信します(未テスト)。
@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));
}
});
}
コールバックの使い方は別の話です