I am trying to create a selected and unselected Item on a the ActionBar in my app. For example, when the user is in a fragment if they click the Item in the ActionBar, the ImageView will switch from a grey to a red square and if they switch to a different fragment then come back it will still be selected. So each fragment can either be selected or unselected based upon the color of the square and if the user clicked it or not. I am unsure how to implement this, anything helps?
Based on the location of the item in the ActionBar, this can be presented as a fragment option. Each fragment that gets inflated has the chance to inflate its own menu items into the action bar. This can be done by calling setHasOptionsMenu(true) in fragment's onCreate or maybe in the constructor. This will cause the onCreateOptionsMenu / onPrepareOptionsMenu / onOptionsItemSelected methods to be called and this gives you the chance to add your menu item which you can control based on your fragment's state.
First off, for saving state in a fragment, you can use onSaveInstanceState() to remember your selected state. You would need a property on your fragment:
private boolean mSelected;
In your onSaveInstanceState() override you save this value:
outState.putBoolean("selected", mSelected);
Then in onCreate() you can recover the value:
if (savedInstanceState != null) {
mSelected = savedInstanceState.getBoolean("selected");
}
And in onCreateView() you use the selected property to set up your ImageView:
imageView.setBackground(mSelected ? R.color.gray : R.color.red); // for example
So now when your user switches away from the fragment then comes back, the ImageView will have the same selection state as before.
Next thing is the action bar. Fragments can make their own changes to the menu. Start by calling setHasMenuOptions(true) in your fragment's onCreateView(). Then you override onCreateOptionsMenu() and onOptionsItemSelected() just like you would for an activity.
Related
I have a navigation drawer in my app. Every Entry in the list of the NavigationDrawer represents one navigation graph. I want to mark the element in which the user currently is.
I managed to get the item to be marked after it is selected and until the visible fragment changes (even if the new fragment is still in the same navGraph). I did that by setting a NavigationItemSelectedListener using NavigationView.setNavigationItemSelectedListener(NavigationView.OnNavigationItemSelectedListener listener). Inside this listeners onNavigationItemSelected(item: MenuItem): Boolean function, I do: item.isChecked = true.
The problem with this is that the item is unchecked after the app starts and the item looses it's checked state as soon as the fragment changes (even if the navGraph doesn't change). How do I do this correctly?
I have also tried to set android:checked="true" in the xml declaration of the menu item I want to be checked when the app starts. It doesn't seem to do anything.
I have also tried to set navView.setCheckedItem(R.id.main_nav_option_one) in the Activity's onCreate function. Again, it doesn't seem to do anything.
Can you try
navView.getMenu().getItem(index).setChecked(true)
in the fragment's onResume?
I managed to solve my problem.
The most important change I had to make is mentioned here. I had to give my menu items the same ID as the ID of the navGraphs. When I did this, I removed my NavigationItemSelectedListener because it was interfering with the automatically generated navigation. Without a NavigationItemSelectedListener I could no longer handle a navigation item being clicked, that doesn't have a corresponding element in the navGraph. However I was able to fix it, by adding the NavigationItemSelectedListener back in, and making the correct calls to NavController.navigate() for every element in the list.
TL;DR:
I had to set the menu item IDs to be the same as my navGraph IDs and make the navigation calls myself anyway in the NavigationItemSelectedListener.
I have a 3 page Fragment in my app, but I need each fragment to have a different ActionBar. For one fragment I have set the current code in the OnCreateView method that adds in an EditText to the ActionBar:
//mainActivityContext is the context for the Main Activity (This is a fragment file)
ActionBar actionBar = mainActivityContext.getActionBar();
// add the custom view to the action bar
actionBar.setCustomView(R.layout.actionbar_view);
search = (EditText) actionBar.getCustomView().findViewById(R.id.searchfield);
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM
| ActionBar.DISPLAY_SHOW_HOME);
Yet this EditText stays persistent throughout all of the ActionBar menus. I only want it on one. I have tried everything, menu.clear();, setHasOptionsMenu(true);, inflater.inflate(R.menu.different_file, menu);, but nothing has worked.
Any help?
There is a very good approach to go about this situation:
on each fragment's onActivityCreated() method call setHasOptionsMenu(true);
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setHasOptionsMenu(true);
}
now you can override onCreateOptionsMenu() and onOptionsItemSelected() inside each fragment.
And also dont forget to call getActivity().supportInvalidateOptionsMenu(); inside onResume() of fragment.
I think this sample by google will be very helpful.
Since the actions are populated by the activity's options menu you can use Activity#invalidateOptionsMenu(). This will dump the current menu and call your activity's onCreateOptionsMenu/onPrepareOptionsMenu methods again to rebuild it.
If you're using action bar tabs to change your fragment configuration there's a better way. Have each fragment manage its own portion of the menu. These fragments should call setHasOptionsMenu(true). When fragments that have options menu items are added or removed the system will automatically invalidate the options menu and call to each fragment's onCreateOptionsMenu/onPrepareOptionsMenu methods in addition to the activity's. This way each fragment can manage its own items and you don't need to worry about performing menu switching by hand.
I am using ActionBarSherlock.
I want to change which ActionBar MenuItems are visible depending on the state of my Activity. (For instance depending on which tab is selected.)
How can I do this?
You can get the ActionMenu within the onCreateOptionsMenu method and store it in your activity and change any item visibility at any time...
You can add all items at the same menu and set it visible or not visible just using:
menu.findItem(R.id.your_item).setVisible(true/false);
in onPrepareOptionsMenu
I need to make two minor changes to an Activity's ActionBar from a Fragment.
The parent FragmentActivity's onCreateOptionMenu and onPrepareOptions handle the menu across the app.
However, in the containing main Fragment view, I want the ActionBar title to change for the sake of navigation. Each time the Fragment changes.
Also, in one instance, I want to add a single menu item as defined in the layout. I rather not duplicate code for this part, do I have to override the same methods and set up entire menu again, including onOptionSelected? Or...?
Edit:
On my menu xml layout, I have this item:
<item
android:id="#+id/Add"
android:title="Add Items"/>
This item needs to be seen in the ActionBar only for one particular Fragment. The rest of the menu is identical to what should be seen for the rest of the app. In the fragment where I need this new item, do I have to also do onCreateOptionsMenu, onPrepareOptionsMenu, and onOptionsItemSelected all over again and duplicate thee OTHER menu items as well? Or can I override those in the Fragment and just pop that one extra menu item in?
1.
getActivity().getActionBar().setTitle();
or
getActivity.getSupportActionBar().setTitle();
more clarification please :)
This answered what I needed for part 2.
Putting this in onActivityCreated:
setHasOptionsMenu(true);
And then adding this too:
#Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
ActivityCompat.invalidateOptionsMenu(getActivity());
MenuItem Add = menu.findItem(R.id.Add);
Add.setVisible(true);
}
The parent Activity sets the R.id.Add as invisible by default.
I have a FragmentActivity which hosts a FragmentStatePagerAdapter. The pager contains multiple instances of the same fragment, in order that the user can swipe between the items in a list. I want to be able to provide the user with an options menu which will act only on the visible item.
For example, I have a list of images displayed in imageviews inside fragments. I want an option menu item allowing the user to set the image as their wallpaper.
At the moment when I try this, when onPrepareOptionsMenu is called, the code is called in multiple fragments (usually the current + next one). The same when an item is selected. This causes the wrong image to be set as the wallpaper.
How can I prevent the options menu triggering for more than the currently visible fragment?
My solution was to use the setOnPageChangeListener method of the ViewPager in order to keep track of which Fragment index was currently visible with the onPageSelected callback. You still have to get the initial index yourself, but in my case this was trivial
You can intercept the options menu callback in the activity's onOptionsItemSelected, and explicitly call the item from the correct fragment there, returning true to indicate that you've handled it.
The trick is to change sethasoptions( true|false) on each fragment before populating menu. This already helped me