Android adicionando animações simples enquanto configurável (view.Gone)

237

Eu projetei um layout simples. Eu terminei o design sem animação, mas agora quero adicionar animações quando o evento de clique em textview e não sei como usá-lo. Meu design xml parece bom ou não? Todas as sugestões serão apreciadas.

My XML

<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:longClickable="false"
    android:orientation="vertical"
    android:weightSum="16" >

<LinearLayout 
    android:layout_width="fill_parent"
    android:layout_height="0dp"
    android:orientation="vertical"
    android:background="#00DDA0"
    android:layout_weight="3" >
</LinearLayout>
 <TextView
        android:id="@+id/Information1"
        android:layout_width="match_parent"
        android:layout_height="1dp" 
        android:text="Child Information" 
        android:background="#0390BE"
        android:layout_weight="0.75"
        android:textColor="#FFFFFF"
        android:layout_gravity="center|fill_horizontal"/>

 <LinearLayout
     android:id="@+id/layout1"
     android:layout_width="fill_parent"
     android:layout_height="0dp"
     android:layout_weight="8.5"
     android:background="#BBBBBB"
     android:orientation="vertical" >

     <TextView
         android:id="@+id/textView1"
         android:layout_width="match_parent"
         android:layout_height="match_parent"        
         android:text="TextView" />
 </LinearLayout>

  <TextView
        android:id="@+id/Information2"
        android:layout_width="match_parent"
        android:layout_height="0dp" 
        android:text="Parent Information" 
        android:background="#0390BE"
        android:layout_weight="0.75"
        android:textColor="#FFFFFF"
        android:layout_gravity="center|fill_horizontal"/>
  <LinearLayout 
          android:id="@+id/layout2"
    android:layout_width="fill_parent"
    android:layout_height="0dp"
    android:orientation="vertical"
    android:background="#BBBBBB"
    android:layout_weight="8.5" >
     <TextView
         android:id="@+id/textView2"
         android:layout_width="match_parent"
         android:layout_height="match_parent"        
         android:text="TextView" />
      </LinearLayout>
   <TextView
        android:id="@+id/Information3"
        android:layout_width="match_parent"
        android:layout_height="0dp" 
        android:text="Siblings" 
        android:background="#0390BE"
        android:layout_weight="0.75"
        android:textColor="#FFFFFF"
        android:layout_gravity="center|fill_horizontal"/>
   <LinearLayout 
          android:id="@+id/layout3"
    android:layout_width="fill_parent"
    android:layout_height="0dp"
    android:orientation="vertical"
    android:background="#BBBBBB"
    android:layout_weight="8.5" >
     <TextView
         android:id="@+id/textView3"
         android:layout_width="match_parent"
         android:layout_height="match_parent"        
         android:text="TextView" />
      </LinearLayout>
    <TextView
        android:id="@+id/Information4"
        android:layout_width="match_parent"
        android:layout_height="0dp" 
        android:text="Teacher Information" 
        android:background="#0390BE"
        android:layout_weight="0.75"
        android:textColor="#FFFFFF"
        android:layout_gravity="center|fill_horizontal"/>
    <LinearLayout 
          android:id="@+id/layout4"
    android:layout_width="fill_parent"
    android:layout_height="0dp"
    android:orientation="vertical"
    android:background="#BBBBBB"
    android:layout_weight="8.5" >
     <TextView
         android:id="@+id/textView4"
         android:layout_width="match_parent"
         android:layout_height="match_parent"        
         android:text="TextView" />
      </LinearLayout>
     <TextView
        android:id="@+id/Information5"
        android:layout_width="match_parent"
        android:layout_height="0dp" 
        android:text="Grade Information" 
        android:background="#0390BE"
        android:layout_weight="0.75"
        android:textColor="#FFFFFF"
        android:layout_gravity="center|fill_horizontal"/>
     <LinearLayout 
          android:id="@+id/layout5"
    android:layout_width="fill_parent"
    android:layout_height="0dp"
    android:orientation="vertical"
    android:background="#BBBBBB"
    android:layout_weight="8.5" >
     <TextView
         android:id="@+id/textView5"
         android:layout_width="match_parent"
         android:layout_height="match_parent"        
         android:text="TextView" />
      </LinearLayout>
      <TextView
        android:id="@+id/Information6"
        android:layout_width="match_parent"
        android:layout_height="0dp" 
        android:text="Health Information" 
        android:background="#0390BE"
        android:layout_weight="0.75"
        android:textColor="#FFFFFF"
        android:layout_gravity="center|fill_horizontal"/>
      <LinearLayout 
          android:id="@+id/layout6"
    android:layout_width="fill_parent"
    android:layout_height="0dp"
    android:orientation="vertical"
    android:background="#BBBBBB"
    android:layout_weight="8.5" >
    <TextView
         android:id="@+id/textView5"
         android:layout_width="match_parent"
         android:layout_height="match_parent"        
         android:text="TextView" 
         android:layout_weight="8.5" />
      </LinearLayout>

</LinearLayout>

Meu java

public class Certify_Info extends Activity {

    private static TextView tv2,tv3,tv5,tv6,tv4,tv1;
    private static LinearLayout l1,l2,l3,l4,l5,l6;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_certify__info);

        tv1=(TextView) findViewById(R.id.Information1);
        tv2=(TextView) findViewById(R.id.Information2);
        tv3=(TextView) findViewById(R.id.Information3);
        tv4=(TextView) findViewById(R.id.Information4);
        tv5=(TextView) findViewById(R.id.Information5);
        tv6=(TextView) findViewById(R.id.Information6); 

        l1=(LinearLayout) findViewById(R.id.layout1);
        l2=(LinearLayout) findViewById(R.id.layout2);
        l3=(LinearLayout) findViewById(R.id.layout3);
        l4=(LinearLayout) findViewById(R.id.layout4);
        l5=(LinearLayout) findViewById(R.id.layout5);
        l6=(LinearLayout) findViewById(R.id.layout6); 

        l2.setVisibility(View.GONE);
        l3.setVisibility(View.GONE); 
        l4.setVisibility(View.GONE); 
        l5.setVisibility(View.GONE);
        l6.setVisibility(View.GONE);

        tv1.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                l2.setVisibility(View.GONE);
                l3.setVisibility(View.GONE); 
                l4.setVisibility(View.GONE); 
                l5.setVisibility(View.GONE);
                l6.setVisibility(View.GONE);
                l1.setVisibility(View.VISIBLE);
            }
        });
        tv2.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                l1.setVisibility(View.GONE);
                l3.setVisibility(View.GONE); 
                l4.setVisibility(View.GONE); 
                l5.setVisibility(View.GONE);
                l6.setVisibility(View.GONE);
                l2.setVisibility(View.VISIBLE);
            }
        });
        tv3.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                l1.setVisibility(View.GONE);
                l2.setVisibility(View.GONE);
                l4.setVisibility(View.GONE); 
                l5.setVisibility(View.GONE);
                l6.setVisibility(View.GONE);
                l3.setVisibility(View.VISIBLE);

            }
        });
        tv4.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                l1.setVisibility(View.GONE);
                l2.setVisibility(View.GONE);
                l3.setVisibility(View.GONE); 
                l4.setVisibility(View.GONE); 
                l5.setVisibility(View.GONE);
                l6.setVisibility(View.GONE);
                l4.setVisibility(View.VISIBLE); 
            }
        });
        tv5.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                l1.setVisibility(View.GONE);
                l2.setVisibility(View.GONE);
                l3.setVisibility(View.GONE); 
                l4.setVisibility(View.GONE); 
                l6.setVisibility(View.GONE);
                l5.setVisibility(View.VISIBLE); 
            }
        });
        tv6.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                l1.setVisibility(View.GONE);
                l2.setVisibility(View.GONE);
                l3.setVisibility(View.GONE); 
                l4.setVisibility(View.GONE); 
                l5.setVisibility(View.GONE);
                l6.setVisibility(View.VISIBLE);
            }
        });

    }
}
uma corrida
fonte

Respostas:

706

Você pode fazer duas coisas para adicionar animações. Primeiro, você pode permitir que o layout animado do Android mude para você. Dessa forma, toda vez que você altera algo no layout, como alterar a visibilidade da visualização ou as posições da visualização, o Android cria automaticamente animações de desbotamento / transição. Para usar esse conjunto

android:animateLayoutChanges="true"

no nó raiz no seu layout.

Sua segunda opção seria adicionar manualmente animações. Para isso, sugiro que você use a nova API de animação introduzida no Android 3.0 (Honeycomb). Eu posso dar alguns exemplos:

Isso diminui um View:

view.animate().alpha(0.0f);

Isso desaparece novamente:

view.animate().alpha(1.0f);

Isso move um Viewdown por sua altura:

view.animate().translationY(view.getHeight());

Isso retorna a Viewsua posição inicial depois que foi movido para outro lugar:

view.animate().translationY(0);

Você também pode usar setDuration()para definir a duração da animação. Por exemplo, isso desaparece Viewpor um período de 2 segundos:

view.animate().alpha(0.0f).setDuration(2000);

E você pode combinar quantas animações desejar, por exemplo, isso diminui a Viewe diminui ao mesmo tempo durante um período de 0,3 segundos:

view.animate()
        .translationY(view.getHeight())
        .alpha(0.0f)
        .setDuration(300);

E você também pode atribuir um ouvinte à animação e reagir a todos os tipos de eventos. Como quando a animação começa, quando termina ou se repete etc. Ao usar a classe abstrata, AnimatorListenerAdaptervocê não precisa implementar todos os retornos de chamada de AnimatorListeneruma só vez, mas apenas aqueles que você precisa. Isso torna o código mais legível. Por exemplo, o código a seguir diminui e diminui Viewsua altura por um período de 0,3 segundos (300 milissegundos) e, quando a animação é concluída, sua visibilidade é definida como View.GONE.

view.animate()
        .translationY(view.getHeight())
        .alpha(0.0f)
        .setDuration(300)
        .setListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                view.setVisibility(View.GONE);
            }
        });
Xaver Kapeller
fonte
6
@ Natix Eu não chamaria essa super chamada de redundante. Não faça edições superficiais de que não há nada errado.
Xaver Kapeller
5
É bom, mas o inverso não funciona corretamente por quê? view.setVisibility (View.VISIBLE); WITH alpha (1.0f), aparece com 100 preenchimentos ...
delive
15
É necessário limpar a animação antes de definir a visibilidade >>, view.clearAnimation(); view.setVisibility(View.GONE);caso contrário, o layout permanecerá invisível e não desaparecerá.
Eftekhari 04/07
2
@Eftekhari Eles não consomem muitos recursos. E se você possui uma versão Android atualizada, mas ainda está com um atraso, provavelmente você tem um telefone antigo com pouca memória ou um chip gráfico ruim. E não estou falando de uma nova biblioteca. Os animadores são nativos. Eles fazem parte do Android Framework. Eles foram lançados há 5 anos e hoje 97,9% de todos os dispositivos os suportam. Não há razão para não usar o Animators ou, pelo menos, ViewCompat.animate()que faz parte da biblioteca de suporte e usa Animators em versões mais recentes e Exibir animações no Android 3.0 e abaixo.
Xaver Kapeller
1
Mas quando 97,9% de todos os dispositivos são o Android 4.0 e superior, não resta muito um caso de uso ViewCompat.animate().
Xaver Kapeller
70

A maneira mais fácil de animar as Visibilityalterações é usar as Transition APIdisponíveis no pacote de suporte (androidx). Basta chamar o TransitionManager.beginDelayedTransitionmétodo e alterar a visibilidade da exibição. Existem várias transições padrão, como Fade, Slide.

import androidx.transition.TransitionManager;
import androidx.transition.Transition;
import androidx.transition.Fade;

private void toggle() {
    Transition transition = new Fade();
    transition.setDuration(600);
    transition.addTarget(R.id.image);

    TransitionManager.beginDelayedTransition(parent, transition);
    image.setVisibility(show ? View.VISIBLE : View.GONE);
}

Onde parenté o pai ViewGroupda exibição animada. Resultado:

insira a descrição da imagem aqui

Aqui está o resultado com a Slidetransição:

import androidx.transition.Slide;

Transition transition = new Slide(Gravity.BOTTOM);

insira a descrição da imagem aqui

É fácil escrever uma transição personalizada se você precisar de algo diferente. Aqui está um exemplo com o CircularRevealTransitionqual escrevi em outra resposta . Ele mostra e oculta a vista com a animação CircularReveal.

Transition transition = new CircularRevealTransition();

insira a descrição da imagem aqui

android:animateLayoutChanges="true"opção faz a mesma coisa, apenas usa a AutoTransition como transição.

ashakirov
fonte
@TouhidulIslam no. Este classes disponíveis no pacote androidx. Tudo é compatível com versões anteriores
ashakirov 29/07/19
2
Que tal expandir / recolher um grupo de visualizações?
TheRealChx101
Você pode fazer vários beginDelayedTransitions?
Jeongbebs
26

Por favor, verifique este link. O que permitirá animações como L2R, R2L, T2B, B2T.

Este código mostra animação da esquerda para a direita

TranslateAnimation animate = new TranslateAnimation(0,view.getWidth(),0,0);
animate.setDuration(500);
animate.setFillAfter(true);
view.startAnimation(animate);
view.setVisibility(View.GONE);

Se você quiser fazê-lo no R2L, use

TranslateAnimation animate = new TranslateAnimation(0,-view.getWidth(),0,0);

para cima para baixo como

TranslateAnimation animate = new TranslateAnimation(0,0,0,view.getHeight());

e vice-versa ..

Null Pointer Exception
fonte
8
Isso desloca a vista de sua posição original.
Relm
24

Tente adicionar esta linha ao layout pai xml

 android:animateLayoutChanges="true"

Seu layout ficará assim

<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:animateLayoutChanges="true"
    android:longClickable="false"
    android:orientation="vertical"
    android:weightSum="16">

    .......other code here

    </LinearLayout>
Ricardo Romo
fonte
isso funcionou para mim. Minha configuração usa um layout de restrição como visualização raiz. Quando o ponto de vista é definido como View.VISIBLE a animação é mostrado
EdgeDev
solução muito simples e elegante
Naveed Ahmad
11

Com base na resposta do @Xaver Kapeller, descobri uma maneira de criar animação de rolagem quando novas visualizações aparecerem na tela (e também animação para ocultá-las).

Vai deste estado:

  • Botão
  • Último botão

para

  • Botão
  • Botão 1
  • Botão 2
  • Botão 3
  • Botão 4
  • Último botão

e vice versa.

Assim, quando o usuário clicar no primeiro botão, os elementos "Botão 1", "Botão 2", "Botão 3" e "Botão 4" aparecerão usando animação fade e o elemento "Último botão" será movido para baixo até o final. A altura do layout também será alterada, permitindo o uso correto da exibição de rolagem.

Este é o código para mostrar elementos com animação:

private void showElements() {
    // Precondition
    if (areElementsVisible()) {
        Log.w(TAG, "The view is already visible. Nothing to do here");
        return;
    }

    // Animate the hidden linear layout as visible and set
    // the alpha as 0.0. Otherwise the animation won't be shown
    mHiddenLinearLayout.setVisibility(View.VISIBLE);
    mHiddenLinearLayout.setAlpha(0.0f);
    mHiddenLinearLayout
            .animate()
            .setDuration(ANIMATION_TRANSITION_TIME)
            .alpha(1.0f)
            .setListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    super.onAnimationEnd(animation);
                    updateShowElementsButton();
                    mHiddenLinearLayout.animate().setListener(null);
                }
            })
    ;

    mLastButton
            .animate()
            .setDuration(ANIMATION_TRANSITION_TIME)
            .translationY(mHiddenLinearLayoutHeight);

    // Update the high of all the elements relativeLayout
    LayoutParams layoutParams = mAllElementsRelativeLayout.getLayoutParams();

    // TODO: Add vertical margins
    layoutParams.height = mLastButton.getHeight() + mHiddenLinearLayoutHeight;
}

e este é o código para ocultar elementos da animação:

private void hideElements() {
    // Precondition
    if (!areElementsVisible()) {
        Log.w(TAG, "The view is already non-visible. Nothing to do here");
        return;
    }

    // Animate the hidden linear layout as visible and set
    mHiddenLinearLayout
            .animate()
            .setDuration(ANIMATION_TRANSITION_TIME)
            .alpha(0.0f)
            .setListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    Log.v(TAG, "Animation ended. Set the view as gone");
                    super.onAnimationEnd(animation);
                    mHiddenLinearLayout.setVisibility(View.GONE);
                    // Hack: Remove the listener. So it won't be executed when
                    // any other animation on this view is executed
                    mHiddenLinearLayout.animate().setListener(null);
                    updateShowElementsButton();
                }
            })
    ;

    mLastButton
            .animate()
            .setDuration(ANIMATION_TRANSITION_TIME)
            .translationY(0);

    // Update the high of all the elements relativeLayout
    LayoutParams layoutParams = mAllElementsRelativeLayout.getLayoutParams();

    // TODO: Add vertical margins
    layoutParams.height = mLastButton.getHeight();
}

Observe que há um truque simples no método para ocultar a animação. No ouvinte de animação mHiddenLinearLayout, tive que remover o próprio ouvinte usando:

mHiddenLinearLayout.animate().setListener(null);

Isso ocorre porque, quando um ouvinte de animação é anexado a uma exibição, na próxima vez que qualquer animação for executada nessa exibição, o ouvinte também será executado. Isso pode ser um bug no ouvinte de animação.

O código fonte do projeto está no GitHub: https://github.com/jiahaoliuliu/ViewsAnimated

Feliz codificação!

Atualização : para qualquer ouvinte conectado às visualizações, ele deve ser removido após o término da animação. Isso é feito usando

view.animate().setListener(null);
jiahao
fonte
Esta é a melhor resposta
Naveen Kumar M
1
A view.animate().setListener(null);declaração salvou meu dia. Definitivamente, isso parece ser um bug.
Michal Vician
@MichalVician Fico feliz que sim!
Jiahao
8

Consegui mostrar / ocultar um menu desta maneira:

MenuView.java (estende FrameLayout)

private final int ANIMATION_DURATION = 500;

public void showMenu()
{
    setVisibility(View.VISIBLE);
    animate()
            .alpha(1f)
            .setDuration(ANIMATION_DURATION)
            .setListener(null);
}

private void hideMenu()
{
    animate()
            .alpha(0f)
            .setDuration(ANIMATION_DURATION)
            .setListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    setVisibility(View.GONE);
                }
            });
}

Fonte

Nelson Almendra
fonte