Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.3k views
in Technique[技术] by (71.8m points)

android - Refresh menu item animation in ActionBarSherlock

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

    case android.R.id.home:
        return true;

    case R.id.searchIcon:
        return true;

    case R.id.startRefresh:
        refreshItem = item;
        refresh();
        return true;
    case R.id.stopRefresh:

        if (refreshItem != null && refreshItem.getActionView() != null) {
            refreshItem.getActionView().clearAnimation();
            refreshItem.setActionView(null);
        }
        return true;
    default:
        return super.onOptionsItemSelected(item);
    }
}


public void refresh() {
    if (FeedActivity.this != null) {
        /*
         * Attach a rotating ImageView to the refresh item as an ActionView
         */
        LayoutInflater inflater = (LayoutInflater) FeedActivity.this
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        ImageView iv = (ImageView) inflater.inflate(
                R.layout.refresh_action_view, null);
        Animation rotation = AnimationUtils.loadAnimation(
                FeedActivity.this, R.anim.clockwise_refresh);
        rotation.setRepeatCount(Animation.INFINITE);
        iv.startAnimation(rotation);
        refreshItem.setActionView(iv);
    }
}

Before Clicking:

enter image description here

After Clicking:

enter image description here

Here the icon is being animated(rotating).

Problem:

why is it shifting to the left?

once it shifts to the left, the icon becomes non clickable and strangely the device back button also doesn't work

EDIT:

In comments below this answer:

Animated Icon for ActionItem

Jake Warton says if you are using a square and correct sized icon for the menu item, you wont get this weird behaviour, to someone who has the same problem.

But i am using a 32x32 image on a device which uses mdpi drawables. Which as stated there must work :(

Thank You

EDIT:

refresh_action_view.xml

<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
    style="@style/Widget.Sherlock.ActionButton"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/ic_refresh" />

Custom Style i use in my app

<style name="My_solid_ActionBar" parent="@style/Widget.Sherlock.Light.ActionBar.Solid.Inverse">
    <item name="background">@drawable/ab_solid_My</item>
    <item name="backgroundStacked">@drawable/ab_stacked_solid_My</item>
    <item name="backgroundSplit">@drawable/ab_bottom_solid_My</item>
    <item name="progressBarStyle">@style/My_ProgressBar</item>
    <item name="android:background">@drawable/ab_solid_My</item>
    <item name="android:backgroundStacked">@drawable/ab_stacked_solid_My</item>
    <item name="android:backgroundSplit">@drawable/ab_bottom_solid_My</item>
    <item name="android:progressBarStyle">@style/My_ProgressBar</item>
</style>
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The issue is that you're not handling all menu inflation in onCreateOptionsMenu(). The basic logic for an ActionBar refresh animation I've seen used in apps with open source , for example Andlytics (and also used myself in projects), is to implement a boolean flag in onCreateOptionsMenu() to decide whether to show the refresh animation.

You can implement it like this: When your refresh() method is called, it sets the boolean isRefreshing flag to true and calls inValidateOptionsMenu() which 'behind the scene' calls onCreateOptionsMenu() to start the animation:

Inflate the menu in onCreateOptionsMenu(...):

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    menu.clear();
    super.onCreateOptionsMenu(menu, inflater);
    //inflate a menu which shows the non-animated refresh icon
    inflater.inflate(R.menu.my_ab_menu, menu);

    if (isRefreshing) {
        //if we're refreshing, show the animation
        MenuItem item = menu.findItem(R.id.refreshMenuItem);
        item.setActionView(R.layout.action_bar_indeterminate_progress);
        ImageView iv = (ImageView) item.getActionView().findViewById(R.id.loadingImageView);
        ((AnimationDrawable) iv.getDrawable()).start();
    }
}

Start animation like so:

 public void refresh(){
        isRefreshing = true;
        inValidateOptionsMenu();
    }

If you want the user to start the animation when he taps the refresh icon, do like this in onOptionsItemSelected():

case R.id.refreshMenuItem:
    isRefreshing = true;
    item.setActionView(R.layout.action_bar_indeterminate_progress);
    ImageView iv = (ImageView) item.getActionView().findViewById(R.id.loadingImageView);
    ((AnimationDrawable) iv.getDrawable()).start();
    //...

To stop the animation call:

isRefreshing = false;
invalidateOptionsMenu();

This code is from a Fragment so you may have to tweak if for an Activity, but I think it communicates the basic idea.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...