3

ボタンを押すと全体として移動する必要がある ViewPager があります。これにはアニメーションを使用します。

それを押すと、「x」を翻訳します。新しい位置を維持するために setFillAfter(true) を使用します。しかし、ViewPager のページを変更すると、元の x 位置に戻ります!

この問題は Android 4.1 でのみ見られましたが、Android 4.0 では問題ありません! したがって、Android ではある種の回帰のように見えます。

他のすべてのものなしで問題を再現できるテストプロジェクトを添付しました。プロジェクトを Eclipse にインポートして自分の目で確かめるために、これを理解するのを手伝ってくれるのが一番いいと思います。

ビデオにも追加しました。1 つは問題が発生している HTC One X で、もう 1 つは問題が発生していない Android 4.0 搭載のタブレットです。

私は必死にこの醜い副作用を修正しようとしてきましたが、今までうまくいきませんでした...

(動画ファイルが大きくてすみません…)

副作用のない Android 4.0 のビデオ

ビデオ 副作用のある Android 4.1

問題を再現できるプロジェクト

編集:

以下を追加しました。

@Override
public void onAnimationEnd(Animation animation) {
    RelativeLayout.LayoutParams lp = (android.widget.RelativeLayout.LayoutParams) myViewPager.getLayoutParams();
    if (!i)
        lp.setMargins(300,0,0,0);
    else
        lp.setMargins(0,0,0,0);

    myViewPager.setLayoutParams(lp);
}

その後、正しい位置にとどまりますが、アニメーションが最後に表示されているようにすばやく「ちらつき」、マージンを変更すると、アニメーション後のオフセットが表示されます。その後、正しい位置にジャンプします。

4

4 に答える 4

3

主な問題は、アニメーション タイプの選択が間違っているようです。ツールとしてのビュー アニメーションは、ViewPager のような複雑なインタラクティブ オブジェクトで使用することを意図していません。ビューの描画場所の低コストのアニメーションのみを提供します。ユーザー アクションに応答するアニメーション化された ViewPager の視覚的な動作は未定義であり、依存するべきではありません。「ゴスト」を実際のオブジェクトに置き換えると、醜いフリックは当然のことです。

API 11 は、最適化されたパフォーマンスのために Views に組み込まれた特殊なプロパティ アニメーターであるため、このケースで使用することを意図したメカニズム: ViewPropertyAnimator、または特殊化されていませんが、より汎用性の高い ObjectAnimator および AnimatorSet 。

プロパティ アニメーションにより、View は実際にその場所を変更し、そこで正常に機能します。

プロジェクトを作成するには、たとえば ViewPropertyAnimator を使用するには、リスナーの設定を次のように変更します。

btn.setOnClickListener(new OnClickListener() {
    boolean b = false;
    @Override
    public void onClick(View v) {
        if(b) {
            myViewPager.animate().translationX(0f).setDuration(700);
        }
        else {
            myViewPager.animate().translationX(300f).setDuration(700);
        }
        b=!b;
    }
});

xml 構成のみを使用する場合は、|ObjectAnimator および AnimatorSet に固執してください。詳細については、上記のリンクを参照してください。

ハニカム以前のデバイスをサポートしたい場合は、Jake Warton のNineOldAndroids プロジェクトを使用できます。それが役立つことを願っています。

于 2013-05-23T09:48:15.440 に答える
1

Crucero は setFillAfter が無効化後に params を調整しないことについて正しいと言っています。ビューが再レイアウトされると (無効化された後にパスが発生します)、そのレイアウト パラメータは常に適用されるものになるため、元の位置に戻る必要があります。

Jschools は onAnimationEnd について正しいです。デバッガーを使用してソース コードをステップ実行することを強くお勧めします。これにより、onAnimationEnd が起動された後にビューの描画位置に影響を与える更新が行われることが分かります。その時点で実際にレイアウト パラメーターが適用されます。したがって、オフセットを 2 倍にしたことによるちらつき。

しかし、これは適切なタイミングで再レイアウトすることで簡単に解決できます。アニメーションの終了時に再配置ロジックを ui メッセージ キューの最後に配置して、アニメーションの後、レイアウトの前にポーリングされるようにします。迷惑なことにこれを行うことを提案する場所はどこにもありませんが、SDK のリリースで理由をまだ見つけていません (これを 1 回だけ実行し、UI スレッドを誤って使用しない場合)、これが機能しないはずです。

一部の古いデバイスで見つかった別の問題により、アニメーションもクリアします。

だから、試してみてください:

@Override
public void onAnimationEnd(final Animation animation) {
   myViewPager.post(new Runnable() {
       @Override
       public public void run() {
           final RelativeLayout.LayoutParams lp = (android.widget.RelativeLayout.LayoutParams) myViewPager.getLayoutParams();
           if (!someBooleanIPresume)
               lp.setMargins(300,0,0,0);
           else
               lp.setMargins(0,0,0,0);

           myViewPager.setLayoutParams(lp);
           myViewPager.clearAnimation();
       }
}
于 2013-05-22T09:18:05.823 に答える
1

これは、アニメーションの setFillAfter(true) が実際にはビューの位置や属性を変更しないためです。ビューの描画キャッシュのビットマップを作成し、アニメーションが終了する場所に残すだけです。画面が再び無効になると (つまり、ViewPager でページが変更されると)、ビットマップは削除され、View が元の位置に戻っているように見えますが、実際には既にそこにありました。

アニメーションが終了した後もビューの位置を保持したい場合は、目的の効果に合わせてビューの LayoutParams を実際に調整する必要があります。これを実現するには、アニメーションの onAnimationEnd メソッドをオーバーライドし、その中のビューの LayoutParams を調整します。

LayoutParams を調整したら、setFillAfter(true) への呼び出しを削除すると、ビューは実際に期待どおりの場所に留まります。

于 2013-05-13T13:39:50.743 に答える