4

ActionBarSherlockアクションバーにAsyncTaskを開始するメニューオプションがあります。バックグラウンドタスクの実行中にアイコンをアニメーション化しようとしています。アイコンをクリックすると、アイコン自体が数ピクセル右に「ジャンプ」し、非常に目立つことを除いて、私はそれを機能させています。何がそれを引き起こしているのか正確にはわかりません。

これは私がこれまでに持っているものです:

private MenuItem refreshItem;   

private void DoRefresh() 
{
    final LayoutInflater inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    final ImageView ivRefresh = (ImageView)inflater.inflate(R.layout.refresh_view, null);

    final Animation rotation = AnimationUtils.loadAnimation(activity, R.anim.refresh);
    ImageView ivRefresh.startAnimation(rotation);

    refreshItem.setActionView(ivRefresh);

    //AsyncTask is kicked off here
}

@Override
public boolean onOptionsItemSelected(final MenuItem item) 
{
    if (item.getItemId() == R.id.refresh) {
        refreshItem = item;
        this.DoRefresh();
        return true;
    } else {
        return super.onOptionsItemSelected(item);
    }
}

refresh_view.xml

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

<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:src="@drawable/refresh"
/>

refresh.xml

<rotate
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromDegrees="0"
    android:toDegrees="360"
    android:pivotX="50%"
    android:pivotY="50%"
    android:repeatCount="infinite"
    android:interpolator="@android:anim/linear_interpolator"
    android:duration="1100" 
/>

アップデート:

運が悪かったので、これをいじくり回していた。アニメーションを無効にしても、アイコンが右にジャンプするため、アニメーションとは関係ありません。コメントアウトするsetActionViewと、アイコンがジャンプしないので、それと関係があります。手がかりがない、私を狂わせる。

4

4 に答える 4

0

これが効果があるかどうかはわかりませんが、pivot値を試してみると、この問題を解決できる可能性があります。おそらく、1つの軸を中心に回転するだけですか?

于 2012-04-11T09:21:03.623 に答える
0

Alex Fu、あなたの記事は非常に役に立ちましたが、いくつかの改善が可能です。

毎回onAnimationEndでアニメーションを再起動するのは非効率的です。代わりに、アニメーションの繰り返し回数を開始する前に無限に設定し、アクションが終了したら繰り返し回数を0に設定します。アニメーションは現在のループを終了し、onAnimationEndを呼び出します。ここでsetActionView(null)を呼び出すことができます。

また、ActionBarSherlockとネイティブICS ActionBarの両方で、アニメーションの最後の数フレームが重なるという問題が発生しました(少なくともエミュレーターでは、実際のデバイスではテストしていません。 setActionView(null)を呼び出した後の静的ボタン。私の解決策は、LinearLayoutでアニメーション化されているImageViewをラップしてから、LinearLayoutでsetVisibility(View.GONE)を呼び出すことでした。ビューをアニメーション化する場合、setVisibilityを使用してビューを非表示にすることはできませんが、親を非表示にすることはできます。

関連するすべてのコードは次のとおりです。

layout / actionbar_progress.xml(IDが必要なのはImageViewのみですが、IDを追加したことに注意してください):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/actionbar_progress_container"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" >

    <ImageView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/actionbar_progress_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="5dp"
        android:src="@drawable/ic_action_refresh"
        style="@style/Widget.Sherlock.ActionButton"
        />
</LinearLayout>

anim / refresh_rotate.xml:

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromDegrees="0"
    android:toDegrees="360"
    android:pivotX="50%"
    android:pivotY="50%"    
    android:duration="1000"
    android:interpolator="@android:anim/linear_interpolator"
    android:repeatCount="infinite">

</rotate>

repeatCountは無限に設定されていますが、Javaコードはとにかく無限に設定する必要があるため、これは必要ありません。

onCreateOptionsMenuに私は持っています

...
menuInflater.inflate(R.menu.main, menu);

mRefreshItem = menu.findItem(R.id.menu_refresh);
...

これは、更新ボタンがクリックされるたびにfindItemを実行しないようにするためです。

onOptionsItemSelectedの場合:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {

    ...

        case R.id.menu_refresh:
            refresh();
            break;

    ...

    }
}

更新メソッドは、ダミーの5秒の遅延ポストです。refreshAnimを呼び出してアニメーションを開始し、終了したらrefreshAnimEndを呼び出してアニメーションを停止します。

private void refresh() {
    refreshAnim();
    getWindow().getDecorView().postDelayed(
        new Runnable() {
            @Override
            public void run() {
                refreshAnimEnd();
            }
        }, 5000);
}

そして、ここにコメント付きの最も重要な部分があります:

private void refreshAnim() {
    LayoutInflater inflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    //The inflated layout and loaded animation are put into members to avoid reloading them every time.
    //For convenience, the ImageView is also extracted into a member
    if (mRefreshIndeterminateProgressView == null || mRefreshRotateClockwise == null) {
        mRefreshIndeterminateProgressView = inflater.inflate(R.layout.actionbar_progress, null);
        mRefreshRotateClockwise = AnimationUtils.loadAnimation(this, R.anim.refresh_rotate);
        mRefreshImage = mRefreshIndeterminateProgressView.findViewById(R.id.actionbar_progress_image);
    }
    //reset some stuff - make the animation infinite again,
    //and make the containing view visible
    mRefreshRotateClockwise.setRepeatCount(Animation.INFINITE);
    mRefreshIndeterminateProgressView.setVisibility(View.VISIBLE);
    mRefreshRotateClockwise.setAnimationListener(new AnimationListener() {
        @Override
        public void onAnimationStart(Animation animation) {}

        @Override
        public void onAnimationRepeat(Animation animation) {}

        @Override
        public void onAnimationEnd(Animation animation) {
            //This is important to avoid the overlapping problem.
            //First hide the animated icon
            //setActionView(null) does NOT hide it!
            //as long as the animation is running, it will be visible
            //hiding an animated view also doesn't work
            //as long as the animation is running
            //but hiding the parent does.
            mRefreshIndeterminateProgressView.setVisibility(View.GONE);
            //make the static button appear again
            mRefreshItem.setActionView(null);
        }
    });
    mRefreshItem.setActionView(mRefreshIndeterminateProgressView);
    //everything is set up, start animating.
    mRefreshImage.startAnimation(mRefreshRotateClockwise);
}

private void refreshAnimEnd() {
    //sanity
    if ( mRefreshImage == null || mRefreshItem == null ) {
        return;
    }
    Animation anim = mRefreshImage.getAnimation();

    //more sanity
    if (anim != null) {
        //let the animation finish nicely
        anim.setRepeatCount(0);
    } else {
        //onAnimationEnd won't run in this case, so restore the static button
        mRefreshItem.setActionView(null);
    }
}
于 2012-06-01T19:03:55.090 に答える
0

通常のActionBarを使用している場合は、これをimg_layout.xmlに追加するだけです。

style="?android:attr/actionButtonStyle"

または、SherLockActionBarを使用します。

style="@style/Widget.Sherlock.ActionButton"
于 2014-11-05T15:08:51.147 に答える
-1

メニューオプションがアクションアイテムの場合は、一貫性を保つために、スタイルWidget.Sherlock.ActionButtonをImageViewに適用する必要があります。アクションアイテムを適切にアニメーション化する方法について書いたこの記事を読んでください。http://alexfu.tumblr.com/post/19414506327/android-dev-animate-action-items

于 2012-04-14T13:33:06.603 に答える