如何在Android中将选项菜单添加到片段


399

我正在尝试从一组片段中将一个项目添加到选项菜单。

我创建了一个新MenuFragment类,并将其扩展为希望包含菜单项的片段。这是代码:

Java:

public class MenuFragment extends Fragment {

    MenuItem fav;

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

    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        fav = menu.add("add");
        fav.setIcon(R.drawable.btn_star_big_off);
    }
}

科特林:

class MenuFragment : Fragment {

    lateinit var fav: MenuItem

    override fun onCreate(savedInstanceState: Bundle) {
        super.onCreate(savedInstanceState)
        setHasOptionsMenu(true)
    }

    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        fav = menu.add("add");
        fav.setIcon(R.drawable.btn_star_big_off);
    }
}

由于某些原因,该onCreateOptionsMenu似乎无法运行。


也许是个愚蠢的问题...您按下菜单按钮对不对?
奥维迪乌

2
..lol ...是的,我按下了菜单按钮,无论是否使用,我都尝试过:fav.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
misterbassman 2011年

嗨,也许这个线程会为您提供帮助或查看api演示以获取有效示例。
kameny 2011年

Answers:


604

调用super方法:

Java:

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

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        // TODO Add your menu entries here
        super.onCreateOptionsMenu(menu, inflater);
    }

科特林:

    override fun void onCreate(savedInstanceState: Bundle) {
        super.onCreate(savedInstanceState)
        setHasOptionsMenu(true)
    }

    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        // TODO Add your menu entries here
        super.onCreateOptionsMenu(menu, inflater)
    }

将log语句放入代码中,以查看是否未调用该方法或代码未修改菜单。

此外,还要确保您呼叫setHasOptionsMenu(boolean)onCreate(Bundle)通知,它应该参与选项菜单处理的片段。


2
感谢您的帮助,我添加了super方法,并意识到我已经删除了@Override,因此又添加了它,eclipse引发了错误,因此我替换了MenuInflater来导入android.view.MenuInflater; 而不是导入android.support.v4.view.MenuInflater; 而现在一切都在工作
misterbassman 2011年

183
在片段的onCreate中不调用setHasOptionsMenu(true)现在让我两次
joshkendrick 2012年

7
我将“活动”转移到“片段”,并遇到了这个问题。方法签名已从public boolean更改为public void,并且参数也已更改。请务必注意这一点!
you786 2012年

14
请注意,Fragment.onCreateOptionsMenu(Menu,MenuInflater)是一个空方法,因此根本不需要调用super。唯一的错误是方法签名错误,并且可能缺少onCreate()中的
setHasOptionsMenu

6
将super.onCreateOptionsMenu替换为inflater.inflate(R.menu.menu_custom,menu);
Code_Worm

197

我遇到了同样的问题,但是我认为最好总结一下并介绍使之正常工作的最后一步:

  1. 在您的Fragment方法中添加setHasOptionsMenu(true)onCreate(Bundle savedInstanceState)方法。

  2. onCreateOptionsMenu(Menu menu, MenuInflater inflater)在Fragment中重写(如果您想在Fragment的菜单中执行其他操作)和onOptionsItemSelected(MenuItem item)方法。

  3. onOptionsItemSelected(MenuItem item)Activity的方法内,请确保在onOptionsItemSelected(MenuItem item)Fragment的方法中实现菜单项操作时返回false 。

一个例子:

活动

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

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {

        case R.id.activity_menu_item:

            // Do Activity menu item stuff here
            return true;

        case R.id.fragment_menu_item:

            // Not implemented here
            return false;
        default:
            break;
    }

    return false;
}

分段

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

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    // Do something that differs the Activity's menu here
    super.onCreateOptionsMenu(menu, inflater);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {

        case R.id.activity_menu_item:

            // Not implemented here
            return false;
        case R.id.fragment_menu_item:

            // Do Fragment menu item stuff here
            return true;

        default:
            break;
    }

    return false;
}

2
只是失踪了,setHasOptionsMenu(true);谢谢
Chad Bingham 2014年

1
在某些设备上的viewPager上,菜单仅在您第二次访问该片段时才会显示
Roel

3
@Marco HC您的代码运行正常。但是,如果我想隐藏“活动”或“片段”的某些菜单怎么办?您提到了在哪里实现哪个选项菜单(活动和片段中)。但是,如果我想隐藏一些菜单怎么办?
Shreyash Mahajan'3

@iDroidExplorer仅保留对该MenuItem的引用,并将可见性设置为走或不可见。那是你的问题吗?
Marco HC 2015年

@iDroidExplorer我尝试了他的代码,我不知道如何,但是当我切换到其他片段时它会自动隐藏菜单。
Noor Ali Butt

156

如果发现onCreateOptionsMenu(Menu menu, MenuInflater inflater)未调用该方法,请确保从Fragment的onCreate(Bundle savedInstanceState)方法中调用以下代码:

setHasOptionsMenu(true)

它给了我类似NullPointerException的错误
Pratik Butani

2
好点子。我从静态newInstance方法调用setHasOptionMenu方法。因为我只在saveInstanceState为null时附加片段,所以当屏幕配置更改时,将不会创建菜单。片段的onCreate方法是将setHasOptionMenu设置为true的正确位置。
argenkiwi

1
我使用的是Toolbar和只好打电话setHasOptionsMenu(true)onCreateView(),而不是onCreate()把它完成。
克鲁格,2016年

60

如果您需要menu刷新webview特定的Fragment,可以使用:

片段

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

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {

    // TODO Add your menu entries here
    inflater.inflate(R.menu.menu, menu);
    super.onCreateOptionsMenu(menu, inflater);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case R.id.exit:
        System.exit(1);
        break;

    case R.id.refresh:
        webView.reload();
        break;
    }
    return true;

}

menu.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/exit" android:title="Exit" android:icon="@drawable/ic_action_cancel" />
    <item android:id="@+id/refresh" android:title="Refresh" android:icon="@drawable/ic_action_refresh" />
</menu>

31

TL; DR

使用android.support.v7.widget.Toolbar和做:

toolbar.inflateMenu(R.menu.my_menu)
toolbar.setOnMenuItemClickListener {
    onOptionsItemSelected(it)
}

独立工具栏

大多数建议的解决方案(例如)setHasOptionsMenu(true)仅在父活动的布局中具有工具栏并通过声明时才起作用setSupportActionBar()。然后,片段可以参与此确切的ActionBar的菜单填充:

Fragment.onCreateOptionsMenu():初始化Fragment主机的标准选项菜单的内容。

如果您想要一个特定片段的独立工具栏和菜单,则可以执行以下操作:

menu_custom_fragment.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/menu_save"
        android:title="SAVE" />
</menu>

custom_fragment.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    ...

CustomFragment.kt

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    val view = inflater.inflate(layout.custom_fragment, container, false)
    val toolbar = view.findViewById<Toolbar>(R.id.toolbar)
    toolbar.inflateMenu(R.menu.menu_custom_fragment)
    toolbar.setOnMenuItemClickListener {
        onOptionsItemSelected(it)
    }
    return view
}

override fun onOptionsItemSelected(item: MenuItem): Boolean {
    return when (item.itemId) {
        R.id.menu_save -> {
            // TODO: User clicked the save button
            true
        }
        else -> super.onOptionsItemSelected(item)
    }
}

是的,就是这么简单。您甚至不需要覆盖onCreate()onCreateOptionsMenu()

PS:这仅适用于android.support.v4.app.Fragmentandroid.support.v7.widget.Toolbar(也请确保在中使用AppCompatActivityAppCompat主题styles.xml)。


1
确实对我有很大帮助
Brahmy adigopula

23

在中,menu.xml您应该添加所有菜单项。然后,您可以隐藏不想在初始加载中看到的项目。

menu.xml

<item
    android:id="@+id/action_newItem"
    android:icon="@drawable/action_newItem"
    android:showAsAction="never"
    android:visible="false"
    android:title="@string/action_newItem"/>

添加setHasOptionsMenu(true)onCreate()方法以调用Fragment类中的菜单项。

FragmentClass.java

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

您无需onCreateOptionsMenu再次在Fragment类中重写。可以通过onPrepareOptionsMenuFragment中可用的替代方法来更改(添加/删除)菜单项。

@Override
public void onPrepareOptionsMenu(Menu menu) {
    menu.findItem(R.id.action_newItem).setVisible(true);
    super.onPrepareOptionsMenu(menu);

}

16

您需要在扩展菜单之前使用menu.clear()。

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

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

1
当您想在不同的片段中使用不同的菜单并且要添加片段而不是替换它们时,这是正确的。
Akshay Mahajan

谢谢!menu.clear()帮助我删除“活动”的菜单选项。
kimcy929

13

就我而言,这是步骤。

步骤1

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Here notify the fragment that it should participate in options menu handling.
    setHasOptionsMenu(true);
}

第2步

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    // First clear current all the menu items
    menu.clear();

    // Add the new menu items
    inflater.inflate(R.menu.post_stuff, menu);

    super.onCreateOptionsMenu(menu, inflater);
}

第三步

 @Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.post_stuff:
            Log.d(TAG, "Will post the photo to server");
            return true;
        case R.id.cancel_post:
            Log.d(TAG, "Will cancel post the photo");
            return true;
        default:
            break;
    }
    return super.onOptionsItemSelected(item);
}

使用menu.clear()清除的上一个菜单,我已经在主要活动上有了菜单。为我工作:)
Anbuselvan Rocky

8

如果要添加菜单自定义

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

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

如果有选项卡视图并且您想为每个片段添加不同的菜单怎么办?
Jainam Jhaveri

7

我遇到了同样的问题,我的片段是ViewPager的页面。发生这种情况的原因是,我在实例化FragmentPagerAdapter时使用的是子片段管理器,而不是活动支持片段管理器。


3

菜单文件:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/play"
        android:titleCondensed="Speak"
        android:showAsAction="always"
        android:title="Speak"
        android:icon="@drawable/ic_play">
    </item>
    <item
        android:id="@+id/pause"
        android:titleCondensed="Stop"
        android:title="Stop"
        android:showAsAction="always"
        android:icon="@drawable/ic_pause">
    </item>
</menu>

活动代码:

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

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {

        case R.id.play:
            Toast.makeText(getApplicationContext(), "speaking....", Toast.LENGTH_LONG).show();
            return false;

        case R.id.pause:
            Toast.makeText(getApplicationContext(), "stopping....", Toast.LENGTH_LONG).show();
            return false;

        default:
            break;
    }

    return false;
}

片段代码:

@Override

public void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {

        case R.id.play:
            text = page.getText().toString();
            speakOut(text);

            // Do Activity menu item stuff here
            return true;

        case R.id.pause:
            speakOf();

            // Not implemented here
            return true;

        default:
            break;
    }
    return false;
}

3

您的代码很好。方法中仅缺少超级:

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    // TODO add your menu : 
    inflater.inflate(R.menu.my_menu, menu);
    //TODO call super
    super.onCreateOptionsMenu(menu, inflater);
}

2

我快疯了,因为这里没有答案对我有用。

要显示菜单,我必须调用: setSupportActionBar(toolbar)

做完了!

注意:如果您的toolbar视图不在同一活动布局中,则不能直接从活动类中使用上面的调用,在这种情况下,您需要从片段类中获取该活动,然后调用setSupportActionBar(toolbar)。记住:您的活动类应扩展AppCompatActivity。

希望这个答案对您有帮助。


1

在创建片段视图之后设置选项菜单对我来说效果很好。

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    setHasOptionsMenu(true);        
}

1

我的问题略有不同。我做的一切都正确。但是我为承载该片段的活动继承了错误的类。

为了清楚起见,如果您要覆盖onCreateOptionsMenu(Menu menu, MenuInflater inflater)该片段,请确保承载该片段的活动类继承android.support.v7.app.ActionBarActivity(以防您想支持低于API级别11的活动)。

我继承了android.support.v4.app.FragmentActivity以支持低于11的API级别。


1

我要添加的一件事是它对我不起作用的原因。

这类似于Napster的答案。

  1. 确保您的片段的托管活动扩展AppCompatActivity,而不是FragmentActivity

    public class MainActivity extends AppCompatActivity {
    
    }

    从Google FragmentActivity 参考文档中:

    注意:如果要实现包含动作栏的活动,则应改用ActionBarActivity类,该类是该类的子类,因此允许您在API级别7和更高级别使用Fragment API。

  2. 要更新Napster的答案- ActionBarActivity现在已弃用,请AppCompatActivity改用。

  3. 使用时AppCompatActivity,还请确保设置“活动主题为Theme.AppCompat或类似主题”(Google Doc)。

注意:android.support.v7.app.AppCompatActivity是的子类android.support.v4.app.FragmentActivity该类类(请参阅AppCompatActivity ref doc)。


1

在菜单文件夹中,创建一个.menu xml文件并添加此xml

<item
    android:id="@+id/action_search"
    android:icon="@android:drawable/ic_menu_search"
    android:title="@string/action_search"
    app:actionViewClass="android.support.v7.widget.SearchView"
    app:showAsAction="always|collapseActionView" />

在您的片段类中,重写此方法,然后

implement SearchView.OnQueryTextListener    in your fragment class



@Override
 public void onViewCreated(View view, Bundle savedInstanceState) {    
  super.onViewCreated(view, savedInstanceState);
  setHasOptionsMenu(true);

}

现在,只需在片段类中设置菜单xml文件

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

    final MenuItem item = menu.findItem(R.id.action_search);
    final SearchView searchView = (SearchView)    
    MenuItemCompat.getActionView(item);


    MenuItemCompat.setOnActionExpandListener(item,
            new MenuItemCompat.OnActionExpandListener() {
                @Override
                public boolean onMenuItemActionCollapse(MenuItem item) {
                    // Do something when collapsed

                    return true; // Return true to collapse action view
                }

                @Override
                public boolean onMenuItemActionExpand(MenuItem item) {
                    // Do something when expanded
                    return true; // Return true to expand action view
                }
            });

}

0

如果以上所有方法均无效,则需要调试并确保已调用onCreateOptionsMenu函数(通过放置调试或写入日志...)

如果未运行,则可能是您的Android主题不支持操作栏。 打开AndroidManifest.xml并android:theme使用主题支持操作栏设置的值

 <activity
     android:name=".MainActivity"
     android:label="@string/app_name"
     android:theme="@style/Theme.AppCompat">

0

在您的onCreate方法上添加setHasOptionMenu()

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

然后覆盖您的onCreateOptionsMenu

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    menu.add("Menu item")
            .setIcon(android.R.drawable.ic_delete)
            .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.