我在我的ActionBarSherlock ActionBar中揭开序幕的的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
,图标不跳,所以它有事情做这一点。 不知道,我发疯。
如果菜单选项的操作项目,你应该将样式Widget.Sherlock.ActionButton到的ImageView保持一致性。 阅读这篇文章,我对如何正确的动画效果的行动项目写道。 http://alexfu.tumblr.com/post/19414506327/android-dev-animate-action-items
我不知道这会不会有什么影响,但如果你玩的pivot
值可能会理清这个问题。 也许只有旋转在一个轴上?
亚历克斯福,你的文章是非常有益的,但也有一些改进,可制成。
重新启动在onAnimationEnd动画每次是低效的。 相反,设置动画repeatcount为无穷你开始之前,那么当动作结束时,repeatcount设置为0动画将完成当前循环,然后调用onAnimationEnd,在那里你可以调用setActionView(空)。
我也遇到一个问题(在模拟器中,至少,还没有一个真正的设备上进行测试,因为我没有一个)与两个ActionBarSherlock和本地ICS动作条,在动画重叠的最后几帧,调用setActionView(空)后的静态按钮。 我的解决办法是换行是在LinearLayout中被动画的ImageView的,然后调用上的LinearLayout setVisibility(View.GONE)。 如果动画视图,使用setVisibility隐藏它不会工作,但隐藏其父意志。
这里是所有相关的代码:
布局/ actionbar_progress.xml(请注意,我添加的ID,虽然只有ImageView的需要之一):
<?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>
动画/ 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);
}
}
只是,如果你使用的是正常的动作条添加到您的img_layout.xml:
style="?android:attr/actionButtonStyle"
或者这与福尔摩斯动作条:
style="@style/Widget.Sherlock.ActionButton"