ListView
をRecyclerView
に置き換えます。リストは問題ありませんが、メソッド OnItemClickListener.onItemClick(AdapterView parent, View v, int position, long id)
と同様に、クリックされた項目とその位置を取得する方法を知りたいです。私たちはListView
で使います。
アイデアをありがとう!
リンクに基づいて: RecyclerViewにonItemClickListener()がないのはなぜですか?そしてRecyclerViewはListviewとどう違うのですか? 、そして@ Duncanの一般的な考えから、私の解決策をここに示します。
アダプタからRecyclerViewClickListener
/Activity
にメッセージを渡すためのインターフェースFragment
を1つ定義します。
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());
}
}
}
テストの後、それはうまくいきます。
[UPDATE]
API 22以降、RecyclerView.ViewHoler.getPosition()
は非推奨になりました。代わりにgetLayoutPosition()
を使用してください。
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;
}
}
}
このコードをアクティビティ内のリサイクラビューを定義する場所に配置します。
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) {
}
}
Click-eventのリサイクル - アダプタではなくアクティビティ/フラグメントからの表示が必要な場合は、次のショートカット方法も使用できます。
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) {
}
}
)
);
以下のコードで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
}
}));
以下のコードを使用してください: -
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では、ルートビューへの参照を保持します(ImageView、TextViewなどでできるので)。 viewHolderクリックを処理するために必要な情報(位置など)とclicklistenerをタグに設定します。
カスタムインタフェースのJavaメソッドでgetLayoutPosition()を使用します。これはアイテムの選択された位置を返します。詳細をチェックする
https://becody.com/get-clicked-item-and-its-position-in-recyclerview/
私は別の方法を使うたびに。 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;
...
}
デザイナから、listItemのonClick
プロパティを単一のパラメータで定義されたメソッドに設定できます。以下に定義されているメソッドの例があります。メソッドgetAdapterPositionは選択されたlistItemのインデックスをあなたに与えます。
public void exampleOnClickMethod(View view){
myRecyclerView.getChildViewHolder(view).getAdapterPosition());
}
RecyclerViewの設定については、こちらのドキュメントを参照してください。 https://developer.Android.com/guide/topics/ui/layout/recyclerview
クリックしたアイテムの位置を見つける最も簡単で簡単な方法は次のとおりです。
私も同じ問題に直面しました。
RecyclerView()のクリック/選択されたアイテムの位置を見つけ、その特定のアイテムに対して特定の操作を実行したいと思いました。
getAdapterPosition()メソッドは、この種のものにとっては魅力的です。私は長い研究の日の後にそして他の多数の方法を試みた後にこの方法を見つけた。
int position = getAdapterPosition();
Toast.makeText(this, "Position is: "+position, Toast.LENGTH_SHORT).show();
追加の方法を使用する必要はありません。 'position'という名前のグローバル変数を作成し、アダプタの主要なメソッド(クラスなど)のいずれかでgetAdapterPosition()で初期化するだけです。
これはこの リンク からの簡単なドキュメントです。
getAdapterPositionバージョン22.1.0で追加されました。int getAdapterPosition()このViewHolderによって表される項目のアダプタ位置を返します。保留中のアダプタの更新があるが新しいレイアウトパスがまだ行われていない場合、これはgetLayoutPosition()とは異なる可能性があることに注意してください。次のレイアウトトラバーサルまで、RecyclerViewはアダプタの更新を処理しません。これにより、ユーザーが画面に表示するものとアダプタのコンテンツに含まれるものとの間に一時的な矛盾が生じる可能性があります。この矛盾は16ms以下になるので重要ではありませんが、ViewHolderの位置を使用してアダプターにアクセスしたい場合は問題になる可能性があります。場合によっては、ユーザーイベントに応じていくつかのアクションを実行するために正確なアダプターの位置を取得する必要があります。その場合は、ViewHolderのアダプタ位置を計算するこのメソッドを使用してください。
お力になれて、嬉しいです。疑問を投げかけてください。
Kotlinの短縮形
メソッドはすべての項目の絶対位置を返します(表示されている項目のみの位置ではありません)。
fun RecyclerView.getChildPositionAt(x: Float, y: Float): Int {
return getChildAdapterPosition(findChildViewUnder(x, y))
}
そして使い方
val position = recyclerView.getChildPositionAt(event.x, event.y)
//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を実装します。