Android dodaje proste animacje przy ustawianiu widoczności (widok. Odszedł)


237

Zaprojektowałem prosty układ. Skończyłem projekt bez animacji, ale teraz chcę dodawać animacje po zdarzeniu kliknięcia widoku tekstu i nie wiem, jak go używać. Czy mój projekt xml wygląda dobrze, czy nie? Wszelkie sugestie będą mile widziane.

Mój 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>

Moja 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);
            }
        });

    }
}

Odpowiedzi:


706

Możesz zrobić dwie rzeczy, aby dodać animacje, najpierw możesz pozwolić Androidowi animować zmiany układu dla Ciebie. W ten sposób za każdym razem, gdy zmienisz coś w układzie, takie jak zmiana widoczności widoku lub pozycji widoku, Android automatycznie utworzy animacje przenikania / przejścia. Aby użyć tego zestawu

android:animateLayoutChanges="true"

w węźle głównym w twoim układzie.

Drugą opcją byłoby ręczne dodawanie animacji. W tym celu sugeruję skorzystanie z nowego API animacji wprowadzonego w systemie Android 3.0 (Honeycomb). Mogę podać kilka przykładów:

To zanika View:

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

Powoduje to zanikanie:

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

To przesuwa się w Viewdół o jego wysokość:

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

Spowoduje to powrót Viewdo pozycji początkowej po przeniesieniu w inne miejsce:

view.animate().translationY(0);

Możesz także użyć setDuration()do ustawienia czasu trwania animacji. Na przykład zanika to Vieww ciągu 2 sekund:

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

Możesz łączyć tyle animacji, ile chcesz, na przykład Viewpowoduje to wyciszenie a i przesunięcie go jednocześnie w dół o 0,3 sekundy:

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

Możesz także przypisać słuchacza do animacji i reagować na wszelkiego rodzaju zdarzenia. Podobnie jak w przypadku rozpoczęcia animacji, jej zakończenia lub powtórzenia itp. Używając klasy abstrakcyjnej AnimatorListenerAdapter, nie musisz implementować wszystkich wywołań zwrotnych AnimatorListenernaraz, a tylko tych, których potrzebujesz. Dzięki temu kod jest bardziej czytelny. Na przykład poniższy kod wycisza Viewruch przesuwa go w dół o wysokość w ciągu 0,3 sekundy (300 milisekund), a po zakończeniu animacji jego widoczność jest ustawiona na 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);
            }
        });

6
@Natix Nie nazwałbym tego super połączenia redundantnym. Nie rób powierzchownych zmian, nie ma nic złego.
— Xaver Kapeller

5
Jest dobrze, ale odwrotność nie działa poprawnie, dlaczego? view.setVisibility (View.VISIBLE); Alfa (1.0f), pojawiają się z 100 dopełnienia górze ...
— Dosta

15
Należy wyczyścić animację przed ustawieniem widoczności >> w view.clearAnimation(); view.setVisibility(View.GONE);przeciwnym razie układ pozostanie niewidoczny i nie zniknie.
— Eftekhari

2
@Eftekhari W ogóle nie wymagają dużych zasobów. A jeśli masz aktualną wersję Androida, ale nadal masz opóźnienie, prawdopodobnie masz starszy telefon z niską pamięcią lub złym układem graficznym. I nie mówię o nowej bibliotece. Animatorzy są rodzimi. Są częścią systemu Android. Zostały wydane 5 lat temu i dziś obsługuje je 97,9% wszystkich urządzeń. Nie ma powodu, aby nie używać Animatorów, a przynajmniej ViewCompat.animate()który jest częścią biblioteki obsługi i używa Animatorów w nowszych wersjach i Wyświetl animacje w systemie Android 3.0 i niższych.
— Xaver Kapeller,

1
Ale gdy 97,9% wszystkich urządzeń to Android 4.0 i nowsze, nie ma już zbyt wiele zastosowań ViewCompat.animate().
— Xaver Kapeller,

70

Najłatwiejszym sposobem animowania Visibilityzmian jest użycie Transition APIpakietu dostępnego w pakiecie wsparcia (Androidx). Wystarczy wywołać TransitionManager.beginDelayedTransitionmetodę, a następnie zmienić widoczność widoku. Istnieje kilka domyślnych Przejścia jak 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);
}

Gdzie parentjest rodzicem ViewGroupwidoku animowanego. Wynik:

wprowadź opis zdjęcia tutaj

Oto wynik Slideprzejścia:

import androidx.transition.Slide;

Transition transition = new Slide(Gravity.BOTTOM);

wprowadź opis zdjęcia tutaj

Łatwo jest napisać niestandardowe przejście, jeśli potrzebujesz czegoś innego. Oto przykład, z CircularRevealTransitionktórym napisałem w innej odpowiedzi . Pokazuje i ukrywa widok z animacją CircularReveal.

Transition transition = new CircularRevealTransition();

wprowadź opis zdjęcia tutaj

android:animateLayoutChanges="true"opcja robi to samo, po prostu używa AutoTransition jako przejścia.


@TouhidulIslam no. Te klasy są dostępne w pakiecie Androidx. Wszystko jest kompatybilne wstecz
— ashakirov

2
Co powiesz na rozwijanie / zwijanie grupy widoków?
— TheRealChx101

Czy możesz zrobić wiele beginDelayedTransitions?
— Jeongbebs

26

Sprawdź ten link. Który pozwoli na animacje takie jak L2R, R2L, T2B, B2T.

Ten kod pokazuje animację od lewej do prawej

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

jeśli chcesz to zrobić z R2L, użyj

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

od góry do dołu jako

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

i vice versa ..


8
To przesuwa widok z pierwotnej pozycji.
— Relm

24

Spróbuj dodać tę linię do układu nadrzędnego xml

 android:animateLayoutChanges="true"

Twój układ będzie wyglądał następująco

<?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>

to działało dla mnie. Moja konfiguracja używa układu ograniczenia jako widoku głównego. Gdy widok jest ustawiony na View.VISIBLE, wyświetlana jest animacja
— EdgeDev

bardzo proste i eleganckie rozwiązanie
— Naveed Ahmad

11

Na podstawie odpowiedzi @Xaver Kapeller wymyśliłem sposób tworzenia animacji przewijania, gdy na ekranie pojawiają się nowe widoki (a także animacja, aby je ukryć).

Wynika z tego stanu:

  • Przycisk
  • Ostatni przycisk

do

  • Przycisk
  • Przycisk 1
  • Przycisk 2
  • Przycisk 3
  • Przycisk 4
  • Ostatni przycisk

i wzajemnie.

Tak więc, gdy użytkownik kliknie pierwszy przycisk, elementy „Przycisk 1”, „Przycisk 2”, „Przycisk 3” i „Przycisk 4” pojawią się przy użyciu animacji zanikania, a element „Ostatni przycisk” przesunie się w dół do końca. Zmieni się również wysokość układu, umożliwiając prawidłowe korzystanie z widoku przewijania.

Oto kod pokazujący elementy z animacją:

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;
}

i to jest kod, aby ukryć elementy animacji:

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();
}

Zauważ, że metoda ukrywania animacji jest prosta. W detektorze animacji mHiddenLinearLayout musiałem usunąć sam detektor za pomocą:

mHiddenLinearLayout.animate().setListener(null);

Dzieje się tak, ponieważ po dołączeniu detektora animacji do widoku, następnym razem, gdy jakakolwiek animacja zostanie wykonana w tym widoku, detektor również zostanie wykonany. Może to być błąd w detektorze animacji.

Kod źródłowy projektu znajduje się na GitHub: https://github.com/jiahaoliuliu/ViewsAnimated

Miłego kodowania!

Aktualizacja : dla każdego detektora dołączonego do widoków należy go usunąć po zakończeniu animacji. Odbywa się to za pomocą

view.animate().setListener(null);

To najlepsza odpowiedź
— Naveen Kumar M

1
view.animate().setListener(null);Oświadczenie zapisany mój dzień. To zdecydowanie wydaje się być błędem.
— Michał Vician

@MichalVician Cieszę się, że tak!
— jiahao

8

Byłem w stanie pokazać / ukryć menu w ten sposób:

MenuView.java (rozszerza 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);
                }
            });
}

Źródło

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.