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);
}
}