Como faço para implementar o menu de contexto para RecyclerView?
Aparentemente, a chamada registerForContextMenu(recyclerView)
não funciona. Estou chamando de um fragmento. Alguém teve algum sucesso na implementação disso?
android
contextmenu
android-recyclerview
Binoy Babu
fonte
fonte
Respostas:
Você não pode implementar diretamente esses métodos como onClickListener , OnContextMenuListener etc. porque RecycleView estende android.view.ViewGroup . Portanto, não podemos usar diretamente esses métodos. Podemos implementar esses métodos na classe do adaptador ViewHolder . Podemos usar o menu de contexto no RecycleView desta forma:
Agora seguimos o mesmo procedimento ao implementar o menu de contexto.
Se você tiver alguma dificuldade, pergunte nos comentários.
fonte
onContextItemSelected
nível de atividade / fragmento.getTitle
funciona,getItemId
funciona, masgetMenuInfo
entrega nulo. Então, como obter oViewHolder
?getMenuInfo()
retorna nulo emonContextItemSelected()
. Talvez as pessoas que o fizeram funcionar tenham umonCreateContextMenu()
método em uma visão mais acima na hierarquia (oRecyclerView
ouFragment
)? Isso pode funcionar, mas nos leva a outras respostas a essa pergunta.menu.add(this.getAdapterPosition(), v.getId(), 0, "Call");
e, em seguida, em seu teste de método de retorno de chamadaitem.getGroupId()
para obter a posiçãoObrigado pela informação e comentários. Consegui alcançar
ContextMenu
para itens emRecyclerview
.Aqui está o que eu fiz
no
onViewCreated
método do Fragment ou noonCreate
método da Activity :Depois, em Adaptador, adicione
fazer a
ViewHolder
classe implementarOnCreateContextMenuListener
onBindViewHolder
método addOnLongClickListener
no holder.itemView para capturar a posição antes de o menu de contexto ser carregado:Em seguida,
onViewRecycled
remova o Listener para que não haja problemas de referência. (pode não ser necessário).Finalmente, em Fragment / Activity, substitua o
onContextItemSelected
como em:fonte
A resposta atual não está correta. Esta é uma implementação funcional:
Em seu fragmento (ou atividade):
E, finalmente, em seu ViewHolder:
fonte
getChildPosition()
está obsoleto agora. Eu usei em seugetChildAdapterPosition()
lugar.getChildPosition()
está obsoleto emcom.android.support:recyclerview-v7:22.0.0
.Experimente isso para um
View
item em recycleViewVocê pode usá-lo para definir dados para um
ViewHolder
itemfonte
A resposta de Prabhakar está correta, mas ele não explicou como obter um dado, relacionado ao item pressionado, quando um item do menu de contexto é selecionado. Podemos usar
onContextItemSelected
callback, masContextMenuInfo
não está disponível (null
) neste caso (se ogetContextMenuInfo()
método não for sobrescrito para uma visão pressionada). Portanto, a solução mais simples é adicionarOnMenuItemClickListener
diretamente aoMenuItem
.fonte
RecyclerView
apenas para substituirgetContextMenuInfo
etc., mesmo que não seja tão eficiente quanto permitir que o fragmento / atividade manipule cliques. Os ouvintes terão acesso aos dados no suporte, portanto, você não precisa de posição. E, teoricamente, você poderia armazenar em cache a posição ao vincular em seu adaptador de qualquer maneira e usar a delegação para chamar seu titular, se necessário, embora usarContext
de uma das visualizações vinculadas às vezes possa ser suficiente.A resposta de @Renaud funcionou para mim, mas primeiro exigiu várias correções de código. É como se ele postasse trechos de várias iterações diferentes de seu código. As mudanças que precisam ser feitas são:
RecyclerContextMenuInfo
eRecyclerViewContextMenuInfo
são da mesma classe. Escolha um nome e fique com ele.ViewHolder
deve implementarView.OnLongClickListener
e lembre-se de chamarsetOnLongClickListener()
o item no construtor.onLongClick()
ouvinte,getView().showContextMenu()
está completamente errado. Você deve chamarshowContextMenuForChild()
seuContextMenuRecyclerView
, caso contrário,ContextMenuInfo
você entraráonCreateContextMenu()
eonContextItemSelected()
será nulo.Meu código editado abaixo:
ContextMenuRecyclerView:
Em seu fragmento:
Em seu ViewHolder:
Além disso, certifique-se de substituir
RecyclerView
porContextMenuRecyclerView
em seu layout!fonte
recyclerView.showContextMenuForChild(itemView);
poritemView.showContextMenu()
.Esta é uma maneira limpa de usar o contexto do menu em itens RecyclerView
Primeiro, você precisa de uma posição de item
Na classe Adaptador:
No
onBindViewHolder
gancho do ouvinte personalizado:Em MainActivity (Activity / Fragment) crie um campo:
No objeto Adaptador, defina o ouvinte personalizado:
Segundo, crie seu menu
Em res -> menu Crie um arquivo contendo seu item de menu
context_menu_main.xml
:Em MainActivity: Implemente
onCreateContextMenu
eonContextItemSelected
:Terceiro, de volta ao seu objeto Adaptador
mostra o menu de contexto.
Mais informações em Menus Documentation
fonte
Esta é uma maneira mais simples de fazer isso com Kotlin que funcionou para mim. O maior desafio é descobrir a posição do item que foi pressionado. Dentro de seu adaptador, você pode colocar este trecho de código e ele será capaz de capturar a posição do item para o qual o menu de contexto é mostrado; Isso é tudo.
fonte
Combinei minha solução com a solução de @Hardik Shah:
Na atividade eu tenho:
No adaptador eu tenho:
No fragmento eu tenho:
fonte
Talvez chegue atrasado para a festa, mas tenho uma solução de trabalho . Eu fiz uma ideia para isso.
Adicionar Menu de Contexto ao RecyclerView
ActivityName.java
RecyclerAdapter.java
fonte
Olá pessoal saiu com uma alternativa que funciona para mim. Acabei de registrar meu itemView com registerContextMenu e o Construtor ViewHolder, também defini um onLongClikcListener para o mesmo View. Na implementação onLongClick (View v), eu simplesmente obtenho a posição clicada com getLayoutPosition () e salvo em uma variável de instância (criei uma classe para representar esses dados, assim como o ContextMenuInfo deve funcionar), mas o mais importante é fazer certifique-se de retornar falso neste método. Tudo o que você precisa fazer agora é onContextItemSelected (item MenuItem), ler os dados que você armazena em sua variável de instância e se forem válidos, você prossegue com suas ações. Aqui está um trecho.
Eu faço o ViewHolder implementar OnLongClickListener, mas você pode fazer da maneira que preferir.
Você também pode definir isso no adaptador ou em outra View que você tenha no ViewHolder (ou seja, uma TextView). O importante é a implementação onLongClik ().
A melhor parte é que você ainda pode processar o evento LongClick retornando true nos casos que desejar, e o conextMenu não aparecerá.
Este método funciona porque registerForContextView torna o View LongClickable e, quando é hora de processar o ContextMenu, o sistema chama performLongClick, que primeiro chama uma implementação onLongClick e, se retornar false, chama showContextMenu.
fonte
Eu uso essa solução há algum tempo e tem funcionado muito bem para mim.
Agora, em seu fragmento ou atividade, implemente os seguintes métodos.
Finalmente, registre-se no contextMenu na tela de reciclagem
Isso deve funcionar!
fonte
Aqui está como você pode implementar o menu de contexto para RecyclerView e obter a posição do item, para o qual o item do menu de contexto foi selecionado:
}
fonte
Uma solução para quem deseja obter a identificação do item ao ligar
ContextMenu
.Se você tiver um
RecyclerView
com itens como este (contendo clicáveisImageView
):então você deve receber callbacks de
onClickListener
.Adaptador
Fragmento
Aviso!
Se você usar um
ViewPager
baseado em um fragmento (todas as páginas são listas semelhantes), você enfrentará um problema. Quando você substituironContextItemSelected
para entender qual item de menu foi selecionado, você obterá uma identificação de item de lista na primeira página! Para superar esse problema, consulte Fragmento errado em ViewPager recebe chamada onContextItemSelected .fonte
Tenho lutado com isso porque o Android não lida bem com isso para mim no RecyclerView, que estava funcionando muito bem para o ListView.
A parte mais difícil é que a parte ContextMenuInfo está embutida dentro de uma View, que você não pode anexar facilmente a não ser sobrescrever a View.
Portanto, você precisará de um invólucro que o ajude a entregar as informações de posição para a Activity.
}
Então, em seu RecyclerAdapter, ao criar ViewHolders, você precisa definir o Wrapper como a visualização raiz e registrar contextMenu em cada visualização.
}
E, por último, em sua Atividade, você poderá fazer o que costuma fazer:
fonte
O melhor era usar o menu de contexto com a visão recicladora se você criar uma visão recicladora customizada e substituir o
getContextMenuInfo()
método e retornar sua própria instância do objeto de informações do menu de contexto para que você possa buscar posições quando ele foi criado e quando o menu é clicado:Dê uma olhada nesta essência que criei:
https://gist.github.com/resengupta/2b2e26c949b28f8973e5
fonte
Expandindo um pouco algumas das respostas acima, se quiser evitar definir manualmente o menu em seu código no Adapter / ViewHolder, você pode usar um PopupMenu e aumentar as opções de menu a partir de um arquivo de recurso menu.xml padrão.
O exemplo abaixo mostra isso, incluindo a capacidade de passar um ouvinte que você pode implementar em seu Fragmento / Atividade para responder a cliques no menu de contexto.
Síntese completa aqui https://gist.github.com/brettwold/45039b7f02ce752ae0d32522a8e2ad9c
fonte
Você pode passar OnCreateContextMenuListener para ViewHolder na ligação. Este ouvinte pode criar um menu personalizado para cada item de dados. Basta adicionar setOnCreateContextMenuListener em seu ViewHolder e chamá-lo durante a vinculação.
}
No adaptador:
fonte
No meu caso, tive que usar dados do meu fragmento no
onContextItemSelected()
método. A solução que acabei escolhendo foi passar uma instância do fragmento para meu adaptador e registrar o item de visualização no portador de visualização:Em seguida,
onCreateContextMenu()
você pode salvar o índice em uma variável local:selectedViewIndex = (int)v.getTag();
e recuperá-lo em
onContextItemSelected()
fonte
A primeira vez que tive esse problema com adaptadores normais, acabei criando minha própria subclasse de Visualização personalizada e armazenando o material de que precisava. Eu realmente não gostei dessa solução e passei muito tempo olhando as grandes ideias que as pessoas propuseram e decidi que não gostava mais delas. Então eu meio que juntei tudo, balancei por um tempo e criei algo novo que eu gosto.
Começamos com algumas classes de utilitários. ContextMenuHandler é uma interface para qualquer objeto que manipulará o menu de contexto. Na prática, esta será uma subclasse ViewHolder, mas em teoria pode ser qualquer coisa
Em seguida, está uma Interface que deve ser implementada por qualquer View que será usada como filho imediato de um RecyclerView.
Em seguida, qualquer visualização que criará um menu de contexto como filho de um RecylcerView deve implementar ViewWIthContextMenu. No meu caso, eu só precisava de uma subclasse de LinearLayout.
E, finalmente, precisamos de uma classe Fragment aprimorada para interceptar as chamadas do menu de contexto e redirecioná-las para o manipulador apropriado.
Com tudo isso instalado, a implementação final é muito simples. O fragmento principal deve ser subclasse FragmentWithContextMenu. Ele configura a RecylerWindow principal normalmente e passa para a subclasse Adapter. A subclasse Adapter parece
É sobre isso. Tudo parece estar funcionando. Ele colocou todas as classes de utilitários em um pacote de menu de contexto separado para que eu pudesse dar nomes às classes que correspondiam às classes que existem como subclasses, mas achei que seria mais confuso.
fonte
Ok, com base na resposta de @Flexo, irei colocar o mPosition em ordem ...
então em onContextItemSelected eu uso
E tudo funciona bem, eu obtenho a posição do array facilmente
fonte