De https://developer.android.com/preview/material/ui-widgets.html
Quando criamos RecyclerView.Adapter
, precisamos especificar ViewHolder
que será vinculado ao adaptador.
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private String[] mDataset;
public MyAdapter(String[] myDataset) {
mDataset = myDataset;
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView mTextView;
public ViewHolder(TextView v) {
super(v);
mTextView = v;
}
}
@Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.some_layout, parent, false);
//findViewById...
ViewHolder vh = new ViewHolder(v);
return vh;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.mTextView.setText(mDataset[position]);
}
@Override
public int getItemCount() {
return mDataset.length;
}
}
Então, é possível criar RecyclerView
com vários tipos de exibição?
Respostas:
Sim é possivel. Apenas implementar getItemViewType () , e cuidar do
viewType
parâmetroonCreateViewHolder()
.Então você faz algo como:
fonte
optionMenuItem
. Como é possível? @AntonSavinSe os layouts para os tipos de exibição forem apenas alguns e as lógicas de ligação forem simples, siga a solução da Anton.
Mas o código ficará confuso se você precisar gerenciar layouts complexos e lógicas de ligação.
Acredito que a solução a seguir será útil para alguém que precise lidar com tipos de exibição complexos.
Classe Base DataBinder
As funções necessárias para definir nesta classe são praticamente as mesmas da classe do adaptador ao criar o tipo de visualização única.
Para cada tipo de exibição, crie a classe estendendo este DataBinder.
Classe DataBinder de amostra
Para gerenciar as classes do DataBinder, crie a classe do adaptador.
Classe Base DataBindAdapter
Crie a classe estendendo essa classe base e instancie as classes do DataBinder e substitua os métodos abstratos
getItemCount
Retorna a contagem total de itens de DataBinders
getItemViewType
Defina a lógica de mapeamento entre a posição do adaptador e o tipo de visualização.
getDataBinder
Retorna a instância do DataBinder com base no tipo de exibição
getPosition
Defina a lógica de conversão na posição do adaptador a partir da posição no DataBinder especificado
getBinderPosition
Define a lógica de conversão para a posição no DataBinder a partir da posição do adaptador
Espero que esta solução seja útil.
Deixei uma solução e amostras mais detalhadas no GitHub, portanto, consulte o link a seguir, se necessário.
https://github.com/yqritc/RecyclerView-MultipleViewTypesAdapter
fonte
public class DataBinder<T extends RecyclerView.ViewHolder>
alguém pode me dizer o que<T someClass>
é chamado, para que eu possa pesquisar no google se eu conseguir o termo. Também quando digoabstract public class DataBinder<T extends RecyclerView.ViewHolder>
que isso significa que essa classe é do tipoViewHolder
, portanto, como resultado, toda classe que estende essa classe será do tipo,viewHolder
essa é a ideia?O abaixo não é um pseudocódigo e eu o testei e funcionou para mim.
Eu queria criar uma visão frontal na minha visão de reciclagem e exibir uma lista de imagens abaixo do cabeçalho, na qual o usuário pode clicar.
Eu usei algumas opções no meu código, não sei se essa é a maneira mais eficiente de fazer isso, então fique à vontade para fazer seus comentários:
fonte
Sim, é possível.
Escreva um detentor de vista genérico:
crie seus titulares de exibição e faça com que eles estendam o GenericViewHolder. Por exemplo, este:
a classe RecyclerView.Adapter se parecerá com esta:
fonte
Crie diferentes ViewHolder para diferentes layouts
O RecyclerView pode ter qualquer número de visualizadores que você desejar, mas para melhor legibilidade, vamos ver como criar um com dois ViewHolders.
public int getItemViewType(int position)
onCreateViewHolder()
método ViewTypeonBindViewHolder()
métodoAqui está um pequeno trecho de código
getItemViewType (int position) é a chave
Na minha opinião, o ponto de partida para criar esse tipo de recyclerView é o conhecimento desse método. Como esse método é opcional para substituir, portanto, não é visível na classe RecylerView por padrão, o que, por sua vez, faz com que muitos desenvolvedores (inclusive eu) se perguntem por onde começar. Depois que você souber que esse método existe, criar esse RecyclerView seria uma tarefa difícil.
Links relevantes:
Confira o projeto em que eu implementei isso
fonte
Sim, é possível. No seu adaptador, getItemViewType Layout como este ....
para link de referência: https://www.journaldev.com/12372/android-recyclerview-example
fonte
seguindo a solução da Anton, crie uma
ViewHolder
que retenha / manipule / delegue diferentes tipos de layouts. Mas não tenho certeza se o novo layout de substituição funcionaria quando a exibição de reciclagemViewHolder
não é o tipo de inserção de dados.Então, basicamente,
onCreateViewHolder(ViewGroup parent, int viewType)
é chamado apenas quando um novo layout de visualização é necessário;getItemViewType(int position)
será chamado para oviewType
;onBindViewHolder(ViewHolder holder, int position)
sempre é chamado ao reciclar a exibição (novos dados são trazidos e tentados exibir com issoViewHolder
).Então, quando
onBindViewHolder
é chamado, ele precisa colocar o layout de exibição correto e atualizar oViewHolder
.A maneira correta de substituir o layout da vista
ViewHolder
é trazer algum problema ou algum problema? Aprecie qualquer comentário!Editar: ViewHolder tem o membro mItemViewType para manter a exibição
Edit: parece que em onBindViewHolder (suporte do ViewHolder, posição int) o ViewHolder transferido foi capturado (ou criado) por getItemViewType (int position) para garantir que seja uma correspondência, portanto, não é necessário se preocupar com o fato de o ViewHolder type não corresponde ao tipo de [posição] dos dados. Alguém sabe mais como o ViewHolder no onBindViewHolder () é captado?
Edit: Parece que a reciclagem
ViewHolder
é escolhida por tipo, então nenhum guerreiro está lá.O Edit: http://wiresareobsolete.com/2014/09/building-a-recyclerview-layoutmanager-part-1/ responde a esta pergunta.
Obtém a reciclagem
ViewHolder
como:ou crie uma nova se não encontrar a reciclagem
ViewHolder
do tipo certo.fonte
Eu tenho uma solução melhor que permite criar vários tipos de exibição de forma declarativa e segura do tipo. Está escrito em Kotlin, o que é realmente bom.
Suportes de visualização simples para todos os tipos de visualização necessários
Há uma abstração do item de dados do adaptador. Observe que um tipo de vista é representado por um hashCode de determinada classe de detentor de vista (KClass no Kotlin)
Só
bindViewHolder
precisa ser substituído em classes de itens adaptador de betão (digite forma segura)A lista desses
AdapterItemMedium
objetos é uma fonte de dados para o adaptador que realmente aceita,List<AdapterItem>
veja abaixo.Parte importante desta solução é uma fábrica de detentores de vistas que fornecerá instâncias novas de um ViewHolder específico
E a classe de adaptador simples se parece com isso
Apenas três etapas para criar um novo tipo de visualização:
ViewHolderProvider
Aqui está um exemplo desse conceito: android-drawer-template Vai ainda mais longe - veja o tipo que atua como um componente giratório, itens de adaptador selecionáveis.
fonte
É muito simples e direto.
Basta substituir o método getItemViewType () no seu adaptador. Com base nos dados, retorne diferentes valores itemViewType. por exemplo, considere um objeto do tipo Person com um membro isMale, se isMale for true, retorne 1 e isMale for false, retorne 2 no método getItemViewType () .
Agora chega ao createViewHolder (pai do ViewGroup, int viewType) , com base em viewType diferente, que pode inflar o arquivo de layout diferente. como o seguinte
em onBindViewHolder (titular do VH, posição int) verifique onde o titular é uma instância de
AdapterFemaleViewHolder
ouAdapterMaleViewHolder
porinstanceof
e, consequentemente, atribua os valores.ViewHolder Pode ser assim
fonte
Embora a resposta selecionada esteja correta, quero apenas elaborá-la. Encontrei aqui um adaptador personalizado útil para vários tipos de exibição no RecyclerView . Sua versão Kotlin está aqui .
O adaptador personalizado está seguindo
fonte
Eu recomendo esta biblioteca de Hannes Dorfmann. Ele encapsula toda a lógica relacionada ao tipo de exibição específico em um objeto separado chamado "AdapterDelegate". https://github.com/sockeqwe/AdapterDelegates
fonte
Na verdade, eu gostaria de melhorar a resposta de Anton .
Como
getItemViewType(int position)
retorna um valor inteiro, você pode retornar o ID do recurso de layout que precisa aumentar. Dessa forma, você salvaria alguma lógica noonCreateViewHolder(ViewGroup parent, int viewType)
método.Além disso, eu não sugeriria cálculos intensivos,
getItemCount()
pois essa função específica é chamada pelo menos 5 vezes durante a renderização da lista, bem como ao renderizar cada item além dos itens visíveis. Infelizmente, como onotifyDatasetChanged()
método é final, você não pode substituí-lo, mas pode chamá-lo de outra função no adaptador.fonte
Note: Integers must be in the range 0 to getViewTypeCount() - 1. IGNORE_ITEM_VIEW_TYPE can also be returned.
Portanto, é melhor escrever um pouco mais de código e não usar hacks.Você pode usar a biblioteca: https://github.com/vivchar/RendererRecyclerViewAdapter
`
Para cada item, você deve implementar um ViewRenderer, ViewHolder, SomeModel:
ViewHolder - é um suporte simples para a visão do reciclador.
SomeModel - é o seu modelo com
ItemModel
interfacePara mais detalhes, você pode procurar documentações.
fonte
A implementação de tipos de exibição se torna mais fácil com o kotlin. Aqui está uma amostra desta biblioteca de luz https://github.com/Link184/KidAdapter
fonte
Você pode negociar multipleViewTypes
RecyclerAdapter
fazendogetItemViewType()
retornar oviewType
valor esperado para essa posiçãoPreparei uma
MultipleViewTypeAdapter
lista para a construção do MCQ para exames que podem gerar uma pergunta que pode ter 2 ou mais respostas válidas (opções da caixa de seleção) e uma única resposta (opções do botão de opção).Para isso, recebo o tipo de pergunta da resposta da API e usei isso para decidir qual exibição devo mostrar para essa pergunta.
Você pode evitar vários preenchimentos de dados do viewHolder com base condicional
onBindViewHolder()
atribuindo os mesmos IDs para visualizações semelhantes nos viewHolders que diferem em seu posicionamento.fonte
Se você deseja usá-lo em conjunto com o Android Data Binding, consulte o https://github.com/evant/binding-collection-adapter - é de longe a melhor solução para os vários tipos de exibição
RecyclerView
eu já vi.você pode usá-lo como
e depois no layout em que a lista está
seus itens da lista devem implementar uma
BaseListItem
interface parecida com estae a visualização do item devem se parecer com isso
Onde
YourListItem
implementaBaseListItem
Espero que ajude alguém.
fonte
primeiro você deve criar 2 xml de layout. depois disso, dentro do adaptador de reciclagem TYPE_CALL e TYPE_EMAIL existem dois valores estáticos com 1 e 2 respectivamente na classe do adaptador.
agora Defina dois valores estáticos no nível da classe Adaptador da visualização Recycler, por exemplo: private static int TYPE_CALL = 1; estática privada int TYPE_EMAIL = 2;
Agora crie o suporte da vista com várias vistas como esta:
Agora codifique como abaixo nos métodos onCreateViewHolder e onBindViewHolder no adaptador recyclerview:
fonte