I'm having some problems consistently animating a 'refresh' icon in the ActionBar of my app.
I have a container FragmentActivity which swaps fragments in and out as the user navigates through the app (either from within the fragment itself or from a SlidingMenu option). So when the app first loads, my FragmentContainer adds FragA. From FragA the user can navigate to FragB which is then swapped in.
In the action bar I display a static 'refresh' icon. As each Fragment loads, I replace this with an animated 'spinner' icon. When the load completes, I revert to the original refresh icon.
Problem is, this animation only works for the original fragment (FragA, in this case). When the user navigates to FragB and selects the refresh icon, the refresh is triggered, but the animation never happens. Similarly, if the back button is pressed to return to FragA, this now follows the same pattern i.e. the refresh button does not animate when pressed.
Things to note...
SlidingFragmentActivity
. setHasOptionsMenu(true)
- I've debugged through this and onCreateOptionsMenu
is being correctly called for each.FragmentTransaction.remove()
and add()
rather than replace()
as I have previously had back-button issues with replace()
- I am using the compatibility lib and I read on here that the replace
implementation is a bit buggy - and not using it certainly fixed the issues I was seeing.Code snippets below:
My code to load the original fragment is....
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.content_frame, new FragA());
ft.addToBackStack(null);
ft.commit();
To 'swap' FragB for 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();
}
This method is declared in the container activity and is called from FragA i.e....
getFragmentContainer().switchContent(new FragB());
The code to spin the icon is called from the new Fragment as it starts to load. Its something like...
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);
Where menu
is assigned to an instance variable of the container when onCreateOptionsMenu
is called.
Update:
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.
If you want to hide Action Bar from the entire application (from all Activities and fragments), then you can use this method. Just go to res -> values -> styles. xml and change the base application to “Theme. AppCompat.
ActionBar actionBar = getActionBar(); actionBar. hide();
Though you can add a Toolbar anywhere within your fragment's view hierarchy, you should generally keep it at the top of the screen. To use the Toolbar in your fragment, provide an ID and obtain a reference to it in your fragment, as you would with any other view.
Never chang menu items somewhere except
onPrepareOtionsMenu(){
}
you should something like this.
in your activity:
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()
}
So now you can call from your frament
((YourActivity)getActivity()).setRefreshing(true);
((YourActivity)getActivity()).setRefreshing(false);
If you are using the same Animation object each time, you may need to reset your animation before attempting to run it again.
Try adding rotation.reset() above your call to startAnimation().
"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."
I can give Explanation to this ,When ever you change orientation (Potrait<->landscape).
An activity is restarted when the orientation changes. I'm guessing your code isn't saving needed information before this restart occurs. You can stop this default behavior by handling specific configuration changes yourself (ie: orientation change). A good tutorial on doing this is located here: Handling Runtime Changes
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With