É possível usar itens de lista expansíveis com o novo RecyclerView? Gosta de ExpandableListView?
É possível usar itens de lista expansíveis com o novo RecyclerView? Gosta de ExpandableListView?
Respostas:
Isso é simples de fazer com os LayoutManagers de estoque, tudo depende de como você gerencia seu adaptador.
Quando você deseja expandir uma seção, basta adicionar novos itens ao adaptador após o cabeçalho. Lembre-se de chamar notificarItemRangeInserted ao fazer isso. Para recolher uma seção, basta remover os itens relevantes e chamar notificarItemRangeRemoved (). Para quaisquer alterações de dados que sejam notificadas adequadamente, a visualização do reciclador animará as visualizações. Ao adicionar itens, uma área a ser preenchida com os novos itens é feita, com os novos itens desaparecendo. A remoção é o oposto. Tudo o que você precisa fazer além do adaptador é definir o estilo de suas visualizações para transmitir a estrutura lógica ao usuário.
Atualização: Ryan Brooks escreveu um artigo sobre como fazer isso.
Obtenha o exemplo de implementação de código de aqui
Defina ValueAnimator dentro de onClick de ViewHolder
@Override
public void onClick(final View view) {
if (mOriginalHeight == 0) {
mOriginalHeight = view.getHeight();
}
ValueAnimator valueAnimator;
if (!mIsViewExpanded) {
mIsViewExpanded = true;
valueAnimator = ValueAnimator.ofInt(mOriginalHeight, mOriginalHeight + (int) (mOriginalHeight * 1.5));
} else {
mIsViewExpanded = false;
valueAnimator = ValueAnimator.ofInt(mOriginalHeight + (int) (mOriginalHeight * 1.5), mOriginalHeight);
}
valueAnimator.setDuration(300);
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
Integer value = (Integer) animation.getAnimatedValue();
view.getLayoutParams().height = value.intValue();
view.requestLayout();
}
});
valueAnimator.start();
}
Aqui está o código final
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private TextView mFriendName;
private int mOriginalHeight = 0;
private boolean mIsViewExpanded = false;
public ViewHolder(RelativeLayout v) {
super(v);
mFriendName = (TextView) v.findViewById(R.id.friendName);
v.setOnClickListener(this);
}
@Override
public void onClick(final View view) {
if (mOriginalHeight == 0) {
mOriginalHeight = view.getHeight();
}
ValueAnimator valueAnimator;
if (!mIsViewExpanded) {
mIsViewExpanded = true;
valueAnimator = ValueAnimator.ofInt(mOriginalHeight, mOriginalHeight + (int) (mOriginalHeight * 1.5));
} else {
mIsViewExpanded = false;
valueAnimator = ValueAnimator.ofInt(mOriginalHeight + (int) (mOriginalHeight * 1.5), mOriginalHeight);
}
valueAnimator.setDuration(300);
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
Integer value = (Integer) animation.getAnimatedValue();
view.getLayoutParams().height = value.intValue();
view.requestLayout();
}
});
valueAnimator.start();
}
}
ExpandableListView
", porque o conteúdo expandido, nesse caso, é uma lista com itens vindos do adaptador. Esta é uma solução degenerada com apenas 1 item permitido como filho dentro do grupo.
https://github.com/gabrielemariotti/cardslib
Esta biblioteca possui uma implementação de uma lista expansível com uma visualização de reciclagem (consulte o aplicativo de demonstração em "CardViewNative" -> "List, Grid e RecyclerView" -> "Cartões expansíveis"). Ele também tem muitas outras combinações legais de cartas / listas.
Alguém reclamou que a solução mencionada acima não pode ser usada com um listview como conteúdo expansível. Mas há uma solução simples: crie um listview e preencha este listview manualmente com suas linhas .
Solução para os preguiçosos: existe uma solução simples se você não quer mudar muito o seu código. Basta usar manualmente seu adaptador para criar visualizações e adicioná-las aoLinearLayout
.
Aqui está o exemplo:
if (mIsExpanded)
{
// llExpandable... is the expandable nested LinearLayout
llExpandable.removeAllViews();
final ArrayAdapter<?> adapter = ... // create your adapter as if you would use it for a ListView
for (int i = 0; i < adapter.getCount(); i++)
{
View item = adapter.getView(i, null, null);
// if you want the item to be selectable as if it would be in a default ListView, then you can add following code as well:
item.setBackgroundResource(Functions.getThemeReference(context, android.R.attr.selectableItemBackground));
item.setTag(i);
item.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// item would be retrieved with:
// adapter.getItem((Integer)v.getTag())
}
});
llExpandable.addView(item);
}
ExpandUtils.expand(llExpandable, null, 500);
}
else
{
ExpandUtils.collapse(llExpandable, null, 500);
}
funções auxiliares: getThemeReference
public static int getThemeReference(Context context, int attribute)
{
TypedValue typeValue = new TypedValue();
context.getTheme().resolveAttribute(attribute, typeValue, false);
if (typeValue.type == TypedValue.TYPE_REFERENCE)
{
int ref = typeValue.data;
return ref;
}
else
{
return -1;
}
}
classe auxiliar: ExpandUtils
Kavin Varnan postou já como animar um layout ... Mas se você quiser usar minha classe, fique à vontade para fazer isso, postei um ponto principal: https://gist.github.com/MichaelFlisar/738dfa03a1579cc7338a
recyclerview
e você pode expandir / ocultar este aninhado e usar todas as otimizações dorecyclerview
Você pode usar o ExpandableLayout como um CheckBox de animação de expansão / recolhimento suave, para que possa usá-lo como CheckBox em ListView e RecyclerView.
Este é o código de amostra para o que é mencionado por @TonicArtos para adicionar e remover itens e para animá-lo enquanto faz, isto é retirado de RecyclerView Animations e amostra do GitHub
1) Adicione Listener dentro de seu onCreateViewHolder () para se registrar para onClick
2) Crie seu OnClickListener personalizado dentro de seu adaptador
private View.OnClickListener mItemListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
TextView tv = (TextView) v.findViewById(R.id.tvItems);
String selected = tv.getText().toString();
boolean checked = itemsList.get(recyclerView.getChildAdapterPosition(v)).isChecked();
switch (selected){
case "Item1":
if(checked){
deleteItem(v);
itemsList.get(recyclerView.getChildAdapterPosition(v)).setChecked(false);
}else {
addItem(v);
itemsList.get(recyclerView.getChildAdapterPosition(v)).setChecked(true);
}
break;
case "Item2":
if(checked){
deleteItem(v);
itemsList.get(recyclerView.getChildAdapterPosition(v)).setChecked(false);
}else {
addItem(v);
itemsList.get(recyclerView.getChildAdapterPosition(v)).setChecked(true);
}
break;
default:
//In my case I have checkList in subItems,
//checkItem(v);
break;
}
}
};
3) Adicione seu addItem () e deleteItem ()
private void addItem(View view){
int position = recyclerView.getChildLayoutPosition(view);
if (position != RecyclerView.NO_POSITION){
navDrawItems.add(position+1,new mObject());
navDrawItems.add(position+2,new mObject());
notifyItemRangeInserted(position+1,2);
}
}
private void deleteItem(View view) {
int position = recyclerView.getChildLayoutPosition(view);
if (position != RecyclerView.NO_POSITION) {
navDrawItems.remove(position+2);
navDrawItems.remove(position+1);
notifyItemRangeRemoved(position+1,2);
}
}
4) Se seu RecyclerViewAdapter não estiver na mesma atividade que Recycler View , passe a instância de recyclerView para o adaptador durante a criação
5) itemList é um ArrayList do tipo mObject que ajuda a manter os estados do item (abrir / fechar), nome, tipo de item (subItems / mainItem) e definir o tema com base em valores
public class mObject{
private String label;
private int type;
private boolean checked;
}