Acessing the 'options' menu from a fragment? Android - java

I currently have an app which has 4 pages, these pages are being added using fragments by a pageViewer, so that I can swipe between them.
What I want, is to be able to access the 'options' menu (the one which has a 'settings' item in it by default) from each page, so that I can perform commands specifically for one page, such as a 'refresh' item, which refreshes the data in the current page.
Could anyone point me in the right direction?
Thanks!

Each Fragment can declare its own menu, which will be automatically merged with the current activity's menu.
class YourPage extends Fragment
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// Signal that this fragment has proper actions
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
{
super.onCreateOptionsMenu(menu, inflater);
// The menu will be added to the action bar
inflater.inflate(R.menu.fragment_page_menu, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case R.id.action_refresh:
{
// Handle the action...
return true;
}
default:
return super.onOptionsItemSelected(item);
}
}
}
Here's a complete example that I made, and also a relevant tutorial.

Related

Activity not opening when clicking menu item

I am trying to tap on the "logout" option whose id is logout but nothing happens. Below is my code
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.requestpayment,menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()){
case R.id.logout:
Intent intent=new Intent(this,Logout.class);
this.startActivity(intent);
break;
}
return super.onOptionsItemSelected(item);
}
please help
in onCreateOptionsMenu method replace
return super.onCreateOptionsMenu(menu);
by
return true;
and replace super.onOptionsItemSelected(item); in onOptionsItemSelected() by return true
You have to return true in onCreateOptionsMenu() and in onOptionsItemSelected() after starting the activity.
The correct way would be like this.
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.requestpayment,menu);
return true;
}
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()){
case R.id.logout:
Intent intent=new Intent(this,Logout.class);
this.startActivity(intent);
return true;
}
return super.onOptionsItemSelected(item);
}
If you chain a overridden method to its superclass(i.e call super.someMethod()), it means you are requesting the superclass to handle the implementation on its own.
You should return true here to tell that you successfully inflated the menu in this child Activity OR succesfully handled the onClick() event on the option items.
NOTE: Mostly, you need to chain a superclass method call, where superclass is reponsible for doing some critical stuffs. For eg:
public class ChildActivity extends AppCompatActivity{
#Override
protected void onCreate(Bundle savedInstanceState) {
//request superclass to do its critical stuffs
super.onCreate(savedInstanceState);
//continue with your logics here
}
Restart Android studio. Let me know if that still persists

Update ActionBar menu depending on navigation destination

I would like to change the menu items displayed in my ActionBar depending on the current destination of my NavController. By "change" I mean inflate a specified menu-xml for each destination.
The behavior could be compared to the integrated way the new navigation system changes the ActionBar title, depending on the given android:label for the destination fragment in the navigation-xml.
So far I setup a basic activity with ActionBar and DrawerLayout using the new Android navigation. Also I created all necessary XML files and Fragments to navigate between.
...
#Override
protected void onCreate(Bundle savedInstanceState)
{
...
this._drawerLayout = this.findViewById(R.id.drawer_layout);
Toolbar toolbar = this.findViewById(R.id.action_bar);
this.setSupportActionBar(toolbar);
ActionBar actionbar = Objects.requireNonNull( this.getSupportActionBar() );
actionbar.setDisplayHomeAsUpEnabled(true);
actionbar.setHomeAsUpIndicator(R.drawable.ic_menu);
NavigationView navigationView = this.findViewById(R.id.navigation_view);
navigationView.setNavigationItemSelectedListener(menuItem -> {
menuItem.setChecked(true);
this._drawerLayout.closeDrawers();
return true;
});
NavController navController = Navigation.findNavController(this, R.id.navigation_host);
NavigationUI.setupWithNavController(toolbar, navController, this._drawerLayout);
}
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
// Here I inflate the ActionBar menu that is kept between all destinations.
// Instead of keeping the same menu between all destinations I want to display different menus depending on the destination fragment.
this.getMenuInflater().inflate(R.menu.actionbar_items, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch(item.getItemId())
{
case android.R.id.home:
this._drawerLayout.openDrawer(GravityCompat.START);
return true;
case R.id.appbar_search:
return true;
}
return super.onOptionsItemSelected(item);
}
I thought about using an individual toolbar in each destination fragment
but I discarded the idea, because I would lose the transition animation between hamburger icon and back-arrow icon.
Is there any way to achieve this with the new navigation system or in any other way?
I just tested this. With the current version (2.2.2) of the navigation library, menu items inflated by each fragment will be added and removed as you navigate around.
But onCreateOptionsMenu is not called by default! To make things work, you have to sprinkle the magic dust and call setHasOptionsMenu(true) during initialisation.
Beware, any menu items inflated by the containing activity will always appear alongside the ones from the current fragment, so if you don't want any common menu items, it's probably easiest to not inflate a menu in the Activity.
Side note: in the Fragment class, onCreateOptionsMenu(menu, inflater) is an empty method, so the call to super.onCreateOptionsMenu(menu, inflater) in your code is a no-op.
I found a way to achieve the desired behavior by calling menu.clear(); before inflating the updated layout. I am still wondering if there is a built-in way to achieve this with the new navigation system.
In the destination Fragment I am using this now:
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
{
super.onCreateOptionsMenu(menu, inflater);
menu.clear();
inflater.inflate(R.menu.toolbar_items_idle, menu);
}

I want to remove the optionMenu when there are no items in ListView (emptyView is shown)?

I have an app that adds items to an sqlite database and returns a cursor, this cursor is then used with a custom CursorAdapter called StoreCursorAdapter to show the items in a ListView.
There is a (delete all) button as an optionsMenuItem.
I want to hide this optionsMenuItem when no items are avaliable in the ListView.
InventoryActivty
EditorActivity
Sorry for the links I am a new user so they don't allow me to embed images yet. :-(
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_inventory);
//Declare the views
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
ListView list = (ListView) findViewById(R.id.list);
emptyView = findViewById(R.id.empty_view);
//Set the screen to be shown when there are no list items
list.setEmptyView(emptyView);
//StoreCursorAdapter is a custom CursorAdapter
mAdapter = new StoreCursorAdapter(this, null);
list.setAdapter(mAdapter);
}
#Override
protected void onStart() {
super.onStart();
invalidateOptionsMenu();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu options from the res/menu/menu_inventory.xml file.
// This adds menu items to the app bar.
getMenuInflater().inflate(R.menu.menu_inventory, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// User clicked on a menu option in the app bar overflow menu
showDeleteConfirmationDialog();
return super.onOptionsItemSelected(item);
}
I tried
1 - emptyView.visibilty() == View.INVISBLE
2 - list.getAdapter == null
but they didn't work
What statement will do the job?!
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
if (//what statement) {
MenuItem menuItem = menu.findItem(R.id.action_delete_all);
menuItem.setVisible(false);
}
return true;
}
Note:
OnStart() gets called after I get back from the EditorActivity
Note:
In my app I can delete individual items from another activity so adding invalidateOptionsMenu(); in the onOptionsItemSelected won't do the job.
the correct condition to put inside onPrepareOptionsMenu is:
menuItem.setVisible(!mAdapter.isEmpty());
that is the same comparison the ListView uses manages the empty view (minus null check) (https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/widget/AdapterView.java#747)
but I believe there's another issue here, is that the data is changing after the activity started, during showDeleteConfirmationDialog(). That means you have to call invalidateOptionsMenu() the moment the data is changed. There're two ways of doing it. One more robust and the other is faster to code:
faster to code (but not very good/clean):
add invalidateOptionsMenu() after the code that executes the DB operations.
more robust/clean
you'll use start/stop callbacks to listen to changes in the data. Something like the following:
#Override protected void onStart(){
super.onStart();
invalidateOptionsMenu();
mAdapter.registerDataSetObserver(dataObserver);
}
#Override protected void onStop(){
mAdapter.unregisterDataSetObserver(dataObserver);
super.onStop();
}
private final DataSetObserver dataObserver = new DataSetObserver(){
#Override public void onChanged(){
invalidateOptionsMenu();
}
#Override public void onInvalidated(){
invalidateOptionsMenu();
}
};
all code above was typed by heart, there're likely typos, but that's the idea and the typos you can fix later at your code.
if you dont have any menu item to show, why are u inflating one, if you dont inflate you wont.
#Override
public boolean onCreateOptionsMenu(Menu menu) {
return false;
}
Unless you need to dynamically remove the menu options based on the current state of the activity, this might help How do you remove an inflated menu/items from the new Lollipop Toolbar?

Menu Item To New Activity

I'm trying to send the user to a new activity using a menu button, and back again. To put it into context, I have a basic calculator that runs when the app is opened (works perfect right now), then I want the user to hit the menu button on his/her phone, (two buttons should pop up Home and Tip Calculator) when the user hits tip calculator it should then load the new activity TipCalculator. Then if the menu button is pressed again, the same two options should appear and the Home button should bring them back to the basic calculator.
This is my Code for the Calculator.java
#Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_calculator, menu);
menu.add(Menu.NONE,HOME_MENU_ID,Menu.NONE,"Home");
menu.add(Menu.NONE,SECOND_MENU_ID,Menu.NONE,"Tip Calculator");
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// TODO Auto-generated method stub
switch(item.getItemId()){
case HOME_MENU_ID:
Intent main = new Intent(this,Calculator.class);
startActivity(main);
finish();
return true;
case SECOND_MENU_ID:
Intent second = new Intent(this,TipCalculator.class);
startActivity(second);
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
This is the code for the TipCalculator.java
public class TipCalculator extends Calculator{
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tipcalculator);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_tipcalculator, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// TODO Auto-generated method stub
Intent main = new Intent(this,Calculator.class);
startActivity(main);
finish();
return super.onOptionsItemSelected(item);
}
}
The menu comes up fine, and the home button will refresh the home page, but the tip calculator button gives me a force close error and crashes on me.

how to add options menu to listview in android?

I am trying an option menu in a class that extends ListAcitivity. How do I add an option menu to this activity, so when I click on the option button an options menu appears at the bottom of the screen.
I searched online but most tutorials refer to this function onCreateOptionsMenu() which is part of Activity class and it does not seem to work in the subclass of ListActivity.
It is Java. ListActivity (and anything that extends it) inherits all of the features and functions of Activity.
Therefore, just overriding onCreateOptionsMenu will work the same.
Boilerplate code:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_xml_name, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_item_id:
// action
break;
}
return true;
}
:)

Categories