Android onOptionsItemSelected method of Fragment doesn't get called - java

there are many questions about the topic but i can't figure out my problem. I have a menu declared in my MainActivity(ActionBarActivity). Now i want to work with MenuItem in onOptionsItemSelected of a Fragment class. Here is my MainActivity methods
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// toggle nav drawer on selecting action bar app icon/title
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
// Handle action bar actions click
switch (item.getItemId()) {
case R.id.add_note:
createNewNote();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private void createNewNote() {
Intent addIntent = new Intent(MainActivity.this, AddNote.class);
startActivity(addIntent);
}
And Fragment methods
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.add_note:
Toast.makeText(getActivity(), "Entered into fragment", Toast.LENGTH_LONG).show();
createNewNote();
return true;
default:
break;
}
return super.onOptionsItemSelected(item);
}
private void createNewNote() {
Intent addIntent = new Intent(getActivity(), AddNote.class);
startActivity(addIntent);
}
Here in MainActivity onOptionsItemSelected get called even in Fragment but doesn't in Fragment as i don't see Toast in Fragment. I think something is missed in my code. Thanks in advance.

inside onOptionsItemSelected() in activity inside your switch after calling createNewNote() instead of returning true return super.onOptionsItemSelected(item)

you must call setHasOptionsMenu() inside onCreate of fragment for menu related method to work.

Your onCreateOptionsMenu() method does not inflate the menu file:
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
}

Related

How do I show menu again on onPrepareOptionsMenu( );

Please help,
I want the menu to be hidden when I enter the Activity at the begining.
And after progressbar is set to gone, the menu will not be hidden.
But when I ran my app, the menu was always hidden.
I don't know how to show the menu on screen again.
HomeActivity.java
public class HomeActivity extends AppCompatActivity {
private ActivityHomeBinding binding;
private ActionBar actionBar;
private Menu menu;
private ProgressBar progressBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityHomeBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
actionBar = getSupportActionBar();
progressBar = binding.progressBar;
progressBar.setVisibility(View.VISIBLE);
// it's not work
onPrepareOptionsMenu(menu);
...
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
this.menu = menu;
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.menu.function_menu, menu);
return true;
}
#Override
public boolean onPrepareOptionsMenu (Menu menu) {
menu.clear();
if (progressBar.getVisibility() == View.VISIBLE) {
onCreateOptionsMenu(menu);
return false;
} else {
onCreateOptionsMenu(menu);
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.menu.function_menu, menu);
return true;
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
Intent intent;
switch (item.getItemId()) {
case R.id.menu_home:
intent = new Intent(HomeActivity.this, HomeActivity.class);
homeActivityResultLauncher.launch(intent);
return true;
case R.id.menu_summary:
intent = new Intent(HomeActivity.this, SummaryActivity.class);
summaryActivityResultLauncher.launch(intent);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}

Different action menu items for each fragment with same navigation drawer in Android

I have a Main activity that hosts a navigation drawer and multiple fragments. Each fragment has its own set of menu items.
Now the problem starts when I add the onOptionsItemSelected method, the navigation Drawer won't open. And when I don't add the onOptionsItemSelected method, navigation Drawer opens but then menu items are not working.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_payment_type_data_stats, parent, false);
setHasOptionsMenu(true);
return v;
}
#Override
public void onCreateOptionsMenu(#NonNull Menu menu, MenuInflater inflater) {
menu.clear();
inflater.inflate(R.menu.menu_payment_type_stats, menu);
Objects.requireNonNull(((MainActivity) Objects.requireNonNull(getActivity())).getSupportActionBar()).setTitle("title");
super.onCreateOptionsMenu(menu, inflater);
}
#SuppressLint("NonConstantResourceId")
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_today:
getDataForToday();
break;
case R.id.action_past_seven:
getDataForPeriod(calendarDates.pastSeventhDate(), calendarDates.todayDate());
break;
case R.id.action_custom_date:
openDatePickerDialog(sdf);
break;
}
return true;
}
If you have any suggestions for fixing this problem, please share.
Can set manually -
`drawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mDrawer.openDrawer(GravityCompat.START);
}
});`
or can try this
mDrawerToggle.syncState();
MainActivity changes:
All you have to do is change onOptionsItemSelected in MainActivity from
#Override
public boolean onOptionsItemSelected(MenuItem item) {
return true;
}
and change it to
#Override
public boolean onOptionsItemSelected(MenuItem item) {
return super.onOptionsItemSelected(item); //important
}
As far as the onCreateOptionsMenu method in MainActivity, you can leave it empty with just
return true
Fragment changes
For fragment (each fragment can have separate action menu items) you need to implement 3 methods
onCreateView
onCreateOptionsMenu
onOptionsItemSelected
Example:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_payment_type_data_stats, parent, false);
setHasOptionsMenu(true); //important
return v;
}
#Override
public void onCreateOptionsMenu(#NonNull Menu menu, MenuInflater inflater) {
menu.clear();
//each frag can have different menu
inflater.inflate(R.menu.menu_payment_type_stats, menu);
super.onCreateOptionsMenu(menu, inflater);
}
#SuppressLint("NonConstantResourceId")
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.action_today:
getDataForToday();
break;
case R.id.action_yesterday:
getDataForPeriod(calendarDates.yesterdayDate(), calendarDates.yesterdayDate());
break;
case R.id.action_past_seven:
getDataForPeriod(calendarDates.pastSeventhDate(), calendarDates.todayDate());
break;
case R.id.action_past_thirty:
getDataForPeriod(calendarDates.pastThirtiethDate(), calendarDates.todayDate());
break;
case R.id.action_custom_date:
openDatePickerDialog(sdf);
break;
}
return false;
}

How to go previous activity searchview back button?

I have a very simple question. I have implemented searchview in my menu. So the activity starts with expanded searchview. And now when I press back button, the searchview first collapse and goes back to previous activity.
Here's my code
#Override
public boolean onCreateOptionsMenu(final Menu menu) {
getMenuInflater().inflate(R.menu.menu_search, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
searchItem.expandActionView();
SearchView mSearchView = (SearchView) MenuItemCompat.getActionView(searchItem);
mSearchView.setQueryHint(getString(R.string.search_hint));
mSearchView.setIconifiedByDefault(false);
mSearchView.setFocusable(true);
mSearchView.setIconified(false);
mSearchView.requestFocus();
mSearchView.setGravity(Gravity.END);
mSearchView.setTextDirection(View.TEXT_DIRECTION_RTL);
//mSearchView.setLayoutParams(new Toolbar.LayoutParams(Gravity.END));
//String searchQuery = getIntent().getStringExtra("SEARCH");
//SearchActivity.this.myAdapter.filter(searchQuery);
TextView searchText = mSearchView.findViewById(android.support.v7.appcompat.R.id.search_src_text);
//searchText.setText(searchQuery);
Typeface customFont = Typeface.createFromAsset(this.getAssets(), "fonts/font.ttf");
searchText.setTypeface(customFont);
try {
ThaanaUtils.thaanafyTextViewSubclass(searchText, "fonts/faruma.ttf");
}catch (IOException e){
e.printStackTrace();
}
searchText.addTextChangedListener(new ThaanaTextWatcher());
View xIcon = ((View) mSearchView.findViewById(R.id.search_plate));
xIcon.setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return true;
}
#Override
public boolean onQueryTextChange(String newText) {
SearchActivity.this.myAdapter.filter(newText);
return true;
}
});
MenuItemCompat.setOnActionExpandListener(searchItem, new MenuItemCompat.OnActionExpandListener() {
#Override
public boolean onMenuItemActionExpand(MenuItem item) {
return true;
}
#Override
public boolean onMenuItemActionCollapse(MenuItem item) {
onBackPressed();
return true;
}
});
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.action_favorites) {
//Intent newActivity = new Intent(SearchActivity.this,FavoritesActivity.class);
//startActivity(newActivity);
}
return super.onOptionsItemSelected(item);
}
#Override
public void onBackPressed()
{
finish();
}
#Override
public boolean onSupportNavigateUp() {
onBackPressed();
return true;
}
But I don't want to show searchview collapsing when pressed back button. I want to go back to previous activity without collapsing searchview.
How can I achieve that?
Any help is appreciated.
Override the onBackPressed() method in your activity and then put your activity redirection code inside the method. This will solve your problem. Happy coding!
#Override
public void onBackPressed() {
// enter your activity redirection code here.
}
If you didn't call finish() on your previous activity, then just call finish() inside the onBackPressed method. This will destroy the current activity(search activity) and will load previous one. Else you need to go through the usual way by declaring an intent.

onCreateOptionsMenu is not called after a fragment add & remove

I have a fragment where I can call ActivityCompat.invalidateOptionsMenu(getActivity()); and the method onCreateOptionsMenu() is successfully called on both: Activity and Fragment.
However, when I add a fragment on top of the fragment with:
transaction.add(R.id.fragment_home, fragment2, "fragment_ID");
transaction.addToBackStack(null);
transaction.commit();
and later close it (either by backPress or by getSupportFragmentManager().popBackStack();), ActivityCompat.invalidateOptionsMenu(getActivity()); becomes unresponsive. onCreateOptionsMenu() is not called at all.
I know for sure, that it will work if I use replace() instead of add(), however, for some reasons, I need to use add().
on Activity:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragment_home);
if (fragment != null)
fragment.onCreateOptionsMenu(menu, getMenuInflater());
return true;
}
on Fragment 1:
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
Log.d(TAG, "onCreateOptionsMenu() called with: ...");
// additional code
super.onCreateOptionsMenu(menu, inflater);
}
Please try below code :
#Override
public boolean onCreateOptionsMenu(Menu menu) {
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragment_home);
if (fragment != null) {
fragment.onCreateOptionsMenu(menu, getMenuInflater());
return true;
}
getMenuInflater().inflate(R.menu.menu_layout, menu);
return super.onCreateOptionsMenu(menu);
}

Where to declare onOptionsItemSelected for global use?

I'm very new to Android development.
In my MainActivity.java file, I've declared an onOptionsItemSelected(MenuItem menu) method that allows the user to jump between the current MainActivity.java page and another page I created called Settings.java.
When the user goes to the Settings.java page, and they click on the Home option from the menu, nothing happens. I know this is because the onOptionsItemSelected(MenuItem menu) is only defined in the MainActivity.java class and not in the Settings.java class.
I'm overcoming this right now by copying the onOptionsItemSelected(MenuItem menu) from MainActivity.java into Settings.java. But this is very redundant.
Where should I be declaring methods that could be reused in different classes?
MainActivity.java
public class MainActivity extends Activity {
...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_settings:
showMsg("Settings Clicked");
this.startActivity(new Intent(this, Settings.class));
return true;
case R.id.action_home:
showMsg("Home clicked");
this.startActivity(new Intent(this, MainActivity.class));
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private void showMsg(String msg) {
Toast toast = Toast.makeText(this.getBaseContext(), msg, Toast.LENGTH_LONG);
toast.show();
}
}
Settings.java
public class Settings extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.settings);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_settings:
this.startActivity(new Intent(this, Settings.class));
return true;
case R.id.action_home:
this.startActivity(new Intent(this, MainActivity.class));
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
If you create an Activity called BaseActivity that has your common onOptionsItemSelected() code then extend this class to create MainActivity and Settings both of these classes will use the super class' (i.e. BaseActivity's) onOptionsItemSelected().
Another approach is to switch to Fragments, since Fragments use the host Activity's onOptionsItemSelected() as well as their own. Both of these tactics allow you to use "centralized" code and not have to maintain multiple "cut and paste" copies.

Categories

Resources