私はでリストをok に置き換えてListView
いRecyclerView
ますが、OnItemClickListener.onItemClick(AdapterView parent, View v, int position, long id)
で使用する方法と同様に、クリックされたアイテムとその位置を取得する方法を知りたいのListView
ですが。
アイデアをありがとう!
私はでリストをok に置き換えてListView
いRecyclerView
ますが、OnItemClickListener.onItemClick(AdapterView parent, View v, int position, long id)
で使用する方法と同様に、クリックされたアイテムとその位置を取得する方法を知りたいのListView
ですが。
アイデアをありがとう!
回答:
リンクに基づく:RecyclerViewにonItemClickListener()がないのはなぜですか?そしてRecyclerViewはListviewとどう違うのですか?、そして@Duncanの一般的な考えも、私はここに私の解決策を与えます:
RecyclerViewClickListener
アダプターからActivity
/にメッセージを渡すためのインターフェースを1つ定義しますFragment
。
public interface RecyclerViewClickListener {
public void recyclerViewListClicked(View v, int position);
}
ではActivity
/ Fragment
インタフェースを実装し、またアダプタにリスナーを渡します。
@Override
public void recyclerViewListClicked(View v, int position){... ...}
//set up adapter and pass clicked listener this
myAdapter = new MyRecyclerViewAdapter(context, this);
でAdapter
とViewHolder
:
public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.ItemViewHolder> {
... ...
private Context context;
private static RecyclerViewClickListener itemListener;
public MyRecyclerViewAdapter(Context context, RecyclerViewClickListener itemListener) {
this.context = context;
this.itemListener = itemListener;
... ...
}
//ViewHolder class implement OnClickListener,
//set clicklistener to itemView and,
//send message back to Activity/Fragment
public static class ItemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
... ...
public ItemViewHolder(View convertView) {
super(convertView);
... ...
convertView.setOnClickListener(this);
}
@Override
public void onClick(View v) {
itemListener.recyclerViewListClicked(v, this.getPosition());
}
}
}
テスト後、正常に動作します。
[ 更新 ]
API 22以降RecyclerView.ViewHoler.getPosition()
は非推奨となったため、代わりにを使用しgetLayoutPosition()
ます。
private static RecyclerViewClickListener itemListener;
コンストラクターで静的な方法で静的を参照します。
onBindViewHolder
。さらに、私のリストアイテムはすべてクリック可能ではありませんでした(アイテムの一部のみ)。
new MyRecyclerViewAdapter(context, this)
?これによりメモリリークが発生する可能性があります
public void recyclerViewListClicked(View v, int position);
修飾子public
はインターフェースメソッドに冗長です
public class MyRvAdapter extends RecyclerView.Adapter<MyRvAdapter.MyViewHolder>{
public Context context;
public ArrayList<RvDataItem> dataItems;
...
constructor
overrides
...
class MyViewHolder extends RecyclerView.ViewHolder{
public TextView textView;
public Context context;
public MyViewHolder(View itemView, Context context) {
super(itemView);
this.context = context;
this.textView = (TextView)itemView.findViewById(R.id.textView);
// on item click
itemView.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
// get position
int pos = getAdapterPosition();
// check if item still exists
if(pos != RecyclerView.NO_POSITION){
RvDataItem clickedDataItem = dataItems.get(pos);
Toast.makeText(v.getContext(), "You clicked " + clickedDataItem.getName(), Toast.LENGTH_SHORT).show();
}
}
});
}
}
}
クリックリスナーを設定する例を次に示します。
Adapter extends RecyclerView.Adapter<MessageAdapter.MessageViewHolder> { ... }
public static class MessageViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView tv_msg;
public TextView tv_date;
public TextView tv_sendTime;
public ImageView sharedFile;
public ProgressBar sendingProgressBar;
public MessageViewHolder(View v) {
super(v);
tv_msg = (TextView) v.findViewById(R.id.tv_msg);
tv_date = (TextView) v.findViewById(R.id.tv_date);
tv_sendTime = (TextView) v.findViewById(R.id.tv_sendTime);
sendingProgressBar = (ProgressBar) v.findViewById(R.id.sendingProgressBar);
sharedFile = (ImageView) v.findViewById(R.id.sharedFile);
sharedFile.setOnClickListener(this);
}
@Override
public void onClick(View view) {
int position = getAdapterPosition();
switch (view.getId()){
case R.id.sharedFile:
Log.w("", "Selected"+position);
break;
}
}
}
int position = getAdapterPosition();
このコードを、アクティビティのリサイクラービューを定義する場所に配置します。
rv_list.addOnItemTouchListener(
new RecyclerItemClickListener(activity, new RecyclerItemClickListener.OnItemClickListener() {
@Override
public void onItemClick(View v, int position) {
Toast.makeText(activity, "" + position, Toast.LENGTH_SHORT).show();
}
})
);
次に、別のクラスを作成し、このコードを配置します。
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);
}
GestureDetector mGestureDetector;
public RecyclerItemClickListener(Context context, OnItemClickListener listener) {
mListener = listener;
mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
});
}
@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) {
}
}
以下のコードでJavaファイルを作成します
public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {
private OnItemClickListener mListener;
public interface OnItemClickListener {
public void onItemClick(View view, int position);
}
GestureDetector mGestureDetector;
public RecyclerItemClickListener(Context context, OnItemClickListener listener) {
mListener = listener;
mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
@Override public boolean onSingleTapUp(MotionEvent e) {
return true;
}
});
}
@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.getChildLayoutPosition(childView));
return true;
}
return false;
}
@Override public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) { }
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
RecyclerViewオブジェクトのリスナーを使用するだけです。
recyclerView.addOnItemTouchListener(
new RecyclerItemClickListener(context, new RecyclerItemClickListener.OnItemClickListener() {
@Override public void onItemClick(View view, int position) {
// TODO Handle item click
}
}));
RecyclerItemClickListener
はデフォルトのandroidクラスではありません。使用しているライブラリまたはクラス自体を提供する必要があります。
アダプターの代わりにアクティビティ/フラグメントからのリサイクルビューのクリックイベントが必要な場合は、次のショートカット方法を使用することもできます。
recyclerView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
final TextView txtStatusChange = (TextView)v.findViewById(R.id.txt_key_status);
txtStatusChange.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e(TAG, "hello text " + txtStatusChange.getText().toString() + " TAG " + txtStatusChange.getTag().toString());
Util.showToast(CampaignLiveActivity.this,"hello");
}
});
return false;
}
});
インターフェイスを使用するなど、他の長い方法を使用することもできます
recyclerViewObject.addOnItemTouchListener(
new RecyclerItemClickListener(
getContext(),
recyclerViewObject,
new RecyclerItemClickListener.OnItemClickListener() {
@Override public void onItemClick(View view, int position) {
// view is the clicked view (the one you wanted
// position is its position in the adapter
}
@Override public void onLongItemClick(View view, int position) {
}
}
)
);
以下のコードを使用してください:
public class SergejAdapter extends RecyclerView.Adapter<SergejAdapter.MyViewHolder>{
...
class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
@Override
public void onClick(View v) {
// here you use position
int position = getAdapterPosition();
...
}
}
}
RecyclerViewはそのようなメソッドを提供していません。
RecyclerViewでクリックイベントを管理するために、ViewHolderをバインドするときに、アダプターにonClickListenerを実装することになりました。ViewHolderでは、(ImageViews、TextViewsなどでできるように)ルートビューへの参照を保持し、バインドするときにviewHolderクリックを処理するために必要な情報(位置など)とクリックリスナーをタグに設定しました
クリックされたアイテムの位置を見つける最も簡単で簡単な方法は次のとおりです。
私も同じ問題に直面しました。
RecyclerView()のクリック/選択されたアイテムの位置を見つけて、その特定のアイテムに対して特定の操作を実行したいと思っていました。
getAdapterPosition()メソッドは、この種のものの魅力のように機能します。この方法は、1日の長い研究の結果、他の多くの方法を試した後で見つかりました。
int position = getAdapterPosition();
Toast.makeText(this, "Position is: "+position, Toast.LENGTH_SHORT).show();
追加のメソッドを使用する必要はありません。'position'という名前のグローバル変数を作成し、アダプターの主要なメソッド(クラスなど)のいずれかでgetAdapterPosition()を使用して初期化するだけです。
このリンクからの簡単なドキュメントを次に示します。
バージョン22.1.0で追加されたgetAdapterPosition int getAdapterPosition()このViewHolderによって表されるアイテムのアダプタの位置を返します。保留中のアダプターの更新はあるが、新しいレイアウトパスがまだ行われていない場合、これはgetLayoutPosition()とは異なる場合があることに注意してください。RecyclerViewは、次のレイアウトトラバーサルまでアダプタの更新を処理しません。これにより、ユーザーが画面に表示するものとアダプタの内容との間に一時的な不整合が生じる可能性があります。この不整合は16ms未満になるため重要ではありませんが、ViewHolder位置を使用してアダプターにアクセスする場合は問題になる可能性があります。場合によっては、ユーザーイベントに応じてアクションを実行するために、アダプターの正確な位置を取得する必要があります。その場合、ViewHolderのアダプタ位置を計算するこのメソッドを使用する必要があります。
お力になれて、嬉しいです。ご不明な点はお気軽にお問い合わせください。
私の簡単な解決策
Make a position holder:
public class PositionHolder {
private int position;
public PositionHolder(int position) {
this.position = position;
}
public int getPosition() {
return position;
}
public void setPosition(int position) {
this.position = position;
}
}
アクティビティから取得する必要があるデータを配置または配置するだけです。
アダプターコンストラクター:
public ItemsAdapter(Context context, List<Item> items, PositionHolder positionHolder){
this.context = context;
this.items = items;
this.positionHolder = positionHolder;
}
活動中:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
selectedPosition = 0;
positionHolder = new PositionHolder(selectedPosition);
initView();
}
onBindViewHolderの項目のアダプタ
onClickLictener
holder.holderButton.setOnClickListener(v -> {
positionHolder.setPosition(position);
notifyDataSetChanged();
});
これで、RecyclerViewで位置を変更するたびに、ホルダーに保持されます(または、リスナーと呼ばれる必要があります)
お役に立てれば幸いです
私の最初の投稿; P
//Create below methods into the Activity which contains RecyclerView.
private void createRecyclerView() {
final RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
MyAdapter myAdapter=new MyAdapter(dataAray,MianActivity.this);
recyclerView.setAdapter(myAdapter);
recyclerView.setItemAnimator(new DefaultItemAnimator());
setRecyclerViewClickListner(recyclerView);
}
private void setRecyclerViewClickListner(RecyclerView recyclerView){
final GestureDetector gestureDetector = new GestureDetector(MainActivity.this,new GestureDetector.SimpleOnGestureListener() {
@Override public boolean onSingleTapUp(MotionEvent e) {
return true;
}
});
recyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
@Override
public boolean onInterceptTouchEvent(RecyclerView recyclerView, MotionEvent motionEvent) {
View child =recyclerView.findChildViewUnder(motionEvent.getX(),motionEvent.getY());
if(child!=null && gestureDetector.onTouchEvent(motionEvent)){
int position=recyclerView.getChildLayoutPosition(child);
String name=itemArray.get(position).name;
return true;
}
@Override
public void onTouchEvent(RecyclerView recyclerView, MotionEvent motionEvent) {
}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean b) {
}
});
}
このようにしてみてください
アダプタークラス:
public class ContentAdapter extends RecyclerView.Adapter<ContentAdapter.ViewHolder> {
public interface OnItemClickListener {
void onItemClick(ContentItem item);
}
private final List<ContentItem> items;
private final OnItemClickListener listener;
public ContentAdapter(List<ContentItem> items, OnItemClickListener listener) {
this.items = items;
this.listener = listener;
}
@Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_item, parent, false);
return new ViewHolder(v);
}
@Override public void onBindViewHolder(ViewHolder holder, int position) {
holder.bind(items.get(position), listener);
}
@Override public int getItemCount() {
return items.size();
}
static class ViewHolder extends RecyclerView.ViewHolder {
private TextView name;
private ImageView image;
public ViewHolder(View itemView) {
super(itemView);
name = (TextView) itemView.findViewById(R.id.name);
image = (ImageView) itemView.findViewById(R.id.image);
}
public void bind(final ContentItem item, final OnItemClickListener listener) {
name.setText(item.name);
itemView.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View v) {
listener.onItemClick(item);
}
});
}
}
}
あなたの活動またはフラグメントで:
ContentAdapter adapter = new ContentAdapter(itemList, this);
注:アクティビティまたはフラグメントで指定したコンテキストに基づいてOnItemClickListenerを実装し、メソッドをオーバーライドします。
いつも別のアプローチを使用しています。人々は、ViewHolderによって表示されるオブジェクトへの参照を保存するのではなく、ビューの位置を保存または取得するようです。
代わりにこのアプローチを使用し、onBindViewHolder()が呼び出されたときにViewHolderに格納し、onViewRecycled()で参照をnullに設定します。
ViewHolderが非表示になるたびに、リサイクルされます。したがって、これは大量のメモリ消費には影響しません。
@Override
public void onBindViewHolder(final ItemViewHolder holder, int position) {
...
holder.displayedItem = adapterItemsList.get(i);
...
}
@Override
public void onViewRecycled(ItemViewHolder holder) {
...
holder.displayedItem = null;
...
}
class ItemViewHolder extends RecyclerView.ViewHolder {
...
MySuperItemObject displayedItem = null;
...
}
カスタムインターフェイスのjavaメソッドでgetLayoutPosition()を使用します。これにより、アイテムの選択した位置が返されます。詳細を確認してください
https://becody.com/get-clicked-item-and-its-position-in-recyclerview/
デザイナーから、onClick
listItem のプロパティを単一のパラメーターで定義されたメソッドに設定できます。以下に定義されているメソッドの例があります。getAdapterPositionメソッドは、選択されたlistItemのインデックスを提供します。
public void exampleOnClickMethod(View view){
myRecyclerView.getChildViewHolder(view).getAdapterPosition());
}
RecyclerViewのセットアップについては、こちらのドキュメントを参照してください:https : //developer.android.com/guide/topics/ui/layout/recyclerview
//simply check if the adapter position you get not less than zero
holder.btnDelItem.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(holder.getAdapterPosition()>=0){
list.remove(holder.getAdapterPosition());
notifyDataSetChanged();
}
}
});
多くの試行錯誤の後、これを行う非常に簡単な方法があることを発見しました。これは、アダプタークラスでインターフェイスを作成し、それをフラグメントで実装することです。ここでひねりが加えられ、オーバーライド関数内のビューモデルをインスタンス化しました。フラグメントを使用して、その関数からデータをviemodelに送信し、そこからどこにでも送信できます。
この方法が適切なコーディング方法であるかどうかはわかりませんが、コメントで教えてください。コメント欄で教えてほしい場合は、スタックオーバーフローを定期的に開いています。
recyclerView.addOnItemTouchListener(object : AdapterView.OnItemClickListener,
RecyclerView.OnItemTouchListener {
override fun onItemClick(p0: AdapterView<*>?, p1: View?, p2: Int, p3: Long) {
TODO("Not yet implemented")
}
override fun onTouchEvent(rv: RecyclerView, e: MotionEvent) {
TODO("Not yet implemented")
}
override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean {
TODO("Not yet implemented")
}
override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {
TODO("Not yet implemented")
}
})
Kotlinを使用する場合