のアイテムRecyclerView
を設定する方法を見つけた人はいますか? 各アイテムの各レイアウトにリスナーを設定することを考えましたが、それは少し面倒です。イベントをリッスンする方法があると確信していますが、よくわかりません。onClickListener
RecyclerView
RecyclerView
onClick
48 に答える
OnClickListener
これは、 for aを実装するためのより適切で密結合度の低い方法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);
}
});
これは、誰かが役に立つと思った場合に備えて、私が最終的に必要としていたものです:
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 アイテムと RecyclerView アイテム (内部ビュー) 内のビューの両方で onClick と onLongClick の両方をサポートします。
選択したビューに 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;
}
そして、holder.getPosition() を使用して onClick() メソッドで位置を取得します (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 のソリューションと内部ビューのソリューションを組み合わせた場合、 RecyclerView Item ビュー onclick( ) とも呼ばれます (画像をクリックすると)。
clickListener
に aを渡すことができます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;
}
個々のアイテムでクリックイベントをキャッチしたい場合は、クラスに実装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();
}
}
}
}
OnClickListener を ViewHolder クラスに実装できます
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);
}
これまでに投稿されたすべての回答は優れたソリューションですが、実装の詳細をあまり扱いたくなく、ListView と同様に機能させたい場合は、次のように TwoWay-View を使用することをお勧めします。
https://github.com/lucasr/twoway-view
この実装は、アイテムの長押しと、押された状態のサポートもサポートしていることに注意してください (これは、この質問に対する他のソリューションに欠けている重要なことです)。
ライブラリ全体を使用したくない場合は、必要に応じてスタンドアロンとして使用できるClickItemTouchListenerクラスを参照してください。現時点で私が見つけた唯一の問題は、長押し + スクロールで、動作が正しくないようです。
これが私がしたことです詳細を読み、ここで要点をダウンロードしてください
ここに同じものを追加
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
の機能がいくつかありません。ListView
たとえばOnItemClickListener
、アイテムがクリックされたときにトリガーされる を追加する機能。
RecyclerView
をアダプターに設定できますがOnClickListener
、そのクリック リスナーを呼び出しコードからアダプターおよび に渡すのはViewHolder
、単純な項目のクリックをキャッチするのに複雑です。
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);
}
}
R.id.item_click_support
ids.xml を使用して定義する必要もあります。
<?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をご覧ください。
にはRecyclerView
がなく、OnClickListener
自分で実装する必要があります。
から項目ビューをクリックしたときに呼び出されるメソッドを使用して、OnItemClickListener
インターフェイスを追加したいと思います。したがって、アイテムのクリックを管理する責任は、 and の外にあります。何をすべきかを決定するアクティビティまたはフラグメント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
}
});
...
}
...
}
私にとって、それを行うためのクリーンな方法はこれです。
アダプター コンストラクター
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);
}
これは、Java 弱参照を使用して行うことができます。意味的には、ビュー ホルダーは、クリック イベントに応答するか、正しいレスポンダーに委任する必要があります。
私たちの目標:
- ビューホルダーは、特定のインターフェイスを実装することを除いて、イベントに応答するクラスについて何も知らない必要があります。
- クリック ハンドラーは、クリックされたビューの RecyclerView 内の位置を取得する必要があります。
- ビューホルダーでどのビューがクリックされたかを識別できるはずです。
- すべてのコンポーネント間の疎結合を維持し、リテイン サイクルが発生しないようにします。
手順:
クリック応答を処理するインターフェースを作成します。
クリックを処理するアクティビティにこのインターフェイスを実装します。
RecyclerView アダプターにメンバー変数を追加して、弱参照とそれを設定するコンストラクターを保持します。
RecyclerView ViewHolder で同じことを行い、メンバー変数を追加して位置を追跡します。
ViewHolder で必要な任意のビューにオンクリック リスナーを設定し、レスポンダーにコールバックしてそれらを処理します。
onBindViewHolder メソッドを変更して、バインド時の位置を設定します。
レスポンダーを ViewHolder に渡します。
レスポンダーでは、ビューで getId() を使用して、クリックされたビューを特定できるようになりました。
そして、ここに要点があるので、すべてがどのように適合するかを見ることができます: RecyclerView クリック処理
ステップ 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/
私はすべての回答を調べましたが、満足できるものではありませんでした。はるかに簡単で高速なソリューションを見つけました。将来の読者のために共有したかった.
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
コンテキストです
orレベルの代わりにorレベルListView
でリスナーを定義できるという点で、実装と同様の結果をもたらす戦略を次に示します。また、アダプターとホルダーの定型的な作業の多くを処理するいくつかの抽象クラスも定義します。Activity
Fragment
Adapter
ViewHolder
抽象クラス
まず、データをビューにバインドするために使用される汎用データ型Holder
を拡張および定義する抽象を定義します。メソッドはサブクラスによって実装され、データをビューにマップします。RecyclerView.ViewHolder
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);
}
Adapter
また、拡張するアブストラクトを作成しますRecyclerView.Adapter<Holder<T>>
。これは 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();
}
}
通常、 には複数の要素がCardView
あるため、それらをラップして整理するにはレイアウト ビューが必要です。そのレイアウト ビューに を
追加できます。1. レイアウトに ID を追加します。この場合、OnClickListener
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. リスナーをレイアウトに追加し、コールバックを使用してoronBindViewHolder
にデータを送信します(テストされていません)。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));
}
});
}
コールバックの使用方法は別の話です
クラスを抽象としてマークし、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);
}
};
長いクリックでも同じことができます