1

my app uses navigation drawer with actionbarsherlock. I want to use action items in the fragment like this:

public class StartFragment extends SherlockFragment {

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_start, container,
            false);

    setHasOptionsMenu(true);
    return rootView;
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    super.onCreateOptionsMenu(menu, inflater);
    inflater.inflate(R.menu.start, menu);
}

// Handle context menu events
public boolean onOptionsItemSelected(MenuItem menuItem) {
    switch (menuItem.getItemId()) {
    case R.id.backup:
        Log.i(TAG, "Backup clicked");
        break;
    case R.id.settings:
        Log.i(TAG, "Settings clicked");
    }
    return (super.onOptionsItemSelected(menuItem));
}

}

The problem is, that the log output is not fired when I click the icon but only when i open the navigation drawer.

Here is the main activity:

import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.RelativeLayout;

import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.MenuItem;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdView;

import xyz.StartFragment;

public class MainActivity extends SherlockFragmentActivity {

// Variables
DrawerLayout mDrawerLayout;
ListView mDrawerList;
ActionBarDrawerToggle mDrawerToggle;
MenuListAdapter mMenuAdapter;
String[] title;
String[] subtitle;
int[] icon;
Fragment fragment1 = new StartFragment();
private CharSequence mDrawerTitle;
private CharSequence mTitle;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.drawer_main);

    // Get the title
    mTitle = mDrawerTitle = getTitle();

    // Generate title
    title = getResources().getStringArray(R.array.actionbar_menu);

    // Generate icon
    icon = new int[] { R.drawable.home, R.drawable.mozart,
            R.drawable.action_settings, R.drawable.action_settings,
            R.drawable.action_settings, R.drawable.collections_cloud };

    // Locate DrawerLayout in drawer_main.xml
    mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);

    // Locate ListView in drawer_main.xml
    mDrawerList = (ListView) findViewById(R.id.listview_drawer);

    // Set a custom shadow that overlays the main content when the drawer
    // opens
    mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow,
            GravityCompat.START);

    // Pass string arrays to MenuListAdapter
    mMenuAdapter = new MenuListAdapter(MainActivity.this, title, icon);

    // Set the MenuListAdapter to the ListView
    mDrawerList.setAdapter(mMenuAdapter);

    // Capture listview menu item click
    mDrawerList.setOnItemClickListener(new DrawerItemClickListener());

    // Enable ActionBar app icon to behave as action to toggle nav drawer
    getSupportActionBar().setHomeButtonEnabled(true);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);

    // ActionBarDrawerToggle ties together the the proper interactions
    // between the sliding drawer and the action bar app icon
    mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
            R.drawable.ic_drawer, R.string.drawer_open,
            R.string.drawer_close) {

        public void onDrawerClosed(View view) {
            // TODO Auto-generated method stub
            super.onDrawerClosed(view);
        }

        public void onDrawerOpened(View drawerView) {
            // TODO Auto-generated method stub
            // Set the title on the action when drawer open
            getSupportActionBar().setTitle(mDrawerTitle);
            super.onDrawerOpened(drawerView);
        }
    };

    mDrawerLayout.setDrawerListener(mDrawerToggle);

    if (savedInstanceState == null) {
        selectItem(0);

    }

}



@Override
public boolean onOptionsItemSelected(MenuItem item) {

    if (item.getItemId() == android.R.id.home) {

        if (mDrawerLayout.isDrawerOpen(mDrawerList)) {
            mDrawerLayout.closeDrawer(mDrawerList);
        } else {
            mDrawerLayout.openDrawer(mDrawerList);
        }
    }


    return super.onOptionsItemSelected(item);
}

// ListView click listener in the navigation drawer
private class DrawerItemClickListener implements
        ListView.OnItemClickListener {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position,
            long id) {
        selectItem(position);
    }
}

private void selectItem(int position) {

    FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
    // Locate Position
    switch (position) {
    case 0:
        ft.replace(R.id.content_frame, fragment1);
        break;
    case 1:
        ft.replace(R.id.content_frame, fragment2);
        break;
    case 2:
        ft.replace(R.id.content_frame, fragment3);
        break;
    }
    ft.commit();
    mDrawerList.setItemChecked(position, true);

    // Get the title followed by the position
    setTitle(title[position]);
    // Close drawer
    mDrawerLayout.closeDrawer(mDrawerList);
}

@Override
protected void onPostCreate(Bundle savedInstanceState) {
    super.onPostCreate(savedInstanceState);
    // Sync the toggle state after onRestoreInstanceState has occurred.
    mDrawerToggle.syncState();
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    // Pass any configuration change to the drawer toggles
    mDrawerToggle.onConfigurationChanged(newConfig);
}

@Override
public void setTitle(CharSequence title) {
    mTitle = title;
    getSupportActionBar().setTitle(mTitle);
}

}

Any clues?

adneal
  • 30,484
  • 10
  • 122
  • 151
Cellist
  • 89
  • 2
  • 11

3 Answers3

3

According to the documentation, you need to call setHasOptionsMenu() in your onCreate of the fragment, so try to add this to your fragment code:

public void onCreate (Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
}

Please note that the documentation tells you to use setHasOptionsMenu in onCreate. Your are calling it in onCreateView

Edit
Also from the documentation here. The onCreateOptionsMenu does not call the super-method, it simply creates the menu and returns true:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.game_menu, menu);
    return true;
}

So you might have to inflate it before calling super-method or not call it at all.

Edit2

I guess it should be the following with actionbarsherlock:

public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getSherlockActivity().getSupportMenuInflater();
    inflater.inflate(R.menu.start, menu);
    return true;
}

But then, the icons don't show up at all

Edit3
I'm sorry, I wasn't clear enough in my Edit. The code you see there is from the Activity. For the Fragment, it looks a little different. So from some more research I found this answer giving working code. This supports my idea from the edit: You have to call the super-method after inflating the layout. In your case, the code in your Fragment has to look like this:

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.start, menu);
    super.onCreateOptionsMenu(menu, inflater);
}
Community
  • 1
  • 1
MalaKa
  • 3,734
  • 2
  • 18
  • 31
  • I tried your suggestion, but the problem is still the same – Cellist Mar 22 '14 at 12:23
  • Hm.. have you removed the `setHasOptionsMenu` from your `onCreateView`? – MalaKa Mar 22 '14 at 12:28
  • Okay, I have found another issue, that might cause the problem. Please See the edited anwer. – MalaKa Mar 22 '14 at 12:37
  • @Cellist One more edit. If this doesn't work. I unfortunately can't tell what the issue is. – MalaKa Mar 22 '14 at 13:35
  • the icons show up now, but still the same problem. I think the problem must be somewhere else. Maybe something with the navigation drawer interferes. Nonetheless thanks for your help. – Cellist Mar 22 '14 at 13:42
1

I believe the 'backup' button belongs to the activity, not the fragment, which is why you're not getting the callback in your fragment's onOptionsItemSelected method.

If you want to execute code from the fragment when this button is pressed you could simply add a method to your fragment, and call that from the activity's onOptionsItemSelected:

Activity:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    if (item.getItemId() == android.R.id.home) {
        fragment1.onUp();
        if (mDrawerLayout.isDrawerOpen(mDrawerList)) {
            mDrawerLayout.closeDrawer(mDrawerList);
        } else {
            mDrawerLayout.openDrawer(mDrawerList);
        }
    }

Fragment:

public void onUp() {
    Log.d("backup clicked");
}
brk3
  • 1,524
  • 2
  • 19
  • 31
  • I don't think so. Because when I don't implement the onOptionsItemSelected method in the fregment, I don't receive click events at all from the fregment. I chose the workaround to create the menus dynammically in the activity. But it doesn't seem right since it doesn't allow loose coupling of activity and fragment. – Cellist Mar 23 '14 at 09:24
0

I got the problem myself. The onOptionsItemSelected-method of the activity was not correct. I found the solution in the documentation in the section about handling clicks on action items: http://developer.android.com/guide/topics/ui/actionbar.html#ActionItems

I implemented the method according to the documentation and everything worked fine.

Cellist
  • 89
  • 2
  • 11