Android Toolbar的用法
Toolbar的强大之处在于,它不仅继承了ActionBar的所有功能,而且灵活性很高,可以配合其他控件来完成一些Material Design的效果,下面来具体的看一下.
首先你要知道,任何一个新建的项目,默认都是会显示ActionBar的,这个想必你已经见识过太多次了,那么这个ActionBar到底是从哪里来的呢?其实这是根据项目中指定的主题来显示的,打开AndroidManifest.xml文件看一下,如图:
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> ... </application>
可以看到,这里使用android.theme属性指定了一个AppTheme的主题,那么这个AppTheme又是在哪里定义的呢?打开res/values/styles.xml文件,代码如下:
<resources> <!-- Base application theme. --> <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> </style> </resources>
这里定义了一个叫AppTheme的主题,然后指定它的parent主题是Theme.APPCompat.Light.DarkActionBar,这个DarkActionBar是一个深色的ActionBar主题,我们之前所有的项目中自带的ActionBar就是因为指定了这个主题才出现的,
而现在我们准备使用Toolbar来代替ActionBar,因此需要指定一个不带ActionBar的主题,通常有Theme.APPCompat.NoActionBar和Theme.APPCompat.Light.NoActionBar这两种主图可选,其中Theme.APPCompat.NoActionBar表示深色主题,它会将界面的主体颜色设成深色,陪衬颜色设成淡色,而Theme.APPCompat.Light.NoActionBar表示淡色主体,它会将界面的主体颜色设成淡色,陪衬颜色设成深色,这里我选择用淡色主题了,如下所示:
<resources> <!-- Base application theme. --> <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> </style> </resources>
然后观察一下AppTheme中的属性重写,这里重写了colorPrimary,colorPrimaryDark和colorAccent这3个属性的颜色,除了这3个属性之外,我们还可以通过textColorPrimary,windowBackground和navigationBarColor等属性来控制更多位置的颜色,不过唯独colorAccent这个属性比较难理解,它不只是用来指定这样一个按钮的颜色,而是更多表达了一个强调的意思,比如一些控件的选中状态也会使用colorAccent的颜色.
现在我们已经将ActionBar隐藏起来了,那么接下来看一看如何使用Toolbar来代替ActionBar,activity_main.xml中的代码,如下:
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.toolbartest.MainActivity"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/> </android.support.constraint.ConstraintLayout>
接下来是MainActivity.Java中的代码,如下:
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); } }
首先通过findViewById()得到Toolbar的实例,然后调用setSupportActionBar()方法将Toolbar的实例传入,这样我们就做到即使用了Toolbar,又让它的外观与功能都能和ActionBar一致了.
现在运行一下程序,如图:
这个标题栏我们再熟悉不过了,虽然看上去和之前的标题没什么两样,但其实它已经是Toolbar而不是ActionBar了,因此它现在也具备了实现Material Design效果的能力.
现在我们再看一下Toolbar比较常用的功能,比如修改标题上显示的文字内容,这段文字内容是在AndroidManifest,xml中指定的,如下:
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity" android:label="Fruits"> ... </activity> </application>
这里给activity增加了一个android:label属性,用于指定在Toolbar中显示的文字内容,如果没有指定的话,会默认使用application中指定的label内容,也就是我们的应用名称.
不过只有一个标题的Toolbar看起来太单调了,我们还可以再添加一些action按钮来让Toolbar更加丰富一些,这里我提前准备了几张图片来作为按钮的图标,将它们放在了drawable目录下,现在右击res目录-->New-->Directory,创建一个menu文件夹,然后右击menu文件夹-->New-->Menu resource file,创建一个toolbar.xml文件,并编写代码:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/backup" android:icon="@drawable/ic_backup" android:title="Backup" app:showAsAction="always" /> <item android:id="@+id/delete" android:icon="@drawable/ic_delete" android:title="Delete" app:showAsAction="ifRoom" /> <item android:id="@+id/settings" android:icon="@drawable/ic_settings" android:title="Settings" app:showAsAction="never" /> </menu>
可以看到,我们通过<item>标签来定义action按钮,android:id用于指定按钮的id,android:icon用于指定按钮的图片,android:title用于指定按钮的文字.
接着使用app:showAsAction来指定按钮的显示位置,之所以这里再次使用了app命名空间,同样是为了能够兼容低版本的系统,showAsAction主要有以下几种值可选,always表示永远显示在Toolbar中,如果屏幕空间不够则不显示,ifRoom表示屏幕空间足够的情况下显示在Toolbar中,不够的话就显示在菜单当中,never则表示永远显示在菜单当中,注意,Toolbar中的action按钮只会显示图标,菜单中的action按钮只会显示文字.
接下来修改MainActivity中的代码,如下:
public class MainActivity extends AppCompatActivity { ... public boolean onCreateOptionsMenu(Menu menu){ getMenuInflater().inflate(R.menu.toolbar,menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()){ case R.id.backup: Toast.makeText(this,"You clicked Backup",Toast.LENGTH_SHORT).show(); break; case R.id.delete: Toast.makeText(this,"You clicked Delete",Toast.LENGTH_SHORT).show(); break; case R.id.settings: Toast.makeText(this,"You clicked Settings",Toast.LENGTH_SHORT).show(); break; default: break; } return true; } }
很简单,我们在onCreateOptionMenu()方法中加载了toolbar.xml这个菜单文件,然后在onOptionsItemSelected()方法中处理各个按钮的点击事件,现在重新运行一下,效果如图:
可以看到,Toolbar上面现在显示了两个action按钮,这是因为Backup按钮指定的显示位置是always,Delete按钮指定的显示位置是ifRoom,而现在屏幕空间很充足,因此两个按钮都会显示在Toolbar中,另外一个Settings按钮由于指定的显示位置是never,所以不会显示在Toolbar中,点击最右边的菜单按钮来展示菜单项,你就能找到Settings了.