2012-06-25 29 views
20

Po pierwszym kliknięciu przycisku przesuńmy wzdłuż osi X View (o 200 pikseli po prawej). I po drugim naciśnięciu przycisku, chcę przesunąć View z powrotem wzdłuż osi X do pierwotnej pozycji.Jak animować tłumaczenie widoku

Sposób View.setTranslationX(float)skacze Widok na docelowych miejscach z poziomych połączeń myView.setTranslationX(200); i myView.setTranslationX(0); odpowiednio. Czy ktoś wie, jak mogę przesunąć do docelowych lokalizacji poziomych?

Uwaga 1: A TranslateAnimation nie jest dobre, ponieważ w rzeczywistości nie poruszać się View ale tylko przedstawia złudzenie nim poruszać.

Uwaga 2: Nie zdawałem sobie sprawy w momencie stawiając pytanie, że metody setTranslationX(float) i setTranslationY(float) zostały wprowadzone jako API Level 11. Jeśli kierujesz Honeycomb (API poziom 11) w górę, a następnie Gautam Odpowiedź K wystarczy. W przeciwnym razie zobacz moją odpowiedź na sugerowane rozwiązanie.

Odpowiedz

5

Ten przez kilka dni mnie zaskoczył (robił to przed Ice Cream Sandwich), ale myślę, że W końcu tam dotarłem!(podziękowania dla Gautama K i Mike'a Israela za prowadzenie) W końcu to, co zrobiłem, to przedłużenie mojego View (a FrameLayout), aby rozpocząć tłumaczenie animacji prawej/lewej, zgodnie z wymaganiami, i słuchanie końca animacji w celu relokacji moja FrameLayout prawo/lewo w stosownych przypadkach, w następujący sposób:

public class SlidingFrameLayout extends FrameLayout 
{ 
    private final int durationMilliseconds = 1000; 
    private final int displacementPixels = 200; 

    private boolean isInOriginalPosition = true; 
    private boolean isSliding = false; 

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

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

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

    @Override 
    protected void onAnimationEnd() 
    { 
    super.onAnimationEnd(); 

    if (isInOriginalPosition) 
     offsetLeftAndRight(displacementPixels); 
    else 
     offsetLeftAndRight(-displacementPixels); 

    isSliding = false; 
    isInOriginalPosition = !isInOriginalPosition; 
    } 

    @Override 
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) 
    { 
    super.onLayout(changed, left, top, right, bottom); 

    // need this since otherwise this View jumps back to its original position 
    // ignoring its displacement 
    // when (re-)doing layout, e.g. when a fragment transaction is committed 
    if (changed && !isInOriginalPosition) 
     offsetLeftAndRight(displacementPixels); 
    } 

    public void toggleSlide() 
    { 
    // check whether frame layout is already sliding 
    if (isSliding) 
     return; // ignore request to slide 

    if (isInOriginalPosition) 
     startAnimation(new SlideRightAnimation()); 
    else 
     startAnimation(new SlideLeftAnimation()); 

    isSliding = true; 
    } 

    private class SlideRightAnimation extends TranslateAnimation 
    { 
    public SlideRightAnimation() 
    { 
     super(
      Animation.ABSOLUTE, 0, 
      Animation.ABSOLUTE, displacementPixels, 
      Animation.ABSOLUTE, 0, 
      Animation.ABSOLUTE, 0); 

     setDuration(durationMilliseconds); 
     setFillAfter(false); 
    } 
    } 

    private class SlideLeftAnimation extends TranslateAnimation 
    { 
    public SlideLeftAnimation() 
    { 
     super(
      Animation.ABSOLUTE, 0, 
      Animation.ABSOLUTE, -displacementPixels, 
      Animation.ABSOLUTE, 0, 
      Animation.ABSOLUTE, 0); 

     setDuration(durationMilliseconds); 
     setFillAfter(false); 
    } 
    } 
} 

I wreszcie, aby przesunąć SlidingFrameLayout prawo/lewo, wszystko co masz zrobić, to wywołać metodę SlidingFrameLayout.toggleSlide(). Oczywiście możesz poprawić to SlidingFrameLayout dla swoich celów, aby przesuwać większą liczbę pikseli, przesuwać na dłużej itp., Ale to powinno wystarczyć do rozpoczęcia :)

25

Spróbuj patrząc ObjectAnimator i jego klasie Super Value Animator

można zrobić coś takiego ObjectAnimator anim = ObjectAnimator.ofFloat(this, "translationX", 0,200); a następnie anim.start();

Użyj wartości boolean i przestawić go z 200,0 w animatora obiektu cofnąć

PS: można użyć setDuration metoda, aby ustawić jak długo animacja powinna zakończyć

Edycja:

Spróbuj patrząc na support library który zapewnia kompatybilność wsteczną.

Edit

Jak @AdilHussain wskazał tam jest biblioteką nazywa nineoldandroids które mogą być używane w tym samym celu na starszych androidów.

+0

@AdilHussain: wtedy musisz zaimplementować funkcjonalność z wątkami się na telefonach, które go nie obsługują. Po prostu sprawdź, czy telefon go obsługuje, lub napisz coś prostego. To najlepsza opcja. – Gautam

+1

Znaleziono tę wspaniałą bibliotekę, która spełnia swoją funkcję: [http://nineoldandroids.com] (http://nineoldandroids.com). Biblioteka dostępna do pobrania jako "jar" stąd: [https://github.com/JakeWharton/NineOldAndroids/downloads](https://github.com/JakeWharton/NineOldAndroids/downloads) –

+1

Wygląda na to, że mówiłem za wcześnie. Podczas tłumaczenia za pomocą biblioteki [nineoldandroids] (https://github.com/JakeWharton/NineOldAndroids) na starszych telefonach (przed Honeycomb) wydaje się, że przyciski w przetłumaczonym widoku zostały przeniesione, ale nadal można je kliknąć w ich starych lokalizacjach (a nie ich nowe lokalizacje). Wysłałem e-maila do autora biblioteki, ale jeszcze nie otrzymałem odpowiedzi. –

2

Miałem podobny problem, TranslateAnimation faktycznie przenosi widok, jeśli teraz wywołasz setFillAfter (android bug). Musiałem zrobić coś podobnego, więc powiedziałem: hej, użyjmy odbiornika animacji, a następnie przenieśmy wszystko do właściwej lokalizacji. Niestety jest też błąd w słuchaczach animacji (stackoverflow solution). Stworzyłem więc własną klasę layoutu zgodnie z rozwiązaniem w stackoverflow solution i dobrze mi było pójść :)

+0

Dzięki za odpowiedź i linki. Chodzi o to, że użycie 'TranslateAnimation' do tego jest trochę nieporządne. Kiedy powiedziałem, że "TranslateAnimation" faktycznie nie przesuwa widoku (pomimo użycia 'setFillAfter (true)'), miałem na myśli, że klikalne elementy są nadal w swoich oryginalnych pozycjach. Zobacz ten film wideo, aby zobaczyć przykład: [http://www.youtube.com/watch?v=VY3kMFrA3wU](http://www.youtube.com/watch?v=VY3kMFrA3wU) –

+1

tak, wygląda dokładnie jak błąd z fillAfter. Dziwne, że pierwszy przycisk działa, jaka jest różnica między tymi dwoma przyciskami? – MikeIsrael

+1

Zalecane rozwiązanie powinno nadal działać we wszystkich wersjach. Zbudowałem niestandardową klasę układu, która zastępuje onAnimationEnd() i tam zmienię marginleft obiektu w razie potrzeby, aby przenieść go do właściwego miejsca. – MikeIsrael