Visualizar itens de expansão / recolhimento

145

Quero expandir / recolher os itens do meu recyclerView para mostrar mais informações. Desejo obter o mesmo efeito do SlideExpandableListView .

Basicamente, no meu viewHolder, tenho uma visualização que não é visível e quero fazer uma animação suave de expansão / recolhimento, em vez de definir a visibilidade como VISÍVEL / EXTREMAMENTE. Eu só preciso que um item seja expandido por vez e seria legal ter alguma elevação para mostrar que o item está selecionado.

É o mesmo efeito da nova lista de histórico de chamadas recentes do Android. As opções "LIGAR DE VOLTA" e "DETALHES" são visíveis apenas quando um item é selecionado.

Ver itens expansíveis

stanete
fonte
Eu tenho uma questão relacionada. No aplicativo Relógio, a atividade do conjunto de alarmes possui um recurso semelhante. É feito da mesma maneira?
User2731584 2/15
Ei, você tem a solução? Também estou procurando a mesma solução para o meu aplicativo.
Arpit Patel
Você achou alguma solução?
Armin Ghoreishi
1
Atualizei a maneira recomendada de fazê-lo de acordo com o Google I / O 2016. Veja minha resposta stackoverflow.com/questions/27203817/…
Heisenberg
veja a minha resposta aqui uma solução simples e legal stackoverflow.com/a/48092441/5962715
Kiran Benny Joseph

Respostas:

192

Não use nenhuma biblioteca para esse efeito. Em vez disso, use a maneira recomendada de fazê-lo, de acordo com as E / S do Google. No método onBindViewHolder do seu recyclerView, faça o seguinte:

final boolean isExpanded = position==mExpandedPosition;
holder.details.setVisibility(isExpanded?View.VISIBLE:View.GONE);
holder.itemView.setActivated(isExpanded);
holder.itemView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        mExpandedPosition = isExpanded ? -1:position;
        TransitionManager.beginDelayedTransition(recyclerView);
        notifyDataSetChanged();
    }
});
  • Onde detalhes está a minha visão de que será exibida ao toque (detalhes da chamada no seu caso. Visibilidade padrão.GONE).
  • mExpandedPosition é uma variável int inicializada para -1

E para os efeitos interessantes que você queria, use-os como seus atributos list_item:

android:background="@drawable/comment_background"
android:stateListAnimator="@animator/comment_selection"

onde comment_background é:

<selector
xmlns:android="http://schemas.android.com/apk/res/android"
android:constantSize="true"
android:enterFadeDuration="@android:integer/config_shortAnimTime"
android:exitFadeDuration="@android:integer/config_shortAnimTime">

<item android:state_activated="true" android:drawable="@color/selected_comment_background" />
<item android:drawable="@color/comment_background" />
</selector>

e comment_selection é:

<selector xmlns:android="http://schemas.android.com/apk/res/android">

<item android:state_activated="true">
    <objectAnimator
        android:propertyName="translationZ"
        android:valueTo="@dimen/z_card"
        android:duration="2000"
        android:interpolator="@android:interpolator/fast_out_slow_in" />
</item>

<item>
    <objectAnimator
        android:propertyName="translationZ"
        android:valueTo="0dp"
        android:duration="2000"
        android:interpolator="@android:interpolator/fast_out_slow_in" />
</item>
</selector>
Heisenberg
fonte
22
Ao usar esse código, a animação de expansão parece estranha. Sempre que o item principal desaparece e tudo muda para uma posição. Você já experimentou algo semelhante?
chris-pollux
6
Eu tento fazer a animação, mas implemento isso no adaptador, mas qual seria a solução para o TransitionManager.beginDelayedTransition(recyclerView);caso eu não consiga ter a referência de exibição do reciclador.
Martín Serrano
2
@Ranveer Funciona mais ou menos. Eu tenho dois recyclerViews bastante semelhantes, mas funciona apenas corretamente para um. Não faço ideia do porquê. @ MartínDaniel que você precisa para passar o recyclerViewcomo um parâmetro no construtor para o adaptador
chris-pollux
26
Esta é uma abordagem terrível. Não acredito que foi recomendado no Google I / O. Mesmo depois de investigar o projeto Plaid e implementar todas as soluções alternativas necessárias, a animação ainda causa algumas falhas importantes no RecyclerView, por exemplo, o primeiro / último item visível desaparecendo prematuramente. Também a rolagem enquanto a animação é executada prejudica muito as coisas. Em geral, não acho que a correção de todos os problemas causados ​​por essa abordagem possa ser chamada de "apenas coloque uma linha e tudo funcionará" conforme anunciado.
Vitali Olshevski
6
Temos alguma maneira mais fácil e atualizada em 2019 para este problema?
Ponomarenko Oleh
76

Para isso, só eram necessárias linhas simples, não complicadas

no seu método onBindViewHolder, adicione o código abaixo

final boolean isExpanded = position==mExpandedPosition;
holder.details.setVisibility(isExpanded?View.VISIBLE:View.GONE);
holder.itemView.setActivated(isExpanded);
holder.itemView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        mExpandedPosition = isExpanded ? -1:position;
        notifyItemChanged(position);
    }
});

mExpandedPosition é uma variável global int inicializada em -1

Para aqueles que querem apenas um item expandido e outros são recolhidos. Usa isto

primeiro declare uma variável global com previousExpandedPosition = -1

então

    final boolean isExpanded = position==mExpandedPosition;
    holder.details.setVisibility(isExpanded?View.VISIBLE:View.GONE);
    holder.itemView.setActivated(isExpanded);

    if (isExpanded)
       previousExpandedPosition = position;

    holder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            mExpandedPosition = isExpanded ? -1:position;
            notifyItemChanged(previousExpandedPosition);
            notifyItemChanged(position);
        }
    });

Feito!!!. Simples e humilde .. :)

Kiran Benny Joseph
fonte
ótima solução. Também eu recomendo para mover ambiente OnClickListeners a onCreateViewHoldervez deonBindViewHolder
YTerle
1
Funciona muito bem, na época havia uma solução decente que apenas permitia o RecyclerViewtrabalho, ou seja, qual é o objetivo do LayoutManagercontrário, se ele não gerencia os layouts! Esta solução é melhor que a solução votada, pois possui menos código, permite RecyclerViewlidar com as coisas e funciona melhor!
Mark Keen
1
não entendia muito bem como adicionar a exibição "detalhes". Deve ser estático para cada titular? E se, para cada item da lista, for necessário adicionar visualizações diferentes?
BekaBot 27/03
@BekaBot é a visão de que você quer esconder durante item de colapso
Kiran Benny Joseph
@KiranBennyJoseph sim, eu entendo. Nesse caso, a visualização deve ser a mesma para todos os itens? E se eu quiser visualizações diferentes para itens diferentes?
BekaBot
72

Não estou dizendo que essa é a melhor abordagem, mas parece funcionar para mim.

O código completo pode ser encontrado em: Exemplo de código em: https://github.com/dbleicher/recyclerview-grid-quickreturn

Primeiro, adicione a área expandida ao layout da célula / item e torne o layout da célula anexa animateLayoutChanges = "true". Isso garantirá que a expansão / recolhimento seja animada:

<LinearLayout
    android:id="@+id/llCardBack"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:background="@android:color/white"
    android:animateLayoutChanges="true"
    android:padding="4dp"
    android:orientation="vertical">

    <TextView
        android:id="@+id/tvTitle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center|fill_horizontal"
        android:padding="10dp"
        android:gravity="center"
        android:background="@android:color/holo_green_dark"
        android:text="This is a long title to show wrapping of text in the view."
        android:textColor="@android:color/white"
        android:textSize="16sp" />

    <TextView
        android:id="@+id/tvSubTitle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center|fill_horizontal"
        android:background="@android:color/holo_purple"
        android:padding="6dp"
        android:text="My subtitle..."
        android:textColor="@android:color/white"
        android:textSize="12sp" />

    <LinearLayout
        android:id="@+id/llExpandArea"
        android:visibility="gone"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="horizontal">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="6dp"
            android:text="Item One" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="6dp"
            android:text="Item Two" />

    </LinearLayout>
</LinearLayout>

Em seguida, faça a sua classe RV Adapter implementar View.OnClickListener para que você possa atuar no item que está sendo clicado. Adicione um campo int para manter a posição da visualização expandida e inicialize-a com um valor negativo:

private int expandedPosition = -1;

Por fim, implemente os métodos ViewHolder, onBindViewHolder () e substitua o método onClick (). Você expandirá a exibição no onBindViewHolder se sua posição for igual a "extendedPosition" e ocultará se não. Você define o valor de extendedPosition no ouvinte onClick:

@Override
public void onBindViewHolder(RVAdapter.ViewHolder holder, int position) {

    int colorIndex = randy.nextInt(bgColors.length);
    holder.tvTitle.setText(mDataset.get(position));
    holder.tvTitle.setBackgroundColor(bgColors[colorIndex]);
    holder.tvSubTitle.setBackgroundColor(sbgColors[colorIndex]);

    if (position == expandedPosition) {
        holder.llExpandArea.setVisibility(View.VISIBLE);
    } else {
        holder.llExpandArea.setVisibility(View.GONE);
    }
}

@Override
public void onClick(View view) {
    ViewHolder holder = (ViewHolder) view.getTag();
    String theString = mDataset.get(holder.getPosition());

    // Check for an expanded view, collapse if you find one
    if (expandedPosition >= 0) {
        int prev = expandedPosition;
        notifyItemChanged(prev);
    }
    // Set the current position to "expanded"
    expandedPosition = holder.getPosition();
    notifyItemChanged(expandedPosition);

    Toast.makeText(mContext, "Clicked: "+theString, Toast.LENGTH_SHORT).show();
}

/**
 * Create a ViewHolder to represent your cell layout
 * and data element structure
 */
public static class ViewHolder extends RecyclerView.ViewHolder {
    TextView tvTitle;
    TextView tvSubTitle;
    LinearLayout llExpandArea;

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

        tvTitle = (TextView) itemView.findViewById(R.id.tvTitle);
        tvSubTitle = (TextView) itemView.findViewById(R.id.tvSubTitle);
        llExpandArea = (LinearLayout) itemView.findViewById(R.id.llExpandArea);
    }
}

Isso deve expandir apenas um item de cada vez, usando a animação padrão do sistema para a alteração do layout. Pelo menos funciona para mim. Espero que ajude.

MojoTosh
fonte
Eu sei como manter apenas um item selecionado. Eu realmente não sei como fazer a animação nesse item. A animação de expansão / recolhimento com a animação padrão do sistema não parece muito suave.
Stanete
1
Ainda não tentei o seguinte, mas com certeza parece que vai funcionar. Verifique a resposta em: stackoverflow.com/a/26443762/2259418
MojoTosh
2
@ user2731584 - Acho que não. Observando (o que acredito ser) sua fonte, parece que o relógio Lollipop está usando um ListView para exibir a lista de alarmes. Layout: android.googlesource.com/platform/packages/apps/DeskClock/+/… Eles parecem ter um código personalizado para animar os itens de expansão / recolhimento nesta lista. Consulte a seguinte fonte: android.googlesource.com/platform/packages/apps/DeskClock/+/…
MojoTosh
1
@MojoTosh você está certo. Eles estão usando o ListView e fazendo a animação usando o código. expandAlarmA função em AlarmClockFragment.javaarquivos executa a parte de expansão.
User2731584 2/15
4
Qual onClick()devo substituir? Não há onClickno adaptador.
Vicky Leong
15

Existe uma biblioteca muito simples de usar com suporte a gradle: https://github.com/cachapa/ExpandableLayout .

Diretamente dos documentos da biblioteca:

<net.cachapa.expandablelayout.ExpandableLinearLayout
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:el_duration="1000"
    app:el_expanded="true">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Click here to toggle expansion" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:text="Fixed height"
        app:layout_expandable="true" />

 </net.cachapa.expandablelayout.ExpandableLinearLayout>

Depois de marcar seus expansíveis vista, basta ligar para qualquer um destes métodos no recipiente: expand(), collapse()outoggle()

Laurențiu Onac
fonte
Ainda é a melhor maneira de fazer isso? Estou tentando seguir o que você escreveu. Eu tenho algumas visualizações de reciclagem que eu quero expandir para mostrar um gráfico quando clicado em
sourlemonaid
10

Sei que já faz muito tempo que a pergunta original foi publicada. Mas acho que para os mais lentos como eu, um pouco de explicação da resposta de @ Heisenberg ajudaria.

Declare duas variáveis ​​na classe do adaptador como

private int mExpandedPosition= -1;
private RecyclerView recyclerView = null;

Em seguida, em onBindViewHolder, conforme indicado na resposta original.

      // This line checks if the item displayed on screen 
      // was expanded or not (Remembering the fact that Recycler View )
      // reuses views so onBindViewHolder will be called for all
      // items visible on screen.
    final boolean isExpanded = position==mExpandedPosition;

        //This line hides or shows the layout in question
        holder.details.setVisibility(isExpanded?View.VISIBLE:View.GONE);

        // I do not know what the heck this is :)
        holder.itemView.setActivated(isExpanded);

        // Click event for each item (itemView is an in-built variable of holder class)
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

 // if the clicked item is already expaned then return -1 
//else return the position (this works with notifyDatasetchanged )
                mExpandedPosition = isExpanded ? -1:position;
    // fancy animations can skip if like
                TransitionManager.beginDelayedTransition(recyclerView);
    //This will call the onBindViewHolder for all the itemViews on Screen
                notifyDataSetChanged();
            }
        });

E, por último, para obter o objeto recyclerView na substituição do adaptador

@Override
public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
    super.onAttachedToRecyclerView(recyclerView);

    this.recyclerView = recyclerView;
}

Espero que isto ajude.

bumbum shahroz
fonte
3
Solução ótima e simples. Pequenas melhorias, use RecyclerView.NO_POSITION em vez do número mágico -1.
Casper Bang
8

Simplesmente não há necessidade de usar bibliotecas de terceiros. Um pequeno ajuste no método demonstrado no Google I / O 2016 e Heisenberg neste tópico, faz o truque.

Uma vez que notifyDataSetChanged() redesenha o completoRecyclerView , notifyDataItemChanged()é uma opção melhor (não a melhor) porque temos a posição e a ViewHolderdisposição e notifyDataItemChanged()apenas redesenha o particular ViewHolderem uma determinada posição .

Mas o problema é que o desaparecimento prematuro do ViewHolderclique e seu surgimento não são eliminados, mesmo quenotifyDataItemChanged() sejam utilizados.

O código a seguir não recorrer a notifyDataSetChanged()ou notifyDataItemChanged()e é testado em API 23 e funciona como um encanto quando usado em uma RecyclerView onde cada ViewHolder tem um CardViewcomo do elemento raiz:

holder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            final boolean visibility = holder.details.getVisibility()==View.VISIBLE;

            if (!visibility)
            {
                holder.itemView.setActivated(true);
                holder.details.setVisibility(View.VISIBLE);
                if (prev_expanded!=-1 && prev_expanded!=position)
                {
                    recycler.findViewHolderForLayoutPosition(prev_expanded).itemView.setActivated(false);
                    recycler.findViewHolderForLayoutPosition(prev_expanded).itemView.findViewById(R.id.cpl_details).setVisibility(View.GONE);
                }
                prev_expanded = position;
            }
            else
            {
                holder.itemView.setActivated(false);
                holder.details.setVisibility(View.GONE);
            }
            TransitionManager.beginDelayedTransition(recycler);              
        }
});

prev_positioné um número inteiro global inicializado com -1. detailsé a visualização completa que é mostrada quando expandida e oculta quando recolhida.

Como dito, o elemento raiz de ViewHolderé um CardViewcom foregrounde stateListAnimatoratributos definidos exatamente como dito por Heisenberg neste tópico.

ATUALIZAÇÃO: A demonstração acima reduzirá o item previamente expandido se um deles estiver expandido. Para modificar esse comportamento e manter o item expandido como ele é, mesmo quando outro item for expandido, você precisará do código a seguir.

if (row.details.getVisibility()!=View.VISIBLE)
    {
        row.details.setVisibility(View.VISIBLE);
        row.root.setActivated(true);
        row.details.animate().alpha(1).setStartDelay(500);
    }
    else
    {
        row.root.setActivated(false);
        row.details.setVisibility(View.GONE);
        row.details.setAlpha(0);
    }
    TransitionManager.beginDelayedTransition(recycler);

ATUALIZAÇÃO: ao expandir os últimos itens da lista, ele pode não ser totalmente visível porque a parte expandida fica abaixo da tela. Para obter o item completo na tela, use o seguinte código.

LinearLayoutManager manager = (LinearLayoutManager) recycler.getLayoutManager();
    int distance;
    View first = recycler.getChildAt(0);
    int height = first.getHeight();
    int current = recycler.getChildAdapterPosition(first);
    int p = Math.abs(position - current);
    if (p > 5) distance = (p - (p - 5)) * height;
    else       distance = p * height;
    manager.scrollToPositionWithOffset(position, distance);

IMPORTANTE: Para que as demonstrações acima funcionem, é necessário manter em seu código uma instância do RecyclerView e do LayoutManager (o posterior para flexibilidade)

Koushik Shom Choudhury
fonte
Obrigado, esta solução funciona para mim. Tento evitar o uso notifyItemChangedporque tenho uma ImageViewimagem que carrega de um URL. notifyItemChangedrecarregar minha imagem a faz parecer estranho
Tam Huynh
A linha que prega é TransitionManager.beginDelayedTransition(recycler);, ótimo achado. Mas descobri que, usando esse método, se eu clicar em várias linhas com spam sequencialmente, ele eventualmente acionará uma falha interna The specified child already has a parent. You must call removeView() on the child's parent first. Imagino que isso se deva à reciclagem da vista nos limites da vista da recicladora, mas não tenho certeza. Alguém teve o mesmo problema?
Roger Oba
Ainda é a melhor maneira de fazer isso? Estou tentando seguir o que você escreveu. Tenho algumas visualizações de reciclagem que quero expandir para mostrar um gráfico quando clicado. Estou tendo dificuldades para entender exatamente o que fazer #
sourlemonaid
Alguém tem o exemplo completo dessa implementação? Quero dizer um exemplo de código de trabalho. Por favor ajude. Eu sou incapaz de entender como fazê-lo?
Munazza 04/07
7

Depois de usar a maneira recomendada de implementar itens expansíveis / recolhíveis que residem em itens de expansão / recolhimentoRecyclerView no RecyclerView respondidos por HeisenBerg , eu vi alguns artefatos visíveis sempre que a RecyclerViewatualização foi feita invocando TransitionManager.beginDelayedTransition(ViewGroup)e subseqüentementenotifyDatasetChanged() .

Sua resposta original:

final boolean isExpanded = position==mExpandedPosition;
holder.details.setVisibility(isExpanded?View.VISIBLE:View.GONE);
holder.itemView.setActivated(isExpanded);
holder.itemView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        mExpandedPosition = isExpanded ? -1 : position;
        TransitionManager.beginDelayedTransition(recyclerView);
        notifyDataSetChanged();
    }
});

Modificado:

final boolean isExpanded = position == mExpandedPosition;
holder.details.setVisibility(isExpanded ? View.VISIBLE : View.GONE);
holder.view.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        if (mExpandedHolder != null) {
            mExpandedHolder.details.setVisibility(View.GONE);
            notifyItemChanged(mExpandedPosition);
        }
        mExpandedPosition = isExpanded ? -1 : holder.getAdapterPosition();
        mExpandedHolder = isExpanded ? null : holder;
        notifyItemChanged(holder.getAdapterPosition());
    }
}
  • detalhes é a visão que você deseja mostrar / ocultar durante a expansão / recolhimento de itens
  • mExpandedPosition é intaquele que controla o item expandido
  • mExpandedHolder é ViewHolderusado durante o recolhimento do item

Observe que o método TransitionManager.beginDelayedTransition(ViewGroup)e notifyDataSetChanged()é substituído por notifyItemChanged(int)para direcionar item específico e alguns pequenos ajustes.

Após a modificação, os efeitos indesejados anteriores devem desaparecer. No entanto, essa pode não ser a solução perfeita. Ele só fez o que eu queria, eliminando os problemas.

::EDITAR::

Para esclarecimento, ambos mExpandedPositione mExpandedHoldersão globais.

Chan Teck Wei
fonte
Por favor, explique como e onde mExpandedHolder é declarado e usado?
Werner
1
@ Werner Eu editei a resposta para mostrar onde é declarada. O uso está no próprio snippet e também no objetivo. É usado para animar o item expandido em colapso.
Chan Teck Wei
Eu amo essa abordagem ao máximo no que diz respeito às animações, mas estou tendo esse pequeno "desbotamento" ao clicar no item. Você tem isso de forma bem ou diferente, isso se deve ao uso de notifyItemChanged ()? drive.google.com/file/d/1GaU1fcjHEfSErYF50otQGLGsIWkSyQSe/…
kazume 15/18
Sim. Como você adivinhou, é causado por notifyItemChanged(). Você pode animar e alterar manualmente a altura do item e adicionar visualizações a ele.
Chan Teck Wei
@ ChanTeckWei: sua solução está funcionando bem, mas a imagem da linha pisca sempre que eu recuo ou expiro a linha do item de revisão de reciclagem. Existe alguma solução para isso?
Pragya Mendiratta
3

Faça o seguinte depois de definir o ouvinte onClick para a classe ViewHolder:

@Override
    public void onClick(View v) {
        final int originalHeight = yourLinearLayout.getHeight();
        animationDown(YourLinearLayout, originalHeight);//here put the name of you layout that have the options to expand.
    }

    //Animation for devices with kitkat and below
    public void animationDown(LinearLayout billChoices, int originalHeight){

        // Declare a ValueAnimator object
        ValueAnimator valueAnimator;
        if (!billChoices.isShown()) {
            billChoices.setVisibility(View.VISIBLE);
            billChoices.setEnabled(true);
            valueAnimator = ValueAnimator.ofInt(0, originalHeight+originalHeight); // These values in this method can be changed to expand however much you like
        } else {
            valueAnimator = ValueAnimator.ofInt(originalHeight+originalHeight, 0);

            Animation a = new AlphaAnimation(1.00f, 0.00f); // Fade out

            a.setDuration(200);
            // Set a listener to the animation and configure onAnimationEnd
            a.setAnimationListener(new Animation.AnimationListener() {
                @Override
                public void onAnimationStart(Animation animation) {

                }

                @Override
                public void onAnimationEnd(Animation animation) {
                    billChoices.setVisibility(View.INVISIBLE);
                    billChoices.setEnabled(false);
                }

                @Override
                public void onAnimationRepeat(Animation animation) {

                }
            });
            // Set the animation on the custom view
            billChoices.startAnimation(a);
        }
        valueAnimator.setDuration(200);
        valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            public void onAnimationUpdate(ValueAnimator animation) {
                Integer value = (Integer) animation.getAnimatedValue();
                billChoices.getLayoutParams().height = value.intValue();
                billChoices.requestLayout();
            }
        });


        valueAnimator.start();
    }
}

Eu acho que isso deve ajudar, é assim que eu implementei e faço o mesmo google na visualização de chamadas recente.

Rensodarwin
fonte
2

Estou surpreso que ainda não haja uma resposta concisa, embora uma animação de expansão / recolhimento seja muito fácil de obter com apenas 2 linhas de código:

(recycler.itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false // called once

junto com

notifyItemChanged(position) // in adapter, whenever a child view in item's recycler gets hidden/shown

Então, para mim, as explicações no link abaixo foram realmente úteis: https://medium.com/@nikola.jakshic/how-to-expand-collapse-items-in-recyclerview-49a648a403a6

Bianca Daniciuc
fonte
1
//Global Variable

private int selectedPosition = -1;

 @Override
    public void onBindViewHolder(final CustomViewHolder customViewHolder, final int i) {

        final int position = i;
        final GetProductCatalouge.details feedItem = this.postBeanses.get(i);
        customViewHolder.lly_main.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                selectedPosition = i;
                notifyDataSetChanged();
            }
        });
        if (selectedPosition == i) {

          if (customViewHolder.lly_hsn_code.getVisibility() == View.VISIBLE) {

            customViewHolder.lly_hsn_code.setVisibility(View.GONE);
            customViewHolder.lly_sole.setVisibility(View.GONE);
            customViewHolder.lly_sole_material.setVisibility(View.GONE);

        } else {

            customViewHolder.lly_hsn_code.setVisibility(View.VISIBLE);
            customViewHolder.lly_sole.setVisibility(View.VISIBLE);
            customViewHolder.lly_sole_material.setVisibility(View.VISIBLE);
        }


        } else {
            customViewHolder.lly_hsn_code.setVisibility(View.GONE);
            customViewHolder.lly_sole.setVisibility(View.GONE);
            customViewHolder.lly_sole_material.setVisibility(View.GONE);
        }
}

insira a descrição da imagem aqui

Keshav Gera
fonte
0

Use dois tipos de exibição no seu RVAdapter. Um para layout expandido e outro para recolhido. E a mágica acontece com a configuração android:animateLayoutChanges="true"para o Google RecyclerView Checkout do efeito alcançado usando isso às 0:42 neste vídeo

penduDev
fonte
mente explicando isso melhor? Não consigo fazê-lo funcionar #
sourlemonaid
@sourlemonaid basicamente você cria vários tipos de exibição para a lista, conforme explicado em stackoverflow.com/a/26245463/3731795 ... Você mantém um controle do índice para o qual o item é expandido e o restante dos itens é recolhido naquele momento . Agora, se (current_item_index == expand_item_index) {return VIEW_TYPE_EXPANDED} else {reutrn VIEW_TYPE_COLLAPSED}
penduDev