2011-12-31 15 views
14

Próbuję animować dwie warstwy przeciągania, aby uzyskać efekt wskaźnika nieokreślonego postępu po usunięciu miodu. Kod XML jest bardzo prosty, ale wydaje się, że tylko jedna warstwa będzie animowana po uruchomieniu na platformach przed Honeycomb.Animacja dwuwarstwowych elementów do rysowania Pre-Honeycomb

<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> 
    <item> 
     <rotate 
      android:drawable="@drawable/abs__spinner_48_outer_holo" 
      android:pivotX="50%" 
      android:pivotY="50%" 
      android:fromDegrees="0" 
      android:toDegrees="1080" /> 
    </item> 
    <item> 
     <rotate 
      android:drawable="@drawable/abs__spinner_48_inner_holo" 
      android:pivotX="50%" 
      android:pivotY="50%" 
      android:fromDegrees="720" 
      android:toDegrees="0" /> 
    </item> 
</layer-list> 

Jest to tylko ograniczenie tych platform czy istnieje alternatywny składni, które można użyć (albo ogólnie lub specyficznie kierowane we wstępnie API11) w celu osiągnięcia żądanej funkcji?

Odpowiedz

11

Rzeczywiście istnieje ograniczenie platformy, mimo że nie jest to coś, co można by pomyśleć. Problem polega na tym, że pre-API11, RotateDrawable zawierał jakiś surowy kod, który wymagałby, aby animacja obracała się zgodnie z ruchem wskazówek zegara, sprawdzając, czy toDegrees była większa niż ; jeśli nie, obaj zostali przymusowi równi wobec siebie. Jeśli zmodyfikowałeś swój przykład, aby drugi element poruszał się w kierunku do przodu (od 0 do 720, lub nawet od -720 do 0), oba obrazy byłyby animowane poprawnie na wszystkich platformach; choć zdaję sobie sprawę, że pokonuje cel tego, do czego dążysz.

Spójrz na wersję z pamięci podręcznej Google Codesearch ma RotateDrawable.inflate(), która jest wersją 2.3 metody użytej do przekształcenia XML w obiekt, a zobaczysz, co mam na myśli.

RotateDrawable.java ... kod wykraczająca jest około 235 linii ...

float fromDegrees = a.getFloat(
      com.android.internal.R.styleable.RotateDrawable_fromDegrees, 0.0f); 
    float toDegrees = a.getFloat(
      com.android.internal.R.styleable.RotateDrawable_toDegrees, 360.0f); 

    toDegrees = Math.max(fromDegrees, toDegrees); //<--There's the culprit 

Dzieje bloku XML podobny do drugiego elementu, który tam masz, i zamienia ją w RotateDrawable że kończy się z ta sama wartość dla fromDegrees i toDegrees (w twoim przypadku, 720), powodując po prostu zatrzymanie obrazu. Możesz to sprawdzić, ustawiając wartość początkową na pewną wartość, nie wielokrotność 360 (jak 765). Zobaczysz, że obraz nadal nie jest animowany, ale jest obrócony do początkowej współrzędnej.

Ta niezręczna kontrola została usunięta ze źródeł typu Honeycomb/ICS, dlatego można wykonywać rotacje wstecz na tych platformach. Także, to nie wygląda istnieje sposób, aby ustawić te wartości z kodu Java, więc zwyczaj RotateDrawableCompat może być w przyszłości :)

HTH

+1

Doskonały wgląd w wewnętrzne funkcjonowanie. Dziękuję Ci! –

+0

Zaktualizowany odnośnik: https://github.com/android/platform_frameworks_base/blob/android-2.3.7_r1/graphics/java/android/graphics/drawable/RotateDrawable.java#L230-235 –

1

Wydaje się szybkiego i brudne rozwiązania, aby to praca w przedziale plastra miodu polega na tym, aby po prostu obrócić z i do drugiego obrotu. To nie jest idealne, ale przynajmniej coś się kręci (nawet jeśli jest trochę bardziej "nudne"). Wygląda na to, że ABS to rozwiązał.

<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> 
    <item> 
     <rotate 
      android:drawable="@drawable/abs__spinner_48_outer_holo" 
      android:pivotX="50%" 
      android:pivotY="50%" 
      android:fromDegrees="0" 
      android:toDegrees="1080" /> 
    </item> 
    <item> 
     <rotate 
      android:drawable="@drawable/abs__spinner_48_inner_holo" 
      android:pivotX="50%" 
      android:pivotY="50%" 
      android:fromDegrees="0" 
      android:toDegrees="720" /> <!-- Like this --> 
    </item> 
    </layer-list> 
Powiązane problemy