Ручка на элементе, длинный щелчок по просмотру ресайклера

У меня есть адаптер, который настраивает recyclerView, и я хочу открыть всплывающее меню при длительном щелчке по элементам recyclerView. Как я могу это сделать?


person Marco Di Munno    schedule 06.05.2015    source источник
comment
возможный дубликат Как создать контекстное меню для RecyclerView   -  person Ben N    schedule 06.05.2015


Ответы (4)


На этот вопрос уже был дан ответ здесь. Во всяком случае, вы можете сделать это так:

class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
    private Article article;

    private TextView nameTextView;

    public ViewHolder(View itemView) {
        super(itemView);
        itemView.setOnClickListener(this);
        itemView.setOnLongClickListener(this);
        nameTextView = (TextView) itemView.findViewById(R.id.grid_item_article_name_textView);
    }

    public void bind(Article article) {
        this.article = article;
        nameTextView.setText(article.getName());
    }

    @Override
    public void onClick(View view) {
        // Context context = view.getContext();
        // article.getName()
    }

    @Override
    public boolean onLongClick(View view) {
        // Handle long click
        // Return true to indicate the click was handled
        return true;
    }
}

Обновление: если вы используете Kotlin, сделайте следующее:

inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), 
    View.OnClickListener, View.OnLongClickListener {

    init {
        itemView.setOnClickListener(this)
        itemView.setOnLongClickListener(this)
    }

    private lateinit var article: Article

    private val titleTextView: TextView = itemView.findViewById(R.id.item_article_title_textView)

    fun bind(article: Article) {
        this.article = article
        titleTextView.text = article.title
    }

    override fun onClick(view: View) {
        listener.onItemClick(article)
    }

    override fun onLongClick(view: View): Boolean {
        Toast.makeText(view.context, "long click", Toast.LENGTH_SHORT).show()
        // Return true to indicate the click was handled
        return true
    }
}
person Albert Vila Calvo    schedule 11.11.2015
comment
Вы должны перевести слушателя в Viewholder, но это все же намного проще, чем все прямые разрешения, добавляющие TouchListeners в RecylerView. - person DSchmidt; 20.10.2018

Я сделал таким образом:

static class ViewHolder extends RecyclerView.ViewHolder {
    TextView tvName;

    ViewHolder(View v) {
        super(v);
        tvName = (TextView) v.findViewById(R.id.textView_Username);
        //Single Tapup
        v.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(v.getContext(), "Position is " + getAdapterPosition(), Toast.LENGTH_SHORT).show();
            }
        });

        //Long Press
        v.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                Toast.makeText(v.getContext(), "Position is " + getAdapterPosition(), Toast.LENGTH_SHORT).show();
                return false;
            }
        });
    }
}
person Däñish Shärmà    schedule 09.02.2016
comment
Это был самый простой способ, который работал для меня! (Я использую RecyclerView с ItemTouchHelper для удаления элемента из представления, а также для обработки значений с помощью длинного щелчка.) Спасибо!!! - person Jimmy; 26.11.2019

Сначала вам нужно зарегистрировать свою активность для прослушивания событий longClick из recyclerView (поэтому вам не нужно использовать какие-либо onLongClickListener...):

registerForContextMenu(recyclerView);

Затем вы создаете ресурс меню (context_menu.xml):

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:title="Mostra documento" android:id="@+id/context_menu_documents_fragment_view"></item>
    <item android:title="Aggiungi ad un contenitore" android:id="@+id/context_menu_documents_fragment_add_to_box"></item>
    <item android:title="Elimina documento" android:id="@+id/context_menu_documents_fragment_delete"></item>
</menu>

В действии, где вы зарегистрировались для контекстного меню, вы переопределяете эти методы:

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

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

    @Override
    public boolean onContextItemSelected(MenuItem item) {

        Toast.makeText(getActivity(), " User selected something ", Toast.LENGTH_LONG).show();


        return false;
    }

Это очень важно, вы должны изменить код в вашем адаптере RecyclerView следующим образом:

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

        ...
        viewHolder.itemView.setLongClickable(true);
        ...
    }

Теперь вы можете показывать контекстное меню и перехватывать выбор пользователя! Но вы не можете узнать, какой элемент щелкнул пользователь, для этого вам нужно использовать собственный RecyclerView, подобный этому (исходный код от Renaud Cerrato):

public class ContextMenuRecyclerView extends RecyclerView {

    private RecyclerContextMenuInfo mContextMenuInfo;



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

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

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

    @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 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;
    }

}

В предыдущем методе onContextItemSelected() вы можете узнать идентификатор и позицию элемента recyclerView, используя этот код:

ContextMenuRecyclerView.RecyclerContextMenuInfo info = (ContextMenuRecyclerView.RecyclerContextMenuInfo) item.getMenuInfo();

Наконец, вам нужно изменить метод getItemId() в вашем адаптере recyclerView и файле макета, чтобы убедиться, что вы используете свой recyclerView, а не Android!

person Mariusz Wiazowski    schedule 17.07.2015

Я изо всех сил пытался получить позицию элемента по клику, это сработало для меня:

public void onClick(View view) {
    ViewHolder holder =(ViewHolder)view.getTag();
    int position = holder.getLayoutPosition();
    Log.d("testing ","pos" +position);
}
person meera    schedule 07.12.2015
comment
int position = getAdapterPosition() вернет позицию выбранного элемента. - person subrahmanyam boyapati; 25.10.2016