【问题标题】:Refresh menu item animation in ActionBarSherlockActionBarSherlock 中刷新菜单项动画
【发布时间】:2012-11-24 07:45:10
【问题描述】:
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);
    }
}

点击前:

点击后:

这里的图标正在动画(旋转)。

问题:

为什么向左移动?

一旦它向左移动,图标变得不可点击,奇怪的是设备后退按钮也不起作用

编辑:

在这个答案下面的 cmets 中:

Animated Icon for ActionItem

Jake Warton 说,如果您为菜单项使用大小正确的方形图标,对于遇到同样问题的人来说,您不会遇到这种奇怪的行为。

但我在使用 mdpi 可绘制对象的设备上使用 32x32 图像。如前所述,它必须起作用:(

谢谢

编辑:

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" />

我在应用中使用的自定义样式

<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>

【问题讨论】:

  • FWIW,这是一个展示您想要的效果的项目,以防它给您任何想法:github.com/commonsguy/cw-omnibus/tree/master/Progress/ActionBar
  • 是的,我使用了你的代码,即使现在进度条(设置为 ActionView)向左移动。其他菜单项都不起作用。
  • 您应该发布一个完整的示例项目来演示您的问题。如果在我上面链接的示例中,我将 about 设为 always 并且第一个操作栏项目,我的 refresh 仍然有效,但没有表现出您描述的行为。
  • @Archie.bpgc 我已经创建了解决方案,也许它可以以某种方式帮助你:stackoverflow.com/a/14360958/492624

标签: android animation actionbarsherlock


【解决方案1】:

问题是您没有处理onCreateOptionsMenu() 中的所有菜单膨胀。我在开源应用程序中看到的ActionBar 刷新动画的基本逻辑,例如Andlytics(我自己也在项目中使用过),是在onCreateOptionsMenu() 中实现一个boolean 标志来决定是否显示刷新动画。

你可以这样实现它:当你的 refresh() 方法被调用时,它会将 boolean isRefreshing 标志设置为 true 并调用 inValidateOptionsMenu() ,后者在“幕后”调用 onCreateOptionsMenu() 来启动动画:

扩充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();
    }
}

像这样开始动画:

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

如果您希望用户在点击刷新图标时启动动画,请在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();
    //...

停止动画调用:

isRefreshing = false;
invalidateOptionsMenu();

此代码来自Fragment,因此您可能需要调整是否为Activity,但我认为它传达了基本思想。

【讨论】:

  • 但是在我看到的所有例子中,没有像 invalidateOptionsMenu(); 这样的东西。就像我在问题中的示例以及 CommonsWare 在 cmets 中发布的 1。不过会试试这个。
  • 有不同的方法可以达到相同的效果。我发现这种方法易于理解和调试。查看 Andlytics 应用示例。你可以从市场上下载它,看看它是如何作为一个真实世界的例子工作的。
  • 我已经编辑了答案以展示如何处理用户启动的刷新,而不仅仅是以编程方式启动刷新动画。当用户点击等时,您必须添加检查它是否已经动画......
  • 这行得通,我发现this post 可用于使操作按钮的样式与标准 android 样式匹配,否则动画开始时间距可能会改变:style="@android:style/Widget.动作按钮"
  • 这很好用,但在 Android 版本
【解决方案2】:

我尝试了与您使用的完全相同的代码,它对我来说效果很好。唯一可能不同的是两件事:

1) refresh_action_view 布局(这是我的比较):

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

2) 你的操作栏的显示选项(这里是我的styles.xml 用于比较)。

<resources>

<style name="AppTheme" parent="Theme.Sherlock.Light.DarkActionBar">
    <item name="android:actionBarStyle">@style/Widget.ActionBar</item>
    <item name="actionBarStyle">@style/Widget.ActionBar</item>
</style>

<style name="Widget.ActionBar" parent="Widget.Sherlock.Light.ActionBar.Solid.Inverse">
    <item name="android:displayOptions">showHome|useLogo|showCustom</item>
    <item name="displayOptions">showHome|useLogo|showCustom</item>
</style>

</resources>

你也可以分享一下吗?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多