0

次の要件を持つアプリがあります

  1. 通常、リスト ビューの行の背景は白である必要があります。
  2. 選択されている場合、リスト ビュー行の背景は青である必要があります。
  3. 2 つのリスト ビュー行に対してアニメーションを実行し、からに遷移させます。

この種の問題を解決するには、セレクターとトランジションを利用できそうです。

linear_layout_selector.xml

<?xml version="1.0" encoding="utf-8"?>    
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:drawable="@drawable/blue" />

    <item android:drawable="@drawable/linear_layout_transition" />
</selector>

linear_layout_transition.xml

<?xml version="1.0" encoding="utf-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/white" />
    <item android:drawable="@drawable/red" />
</transition>

simple_list_item_1.xml

<?xml version="1.0" encoding="utf-8"?>

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/text1"
    android:layout_width="match_parent"
    android:layout_height="48dp"
    android:background="@drawable/linear_layout_selector"
/>

アニメーションを実行する Java コード

{
    // Animate 1st row.
    View view0 = this.getListView().getChildAt(0);
    StateListDrawable stateListDrawable = (StateListDrawable)view0.getBackground();    
    Drawable currentDrawable = stateListDrawable.getCurrent();
    if (currentDrawable instanceof TransitionDrawable) {
        final TransitionDrawable transitionDrawable = (TransitionDrawable) currentDrawable;
        transitionDrawable.resetTransition();
        transitionDrawable.startTransition(0);
        transitionDrawable.reverseTransition(1000);
    } else {
        Log.i("CHEOK", "WTF! 1st currentDrawable is " + currentDrawable);
    }
}
{
    // Animate 3rd row.
    View view2 = this.getListView().getChildAt(2);
    StateListDrawable stateListDrawable = (StateListDrawable)view2.getBackground();    
    Drawable currentDrawable = stateListDrawable.getCurrent();
    if (currentDrawable instanceof TransitionDrawable) {
        final TransitionDrawable transitionDrawable = (TransitionDrawable) currentDrawable;
        transitionDrawable.resetTransition();
        transitionDrawable.startTransition(0);
        transitionDrawable.reverseTransition(1000);
    } else {
        Log.i("CHEOK", "WTF! 3rd currentDrawable is " + currentDrawable);
    }
}

Android 4.1 および Android 2.3.3 のように、すべてが期待どおりに機能します。

しかし、Android 4.2 になると、問題が発生します。正常な状態では、次のことが観察されました。

ここに画像の説明を入力

  1. 通常時は2列目から全列が赤くなっていました。
  2. 通常の状況では、1 行目の背景は のままTransitionDrawableです。ただ、2列目以降の背景は謎が多めでした。これはログから確認できます

なんてこった!3番目の currentDrawable は android.graphics.drawable.LayerDrawable@b3068498 です

この問題を説明するための完全なプロジェクトは、 https ://www.dropbox.com/s/hbalqjzzw5tu7e9/transition_bug.zip からダウンロードできます。

ふと思ったのですが、これはバグですか?なぜ になるTransitionDrawableことができLayerDrawableますか?これを克服するための回避策はありますか?

ノート

linear_layout_transitionTextView の背景として直接適用すると、問題はなくなります。ただし、セレクターが提供する機能は失われます。

4

1 に答える 1

1

これは JellyBean のバグのようです。Resources#getDrawable(int)最初のリクエストでは正しいタイプ ( TransitionDrawable) を返しますが、連続するリクエストでは間違ったタイプ (この場合はLayerDrawable) を返します。

次のようにクローンを作成するときに同じことが起こることに気付きましたDrawable(自分自身をキャッシュして再利用しようとしていましたDrawable)。

Drawable clonedDrawable = backgroundDrawable.getConstantState().newDrawable();
convertView.setBackgroundDrawable(clonedDrawable);

この問題は、セレクターを ListView ( ListView#setSelector(int)) に設定TransitionDrawableし、リスト項目 ( convertView) の背景として設定することで解決できます。

于 2013-07-22T15:29:49.887 に答える