如何在Android操作栏中添加开关?

55
5个回答

100

创建一个名为 switch_layout.xml 的开关布局。菜单的自定义布局应始终使用 RelativeLayout

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >

    <Switch
        android:id="@+id/switchForActionBar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="" />

</RelativeLayout>

然后,在您的 mainmenu.xml 文件中添加以下内容:

<menu xmlns:android="http://schemas.android.com/apk/res/android" >
    <item
        android:id="@+id/myswitch"
        android:title=""
        android:showAsAction="always"
        android:actionLayout="@layout/switch_layout"
    />   
</menu>

在你的活动中,像往常一样填充 mainmenu.xml

getMenuInflater().inflate(R.menu.mainmenu, menu);
return true;

2
“自定义菜单布局应始终使用RelativeLayout”,这是有相关文档支持的吗? - Yeung
12
要使Switch与标题具有相同的高度,您应该在Switch中添加android:layout_centerVertical="true" - Hải Phong
1
不要忘记为片段添加“setHasOptionsMenu(true);”,以强制调用onCreateOptionsMenu。 - ckp
42
如果开关不可见,对于actionLayoutshowAsAction请使用app命名空间。 - Harsh Vakharia
3
我正在使用appcompat,并在actionLayout和showAsAction中使用app命名空间,但我无法在onOptionsItemSelected方法中处理其点击事件,请问该怎么做? - Firas Al Mannaa
显示剩余6条评论

36

最后我终于找到问题所在了:如果你正在使用新的AppCompat,那么在Switch布局中你应该使用android.support.v7.widget.SwitchCompat而不是Switch,否则它将不会显示在ActionBar上(假定您也在使用AppCompat ActionBar),嗯,actionLayout属性不起作用,必须在代码中设置。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/switchView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">

    <android.support.v7.widget.SwitchCompat
        android:id="@+id/switchForActionBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="" />

</RelativeLayout>

然后在代码中设置布局:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_main, menu);
    MenuItem item = menu.findItem(R.id.on_off_switch);
    item.setActionView(R.layout.on_off_switch);
    return true;
}

1
使用 SwitchCompat 的另一个优点是:开关显示出了更加时尚的外观(例如材料设计)。 - DenisGL
15
为什么每个人都在RelativeLayout上使用android:orientation="horizontal" - zackygaurav
1
@zackygaurav 作为我的测试,它不需要使用 RelativeLayout,我正在使用 LinearLayout 并且它完美地工作。 - drakeet

33

如果小部件未出现在操作栏中,可能是因为您正在为操作栏使用appCompat。要解决此问题,请在menu.xml中的“showAsAction”和“actionLayout”前面将“android:”切换为“app:”

在xml中添加项目,使用app:替换android:

<menu xmlns:android="http://schemas.android.com/apk/res/android" >
            <item
                android:id="@+id/myswitch"
                android:title=""
                app:showAsAction="always"
                app:actionLayout="@layout/switch_layout"
            />   
        </menu>

制作用于您的“app:actionLayout”的布局
switch_layout

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >
    <Switch
        android:id="@+id/switchAB"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        />
</RelativeLayout>

像平常一样在您的ActionBarActivity中展开菜单

   getMenuInflater().inflate(R.menu.mainmenu, menu);
    return true;

如果开关没有显示出来,这应该会在您的操作栏中显示开关。


这是对上述答案微妙但极好的简化/补充! - swooby
1
这些细节很容易被忽视和忘记调整,但却非常重要。我曾经花了数小时来找出问题所在。现在,如果菜单中没有显示某些内容,我有一个经验法则是检查命名空间。 - ChallengeAccepted
我知道这已经很久了,但这个答案对我有用,现在的问题是如何获取开关,以便可以通过编程方式附加监听器? - clifford_owino

13

想要添加的人,

将CheckedChangeListener设置为相同的Switch

Kotlin

override fun onCreateOptionsMenu(menu: Menu?): Boolean {
    menuInflater.inflate(R.menu.menu_main, menu)
    val item = menu!!.findItem(R.id.my_switch_item)
    item.setActionView(R.layout.switch_layout)

    val mySwitch = item.actionView.findViewById(R.id.switch_id)
    mySwitch.setOnCheckedChangeListener(object : CompoundButton.OnCheckedChangeListener{
        override fun onCheckedChanged(p0: CompoundButton?, isChecked: Boolean) {
            // do what you want with isChecked
        }
    })

    return true
}

Java

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu_main, menu);
    MenuItem item = menu.findItem(R.id.my_switch_item);
    item.setActionView(R.layout.switch_layout);

    Switch mySwitch = item.getActionView().findViewById(R.id.switch_id);
    mySwitch.setOnCheckedChangeListener(new OnCheckedChangeListener() {
         @Override
         public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                  // do something based on isChecked
         }
    });
    return true;
}

附注:您可以将引用更改为Switch或SwitchCompat。


5
Ezequiel提供的解决方案很棒并且有效。这里提供另一种方法:
定义你自己的布局:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" >
    <Switch
        android:id="@+id/actionbar_switch"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="" />
</RelativeLayout>

通过程序将其inflate:
ActionBar actionBar = getSupportActionBar();
actionBar.setCustomView(R.layout.actionbar_top);
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_SHOW_CUSTOM);
...
Switch button = (Switch) findViewById(R.id.actionbar_switch);

1
哇...这解决了我的问题!!!我似乎无法使用Ezequiel的解决方案,但这是适合我的解决方案!也许这与我正在使用的新工具栏作为操作栏有关???不管怎样,谢谢!注意:这似乎与我最初的方法不同,我希望它成为菜单的自定义视图...但是否有一种方法将此自定义视图对齐到操作栏的右侧? - Vu Nguyen
@FabricioPH,我使用了你的方法,它起作用了。问题是操作栏消失了。我应该怎么做才能保留它? - arthursfreire
1
@arthursfreire 你好。我不完全确定你的代码是什么样子的,但请查看onCreate方法,特别是在这里的第80行之后 https://github.com/fabriph/peer-instruction/blob/master/student-app-studio/PIStudent/app/src/main/java/com/fabricioph/pistudent/HomeActivity.java - Rudolf Real
1
@arthursfreire 这是我自己编写的完全功能代码,我仍在继续开发该项目,支持SDK 16到21。 - Rudolf Real
@FabricioPH,我尝试了你的方法,去掉了启用主页按钮和显示主页为向上的选项,但仍然没有起作用... - arthursfreire
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接