ToolBar使用

ToolBar

基本使用

Toolbar是在Android5.0开始推出的一个MaterialDesign风格的导航控件,Google非常推荐大家使用Toolbar 来作为Android客户端的导航栏,以此来取代之前的Actionbar。与Actionbar相比,Toolbar明显要灵活的多。它不像Actionbar一样,一定要固定在Activity的顶部,而是可以放到界面的任意位置。

Toobar是Android5.0才引入的,Google也在兼容包appcompat-v7中提供了向下兼容的ToolBar:android.support.v7.widget.Toolbar

首先,我们要在build.gradle中添加依赖。

compile 'com.android.support:appcompat-v7:24.2.0'

接着,禁用掉主题提供的actionbar。

<!-- 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>

然后我们就可以在布局文件中添加ToolBar。ToolBar相对于其它控件,并没有什么特殊之处,添加ToolBar和添加其它控件一样。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    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"
        android:background="?attr/colorPrimary"
        android:minHeight="?attr/actionBarSize"
        app:titleTextColor="@android:color/white"/>
</LinearLayout>

最后,在Activity或者Fragment中,通过调用setSupportActionBar让ToolBar扮演ActionBar的角色。

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
    }
}

一旦设置了Toolbar作为activity的actionbar,就可以调用ActionBar类提供的方法来设置ActionBar。ActionBar常用的方法:

  • hide():隐藏ActionBar
  • show():显示ActionBar
  • isShowing():判断ActionBar是否显示
  • setBackgroundDrawable(Drawable drawable):为ActionBar设置背景。
  • setDisplayHomeAsUpEnabled(boolean b):是否显示返回的按钮。
  • setDisplayShowHomeEnabled(boolean b);是否显示icon
  • setDisplayShowTitleEnabled(boolean b);是否显示标题
  • setDisplayShowCustomEnabled(boolean b);是否显示自定义view
  • setIcon();设置Icon
  • setTitle();设置标题
  • getSelectedNavigationIndex()获取选择条目的索引。

添加Action Buttons

当你开启Activity时,系统通过调用Activity的onCreateOptionsMenu()方法来放置action buttons。使用这个方法inflate一个定义所有action buttons的菜单资源。

<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/action_search"
        android:icon="@drawable/ic_search_white_24dp"
        android:title="@string/action_search"
        app:showAsAction="ifRoom"/>
    <item
        android:id="@+id/action_add_alarm"
        android:icon="@drawable/ic_add_alarm_white_24dp"
        android:title="@string/action_alarm"
        app:showAsAction="ifRoom"/>
</menu>

然后调用Activity的onCreateOptionsMenu()方法中添加将所有的action button添加到ActionBar上。

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu items for use in the action bar
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.main_activity_actions, menu);
    return super.onCreateOptionsMenu(menu);
}

想要item直接显示在actionbar上,需要在标签中,添加一个showAsAction="ifRoom"属性。

<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:yourapp="http://schemas.android.com/apk/res-auto" >
    <item android:id="@+id/action_search"
          android:icon="@drawable/ic_action_search"
          android:title="@string/action_search"
          yourapp:showAsAction="ifRoom"  />
    ...
</menu>

如果没有足够的空间,它将以悬浮菜单的样式显示。

注意上面的showAsAction 属性使用了一个自定义命名空间。在使用supportlibrary定义的属性必须自定义命名空间。因为这些属性在一些老的Android设备上不存在。

如果同时指定了title和icon属性,action item默认只显示icon.如果需要显示标题,需要为showAsAction属性添加withText值,如果icon可用并且actionbar空间不足时,title将不显示。

<item yourapp:showAsAction="ifRoom|withText" ... />

尽管可能你不需要显示title,但是仍然要指定title属性的值。

  • 如果空间不足,菜单将以悬浮状态显示,并且只显示title。
  • 如果action item只显示icon,用户可以通过长按条目显示title。

你也可以设置showAsAction属性的值为always,让一个actionitem一直显示,但是你最好不要让一个action item一直显示。这样做在窄屏上出现一些布局适配的问题。

处理条目点击

当用户点击一个条目时,系统将点击的MenuItem传递给Activity的onOptionsItemSelected() 方法。

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle presses on the action bar items
    switch (item.getItemId()) {
        case R.id.action_search:
            Toast.makeText(this, "点击了搜索", Toast.LENGTH_SHORT).show();
            return true;
        case R.id.action_add_alarm:
            Toast.makeText(this, "点击了添加闹钟", Toast.LENGTH_SHORT).show();
            return true;
        //向上返回的按钮的id是android.R.id.home 所以通过下面代码就能实现点击返回按钮返回的功能。
        case android.R.id.home:
            finish();
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}

添加Action View

Action View 提供了一些复杂操作的快速入口,不需要改变Acitivity或者Fragment,并且不用替换ActionBar.例如,如果你想进行搜索,你可以通过给actionbar添加一个SearchView组件来实现。

我们可以通过给acionlayout属性指定一个布局资源或者给actionViewClass属性指定一个组件类来添加一个Action View.

<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/action_search"
        android:icon="@drawable/ic_search_white_24dp"
        android:title="@string/action_search"
        app:showAsAction="ifRoom|collapseActionView"
        app:actionViewClass="android.support.v7.widget.SearchView"/>
    <item
        android:id="@+id/action_add_alarm"
        android:icon="@drawable/ic_add_alarm_white_24dp"
        android:title="@string/action_alarm"
        app:showAsAction="ifRoom"/>
</menu>

注意showAsAction属性包含了一个collapseActionView值。

我们可以在onCreateOptionsMenu()方法中配置action view。通过静态方法MenuItemCompat.getActionView()可以获取一个到action view对象。这个方法需要传递一个MenuItem对象。

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu items for use in the action bar
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.main_menu, menu);
    MenuItem searchItem = menu.findItem(R.id.action_search);
    SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
    searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
        @Override
        public boolean onQueryTextSubmit(String query) {//进行搜索
            Toast.makeText(MainActivity.this, "搜索"+query, Toast.LENGTH_SHORT).show();
            return false;
        }
        @Override
        public boolean onQueryTextChange(String newText) {
            return false;
        }
    });
    return super.onCreateOptionsMenu(menu);
}

处理可折叠的Action View

为了节省action bar的空间,可以将action view折叠成一个action button。当这个action button被选中时,action view将会被展开。只要为showAsAction属性添加一个collapseActionView值就可以让action view变的可折叠。

当用户点击action button,action view能够自动的展开,不需要在onOptionsItemSelected()方法中进行点击处理。但是如果将其返回值设置为true,action view将不会被展开。

当点下手机的返回按钮或者action bar的返回按钮,action view将会被折叠。

通过OnActionExpandListener监听器,可以监听到action view折叠和展开。

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu items for use in the action bar
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.main_menu, menu);
    MenuItem searchItem = menu.findItem(R.id.action_search);
    MenuItemCompat.setOnActionExpandListener(searchItem, new MenuItemCompat.OnActionExpandListener() {
        @Override
        public boolean onMenuItemActionCollapse(MenuItem item) {
            Toast.makeText(MainActivity.this, "折叠", Toast.LENGTH_SHORT).show();
            return true;
        }

        @Override
        public boolean onMenuItemActionExpand(MenuItem item) {
            Toast.makeText(MainActivity.this, "展开", Toast.LENGTH_SHORT).show();
            return true;
        }
    });
    return super.onCreateOptionsMenu(menu);
}

添加 Action Provider

类似action view,action provider通过自定义布局来替换一个操作按钮.但是action provider控制所有的动作行为并且在被点击时能够显示一个子菜单。

通过为actionViewClass属性设置一个ActionProvider类,来添加action provider.也可以通过继承ActionProvider来创建自定义的action provider.Android提供了一些action provider,例如ShareActionProvider。

由于每一个ActionProvider类定义自己的动作行为,所以不需要通过onOptionsItemSelected()方法来设置其点击事件,但是你仍然可以通过此方法来设置其他操作,也可以通过onPerformDefaultAction()来设置别的操作。

如果action Provider提供一个子菜单,用户打开列表或者选中一个子菜单,activity将不调用onOptionsItemSelected()。

使用ShareActionProvider添加一个分享操作需要一下步骤:
1.设置actionProviderClass属性值为ShareActionProvider类.

<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/action_search"
        android:icon="@drawable/ic_search_white_24dp"
        android:title="@string/action_search"
        app:showAsAction="ifRoom|collapseActionView"
        app:actionViewClass="android.support.v7.widget.SearchView"/>
    <item
        android:id="@+id/action_share"
        android:icon="@drawable/ic_share_white_24dp"
        android:title="@string/action_share"
        app:actionProviderClass="android.support.v7.widget.ShareActionProvider"
        app:showAsAction="ifRoom"/>
</menu>

2.定义你想要分享的Intent。在onCreateOptionsMenu()方法中调用MenuItemCompat.getActionProvider()获取ShareActionProvider对象,然后调用ShareActionProvider的setShareIntent()设置分享意图。

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu items for use in the action bar
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.main_menu, menu);
    MenuItem shareItem = menu.findItem(R.id.action_share);
    ShareActionProvider shareActionProvider = (ShareActionProvider)
            MenuItemCompat.getActionProvider(shareItem);
    shareActionProvider.setShareIntent(getDefaultIntent());
    return super.onCreateOptionsMenu(menu);
}

private Intent getDefaultIntent() {
    Intent intent = new Intent(Intent.ACTION_SEND);
    intent.setType("image/*");
    return intent;
}
创建自定义的ActionProvider

要创建自定义的ActionProvider只需要简单的继承ActionProvider类,并且实现下列方法。

OnCreateActionView()这个方法用来获取action view。使用从构造器中接收的Context对象,获取一个LayoutInflater对象的实例,并且用XML资源来填充操作视窗,然后注册事件监听器。

public View onCreateActionView(MenuItem forItem) {
    // Inflate the action view to be shown on the action bar.
    LayoutInflater layoutInflater = LayoutInflater.from(mContext);
    View view = layoutInflater.inflate(R.layout.action_provider, null);
    ImageButton button = (ImageButton) view.findViewById(R.id.button);
    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // Do something...
        }
    });
    return view;
}

onPerformDefaultAction()在选中悬浮菜单中的菜单时,系统会调用这个方法,并且操作提供器应该这对这个选中的菜单项执行默认的操作。但是,如果你的操作提供器提供了一个子菜单,即使是悬浮菜单中一个菜单项的子菜单,那么也要通过onPrepareSubMenu()回调方法来显示子菜单。这样onPerformDefaultAction()在子菜单显示时就不会被调用。注意:实现了onOptionsItemSelected()回调方法的Activity或Frament对象能够通过处理item-selected事件(并且返回true)来覆盖操作提供器的默认行为,这种情况下,系统不会调用onPerformDefaultAction()方法。

参考

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容