Animated menu item “jumps” when animation starts

2019-01-26 14:15发布

问题:

I am using the code from this question: Animated Icon for ActionItem to animate my refresh ActionBarButton. It works fine, except that the style doesn't seem to be right. When I click the item, it starts rotating, but only after it "jumps" a few pixels. It seems like the style of the ImageView is different from the style of the menu item.

The item is defined like this:

<item
    android:id="@+id/action_refresh"
    android:orderInCategory="100"
    android:icon="@drawable/ic_menu_refresh"
    android:showAsAction="ifRoom"

    <!-- added this myself, didn't have any effect -->
    style="@android:style/Widget.ActionButton"  
    android:title="@string/action_refresh"/>

and the ImageView like this:

<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:contentDescription="@string/action_refresh"
    android:src="@drawable/ic_menu_refresh"
    style="@android:style/Widget.ActionButton" />

How can I style my menuitem to match the ImageView in the rotation, or the other way round?

回答1:

I found the solution by setting the View also for the non-animated item to be the same. In the menu.xml:

<item
    android:id="@+id/action_refresh"
    android:orderInCategory="100"
    android:icon="@drawable/ic_menu_refresh"
    android:actionLayout="@layout/refresh_action_view"
    android:showAsAction="ifRoom"
    style="@android:style/Widget.ActionButton"
    android:title="@string/action_refresh"/>

Then, in onCreateOptionsMenu, I fetch the view in a member variable, and attach an onclick handler:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.orders, menu);
    final Menu m = menu;
    refreshItem = menu.findItem(R.id.action_refresh);
    refreshItem.getActionView().setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View v) {   
                        m.performIdentifierAction(refreshItem.getItemId(), 0);
                    }
            });
    return true;
}

In onCreate, we load the animation:

    rotation = AnimationUtils.loadAnimation(this, R.anim.clockwise_refresh);
    rotation.setRepeatCount(Animation.INFINITE);

Finally, call this to start the animation:

refreshItem.getActionView().startAnimation(rotation);

and this to stop it:

refreshItem.getActionView().clearAnimation();


回答2:

It's better to change the ImageView to an ImageButton, and not to change the layout on the menu item in menu.xml, then the image will not jump, and you also don't need to add the click handler. It will also be the correct size, which will not be the case if you use an ImageView instead of an ImageButton.

This is all you need:

<ImageButton xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/action_refresh"
android:src="@drawable/ic_menu_refresh"
android:id="@+id/refresh_view"
style="@android:style/Widget.ActionButton" />


回答3:

Put some padding in ImageView. In my case, 8dp on each side.

<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:paddingRight="8dp"
    android:paddingLeft="8dp"
    android:src="@drawable/ic_action_important" />