6

Pracowałem głównie z iOS i przyzwyczaiłem się do bardzo płynnych i płynnych animacji zmian ekranu. Pracuję teraz nad aplikacją na Androida i nie mogę przez całe życie uzyskać transakcji fragmentacji, aby płynnie dodawać/zamieniać fragment.Jak uzyskać płynne animacje transakcji fragmentów na Androidzie

Mój set up przedstawia się następująco: MainActivity ma FrameLayout dla swojej xml, który od razu załadować FragmentA się na MainActivity „s OnCreate. Moja aplikacja następnie zastąpi z FragmentB, , , ect. Moja cała aplikacja ma 1 aktywność.

na kliknięcia przycisku nazywam następujące czynności, aby dodać/wymienić aktualny fragment:

 getFragmentManager() 
      .beginTransaction() 
      .setCustomAnimations(R.animator.slide_in, android.R.animator.fade_out, android.R.animator.fade_in, R.animator.slide_out) 
      .addToBackStack(null) 
      .add(R.id.fragment_1, fragment) 
      .commit(); 

slide_in.xml wygląda (slide_out.xml jest oczywiście odwrotnie):

<?xml version="1.0" encoding="utf-8"?> 
<set xmlns:android="http://schemas.android.com/apk/res/android"> 
    <objectAnimator 
      android:interpolator="@android:interpolator/linear" 
      android:propertyName="xFraction" 
      android:valueType="floatType" 
      android:valueFrom="1.0" 
      android:valueTo="0" 
      android:duration="@android:integer/config_shortAnimTime" 
     /> 
</set> 

przesuwne w i obecnie jestem animowanie xFraction który mam podklasy LinearLayout zrobić tak:

public class SlidingLinearLayout extends LinearLayout { 

    private float yFraction = 0; 
    private float xFraction = 0; 

    public SlidingLinearLayout(Context context) { 
     super(context); 
    } 

    public SlidingLinearLayout(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    public SlidingLinearLayout(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
    } 

    private ViewTreeObserver.OnPreDrawListener preDrawListener = null; 

    public void setYFraction(float fraction) { 

     this.yFraction = fraction; 

     if (getHeight() == 0) { 
      if (preDrawListener == null) { 
       preDrawListener = new ViewTreeObserver.OnPreDrawListener() { 
        @Override 
        public boolean onPreDraw() { 
         getViewTreeObserver().removeOnPreDrawListener(preDrawListener); 
         setYFraction(yFraction); 
         return true; 
        } 
       }; 
       getViewTreeObserver().addOnPreDrawListener(preDrawListener); 
      } 
      return; 
     } 

     float translationY = getHeight() * fraction; 
     setTranslationY(translationY); 
    } 

    public float getYFraction() { 
     return this.yFraction; 
    } 

    public void setXFraction(float fraction) { 

     this.xFraction = fraction; 

     if (getWidth() == 0) { 
      if (preDrawListener == null) { 
       preDrawListener = new ViewTreeObserver.OnPreDrawListener() { 
        @Override 
        public boolean onPreDraw() { 
         getViewTreeObserver().removeOnPreDrawListener(preDrawListener); 
         setXFraction(xFraction); 
         return true; 
        } 
       }; 
       getViewTreeObserver().addOnPreDrawListener(preDrawListener); 
      } 
      return; 
     } 

     float translationX = getWidth() * fraction; 
     setTranslationX(translationX); 
    } 

    public float getxFraction() { 
     return xFraction; 
    } 
} 

Więc mój problem jest przez większość czasu, kiedy najpierw kliknąłem przycisk, aby dodać/zastąpić fragment, nie otrzymuję animacji, którą po prostu wyskakuje na miejsce. Jednak więcej razy, gdy naciśniesz przycisk Wstecz, a fragment wyskoczy z backstacku, animacja zostanie wykonana zgodnie z oczekiwaniami. Czuję, że jest to problem z inicjalizacją podczas próby animowania. Kiedy fragment jest w pamięci i animowany poza ekranem, robi to o wiele lepiej, niż gdy tworzony jest nowy fragment, a następnie animowany na ekranie. Ciekaw jestem, czy inni tego doświadczyli, a jeśli tak, to jak to rozwiązali.

To jest irytacja, która nękała moją twórczość na Androida, którą chciałbym odpocząć! Każda pomoc będzie bardzo ceniona. Dzięki!

+0

Ostatnio miałem ten sam problem. Po raz pierwszy przejście przebiega, jest trochę janky. Odkryłem, że wyeliminowanie niepotrzebnych alfów pomaga, ale nie usuwa całkowicie problemu. – Eliezer

Odpowiedz

1

Z mojego doświadczenia wynika, że ​​jeśli fragment wykonuje zbyt dużo pracy przy obciążeniu, system zasadniczo pominie animację enter i po prostu wyświetli fragment. W moim przypadku rozwiązaniem było utworzenie detektora animacji w module onCreateAnimation, aby poczekać, aż animacja wejścia zakończy się przed wykonaniem intensywnej pracy, która spowodowała pominięcie animacji.

@Override 
public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) { 
    if (nextAnim == 0) { 
     return super.onCreateAnimation(transit, enter, nextAnim); 
    } 

    Animation anim = android.view.animation.AnimationUtils.loadAnimation(getContext(), nextAnim); 
    anim.setAnimationListener(new Animation.AnimationListener() { 
     @Override 
     public void onAnimationStart(Animation animation) {} 
     @Override 
     public void onAnimationEnd(Animation animation) { 
      // Do any process intensive work that can wait until after fragment has loaded 
     } 

     @Override 
     public void onAnimationRepeat(Animation animation) {} 
    }); 
    return anim; 
} 
Powiązane problemy