2012-01-04 10 views
49

Jak programowo przetłumaczyć dowolny widok bez korzystania z animacji (android.view.animation.*)?Programatycznie przetłumaczyć przeglądanie w widoku pionowym

API 11 wprowadzono setTranslationX i setTranslationY, setX i setY i getMatrix — z których wszystkie mogą być wykorzystane do osiągnięcia co szukam. Nie mogę jednak znaleźć odpowiednika na wcześniejszych poziomach API.

W swojej implementacji android.view.animation.TranslateAnimation używa getMatrix (już od API 4), ale przez ten czas był prywatnym API.

Czy jest jakiś sposób, aby to osiągnąć bez uciekania się do refleksji?

+76

Ten niezręczny moment, kiedy masz zamiar odpowiedzieć „używać nineoldandroid” ... – yarian

Odpowiedz

14

Ulubione ponieważ chciałbym być udowodnione źle na tym jednym, ale wpadłem na podobny ściany podczas wykonywania niektórych badań Drag-n-drop chwilę z powrotem.

Jestem prawie pewien, że utknąłeś z offsetTopAndBottom() i offsetLeftAndRight() do przenoszenia View wokół bez animacji we wczesnych API. Dużym minusem jest to, że metody te faktycznie modyfikują wartości górną/dolną/lewą/prawą, więc jeśli chcesz wrócić do miejsca, z którego zacząłeś, musisz wykonać dość ciężkie śledzenie.

Innym rozwiązaniem byłoby po prostu użyć TranslateAnimation o bardzo krótkim czasie trwania i ustawić fillAfter ...

Inne opcje wymagają podklasy, a mimo to nie są ładne, jak tłumaczenia CanvasView rysuje dalej. Problem polega na tym, że musisz utworzyć rodzica, który nie klipuje swoich dzieci, aby widok mógł rysować poza własnymi granicami.

+0

Możesz także użyć klasy kontenera podklasy, której używasz, zastąpisz jej metodę onLayout i ustaw x/y/width/height z tam do dowolnych wartości w dowolnym momencie dla każdego widoku – Grishka

+6

To jest głupia sytuacja. Ironią jest to, że tak naprawdę próbuje animować tłumaczenie tych widoków, ale za pośrednictwem interfejsu API Honeycomb (http://nineoldandroids.com). Miałem nadzieję dostarczyć kompatybilną implementację sortów bezpośrednio w bibliotece na potrzeby tłumaczenia przed ubojem, tak, że ktoś korzystający z biblioteki nie musiał specjalnego przypadku w swoim własnym kodzie. Próbowałem metod przesunięcia, jak powiedziałeś, ale jest to dość trudne, niezawodnie śledząc oryginalną lokalizację i przewidywanie lokalizacji klatki kluczowej. Refleksja wygląda coraz lepiej ... –

+0

Czy udało Ci się wprowadzić tę implementację kompilacji? To byłoby niesamowite! – yahya

11

Tak, możesz użyć TłumaczAnimation. Przy ustawieniu fillAfter na wartość true Twój widok pozostanie przetłumaczony nawet po zakończeniu animacji. Oto przykład:

TranslateAnimation anim=new TranslateAnimation(0, 0, 20, 20); 
anim.setFillAfter(true); 
anim.setDuration(0); 
yourView.startAnimation(anim); 
+1

To działa, niestety widoki pozostaną w ich pierwotnej lokalizacji, co oznacza, że ​​cele typu "kliknij/dotknij" nie będą się przesuwać :( – alopix

+0

To jest niesamowite ... dzięki – shripal

+0

jego działanie, ale kliknięcie będzie w tym samym miejscu dla tłumaczenia przed ubojem. rozwiązanie? – Ram

1

Wystąpił ten sam problem. Udało mi się osiągnąć tłumaczenie, manipulując układem stron, w szczególności marginesami, poglądów, które chciałem przetłumaczyć. Możesz użyć wartości ujemnych dla marginesów btw.

+0

Najlepsze rozwiązanie, gdy chcesz także przenosić cele dotykowe i dotykowe :) – alopix

6

Odpowiedź Grishki bardzo mi pomogła, działa idealnie. W celu animacji tłumaczenia za pomocą interfejsu API Honeycomb z dziewięciolamelami, ustawiłem FloatEvaluator dla wartości translacji, a następnie użyłem setTranslationX na Honeycomb + lub w metodzie TranslateAnimation. Tu jest mój kodu:

public class TranslationXEvaluator extends FloatEvaluator { 

private View view; 

public TranslationXEvaluator(View view) { 
    this.view = view; 
} 

@Override 
public Float evaluate(float fraction, Number startValue, Number endValue) { 
    float translationX = super.evaluate(fraction, startValue, endValue); 
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 
     view.setTranslationX(translationX); 
    } else { 
     TranslateAnimation anim = new TranslateAnimation(translationX, translationX, 0, 0); 
     anim.setFillAfter(true); 
     anim.setDuration(0); 
     view.startAnimation(anim); 
    } 
    return translationX; 
} 

} 
1

Jedną z alternatyw dla TranslateAnimation jest podklasowanie widoku i tłumaczenie płótna w dispatchDraw. Coś jak:

public class TranslateView extends View { 

     private float mTranslationX = 0; 
     private float mTranslationY = 0; 
     private boolean mWillUseSDKTranslation = true; 

     @Override 
     protected void dispatchDraw(final Canvas canvas) { 
      if (mWillUseSDKTranslation == false) { 
       // keep track of the current state 
       canvas.save(Canvas.MATRIX_SAVE_FLAG); 
       // translate 
       canvas.translate(mTranslationX, mTranslationY); 
       // draw it 
       super.dispatchDraw(canvas); 
       // restore to the previous state 
       canvas.restore(); 
      } else { 
       super.dispatchDraw(canvas); 
      } 
     } 

     public void setTranslationValue(final float aTranslationX, final float aTranslationY) { 
      if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { 
       mWillUseSDKTranslation = false; 
       mTranslationX = aTranslationX; 
       mTranslationY = aTranslationY; 
       invalidate(); 
      } else { 
       setTranslationX(aTranslationX); 
       setTranslationY(aTranslationY); 
      } 
     } 

    } 
0

Rozwiązaniem znalazłem ustawić marginesy ujemne przy użyciu:

layoutParams.setMargins(left, top, right, bottom); 
yourView.setLayoutParams(layoutParams); 
Powiązane problemy