I have a problem with developing an app for both tablets and smartphones with fragments.
When app is executed on smartphone, I show a fragment with a list (categories). When clicking on an item, I start a new activity that holds a ViewPager that inflates Fragments with another list (detail).
When app is executed on tablet I have a layout with two fragments inside. The left one is the categories list and the right one is the detail list.
Up to here there's no problem, but when setting onOptionsItemSelected I have problems.
When executing app on smartphone, everything is working well. This works:
Activity containing ViewPager
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.icShare:
sharePortal();
break;
default:
break;
}
return super.onOptionsItemSelected(item);
}
Fragment inflated by ViewPager
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.icFavourite:
Utils.setFavouritePortal(mContext, mPortal);
getActivity().invalidateOptionsMenu();
return true;
case R.id.icShowFavourites:
showFavouriteArticles();
return true;
default:
break;
}
return super.onOptionsItemSelected(item);
}
But when executing the app in tablet, onOptionsItemSelected is not called. This is the code:
Fragment containing ViewPager
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.icShowFavourites:
Log.e("asdf", "asdfasdf - test tablet");
break;
default:
break;
}
return super.onOptionsItemSelected(item);
}
Fragment inflated by ViewPager
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.icFavourite:
Utils.setFavouritePortal(mContext, mPortal);
getActivity().invalidateOptionsMenu();
return true;
case R.id.icShowFavourites:
showFavouriteArticles();
return true;
default:
break;
}
return super.onOptionsItemSelected(item);
}
The only difference is that when executing on smartphone, the first onOptionsItemSelected is hold by an Activity and in tabled is hold by a fragment. I also tried to execute the onOptionsItemSelected from the Activity containing the fragment that contains the ViewPager inflating other fragments with no luck.
How can I get it working?
Thank you in advance!
Try to put setHasOptionsMenu(true); inside the fragment where you want onOptionsItemSelected() to be called.
Documentation
The fragment should call setHasOptionsMenu(true), and should implement onCreateOptionsMenu() and onOptionsItemSelected().
Related
I added a Navigation Drawer to my Activity and it seems to be working fine. The problem is that I have another icon on my Toolbar called info, which is now not responding. This info item exists in my menu.xml file:
<item
android:id="#+id/info"
android:title="Info"
android:icon="#drawable/ic_info_outline_black_24dp"
android:orderInCategory="100"
app:showAsAction="always" />
I inflate this menu in my Java code:
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.action_bar_items, menu);
return true;
}
And add it to my onOptionsItemsSelectedMethod, which also contains my navigation drawer:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case R.id.home:{
if (drawerLayout.isDrawerOpen(drawerList)){
drawerLayout.closeDrawer(drawerList);
}else{
drawerLayout.openDrawer(drawerList);
}
return true;
}case R.id.info:{
Toast.makeText(getApplicationContext(),"HEY",Toast.LENGTH_LONG).show();
}
default:return super.onOptionsItemSelected(item);
}
}
The icon pops up on my ToolBar but does not respond when I click on it. Please help. Thank you.
IDs need to be kept consistent
in xml you have :
android:id="#+id/infoActionBar"
in java code, you are looking for :
case R.id.info:
Change either of those, to match with the other one.
Edit:
Replace case R.id.home: with case android.R.id.home:
Your info button id in your xml is android:id="#+id/infoActionBar" and you try to call case R.id.info: so please change one of them and try again :)
infoActionBar vs info
In onOptionsItemSelectedit must be id of the item not the title in case of item.getItemId()
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case R.id.home:{
if (drawerLayout.isDrawerOpen(drawerList)){
drawerLayout.closeDrawer(drawerList);
}else{
drawerLayout.openDrawer(drawerList);
}
return true;
}case R.id.infoActionBar:{
Toast.makeText(getApplicationContext(),"HEY",Toast.LENGTH_LONG).show();
}
default:return super.onOptionsItemSelected(item);
}
}
I am using actionBar.setDisplayHomeAsUpEnabled(true); for back navigation functionality but it is not working as properly as i need it and when i am using back button of my phone it works properly.
Is there any way to code on a button such that it work same as back navigation button of phone?
Along with
actionBar.setDisplayHomeAsUpEnabled(true);
or
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
you can try using this in Activity, too:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
onBackPressed();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
So your menu item "Home"'s click will be handled using that.
I know this has been answered, but i always do this in my method when having the same back-button-like capability in another ActionBarActivity.
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()){
case android.R.id.home:
finish();
break;
}
return super.onOptionsItemSelected(item);
}
and ofcourse:
actionBar.setDisplayHomeAsUpEnabled(true);
You may/may not used this, its up to you :)
I have an activity(say activity X) which contains a search box. On searching, I move on to another activity.( say Activity Y) I have used SherlockFragmentActivity to extend this Activity class and inside this activity I am loading a single fragment(say fragment A).
This fragment has many rows and on click of each row I am loading another fragment(say fragment B).
The problem is on clicking home button on my navigation bar from fragment B, Activity X is getting loaded and not fragment A.
I want fragment A to be loaded. How can I accomplish this?
What I have tried was: In my Activity Y,
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
#Override public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home :
this.getSupportFragmentManager().popBackStack();
return true;
}
return super.onOptionsItemSelected(item);
}
you can try like this.
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
newFragment=new FragementA();
FragmentTransaction transaction=getFragmentManager().beginTransaction();
transaction.replace(R.id.myFragement,newFragment);
transaction.addToBackStack(null);
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
transaction.commit();
return true;
}
I have 2 activities with action bar which has this code in its onCrate method:
getActionBar().setDisplayHomeAsUpEnabled(true);
And here is the onOptionsItemSelected:
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case android.R.id.icon:
finish();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
The first activity has a parent activity (configured in the manifest) the second one just opened from fragment (without parent fragment configured in the manifest). In the first activity, when I click the icon, the activity item.getItemId() value is the same as android.R.id.icon which then falls in the switch statement (case: Android.R.id.icon). In the second activity those values are deferent. Why this is happening? I would like to fall in the case: Android.R.id.icon in both activities.
Instead of using android.R.id.icon use android.R.id.home
Try this code:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
// Respond to the action bar's Up/Home button
case android.R.id.home:
NavUtils.navigateUpFromSameTask(this);
return true;
}
return super.onOptionsItemSelected(item);
}
For more detail check this link
Use this type of code
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(1, 1, 1, "Done").setIcon(R.drawable.img_done)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
menu.add(1, 2, 2, "Save").setIcon(R.drawable.img_save)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
return true;
}
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case 1:
// Write your code for the first button
break;
case 2:
// Write your code for the second button
break;
}
return true;
}
Try this:
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case R.id.icon: //where 'icon' would be your item ID from menu.xml.
finish();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
you are using android.R.id.icon that might be wrong. Instead of that you may want to use R.id.icon.
There is a difference between both R.id.icon and android.R.icon files.
Also make sure that you are not using following import
import android.R;
It may lead you to unwanted results.
Let's say I have a ListFragment A that is rooted from MainActivity A. User presses a list from List A and go to the FragmentActivity B. FragmentActivity holds 3 tabs of fragments.
So, I want to put an up navigation to the FragmentActivity B, so that it goes back to ListFragment A. How do I go about that?
This is my try, so far no luck:
public class ItemDetailActivity extends FragmentActivity implements ActionBar.TabListener {
...
actionBar.setDisplayHomeAsUpEnabled(true);
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
LatestFragment fragment = new LatestFragment();
getSupportFragmentManager().beginTransaction()
.replace(R.id.pager, fragment).addToBackStack(null)
.commit();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
LatestFragment is the ListFragment A I want to go back to.
However, I got an error that says I have to implement OnLatestSelectedListener because in LatestFragment, I already put an interface to pass values.
What else can I go inside onOptionsItemSelected?
Assuming you started ItemDetailActivity with a standard intent, you should just be able to use back action like this:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
super.onBackPressed();
finish();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
If fragment A is in your main activity then you can also look in to using ActionBar. Back button takes you to the main activity. It is quite easy to implement as well.
I assume your FragmentActivityB has got the back button.
if not you can get it by
getActionBar().setDisplayHomeAsUpEnabled(true);
<meta-data android:name="android.support.PARENT_ACTIVITY"
android:value="#######" />
Now you can just identify fragments rooted with MainActivity using some flags like ViewNumber(1,2,3).
Implement the method onMenuItemSelected(....) and pass the viewNumber ie; the Fragment Which you want to show.
#Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
//We are implementing this method to respond to the back button on the action bar.
int itemId = item.getItemId();
switch (itemId) {
case android.R.id.home:
Intent i = new Intent(this,MainActivity.class);
i.putExtra("viewNumber",2);
startActivity(i);
break;
}
return true;
}//onMenuItemSelected
In MainActivity get the viewNumber using Bundles, and you can have some method like this to work out and display the desired Fragment.
private void displayView(int position) {
// update the main content by replacing fragments
Fragment fragment = null;
switch (position) {
case 1:
fragment = new ListFragmentB();
break;
case 2:
fragment = new ListFragmentA();
break;
default:
break;
}
if (fragment != null) {
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.frame_container, fragment).commit();
}
}
}
I hope it will solve your problem.