Toolbar其实是一个ActionBar的变体,大大扩展了Actionbar。我们可以像对待一个独立控件一样去使用ToolBar,可以将它放到屏幕的任何位置,不必拘泥于顶部,还可以将它改变高度或者是在ToolBar上使用动画。从最新的SDK看,很多actionbar的方法已经变成了废弃的了,所以我们可以断定未来就是Toolbar将会完全取代ActionBar!

下面我们来讲如何使用这个控件。

1.布局文件

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" > <android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true" android:background="@color/colorPrimary" >
</android.support.v7.widget.Toolbar>
</RelativeLayout>

我们在布局中使用它的时候可能会遇到这样的问题——不能被实例化

The following classes could not be instantiated:
- android.support.v7.widget.Toolbar (Open Class, Show Error Log)
See the Error Log (Window > Show View) for more details.

解决方法:重启下Eclipse。

解决方法来自:http://stackoverflow.com/questions/16907504/the-following-classes-could-not-be-instantiated-com-facebook-widget-loginbutt

Sometimes, when a new resource is added, Eclipse doesn't compile correctly the new code (maybe a caching issue), causing this error.Normally, simply restarting Eclipse is enough to fix the problem.

还可能遇到这样的问题——丢失样式

Missing styles. Is the correct theme chosen for this layout?
Use the Theme combo box above the layout to choose a different layout, or fix the theme style references.

Failed to find style 'toolbarStyle' in current theme

解决方法:在可视化布局窗口中更改下主题样式,我由之前的AppTheme改为AppBaseTheme就解决了。

方法来自:http://blog.csdn.net/romaticxiaoyu/article/details/7241512

好了,解决完这两个问题后我们可以看到这个控件啦。控件的颜色是我们之前在color中指定的颜色,通过background=”“来设置的。

2.将其与Actionbar进行关联

我们先看看之前的Actionbar是什么样的

  

现在在代码中找到这个控件然后设置给Actionbar(setSupportActionBar(toolbar)),但有两个前提。

1.主题中必须设置没有Actionbar(<item name="windowActionBar">false</item>),否则就会出现报里两个actionbar的错误

<resources xmlns:android="http://schemas.android.com/apk/res/android">

    <!--
Base application theme, dependent on API level. This theme is replaced
by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
-->
<style name="AppBaseTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!--
Theme customizations available in newer API levels can go in
res/values-vXX/styles.xml, while customizations related to
backward-compatibility can go here. -->
</style> <!-- Application theme. -->
<style name="AppTheme" parent="AppBaseTheme"> <!-- All customizations that are NOT specific to a particular API-level can go here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/primary_material_light</item>
<item name="android:textColorPrimary">@android:color/white</item>
<item name="android:windowNoTitle">true</item>
<item name="windowActionBar">false</item>
</style> </resources>

2.当前Activity必须继承自ActionBarActivity

public class MainActivity extends ActionBarActivity {

    @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
if (toolbar != null) {
setSupportActionBar(toolbar);
}
}
}

如果你不想将toolbar和actionbar联系到一起,想把其作为一个单个的控件,那么可以不用去setSupportActionBar,也不用在activity中onCreateOptionsMenu,你可以直接用:

public void inflateMenu(int resId)

这个方法来构建一个menu,这样toolbar就可以变成一个完全独立于activity的控件了。这里需要注意的是,如果你这么定义了,那么activity的回调方法是不会监听toolbar上menu的点击事件的,所有点击事件都要通过toolbar提供的监听器来实现,比如这样:

     toolbar.inflateMenu(R.menu.aaa_menu_main);
//setSupportActionBar(toolbar);
toolbar.setNavigationIcon(getResources().getDrawable(R.drawable.ic_launcher));//设置导航按钮
toolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override
public void onClick(View v) { }
});
toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem menuItem) {
int id = menuItem.getItemId();
if (id == R.id.action_add_new_item) { return true;
} else {
return false;
}
}
});

有关监听器的设置可以参考下文的监听器部分。

解决显示效果的问题:

设置完后我们发现又来了问题,明明刚刚用系统Actionbar的时候显示的不错,但将Actionbar变为Toolbar后就出现了下面的效果。

  

我们发现三个点菜单图标变成了黑色,这个还好说我们换个图片就行了,关键是点开后的菜单背景变成了白色,体验很差。于是我们就开始想怎么解决呢?其实也简单,把主题样式换成继承自:Theme.AppCompat就行了。我为了防止主题错乱,将别的版本的主题文件全删除了,就留了一个values中的,并且将主题的背景色设为#eeeeee

(<item name="android:windowBackground">@color/windowBackground</item> )

<resources xmlns:android="http://schemas.android.com/apk/res/android">

    <!--
Base application theme, dependent on API level. This theme is replaced
by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
-->
<style name="AppBaseTheme" parent="Theme.AppCompat">
<!--
Theme customizations available in newer API levels can go in
res/values-vXX/styles.xml, while customizations related to
backward-compatibility can go here. -->
</style> <!-- Application theme. -->
<style name="AppTheme" parent="AppBaseTheme"> <!-- All customizations that are NOT specific to a particular API-level can go here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/primary_material_light</item>
<item name="android:textColorPrimary">@android:color/white</item>
<item name="android:windowBackground">@color/windowBackground</item>
<item name="android:windowNoTitle">true</item>
<item name="windowActionBar">false</item>
</style> </resources>

  

3.详细设置

通过查询文档(http://android.cordovachina.cn/reference/android/widget/Toolbar.html)我们会发现这里有很多set和get方法,下面是一些例子

        Drawable drawable = getResources().getDrawable(R.drawable.ic_navigation);

        toolbar.setTitle("ToolBar Title");//设置标题
toolbar.setSubtitle("This is subtitle");//设置子标题
toolbar.setTitleTextColor(Color.parseColor("#ff0000"));//设置标题颜色
toolbar.setLogo(R.drawable.ic_launcher);//设置logo图片
toolbar.setNavigationIcon(drawable);//设置导航按钮

Toolbar.LayoutParams 这个属性是toolbar的特有属性,用来添加子视图的,文档原文如下:

  • One or more custom views. The application may add arbitrary child views to the Toolbar. They will appear at this position within the layout. If a child view'sToolbar.LayoutParams indicates a Gravity value of CENTER_HORIZONTAL the view will attempt to center within the available space remaining in the Toolbar after all other elements have been measured.
  • 可以添加一个或多个定制视图。可以往toolbar中添加任意多个视图。它们将会在toolbar中出现。如果子视图的的布局属性是CENTER_HORIZONTAL(横向居中),那么这个视图会将在toolbar中其他元素绘制好后尽可能的在剩下的空间中居中显示。
        TextView subView = new TextView(this);
subView.setText("subTextView");
//设定布局的各种参数
Toolbar.LayoutParams params = new Toolbar.LayoutParams(
Toolbar.LayoutParams.WRAP_CONTENT,
Toolbar.LayoutParams.WRAP_CONTENT,
Gravity.CENTER);
params.setMargins(3, 3, 3, 4);//设置外边界 subView.setLayoutParams(params);
toolbar.addView(subView);

这里我添加的textview虽然设置了居中,但是因为它会等其他元素绘制好后再设置自己的位置,所以就被上面的MenuItem压扁了。

4.监听器(可选)

我们在activity中有个回调方法来监听每个item的点击事件,现在在toolbar中也提供了这个接口进行监听。文档中写的是,如果每个itme没有独立的监听器,那么可以在toolbar中绑定监听器。我个人认为还是按照往常一样的写法吧,便于管理。

<1>常规方法,在Acitivity中监听

    @Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
} @Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
Toast.makeText(getApplicationContext(), "setting", 0).show();
return true;
}
return super.onOptionsItemSelected(item);
}

<2>ToolBar中设置监听MenuItem的方法

这里需要注意的是如果你通过toolbar添加了监听器,那么在onOptionsItemSelected()中就监听不到事件了,所以二选一吧。

      toolbar.setOnMenuItemClickListener(new OnMenuItemClickListener() {

            @Override
public boolean onMenuItemClick(MenuItem item) {
// TODO 自动生成的方法存根
System.out.println("click + "+item.getItemId());
return false;
}
});

<3>在ToolBar中设置NavigationIcon的监听器

navigationIcon不能通过toolbar的setOnMenuItemListener()监听,可以在toolbar的setNavigationOnClickListener()中监听,也能在Activity的onOptionsItemSelected()中监听到,两种监听方式只能选择其一。

    toolbar.setNavigationOnClickListener(new OnClickListener() {

            @Override
public void onClick(View v) {
// TODO 自动生成的方法存根
System.out.println("click Navigation ");
}
});

5.ActionMode

这里说个比较有意思的一点,startSupportActionMode()方法在toolbar上是独立存在的。也就是说它不会像和Actionbar融合一样和Toolbar进行融合。ActionMode依旧可用,而且显示位置仍旧在屏幕上方。此外,颜色发生了一定的改变。看图↓

如果对ActionMode还不熟悉的人,可以去看看这篇文章:http://www.cnblogs.com/tianzhijiexian/p/3871416.html

全部Java代码

package com.kale.toolbartest;

import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.view.ActionMode;
import android.support.v7.widget.Toolbar;
import android.support.v7.widget.Toolbar.OnMenuItemClickListener;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;
import android.widget.Toast; public class MainActivity extends ActionBarActivity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//找到ToolBar
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
if (toolbar != null) {
setSupportActionBar(toolbar);
}
//建立一个drawable对象,作为导航的图片。
Drawable drawable = getResources().getDrawable(R.drawable.ic_navigation); toolbar.setTitle("ToolBar Title");//设置标题
toolbar.setSubtitle("This is subtitle");//设置子标题
toolbar.setTitleTextColor(Color.parseColor("#ff0000"));//设置标题颜色
toolbar.setLogo(R.drawable.ic_launcher);//设置logo图片
toolbar.setNavigationIcon(drawable);//设置导航按钮 //添加子视图
TextView subView = new TextView(this);
subView.setText("subTextView");
//设定布局的各种参数
Toolbar.LayoutParams params = new Toolbar.LayoutParams(
Toolbar.LayoutParams.WRAP_CONTENT,
Toolbar.LayoutParams.WRAP_CONTENT,
Gravity.CENTER);
params.setMargins(3, 3, 3, 4);//设置外边界 subView.setLayoutParams(params);//给子视图设定参数,当然也可以在addview时进行设置
toolbar.addView(subView); toolbar.setOnMenuItemClickListener(new OnMenuItemClickListener() { @Override
public boolean onMenuItemClick(MenuItem item) {
// TODO 自动生成的方法存根
System.out.println("click "+item.getItemId());
return false;
}
});
toolbar.setNavigationOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
// TODO 自动生成的方法存根
System.out.println("click Navigation ");
}
});
startSupportActionMode(new ActCallback());
} @Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
} @Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
Toast.makeText(getApplicationContext(), "setting", 0).show();
return true;
}
Toast.makeText(getApplicationContext(), "MenuItem", 0).show();
return super.onOptionsItemSelected(item);
} /**
* @author:Jack Tony
* @tips :处理ActionMode的生命周期事件
* 感谢:http://xyzlmn.blog.51cto.com/2532390/1344872
* @date :2014-7-27
*/
private class ActCallback implements ActionMode.Callback {
/*
* @see
* android.support.v7.view.ActionMode.Callback#onCreateActionMode(android
* .support.v7.view.ActionMode, android.view.Menu) 第一次初始化的时候调用
*/
@Override
public boolean onCreateActionMode(ActionMode arg0, Menu menu) {
MenuItem saveItem = menu.add("save").setIcon(R.drawable.ic_launcher);
MenuItemCompat.setShowAsAction(saveItem, MenuItemCompat.SHOW_AS_ACTION_IF_ROOM); MenuItem searchItem = menu.add("Search").setIcon(R.drawable.ic_navigation);
MenuItemCompat.setShowAsAction(searchItem, MenuItemCompat.SHOW_AS_ACTION_IF_ROOM); MenuItem refreshItem = menu.add("Refresh").setIcon(R.drawable.ic_launcher);
MenuItemCompat.setShowAsAction(refreshItem, MenuItemCompat.SHOW_AS_ACTION_IF_ROOM);
return true;
} /*
* @see
* android.support.v7.view.ActionMode.Callback#onPrepareActionMode(android
* .support.v7.view.ActionMode, android.view.Menu) 在初始化后和每次重新构建的时候调用
*/
@Override
public boolean onPrepareActionMode(ActionMode arg0, Menu arg1) {
return false;
} /*
* @see
* android.support.v7.view.ActionMode.Callback#onActionItemClicked(android
* .support.v7.view.ActionMode, android.view.MenuItem) 但控件被点击的时候调用
*/
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
Toast.makeText(MainActivity.this, "Got click: " + item.getTitle(), Toast.LENGTH_SHORT).show();
mode.finish();
return false;
} /*
* @see
* android.support.v7.view.ActionMode.Callback#onDestroyActionMode(android
* .support.v7.view.ActionMode) 当mode被关闭的时候调用
*/
@Override
public void onDestroyActionMode(ActionMode arg0) { } }
}

源码下载:http://download.csdn.net/detail/shark0017/8135301

参考自:

http://blog.csdn.net/hjj0212/article/details/7065050

Material Designer的低版本兼容实现(四)—— ToolBar的更多相关文章

  1. Material Designer的低版本兼容实现(一)—— 简介 & 目录

    很长一段时间没写东西了,其实是因为最近在研究Material Designer这个东西,熬夜熬的身体也不是很好了.所以就偷懒没写东西,这回开的这个系列文章是讲如何将Material Designer在 ...

  2. Material Designer的低版本兼容实现(五)—— ActivityOptionsCompat

    extends:http://www.cnblogs.com/tianzhijiexian/p/4087917.html 本文是对API中的方法做了介绍,如果想要看如何让这些方法兼容4.x或2.x可以 ...

  3. Material Designer的低版本兼容实现(二)—— Theme

    Theme material主题可以定义为如下形式: @android:style/Theme.Material @android:style/Theme.Material.Light @androi ...

  4. Material Designer的低版本兼容实现(十)—— CheckBox & RadioButton

    ChekBox的用途我们就不必多说了,算是一个很古老的控件了,何其类似的还有RadioButton,这个东西因为我目前还没写出来,所以用了别人的一个lib,这下面会说到.顺便说一句,如果你的app是在 ...

  5. Material Designer的低版本兼容实现(三)——Color

    在Material Designer中,色彩再一次被摆到了重要的位置上.官方文档中竟然给出了500种配色方案进行选择.就是为了给不同的手机.电视.手表上带来一直的用户体验. 更多用于控制色彩的属性,可 ...

  6. Material Designer的低版本兼容实现(十四)—— CardView

    今天说的又是一个5.0中才有的新控件——CardView(卡片视图).这个东东其实我们早就见过了,无论是微博还是人人客户端,它都有出现.通常我们都是通过自定义一个背景图片,然后通过给layout进行设 ...

  7. Material Designer的低版本兼容实现(十二)—— Slider or SeekBar

    Slider,我更喜欢叫他SeekBar,其实是一个东西啦,就是拖动条.5.0的拖动条和4.x上的HOLO风格完全不同,平添了一些精致.此外还加入了数值指示器,让用户在滑动的时候就能知道现在到了什么位 ...

  8. Material Designer的低版本兼容实现(十三)—— ProgressBar

    进度条我们都很常见了,新的设计规范中提出了各式各样的进度条,本篇就会介绍大部分进度条的实现.实现方式和规范的示例图可能略有差异,还是那句话根据具体需求进行改变吧. PS:本文较长 参考文档:http: ...

  9. Material Designer的低版本兼容实现(十一)—— Switch

    5.0中的switch和之前完全不同了,漂亮不漂亮咱们另说,总之4.x上是没有这样的效果了.实现方式有两种,一种是用这个兼容包来做类似的效果,一种是用传统的checkbox来代替.我感觉兼容包的效果是 ...

随机推荐

  1. day11--RabbitMQ、Redis

        RabbitMQ:就是消息队列与Python里面的queue功能类似.线程和进程queue只能Python自己使用:不同机器和程序传递消息就要使用RabbitMQ了,中间传递. RabbitM ...

  2. Yeoman generator

    使用Yeoman generator来规范工程的初始化 前言 随着开发团队不断发展壮大,在人员增加的同时也带来了协作成本的增加:业务项目越来越多,类型也各不相同.常见的类型有基础组件.业务组件.基于R ...

  3. 【LOJ】#2084. 「NOI2016」网格

    题解 之前用的mapTLE了,今天用了个hash把题卡了过去,AC数++ 我们只要保留一个点为中心周围5 * 5个格子就可以 如果一个点周围5*5个格子有两个不连通,那么显然输出0 如果一个出现了一个 ...

  4. kafka 基础知识梳理

    一.kafka 简介 kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者规模的网站中的所有动作流数据.这种动作(网页浏览,搜索和其他用户的行动)是在现代网络上的许多社会功能的一个关键因 ...

  5. 【转】java取整和java四舍五入方法

    java取整和java四舍五入方法 import java.math.BigDecimal; import java.text.DecimalFormat; public class TestGetI ...

  6. vue在生产环境清除console.log

    在开发环境中我们喜欢用console.log测试代码,但是部署到生产环境我们不可能一个一个把console.log给手动删除了. 在build/webpack.prod.conf.js文件里加上这样一 ...

  7. 多线程学习笔记七之信号量Semaphore

    目录 简介 数据结构 示例 实现分析 构造方法 信号量的获取(公平方式) 信号量的释放(公平方式) nonfairTryAcquireShared(int acquires) 总结 简介   Sema ...

  8. 网络数据包信息收集工具ferret-sidejack

    网络数据包信息收集工具ferret-sidejack   网络数据包传递用户的各种操作和对应的信息.但是由于各种数据混在一起,不利于渗透测试人员分析.Kali Linux提供了一款信息搜集工具ferr ...

  9. maven执行update命令时报org/apache/maven/shared/filtering/MavenFilteringException错误

    原 maven执行update命令时报org/apache/maven/shared/filtering/MavenFilteringException错误 在eclipse中对准项目执行maven- ...

  10. Xtreme9.0 - Light Gremlins 容斥

    Xtreme9.0 - Light Gremlins 题目连接: https://www.hackerrank.com/contests/ieeextreme-challenges/challenge ...