Android - 从 Fragment 中为 ActionBar 图标设置动画时出现问题

问题描述 投票:0回答:6
我在应用程序的 ActionBar 中

持续动画“刷新”图标时遇到一些问题。

我有一个容器 FragmentActivity,当用户浏览应用程序时(无论是从片段本身还是从 SlidingMenu 选项),它都会交换片段。因此,当应用程序首次加载时,我的 FragmentContainer 会添加 FragA。用户可以从 FragA 导航到 FragB,然后将其换入。

在操作栏中,我显示一个静态的“刷新”图标。当每个片段加载时,我将其替换为动画“旋转器”图标。加载完成后,我恢复到原来的刷新图标。

问题是,此动画仅适用于原始片段(在本例中为 FragA)。当用户导航到 FragB 并选择刷新图标时,会触发刷新,但动画永远不会发生。同样,如果按下后退按钮返回 FragA,现在将遵循相同的模式,即刷新按钮在按下时不会出现动画。

注意事项...

    我正在使用 ActionBarSherlock 和 SlidingMenu 实现,网址为
  1. https://github.com/jfeinstein10/SlidingMenu。所以上面的活动其实是一个SlidingFragmentActivity
  2. 两个片段都调用
  3. setHasOptionsMenu(true)
     - 我已经通过此进行了调试,并且每个片段都正确调用了 
    onCreateOptionsMenu
  4. 两个片段的图标都正确显示 - 当我离开“默认”片段时,动画没有发生。
  5. 使用 SlidingMenu 导航时,我看到相同的行为 - FragA 加载,动画有效 -> SlidingMenu 用于导航到不同的片段...动画不起作用 -> 返回到 FragA 的按钮...动画不起作用也在这里工作。
  6. 我正在使用
  7. FragmentTransaction.remove()
    add()
     而不是 
    replace()
    ,因为我以前遇到过 
    replace()
     的后退按钮问题 - 我正在使用兼容性库,我在这里读到 
    replace
     实现是一个有点问题 - 不使用它确实解决了我所看到的问题。
以下代码片段:

我加载原始片段的代码是......

FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); ft.add(R.id.content_frame, new FragA()); ft.addToBackStack(null); ft.commit();

将 FragB '交换' 为 FragA....

public void switchContent(PysoBaseFragment fragment) { FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); ft.remove(existingFragment); ft.add(R.id.content_frame, fragment); ft.addToBackStack(null); ft.commit(); }

此方法在容器活动中声明,并从 FragA 调用,即...

getFragmentContainer().switchContent(new FragB());

在新片段开始加载时,会调用旋转图标的代码。它就像...

ImageView spinnerActionView = (ImageView) inflater.inflate(R.layout.refresh_action_view, null); Animation rotation = AnimationUtils.loadAnimation(this, R.anim.rotate_animation); rotation.setRepeatCount(Animation.INFINITE); spinnerActionView.startAnimation(rotation); menuItemRefresh = menu.findItem(R.id.menu_refresh); menuItemRefresh.setActionView(spinnerActionView);

其中,当调用

menu

 时,将 
onCreateOptionsMenu
 分配给容器的实例变量。

更新:

我注意到这个领域的另一个奇怪的错误(我很高兴将其添加为一个单独的问题,但我在这里更新它,希望它能阐明我原来的问题 - 我相信两者都是造成的通过我如何从我的片段配置我的操作栏)。

当我第一次加载片段时,会显示 1 个静态刷新图标。如果我旋转屏幕...会出现另一个刷新图标...当我向后旋转屏幕时,会出现第三个刷新图标!

更奇怪的是,单击后退按钮

依次删除每个附加图标,最后(第四次单击)返回到上一个屏幕。

android android-fragments actionbarsherlock android-support-library slidingmenu
6个回答
5
投票
切勿更改菜单项,除非

onPrepareOtionsMenu(){ }

你应该是这样的。

在您的活动中:

boolean mIsRefreshing =false; public boolean onPrepareOptionsMenu(Menu menu) { if(mIsRefreshing){ final MenuItem menuItemRefresh = menu.findItem(R.id.menu_refresh); menuItemRefresh.setActionView(spinnerActionView); } return true; } public void setRefreshing(boolean refreshing){ mIsRefreshing = refreshing; invalidateOptionsMenu(); //supportInvelidateOptionsMenu() }

现在您可以从您的框架中拨打电话

((YourActivity)getActivity()).setRefreshing(true); ((YourActivity)getActivity()).setRefreshing(false);
    

1
投票
如果您每次都使用相同的动画对象,则可能需要在尝试再次运行动画之前重置动画。

尝试在 startAnimation() 调用上方添加rotation.reset()。


1
投票
"I've noticed another weird bug in this area (I'm happy to add this as a separate question, but I'm updating it here in the hope that it will shed some light on my original problem - I believe both are caused by how I have configured my action-bar from my Fragments). When I first load a fragment I have 1 static refresh icon displayed. If I rotate the screen... another refresh icon appears... when I rotate the screen back, a 3rd refresh icon appears! Stranger still, clicking the back-button removes each additional icon in turn, before finally (on the 4th click) returning to the previous screen."

我可以对此进行解释,每当你改变方向(肖像

风景)时。 <->

当方向改变时,活动将重新启动。我猜您的代码在重新启动之前没有保存所需的信息。您可以通过自己处理特定的配置更改(即:方向更改)来停止此默认行为。有关执行此操作的一个很好的教程位于此处:处理运行时更改


1
投票
您正在添加一个动作视图来添加动画。如果您尝试做其他事情,例如更改菜单项的图标(即使它不是动画的,只是为了看看它是否发生变化),这是否有效?


1
投票
仅在主活动(我的意思是滑动片段活动)中调用 onCreateOptionsMenu() 。无需从每个片段调用 onCreateOptionsMenu() 。我在下面给出了一个示例片段。

Call from fragment (whenerver loading starts and end) yourSlidingFragmnetActivity.refresh = true/false; (u can have this logic of your own) getActivity().supportInvalidateOptionsMenu(); @Override public boolean onCreateOptionsMenu(Menu menu) { menu.add(BaseListActivity.DEFAULT_GROUP_ID, BaseListActivity.MENU_ITEM_RELOAD_LIST, BaseListActivity.DEFAULT_ORDER, "Refresh").setIcon(R.drawable.ic_menu_refresh_new) .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == BaseListActivity.MENU_ITEM_RELOAD_LIST) { item.setActionView(R.layout.progressbar_layout); item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); return true; } return true; } public static boolean refresh = false; @Override public boolean onPrepareOptionsMenu(Menu menu) { MenuItem item = menu.getItem(0); if (refresh) { item.setActionView(R.layout.progressbar_layout); } else { item.setIcon(R.drawable.ic_menu_refresh_new); } return true; } R.layout.progressbar_layout: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:addStatesFromChildren="true" android:focusable="true" android:paddingLeft="4dp" android:paddingRight="4dp" android:gravity="center" style="?attr/actionButtonStyle"> <ProgressBar android:layout_width="wrap_content" android:layout_height="wrap_content" android:focusable="true" style="@android:style/Widget.ProgressBar.Small"/> </LinearLayout>

我也在使用jfeinstein10 movingmenu lib,我没有添加或删除片段,我总是替换它们,并且在oncreate menthod中使用这样的

private Fragment mContent; if(mContent == null){ mContent = new SampleFragment(); } // set the Above View setContentView(R.layout.content_frame); getSupportFragmentManager() .beginTransaction() .replace(R.id.content_frame,mContent) .commit();
    

0
投票
我知道为时已晚,但我现在遇到了这个问题,经过 2 天的研究,我得出的结论是,如果您使用 ActionBarDrawerToggle,则每次在我的情况下切换片段时都需要syncState()

toggle.syncState()
在 MainActivity 类中的 onOptionsItemSelected() 方法中,每次片段更改时都会调用该方法并且它有效

© www.soinside.com 2019 - 2024. All rights reserved.