Cara membuat menu konteks untuk RecyclerView

98

Bagaimana cara menerapkan menu konteks untuk RecyclerView?Rupanya panggilan registerForContextMenu(recyclerView)tidak berfungsi. Saya menyebutnya dari sebuah fragmen. Apakah ada yang berhasil menerapkan ini?

Binoy Babu
sumber
Saya di perahu yang sama. Mencoba berbagai penilaian ListView dengan AdapterContextMenuInfo - tetapi tidak bisa mendapatkan info.position
RoundSparrow hilltx
Saya pikir hari-hari menu konteks sudah berakhir.
Binoy Babu
4
Hai - Saya berhasil;) refeerence: stackoverflow.com/questions/2321332/… - ViewHolder untuk saya adalah pendengar onClick - Saya juga menjadikannya OnCreateContextMenuListener. Kunci untuk semua ini adalah saya menyadari hanya SATU Menu yang dapat dibuka pada satu waktu - jadi adaptor hanya perlu int untuk diberi tahu mana item daftar RecyclerView terakhir yang menunya diklik ... maka Fragmen / Aktivitas dapat tanyakan adaptor ketika mendapat klik item menu yang sebenarnya.
RoundSparrow hilltx

Jawaban:

92

Anda tidak dapat langsung mengimplementasikan metode ini seperti onClickListener , OnContextMenuListener , dll. Karena RecycleView memperluas android.view.ViewGroup . Jadi kami tidak bisa langsung menggunakan metode ini. Kita bisa mengimplementasikan metode ini di kelas adaptor ViewHolder . Kita bisa menggunakan menu konteks di RecycleView seperti ini:

public static class ViewHolder extends RecyclerView.ViewHolder implements OnCreateContextMenuListener {

    TextView tvTitle;
    ImageView ivImage;

    public ViewHolder(View v) {
        super(v);
        tvTitle =(TextView)v.findViewById(R.id.item_title);
        v.setOnCreateContextMenuListener(this);


    }

Sekarang kita mengikuti prosedur yang sama saat mengimplementasikan menu konteks.

@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {

    menu.setHeaderTitle("Select The Action");    
    menu.add(0, v.getId(), 0, "Call");//groupId, itemId, order, title   
    menu.add(0, v.getId(), 0, "SMS"); 

}

Jika Anda mengalami kesulitan, tanyakan dalam komentar.

Prabhakar
sumber
7
Oke, lalu kita menerapkan onContextItemSelecteddi level aktivitas / fragmen. getTitleberfungsi, getItemIdberfungsi, tetapi getMenuInfomemberikan null. Jadi, bagaimana cara mendapatkannya ViewHolder?
Michael Schmidt
@MichaelSchmidt dapatkah Anda menunjukkan kode Anda di mana Anda menerapkan info menu Konteks.
ID
7
Setelah bereksperimen sedikit, saya juga tidak bisa membuat ini berfungsi, getMenuInfo()mengembalikan nol onContextItemSelected(). Mungkin orang-orang yang berhasil membuatnya bekerja kebetulan memiliki onCreateContextMenu()metode untuk melihat lebih jauh hierarki ( RecyclerViewatau Fragment)? Itu bisa berhasil tetapi kemudian membawa kita ke jawaban lain untuk pertanyaan ini.
NeilS
3
Prabhakbar Anda tidak menyebutkan bagaimana cara mendapatkan item yang diklik dan juga tampilan?
Benjamin Stürmer
6
Anda dapat menggunakan menu.add(this.getAdapterPosition(), v.getId(), 0, "Call");dan kemudian dalam pengujian metode panggilan balik untuk item.getGroupId()mendapatkan posisi
JacobPariseau
100

Terima kasih atas info dan komentarnya. Saya bisa meraih ContextMenuitem dalam Recyclerview.

Inilah yang saya lakukan

dalam onViewCreatedmetode Fragmen atau metode Aktivitas onCreate:

registerForContextMenu(mRecyclerView);

Kemudian di Adaptor tambahkan

private int position;

public int getPosition() {
    return position;
}

public void setPosition(int position) {
    this.position = position;
}

membuat ViewHolderkelas mengimplementasikanOnCreateContextMenuListener

public static class ViewHolder extends RecyclerView.ViewHolder 
        implements View.OnCreateContextMenuListener {

    public ImageView icon;

    public TextView fileName;
    public ImageButton menuButton;


    public ViewHolder(View v) {
        super(v);
        icon = (ImageView)v.findViewById(R.id.file_icon);
        fileName = (TextView)v.findViewById(R.id.file_name);
        menuButton = (ImageButton)v.findViewById(R.id.menu_button);
        v.setOnCreateContextMenuListener(this);
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, 
        ContextMenu.ContextMenuInfo menuInfo) {
        //menuInfo is null
        menu.add(Menu.NONE, R.id.ctx_menu_remove_backup, 
            Menu.NONE, R.string.remove_backup);
        menu.add(Menu.NONE, R.id.ctx_menu_restore_backup,
            Menu.NONE, R.string.restore_backup);
    }
}

onBindViewHoldermetode tambahkan OnLongClickListenerpada holder.itemView untuk menangkap posisi sebelum menu konteks dimuat:

holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
    @Override
    public boolean onLongClick(View v) {
        setPosition(holder.getPosition());
        return false;
    }
});

Kemudian di onViewRecycledhapus Listener agar tidak ada masalah referensi. (mungkin tidak diperlukan).

@Override
public void onViewRecycled(ViewHolder holder) {
    holder.itemView.setOnLongClickListener(null);
    super.onViewRecycled(holder);
}

Akhirnya di Fragment / Activity menimpa onContextItemSelectedseperti di bawah:

@Override
public boolean onContextItemSelected(MenuItem item) {
    int position = -1;
    try {
        position = ((BackupRestoreListAdapter)getAdapter()).getPosition();
    } catch (Exception e) {
        Log.d(TAG, e.getLocalizedMessage(), e);
        return super.onContextItemSelected(item);
    }
    switch (item.getItemId()) {
        case R.id.ctx_menu_remove_backup:
            // do your stuff
            break;
        case R.id.ctx_menu_restore_backup:
            // do your stuff
            break;
    }
    return super.onContextItemSelected(item);
}
Hardik Shah
sumber
1
position = ((BackupRestoreListAdapter) getAdapter ()). getPosition (); -> get error: Metode getAdapter () tidak ditentukan untuk tipe ..., dapatkah Anda menampilkan metode
getAdapter
1
Saran bagus, terima kasih. Kecil: viewHolder.getPosition () tidak digunakan lagi. Apa saran Anda untuk perbaikan?
tm1701
10
gunakan viewHolder.getAdapterPosition () daripada getPosition ()
Sagar Chavada
2
Bagi mereka yang mendapatkan kesalahan getAdapter (), saya menyelesaikannya dengan menyimpan referensi ke RecyclerView saya dan kemudian menggunakannya seperti: ((BackupRestoreListAdapter) recyclerView.getAdapter ()). GetPosition ();
Kevin Amorim
1
Dan di mana tepatnya R.id.ctx_menu_remove_backup?
akubi
29

Jawaban saat ini tidak benar. Berikut implementasi yang berfungsi:

public class ContextMenuRecyclerView extends RecyclerView {

  private RecyclerViewContextMenuInfo mContextMenuInfo;

  @Override
  protected ContextMenu.ContextMenuInfo getContextMenuInfo() {
    return mContextMenuInfo;
  }

  @Override
  public boolean showContextMenuForChild(View originalView) {
    final int longPressPosition = getChildPosition(originalView);
    if (longPressPosition >= 0) {
        final long longPressId = getAdapter().getItemId(longPressPosition);
        mContextMenuInfo = new RecyclerViewContextMenuInfo(longPressPosition, longPressId);
        return super.showContextMenuForChild(originalView);
    }
    return false;
  }

  public static class RecyclerViewContextMenuInfo implements ContextMenu.ContextMenuInfo {

    public RecyclerViewContextMenuInfo(int position, long id) {
        this.position = position;
        this.id = id;
    }

    final public int position;
    final public long id;
  }
}

Di Fragmen (atau Aktivitas) Anda:

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    mRecyclerView = view.findViewById(R.id.recyclerview);
    registerForContextMenu(mRecyclerView);
}

@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
    super.onCreateContextMenu(menu, v, menuInfo);
    // inflate menu
    MenuInflater inflater = getActivity().getMenuInflater();
    inflater.inflate(R.menu.my_context_menu, menu);
}

@Override
public boolean onContextItemSelected(MenuItem item) {
    return super.onContextItemSelected(item);
    RecyclerViewContextMenuInfo info = (RecyclerViewContextMenuInfo) item.getMenuInfo();
    // handle menu item here
}

Dan terakhir, di ViewHolder Anda:

class MyViewHolder extends RecyclerView.View.ViewHolder {
    ...
    private void onLongClick() {
        itemView.showContextMenu();
    }
}
Renaud Cerrato
sumber
Silakan, tambahkan konstruktor RecyclerView yang harus Anda terapkan di ContextMenuRecyclerView Anda. Dan juga, getChildPosition()sekarang sudah usang. Saya menggunakan getChildAdapterPosition()sebagai gantinya.
Juan José Melero Gómez
1
Catatan: Maaf, saya lupa menambahkan: getChildPosition()sudah tidak berlaku lagi di com.android.support:recyclerview-v7:22.0.0.
Juan José Melero Gómez
1
ini tidak bekerja. Anda tidak bisa mengakses getView (). showContextMenu () dari RecyclerView.View.ViewHolder.
Mulgard
4
Ini berhasil untuk saya. Tapi tidak perlu ada onLongClick () di MyViewHolder, cukup dengan menyetel itemView.setLongClickable (true) di konstruktor, menu konteks akan muncul saat OnLongClickListener tidak terdaftar.
alders
2
Penting juga: saat memperluas RecyclerView ke ContextMenuRecyclerView, jangan lupa untuk MENAMBAHKAN KONSTRUKTOR yang disarankan oleh IDE. Secara khusus, jika Anda tidak mengimplementasikan konstruktor dua argumen yang menggunakan Context dan AttributeSet, Android tidak akan bisa memekarkan XML tata letak Anda.
lidkxx
24

Coba ini untuk Viewitem di recycleView

.setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() {
        @Override
        public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
            menu.add("delete").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
                @Override
                public boolean onMenuItemClick(MenuItem item) {

                    //do what u want
                    return true;
                }
            });
        }
    });

Anda dapat menggunakannya dengan mengatur data ke ViewHolderitem

Sergey Bondarenko
sumber
Persis yang saya butuhkan untuk menu konteks pada tampilan gambar di dalam tampilan daur ulang
Themos
2
Untuk siapa pun yang melihat ini sekarang, ini hanya berfungsi di API 23 ke atas.
SWoo
16

Jawaban Prabhakar benar, tapi dia tidak menjelaskan bagaimana cara mendapatkan suatu data, terkait item yang ditekan, ketika item menu konteks dipilih. Kita bisa menggunakan onContextItemSelectedcallback, tetapi ContextMenuInfotidak tersedia ( null) dalam kasus ini (jika getContextMenuInfo()metode tidak diganti untuk tampilan yang ditekan). Jadi, solusi paling sederhana adalah menambahkan OnMenuItemClickListenerlangsung ke MenuItem.

private class ViewHolder extends RecyclerView.ViewHolder {
    private final TextView mTitleTextView;
    private MyItemData mData;

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

        mTitleTextView = (TextView)view.findViewById(R.id.title);

        view.setOnCreateContextMenuListener(mOnCreateContextMenuListener);
    }

    public void bind(@NonNull MyItemData data) {
         mData = data;

         String title = mData.getTitle();
         mTitleTextView.setText(title);
    }

    private final View.OnCreateContextMenuListener mOnCreateContextMenuListener = new View.OnCreateContextMenuListener() {
        @Override
        public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
            if (mData!= null) {
                MenuItem myActionItem = menu.add("My Context Action");
                myActionItem.setOnMenuItemClickListener(mOnMyActionClickListener);
            }
        }
    };

    private final MenuItem.OnMenuItemClickListener mOnMyActionClickListener = new MenuItem.OnMenuItemClickListener() {
        @Override
        public boolean onMenuItemClick(MenuItem item) {
            //todo: process item click, mData is available here!!!
            return true;
        }
    };
}
Valeriy Katkov
sumber
1
Jelaskan dengan jelas, apa yang dilakukan cuplikan kode Anda dan bagaimana caranya. Hanya kode yang disalin tidak cukup, bahkan jika itu bermanfaat.
peterh - Pulihkan Monica
Ini tampaknya merupakan kompromi yang wajar jika Anda tidak ingin membuat subkelas khusus RecyclerViewhanya untuk ditimpa getContextMenuInfo, dll., Meskipun tidak seefisien membiarkan fragmen / aktivitas menangani klik. Pendengar akan memiliki akses ke data di pemegang, jadi Anda tidak perlu posisi. Dan secara teoritis Anda dapat menyimpan posisi setelah mengikat di adaptor Anda, dan menggunakan delegasi untuk memanggil pemegang Anda jika Anda harus, meskipun menggunakan Contextdari salah satu tampilan terikat terkadang sudah cukup.
qix
10

@ Jawaban Renaud berhasil untuk saya tetapi memerlukan beberapa perbaikan kode terlebih dahulu. Sepertinya dia memposting potongan dari beberapa iterasi berbeda dari kodenya. Perubahan yang perlu dilakukan adalah:

  • RecyclerContextMenuInfodan RecyclerViewContextMenuInfomerupakan kelas yang sama. Pilih nama dan pertahankan.
  • The ViewHolderharus menerapkan View.OnLongClickListener, dan ingat untuk memanggil setOnLongClickListener()pada item dalam konstruktor.
  • Di onLongClick()pendengar, getView().showContextMenu()benar-benar salah. Anda harus memanggil showContextMenuForChild()Anda ContextMenuRecyclerView, jika tidak, ContextMenuInfoAnda masuk onCreateContextMenu()dan onContextItemSelected()akan menjadi nol.

Kode yang saya edit di bawah ini:

ContextMenuRecyclerView:

public class ContextMenuRecyclerView extends RecyclerView {

    private RecyclerViewContextMenuInfo mContextMenuInfo;

    @Override
    protected ContextMenu.ContextMenuInfo getContextMenuInfo() {
        return mContextMenuInfo;
    }

    @Override
    public boolean showContextMenuForChild(View originalView) {
        final int longPressPosition = getChildPosition(originalView);
        if (longPressPosition >= 0) {
            final long longPressId = getAdapter().getItemId(longPressPosition);
                mContextMenuInfo = new RecyclerViewContextMenuInfo(longPressPosition, longPressId);
            return super.showContextMenuForChild(originalView);
        }
        return false;
    }

    public static class RecyclerViewContextMenuInfo implements ContextMenu.ContextMenuInfo {

        public RecyclerViewContextMenuInfo(int position, long id) {
            this.position = position;
            this.id = id;
        }

        final public int position;
        final public long id;
    }
}

Dalam fragmen Anda:

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    mRecyclerView = view.findViewById(R.id.recyclerview);
    registerForContextMenu(mRecyclerView);
}

@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
    super.onCreateContextMenu(menu, v, menuInfo);
    // inflate menu here
    // If you want the position of the item for which we're creating the context menu (perhaps to add a header or something):
    int itemIndex = ((ContextMenuRecyclerView.RecyclerViewContextMenuInfo) menuInfo).position;
}

@Override
public boolean onContextItemSelected(MenuItem item) {
    ContextMenuRecyclerView.RecyclerViewContextMenuInfo info = (ContextMenuRecyclerView.RecyclerViewContextMenuInfo) item.getMenuInfo();
    // handle menu here - get item index or ID from info
    return super.onContextItemSelected(item);
}

Di ViewHolder Anda:

class MyViewHolder extends RecyclerView.ViewHolder implements View.OnLongClickListener {

    public MyViewHolder( View itemView ) {
        super( itemView );
        itemView.setOnLongClickListener( this );
    }

    @Override public boolean onLongClick() {
        recyclerView.showContextMenuForChild( v );
        return true;
    }
}

Juga, pastikan Anda mengganti RecyclerViewdengan ContextMenuRecyclerViewdalam tata letak Anda!

josh2112
sumber
1
Terima kasih @ josh2112 karena telah menunjukkan kesalahan ketik kepada saya, saya baru saja memperbaikinya - TAPI terkait poin terakhir Anda, Anda dapat menggantinya recyclerView.showContextMenuForChild(itemView);dengan itemView.showContextMenu().
Renaud Cerrato
1
Penting juga: saat memperluas RecyclerView ke ContextMenuRecyclerView, jangan lupa untuk MENAMBAHKAN KONSTRUKTOR yang disarankan oleh IDE. Secara khusus, jika Anda tidak mengimplementasikan konstruktor dua argumen yang menggunakan Context dan AttributeSet, Android tidak akan bisa memekarkan XML tata letak Anda.
lidkxx
5

Berikut adalah cara bersih untuk menggunakan konteks menu pada item RecyclerView

Pertama, Anda membutuhkan posisi barang

Di kelas Adaptor:

 /**
 * Custom on long click item listener.
 */
onLongItemClickListener mOnLongItemClickListener;

public void setOnLongItemClickListener(onLongItemClickListener onLongItemClickListener) {
    mOnLongItemClickListener = onLongItemClickListener;
}

public interface onLongItemClickListener {
    void ItemLongClicked(View v, int position);
}

Dalam onBindViewHolderkaitannya dengan pendengar khusus:

        // Hook our custom on long click item listener to the item view.
        holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                if (mOnLongItemClickListener != null) {
                    mOnLongItemClickListener.ItemLongClicked(v, position);
                }

                return true;
            }
        });

Dalam MainActivity (Activity / Fragment) buat bidang:

private int mCurrentItemPosition;

Di objek Adapter Anda, setel pendengar kustom:

    mAdapter.setOnLongItemClickListener(new FileAdapter.onLongItemClickListener() {
        @Override
        public void ItemLongClicked(View v, int position) {
            mCurrentItemPosition = position;
        }
    });

Sekarang Anda memiliki posisi yang enak untuk item apa pun yang telah lama Anda klik 😋

Kedua, buat menu Anda

Di res -> menu Buat file dengan item menu Anda context_menu_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/delete" android:title="Delete"/>
<item android:id="@+id/share" android:title="Share"/>
</menu>

Dalam MainActivity: Terapkan keduanya onCreateContextMenudan onContextItemSelected:

@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.context_menu_main, menu);
}

@Override
public boolean onContextItemSelected(MenuItem item) {
    int id = item.getItemId();
    if (id == R.id.delete) {

    }

    if (id == R.id.share) {

    }

    return true;
}

Ketiga, kembali ke objek Adaptor Anda

  1. Daftarkan menu konteks Anda.
  2. tampilkan menu konteks.

    registerForContextMenu(mRecyclerView);
    mAdapter.setOnLongItemClickListener(new FileAdapter.onLongItemClickListener() {
        @Override
        public void ItemLongClicked(View v, int position) {
            mCurrentItemPosition = position;
            v.showContextMenu();
        }
    });

Semoga saya tidak melupakan apa pun 🤔

Info lebih lanjut di Dokumentasi Menu

MohammadL
sumber
Terima kasih! Bagaimana cara mengirimkan data ke menu konteks? Misalnya, id item, teks item, dan sebagainya.
CoolMind
4

Berikut cara yang lebih sederhana untuk melakukannya dengan Kotlin yang berhasil untuk saya. Tantangan utamanya adalah mencari tahu posisi item yang ditekan. Di dalam adaptor Anda, Anda dapat menempatkan cuplikan kode ini dan itu akan dapat menangkap posisi item yang menu konteksnya ditampilkan; itu saja.

override fun onBindViewHolder(holder: YourViewHolder, position: Int) {

...     

    holder.view.setOnCreateContextMenuListener { contextMenu, _, _ -> 
            contextMenu.add("Add").setOnMenuItemClickListener {
                    longToast("I'm pressed for the item at position => $position")
                    true    
            }       
    }       

} 
Mickey Mouse
sumber
2
Ini adalah cara paling alami dan terkendali untuk melakukannya
nima
3

Saya mungkin terlambat ke pesta tetapi saya memiliki solusi yang berfungsi . Saya telah membuat intisari untuk itu.

Tambahkan Menu Konteks ke RecyclerView

ActivityName.java

//Import Statements

public class ActivityName extends AppCompatActivity {
    private RecyclerView mRecyclerView;
    private RecyclerView.Adapter mAdapter;
    private RecyclerView.LayoutManager mLayoutManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_view_birthdays);


        //Recycle View
        mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
        mLayoutManager = new LinearLayoutManager(getApplicationContext());
        mRecyclerView.setLayoutManager(mLayoutManager);
        mAdapter = new BirthdaysListAdapter(data, this);
        mRecyclerView.setAdapter(mAdapter);


    }

RecyclerAdapter.java

//Import Statements


public class BirthdaysListAdapter extends RecyclerView.Adapter<BirthdaysListAdapter.ViewHolder> {
    static Context ctx;

    private List<typeOfData> Data;


    public BirthdaysListAdapter(List<typeOfData> list, Context context) {
        Data = list;
        this.ctx = context;

    }

    BirthdaysListAdapter() {
    }

    public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnCreateContextMenuListener {
        public TextView name;
        public TextView Birthday;
        public ImageView colorAlphabet;
        public TextView textInImg;


        public ViewHolder(View v) {
            super(v);
            name = (TextView) v.findViewById(R.id.name);
            Birthday = (TextView) v.findViewById(R.id.Birthday);
            colorAlphabet = (ImageView) v.findViewById(R.id.colorAlphabet);
            textInImg = (TextView) v.findViewById(R.id.textInImg);


            v.setOnCreateContextMenuListener(this); //REGISTER ONCREATE MENU LISTENER
        }

        @Override
        public void onCreateContextMenu(ContextMenu menu, View v                         //CREATE MENU BY THIS METHOD
                                        ContextMenu.ContextMenuInfo menuInfo) {
            new BirthdaysListAdapter().info = (AdapterView.AdapterContextMenuInfo) menuInfo;
            MenuItem Edit = menu.add(Menu.NONE, 1, 1, "Edit");
            MenuItem Delete = menu.add(Menu.NONE, 2, 2, "Delete");
            Edit.setOnMenuItemClickListener(onEditMenu);
            Delete.setOnMenuItemClickListener(onEditMenu);


        }
//ADD AN ONMENUITEM LISTENER TO EXECUTE COMMANDS ONCLICK OF CONTEXT MENU TASK
        private final MenuItem.OnMenuItemClickListener onEditMenu = new MenuItem.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {


                DBHandler dbHandler = new DBHandler(ctx);
                List<WishMen> data = dbHandler.getWishmen();

                switch (item.getItemId()) {
                    case 1:
                        //Do stuff
                        break;

                    case 2:
                       //Do stuff

                        break;
                }
                return true;
            }
        };


    }


    public List<ViewBirthdayModel> getData() {
        return Data;
    }


    @Override
    public long getItemId(int position) {

        return super.getItemId(position);
    }


    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_view_birthdays, parent, false);
        ViewHolder vh = new ViewHolder(view);
        return vh;
    }

    @Override
    public void onBindViewHolder(final ViewHolder holder, int position) {
        holder.name.setText(Data.get(position).getMan().getName());
        holder.Birthday.setText(Data.get(position).getMan().getBday());
        holder.colorAlphabet.setBackgroundColor(Color.parseColor(Data.get(position).getColor()));
        holder.textInImg.setText(String.valueOf(Data.get(position).getMan().getName().toUpperCase().charAt(0)));
           }


    @Override
    public int getItemCount() {
        return Data.size();
    }

    private int position;

    public int getPosition() {

        return position;
    }

    public void setPosition(int position) {
        this.position = position;
    }

}
Gaurav Sharma
sumber
3

Saya telah menggabungkan solusi saya dengan solusi dari @Hardik Shah:

Dalam aktivitas saya memiliki:

@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
    super.onCreateContextMenu(menu, v, menuInfo);
    if (v.getId() == R.id.rvQuests) {
        getMenuInflater().inflate(R.menu.list_menu, menu);
    }
}

Di Adaptor saya punya:

private MainActivity context;
private int position;

public int getPosition() {
    return position;
}

public void setPosition(int position) {
    this.position = position;
}

public QuestsAdapter(MainActivity context, List<Quest> objects) {
    this.context = context;
    this.quests.addAll(objects);
}

public class QuestViewHolder extends RecyclerView.ViewHolder {
    private QuestItemBinding questItemBinding;

    public QuestViewHolder(View v) {
        super(v);
        questItemBinding = DataBindingUtil.bind(v);
        v.setOnCreateContextMenuListener(context);
    }
}

@Override
public void onBindViewHolder(final QuestViewHolder holder, int position) {
    Quest quest = quests.get(position);
    holder.questItemBinding.setQuest(quest);
    holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View v) {
            setPosition(holder.getAdapterPosition());
            return false;
        }
    });
}

@Override
public void onViewRecycled(QuestViewHolder holder) {
    holder.itemView.setOnLongClickListener(null);
    super.onViewRecycled(holder);
}

Dalam fragmen saya memiliki:

@Override
public boolean onContextItemSelected(MenuItem item) {
    int position = ((QuestsAdapter) questsList.getAdapter()).getPosition();
    switch (item.getItemId()) {
        case R.id.menu_delete:
            Quest quest = questsAdapter.getItem(position);
            App.getQuestManager().deleteQuest(quest);
            questsAdapter.remove(quest);
            checkEmptyList();
            return true;
        default:
            return super.onContextItemSelected(item);
    }
}
Himpunan
sumber
1

Halo teman-teman, keluar dengan satu alternatif yang cocok untuk saya. Saya baru saja mendaftarkan itemView saya dengan registerContextMenu dan Konstruktor ViewHolder, juga menyetel onLongClikcListener ke View yang sama. Dalam implementasi onLongClick (View v), saya cukup mendapatkan posisi diklik dengan getLayoutPosition () dan menyimpan dalam variabel instan (saya membuat kelas untuk mewakili data ini, seperti ContextMenuInfo diharapkan berfungsi), tetapi yang lebih penting adalah membuat yakin Anda mengembalikan false dalam metode ini. Yang harus Anda lakukan sekarang adalah di onContextItemSelected (item MenuItem), baca data yang Anda simpan di variabel instance Anda dan jika valid, lanjutkan dengan tindakan Anda. Ini cuplikannya.

  public MyViewHolder(View itemView){
super(itemView);
registerForContextMenu(itemView);
itemView.setOnLongClickListener(this);
}

Saya membuat ViewHolder mengimplementasikan OnLongClickListener, tetapi Anda dapat melakukannya dengan cara apa pun yang Anda inginkan.

@Override
public boolean onLongClick(View v){
    mCurrentLongItem = new ListItemInfo(v.getId(), getLayoutPosition());
    return false; // REMEMBER TO RETURN FALSE.
  }

Anda juga dapat menyetel ini di adaptor, atau ke Tampilan lain yang Anda miliki di ViewHolder (yaitu TextView). Yang penting adalah implementasi onLongClik ().

@Override
public boolean onContextItemSelected(MenuItem item) {
    switch (item.getItemId()){
        case R.id.client_edit_context_menu:
            if(mCurrentLongItem != null){
                 int position = mCurrentLongItem.position;
                //TAKE SOME ACTIONS.
                mCurrentLongItem = null;
            }
            return true;
    }
    return super.onContextItemSelected(item);
}

Bagian terbaiknya adalah Anda masih bisa memproses kejadian LongClick yang mengembalikan true dalam kasus yang Anda inginkan, dan conextMenu tidak akan muncul.

Metode ini berfungsi karena registerForContextView membuat View LongClickable, dan saat waktunya memproses ContextMenu, sistem akan memanggil performLongClick, yang pertama-tama memanggil implementasi onLongClick, dan jika menampilkan false, maka sistem akan memanggil showContextMenu.

Raziel 25
sumber
1

Saya telah menggunakan solusi ini untuk beberapa waktu sekarang dan telah bekerja cukup baik untuk saya.

public class CUSTOMVIEWNAME extends RecyclerView { 

public CUSTOMVIEWNAME(Context context) {
    super(context);
}

public CUSTOMVIEWNAME (Context context, AttributeSet attrs) {
    super(context, attrs);
}

public CUSTOMVIEWNAME (Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
}

private RecyclerContextMenuInfo mContextMenuInfo;

@Override
protected ContextMenu.ContextMenuInfo getContextMenuInfo() {
    return mContextMenuInfo;
}

@Override
public boolean showContextMenuForChild(View originalView) {
    final int longPressPosition = getChildAdapterPosition(originalView);
    if (longPressPosition >= 0) {
        final long longPressId = getAdapter().getItemId(longPressPosition);
        mContextMenuInfo = new RecyclerContextMenuInfo(longPressPosition,    `           longPressId);
        return super.showContextMenuForChild(originalView);
    }
    return false;
}

public class RecyclerContextMenuInfo implements ContextMenu.ContextMenuInfo             {

    public RecyclerContextMenuInfo(int position, long id) {
        this.position = position;
        this.id = id;
    }

    final public int position;
    final public long id;
}
}

Sekarang di fragmen atau Aktivitas Anda, terapkan metode berikut.

  @Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
    super.onCreateContextMenu(menu, v, menuInfo);

    // Inflate Menu from xml resource
    MenuInflater menuInflater = getMenuInflater();
    menuInflater.inflate(R.menu.context_menu, menu);
}

@Override
public boolean onContextItemSelected(MenuItem item) {
    ContextMenuRecyclerView.RecyclerContextMenuInfo info = (ContextMenuRecyclerView.RecyclerContextMenuInfo) item.getMenuInfo();
    Toast.makeText(InstanceOfContext , " User selected  " + info.position, Toast.LENGTH_LONG).show();

    return false;
}

Akhirnya Daftarkan ke contextMenu di recyclerview

   //for showing a popup on LongClick of items in recycler.
    registerForContextMenu(recyclerView);

Seharusnya itu berhasil!

Rakesh Gopathi
sumber
1

Berikut adalah cara mengimplementasikan menu konteks untuk RecyclerView, dan mendapatkan posisi item, yang item menu konteksnya telah dipilih:

public class YourAdapter extends RecyclerView.Adapter<YourAdapter.ViewHolder> {

... 

@Override
public void onBindViewHolder(@NonNull final ViewHolder viewHolder, int position) {

    ...

    viewHolder.itemView.setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() {
        @Override
        public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
            menu.add(0, R.id.mi_context_disable, 0, R.string.text_disable)
                    .setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
                        @Override
                        public boolean onMenuItemClick(MenuItem item) {
                            // can do something with item at position given below,
                            // viewHolder is final
                            viewHolder.getAdapterPosition();
                            return true;
                        }
                    });
            menu.add(0, R.id.mi_context_remove, 1, R.string.text_remove)
                    .setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
                        @Override
                        public boolean onMenuItemClick(MenuItem item) {                                
                            // can do something with item at position given below,
                            // viewHolder is final
                            viewHolder.getAdapterPosition();
                            return true;
                        }
                    });
        }
    });
}

static class ViewHolder extends RecyclerView.ViewHolder {
    private View itemView;

    private ViewHolder(@NonNull View itemView) {
        super(itemView);
        this.itemView = itemView;
    }
}

}

B-GangsteR
sumber
1

Solusi bagi yang ingin mendapatkan id item saat menelepon ContextMenu.

Jika Anda memiliki RecyclerViewdengan item seperti ini (mengandung dapat diklik ImageView):

daftar

maka Anda akan menerima panggilan balik dari onClickListener.

Adaptor

class YourAdapter(private val contextMenuCallback: ContextMenuCallback) :
    RecyclerView.Adapter<YourAdapter.ViewHolder>() {

    private var items: MutableList<Item> = mutableListOf()

    ...

    override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
        val item = items[position] as Item
        updateItem(viewHolder, item)

        setOnClickListener(viewHolder.itemView, items[position].id, items[position].title)
    }

    private fun setOnClickListener(view: View, id: Int, title: String) {
//        view.setOnClickListener { v ->  }
        // A click listener for ImageView `more`.
        view.more.setOnClickListener {
            // Here we pass item id, title, etc. to Fragment.
            contextMenuCallback.onContextMenuClick(view, id, title)
        }
    }


    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val titleTextView: TextView = itemView.title
    }

    class Item(
        val id: Int,
        val title: String
    )

    interface ContextMenuCallback {
        fun onContextMenuClick(view: View, id: Int, title: String)
    }
}

Pecahan

class YourFragment : Fragment(), YourAdapter.ContextMenuCallback {

    private var adapter: YourAdapter? = null
    private var linearLayoutManager: LinearLayoutManager? = null
    private var selectedItemId: Int = -1
    private lateinit var selectedItemTitle: String


    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        adapter = YourAdapter(this)
        view.recycler_view.apply {
            layoutManager = linearLayoutManager
            adapter = this@YourFragment.adapter
            setHasFixedSize(true)
        }

        registerForContextMenu(view.recycler_view)
    }

    override fun onCreateContextMenu(menu: ContextMenu?, v: View?,
                                     menuInfo: ContextMenu.ContextMenuInfo?) {
        activity?.menuInflater?.inflate(R.menu.menu_yours, menu)
    }

    override fun onContextItemSelected(item: MenuItem?): Boolean {
        super.onContextItemSelected(item)
        when (item?.itemId) {
            R.id.action_your -> yourAction(selectedItemId, selectedItemTitle)
            ...
        }
        return true
    }

    override fun onContextMenuClick(view: View, id: Int, title: String) {
        // Here we accept item id, title from adapter and show context menu.
        selectedItemId = id
        selectedItemTitle = title
        view.showContextMenu()
    }
}

Peringatan!

Jika Anda menggunakan ViewPagerberdasarkan satu fragmen (semua halaman adalah daftar serupa), Anda akan menghadapi masalah. Saat Anda menimpa onContextItemSelecteduntuk memahami item menu apa yang dipilih, Anda akan mendapatkan id item daftar dari halaman pertama! Untuk mengatasi masalah ini, lihat Fragmen yang salah di ViewPager menerima panggilan onContextItemSelected .

CoolMind
sumber
0

Saya telah berjuang dalam hal ini karena Android tidak menangani ini dengan baik untuk saya di RecyclerView, yang bekerja sangat baik untuk ListView.

Bagian yang paling sulit adalah bagian ContextMenuInfo disematkan di dalam Tampilan, yang tidak dapat Anda lampirkan dengan mudah selain menimpa Tampilan.

Jadi, Anda memerlukan pembungkus yang membantu Anda mengirimkan info posisi ke Aktivitas.

public class RecyclerContextMenuInfoWrapperView extends FrameLayout {
private RecyclerView.ViewHolder mHolder;
private final View mView;

public RecyclerContextMenuInfoWrapperView(View view) {
    super(view.getContext());
    setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
    mView = view;
    addView(mView);
}

public void setHolder(RecyclerView.ViewHolder holder) {
    mHolder = holder;
}

@Override
protected ContextMenu.ContextMenuInfo getContextMenuInfo() {
    return new RecyclerContextMenuInfo(mHolder.getPosition(), mHolder.getItemId());
}

public static class RecyclerContextMenuInfo implements ContextMenu.ContextMenuInfo {

    public RecyclerContextMenuInfo(int position, long id) {
        this.position = position;
        this.id = id;
    }

    final public int position;
    final public long id;
}

}

Kemudian di RecyclerAdapter, saat Anda membuat ViewHolders, Anda perlu menyetel Wrapper sebagai tampilan root, dan mendaftarkan contextMenu pada setiap tampilan.

public static class AdapterViewHolder extends RecyclerView.ViewHolder {
    public AdapterViewHolder(  View originalView) {
        super(new RecyclerContextMenuInfoWrapperView(originalView);
        ((RecyclerContextMenuInfoWrapperView)itemView).setHolder(this);
        yourActivity.registerForContextMenu(itemView);
        itemView.setOnCreateContextMenuListener(yourListener);
    }

}

Dan terakhir, dalam Aktivitas Anda, Anda akan dapat melakukan apa yang biasanya Anda lakukan:

@Override
public boolean onContextItemSelected(MenuItem item) {
    int position = ((RecyclerContextMenuInfoWrapperView.RecyclerContextMenuInfo)item.getMenuInfo()).position;
    // do whatever you need as now you have access to position and id and everything
Zoro
sumber
0

Yang terbaik adalah menggunakan menu Konteks dengan tampilan pendaur ulang adalah jika Anda membuat tampilan pendaur ulang khusus dan menimpa getContextMenuInfo()metode dan mengembalikan instance Anda sendiri dari objek info menu Konteks sehingga Anda dapat mengambil posisi saat dibuat dan saat menu diklik:

@Override
protected ContextMenu.ContextMenuInfo getContextMenuInfo() {
    return mContextMenuInfo;
}

Lihatlah inti yang telah saya buat ini:

https://gist.github.com/resengupta/2b2e26c949b28f8973e5

ReeSen
sumber
0

Memperluas beberapa jawaban di atas sedikit, jika Anda ingin menghindari mendefinisikan menu secara manual dalam kode Anda di Adapter / ViewHolder, maka Anda dapat menggunakan PopupMenu dan memekarkan opsi menu dari file sumber menu.xml standar.

Contoh di bawah menunjukkan ini termasuk kemampuan untuk meneruskan pemroses yang bisa Anda terapkan di Fragmen / Aktivitas untuk merespons klik menu konteks.

public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder> {

private List<CustomObject> objects;
private OnItemSelectedListener listener;
private final boolean withContextMenu;

class ViewHolder extends RecyclerView.ViewHolder
        implements View.OnClickListener, View.OnCreateContextMenuListener, PopupMenu.OnMenuItemClickListener {

    @BindView(R.id.custom_name)
    TextView name;

    @BindView(R.id.custom_value)
    TextView value;

    ViewHolder(View view) {
        super(view);
        ButterKnife.bind(this, view);
        view.setOnClickListener(this);
        if (withContextMenu) {
            view.setOnCreateContextMenuListener(this);
        }
    }

    @Override
    public void onClick(View v) {
        int position = getAdapterPosition();
        if (listener != null) {
            listener.onCustomerSelected(objects.get(position));
        }
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
        PopupMenu popup = new PopupMenu(v.getContext(), v);
        popup.getMenuInflater().inflate(R.menu.custom_menu, popup.getMenu());
        popup.setOnMenuItemClickListener(this);
        popup.show();
    }

    @Override
    public boolean onMenuItemClick(MenuItem item) {
        if (listener != null) {
            CustomObject object = objects.get(getAdapterPosition());
            listener.onCustomerMenuAction(object, item);
        }
        return false;
    }
}

public CustomerAdapter(List<CustomObject> objects, OnItemSelectedListener listener, boolean withContextMenu) {
    this.listener = listener;
    this.objects = objects;
    this.withContextMenu = withContextMenu;
}

public interface OnItemSelectedListener {

    void onSelected(CustomObject object);

    void onMenuAction(CustomObject object, MenuItem item);
}

@Override
public CustomerAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.snippet_custom_object_line, parent, false);
    return new ViewHolder(v);
}

@Override
public void onBindViewHolder(CustomAdapter.ViewHolder holder, int position) {
    CustomObject object = objects.get(position);
    holder.name.setText(object.getName());
    holder.value.setText(object.getValue());
}

@Override
public int getItemCount() {
    return objects.size();
}
}

Inti lengkapnya di sini https://gist.github.com/brettwold/45039b7f02ce752ae0d32522a8e2ad9c

Brett Cherrington
sumber
0

Anda bisa meneruskan OnCreateContextMenuListener ke ViewHolder saat bind. Listener ini dapat membuat menu kustom untuk setiap item data. Cukup tambahkan setOnCreateContextMenuListener di ViewHolder Anda dan panggil selama pengikatan.

     public static class ItemViewHolder extends RecyclerView.ViewHolder
     {


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


        }
        void setOnCreateContextMenuListener(View.OnCreateContextMenuListener listener) {
            itemView.setOnCreateContextMenuListener(listener);
        }

}

Di adaptor:

      @Override
     public void onBindViewHolder(ItemViewHolder viewHolder,
                    int position) {
         final MyObject myObject = mData.get(position);
         viewHolder.setOnCreateContextMenuListener(new OnCreateContextMenuListener(){

                    @Override
                    public void onCreateContextMenu(ContextMenu menu,
                            View v, ContextMenuInfo menuInfo) {
                        switch (myObject.getMenuVariant() {
                            case MNU_VARIANT_1:
                                menu.add(Menu.NONE, CTX_MNU_1, 
                                        Menu.NONE,R.string.ctx_menu_item_1);    
                                menu.add(Menu.NONE, CTX_MNU_2,Menu.NONE, R.string.ctx_menu_item_2); 
                            break;
                            case MNU_VARIANT_2:
                                menu.add(Menu.NONE, CTX_MNU_3,Menu.NONE, R.string.ctx_menu_item_3); 
                            break;
                            default:
                                menu.add(Menu.NONE, CTX_MNU_4, 
                                        Menu.NONE, R.string.ctx_menu_item_4);   

                        }
                    }

                });
     }
Alexey Usmanov
sumber
0

Dalam kasus saya, saya harus menggunakan data dari fragmen saya dalam onContextItemSelected()metode ini. Solusi yang akhirnya saya lakukan adalah meneruskan instance fragmen ke adaptor saya dan mendaftarkan item tampilan di view holder:

@Override
public void onBindViewHolder(final MyListAdapter.ViewHolder viewHolder, int position) {
    final Object rowObject = myListItems.get(position);

    // Do your data binding here

    viewHolder.itemView.setTag(position);
    fragment.registerForContextMenu(viewHolder.itemView);
}

Kemudian onCreateContextMenu()Anda dapat menyimpan indeks ke variabel lokal:

selectedViewIndex = (int)v.getTag();

dan mengambilnya kembali onContextItemSelected()

Eric B.
sumber
0

Pertama kali saya mengalami masalah ini dengan adaptor normal, saya akhirnya membuat subkelas View kustom saya sendiri dan menyimpan hal-hal yang saya butuhkan di dalamnya. Saya benar-benar tidak menyukai solusi itu dan menghabiskan banyak waktu untuk melihat ide-ide hebat yang telah diusulkan orang, dan memutuskan bahwa saya tidak menyukainya lebih baik. Jadi saya mengumpulkan semuanya, mengguncangnya sebentar, dan keluar dengan sesuatu yang baru yang saya suka.

Kami mulai dengan beberapa kelas utilitas. ContextMenuHandler adalah antarmuka untuk objek apa pun yang akan menangani menu konteks. Dalam praktiknya, ini akan menjadi subkelas ViewHolder, tetapi secara teori bisa jadi apa saja

/**
 * Interface for objects that wish to create and handle selections from a context
 * menu associated with a view
 */
public interface ContextMenuHandler extends View.OnCreateContextMenuListener {

  boolean onContextItemSelected(MenuItem item);
}

Berikutnya adalah Antarmuka yang harus diimplementasikan oleh Tampilan apa pun yang akan digunakan sebagai turunan langsung dari RecyclerView.

public interface ViewWithContextMenu {
  public void setContextMenuHandler(FragmentWithContextMenu fragment, ContextMenuHandler handler);

  public ContextMenuHandler getContextMenuHandler();
}

Selanjutnya, setiap tampilan yang akan membuat menu konteks sebagai anak dari RecylcerView harus mengimplementasikan ViewWIthContextMenu. Dalam kasus saya, saya hanya membutuhkan subclass LinearLayout.

public class LinearLayoutWithContextMenu extends LinearLayout implements ViewWithContextMenu {

  public LinearLayoutWithContextMenu(Context context) {
    super(context);
   }

  public LinearLayoutWithContextMenu(Context context, AttributeSet attrs) {
    super(context, attrs);
  }

  private ContextMenuHandler handler;

  @Override
  public void setContextMenuHandler(FragmentWithContextMenu fragment, ContextMenuHandler handler) {
    this.handler = handler;
    setOnCreateContextMenuListener(fragment);
  }

  @Override
  public ContextMenuHandler getContextMenuHandler() {
    return handler;
  }
}

Dan terakhir, kita membutuhkan kelas Fragment yang telah ditingkatkan untuk mencegat panggilan menu konteks dan mengarahkannya ke penangan yang sesuai.

public class FragmentWithContextMenu extends Fragment {

  ContextMenuHandler handler = null;

  @Override
  public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
    super.onCreateContextMenu(menu, view, menuInfo);
    handler = null;
    if (view instanceof ViewWithContextMenu) {
      handler = ((ViewWithContextMenu)view).getContextMenuHandler();
      if (handler != null) handler.onCreateContextMenu(menu, view, menuInfo);
    }
  }

  @Override
  public boolean onContextItemSelected(MenuItem item) {
    if (handler != null) {
      if (handler.onContextItemSelected(item)) return true;
    }
    return super.onContextItemSelected(item);
  }
}

Dengan semua ini di tempat, implementasi akhir cukup sederhana. Fragmen utama harus subkelas FragmentWithContextMenu. Ini mengatur RecylerWindow utama secara normal dan meneruskan dirinya sendiri ke subkelas Adapter. Subkelas Adaptor terlihat seperti

public class Adapter extends RecyclerView.Adapter<Adapter.ViewHolder> {

  private final FragmentWithContextMenu fragment;

  Adapter(FragmentWithContextMenu fragment) {
    this.fragment = fragment;
  }

  @Override
  public Adapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(context)
        .inflate(R.layout.child_view, parent, false);
    return new ViewHolder(view);
  }

  @Override
  public void onBindViewHolder(final Adapter.ViewHolder holder, int position) {
    // Logic needed to bind holder to specific position
    // ......
  }

  @Override
  public int getItemCount() {
    // Logic to return current item count
    // ....
  }

  public class ViewHolder extends RecyclerView.ViewHolder implements ContextMenuHandler {

    ViewHolder(View view) {
      super(view);
      ((ViewWithContextMenu)view).setContextMenuHandler(fragment, this);

      view.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {

          // Do stuff to handle simple clicks on child views
          // .......
        }
      });
    }

   @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {

      // Logic to set up context menu goes here
      // .... 
    }

    @Override
    public boolean onContextItemSelected(MenuItem item) {

      // Logic to handle context menu item selections goes here
      // ....

      return true;
    }
  }
}

Itu saja. Semuanya tampaknya berhasil. Itu meletakkan semua kelas utilitas dalam paket menu konteks terpisah sehingga saya bisa memberikan nama kelas yang cocok dengan kelas yang ada subclass, tapi saya pikir akan lebih membingungkan.

kencorbin.dll
sumber
-1

Ok, berdasarkan jawaban @ Flexo, mPosition akan saya pesan ...

protected class ExampleViewHolder extends RecyclerView.ViewHolder implements View.OnCreateContextMenuListener {

    int mPosition;

    public KWViewHolder(View itemView) {
        super(itemView);
        itemView.setOnCreateContextMenuListener(this);
    }

    public void setPosition(int position) {
        mPosition = position;
    }

    @Override
    public void onCreateContextMenu(ContextMenu contextMenu, View view, ContextMenu.ContextMenuInfo contextMenuInfo) {
        contextMenu.setHeaderTitle(R.string.menu_title_context);
        contextMenu.add(0, R.id.menu_delete, mPosition, R.string.delete);
    }
}

lalu di onContextItemSelected saya gunakan

item.getOrder() 

Dan semua bekerja dengan baik saya mendapatkan posisi array dengan mudah

windX
sumber