ToolBar的使用

        google推荐使用ToolBar代替ActionBar,同时还设计了Meterial Design的控件能跟他进行交互,但是由于ToolBar需要较高的版本支持,所以如果需要兼容的话,需要使用兼容包appcompat-v7兼容包,而Activity需要继承自AppCompatActivity,然后style需要继承自parent=“Theme.AppCompat.Light.NoActionBar”的风格,这里这种风格会去掉就版本的ActionBar,当然和可以继承Theme.AppCompat的风格,然后再<item name="windowActionBar">false</item>里面去掉。

        ToolBar的使用有两种方式,一种是直接作为控件使用,一种是作为ActionBar进行使用。

        对于直接使用ToolBar的,就是将ToolBar作为普通控件那样放在布局里面就可以了,但是需要注意的是,如果直接作为控件使用而不进行任何设置,那么ToolBar将是什么都没有的,这点跟将ToolBar作为ActionBar,将ToolBar作为ActionBar使用即使不进行任何设置也会有图标,标题。

        对于将ToolBar作为ActionBar使用的情况,需要使用setSupportActionBar(ToolBar),这样ToolBar就可以作为ActionBar使用了,同时注意,ActionBar的menu也就植入ToolBar了,我们对ActionBar的操作也就可以在ToolBar上使用了。


        另外,原本的ActionBar的tab模式,这里建议使用Meterial Design的TabLayout进行,这个优化的更好!


        另外,这里涉及到一个AppBarLayout控件,这个控件往往包裹着ToolBar,之所以使用他,从google将标题栏统称为app bar可以看出,AppBarLayout可以包裹ToolBar和TabLayout这些控件,而ToolBar仅仅代表标题栏。例如xml如下:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    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:orientation="vertical">




    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">


        <android.support.v7.widget.Toolbar
            android:id="@+id/third_activity_toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"/>


        <android.support.design.widget.TabLayout
            android:id="@+id/tab_layout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_scrollFlags="scroll|enterAlways"
            app:tabIndicatorColor="@color/medium_blue"
            app:tabSelectedTextColor="@color/medium_blue"
            app:tabTextAppearance="@style/TabText"
            app:tabTextColor="@color/gray_text"/>


    </android.support.design.widget.AppBarLayout>


    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"/>


</android.support.design.widget.CoordinatorLayout>


        使用Meterial Design的控件跟ToolBar进行交互已经在之前http://blog.csdn.net/hangeqq685042/article/details/47954429中讲过了,这里不再讲。

        下面讲讲使用ToolBar代替ActionBar的过程。

        在ToolBar的style设计中,可以使用如下代码进行:

<style name= "AppTheme.Base"  parent= "Theme.AppCompat" >
   <item name= "windowActionBar" > false </item>
   <item name= "android:windowNoTitle" > true </item>
   <!-- Actionbar color -->
   <item name= "colorPrimary" >@color/accent_material_dark</item>
   <!--Status bar color-->
   <item name= "colorPrimaryDark" >@color/accent_material_light</item>
   <!--Window color-->
   <item name= "android:windowBackground" >@color/dim_foreground_material_dark</item>
</style>
这里需要注意的是android:windowNoTitle设置标题;

colorPrimary设置设置标题栏颜色;

colorPrimaryDark设置状态栏颜色;

android:windowBackground设置布局背景;

android:navigationBarColor对导航栏设置背景颜色;

textColorPrimary设置标题颜色



        常见的ToolBar使用方式代码一般如下:

Toolbar mToolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(mToolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);//返回箭头
        mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onBackPressed();
            }
        });
这里

setDisplayHomeAsUpEnabled(true)将使用系统的返回按钮,setNavigationOnClickListener设置返回按钮监听;

setNavigationViewIcon设置返回按钮左边的按钮,同时,这个方法需要在调用过setSupportActionBar(ToolBar)之后调用才有效;

setLogo设置图标;

setDisplayUseLogoEnabled设置图标是否显示。

setTitle设置标题,setSubTitle设置副标题;

setOnMenuItemListener设置最右边的选项按钮监听。


        这里注意,最右边按钮是onCreateOptionsMenu中返回的menu。也就是下面代码中item描述的按钮:

       xmlns:app= "http://schemas.android.com/apk/res-auto"
       xmlns:tools= "http://schemas.android.com/tools"
       tools:context= ".MainActivity" >
   <item android:id= "@+id/action_edit"
         android:title= "@string/action_edit"
         android:orderInCategory= "80"
         android:icon= "@drawable/ab_edit"
         app:showAsAction= "ifRoom"  />                                                                                                                                 
   <item android:id= "@+id/action_share"
         android:title= "@string/action_edit"
         android:orderInCategory= "90"
         android:icon= "@drawable/ab_share"
         app:showAsAction= "ifRoom"  />
   <item android:id= "@+id/action_settings"
         android:title= "@string/action_settings"
         android:orderInCategory= "100"
         app:showAsAction= "never" />



        ToolBar继承自ViewGroup,是一个布局控件。而ToolBar中的标题默认是向左对齐的,所以如果我们需要标题居中,那么就需要将标题去掉,然后再ToolBar里面放置一个TextView即可。


        这样,app bar常见的menu,tab,title等就实现了。



        对于app bar,还有一个需要注意的地方,那就是overflow,当app bar空间不够用的时候,会将原本的控件放在最右边三个点的按钮里面。说到overflow就需要从ActionBar说起,在ActionBar里面,当app bar控件不够的时候会将多出的按钮放在最右边的三个点的按钮里面,这个按钮就是overflow了,但是如果手机有menu按钮,那么overflow就不会显示,所以如果需要overflow一直显示,那么就需要自定义一个Application如下:

public class UIApplication extends Applications{
    public void onCreate() {        try {
            ViewConfiguration config = ViewConfiguration.get(this);
            Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
            if (menuKeyField != null) {
                menuKeyField.setAccessible(true);
                menuKeyField.setBoolean(config, false);
            }
        }
        catch (Exception ex) {
            // Ignore
        }
        super.onCreate();
    }


这些代码可以让overflow一直出现,当然,这里可以定义在Activity,只是定义在Application中就不用总是去Activity了。另外需要注意,ActionBar需要使用兼容包的。注意,在实际的使用中,ActionBar的overflow实际上在Pad上并没有显示,所以这种方法其实也并不是很有用。

        可以使用下面的方法让overflow一直显示:

官方做法:

private void setOverflowShowingAlways() {
  try {
   ViewConfiguration config = ViewConfiguration.get(this);
   Field menuKeyField = ViewConfiguration.class
     .getDeclaredField("sHasPermanentMenuKey");
   menuKeyField.setAccessible(true);
   menuKeyField.setBoolean(config, false);
  } catch (Exception e) {
   e.printStackTrace();
  }
 }

或者

其他做法:

private void getOverflowMenu() {
  try {
   ViewConfiguration config = ViewConfiguration.get(this);
   Field menuKeyField = ViewConfiguration.class
     .getDeclaredField("sHasPermanentMenuKey");
   if (menuKeyField != null) {
    menuKeyField.setAccessible(true);
    menuKeyField.setBoolean(config, false);
   }
  } catch (Exception e) {
   e.printStackTrace();
  }
 }

最后注意item项需要添加android:showAsAction="never"。


        重写这个方法可以改变OverFlow按钮只显示文字的特性,这里还涉及到一个MenuBuilder类,但是这个类是内部类,这个类可以设置很多特性,如OverFlow的item项的属性,这里应该注意,MenuBuilder.setOptionalIconsVisible就是用于设置图标是否显示的,但是我们不可以直接设置,因为这个类是内部类,所以用的是回调显示,也就是说,可以在onCreateOptionsMenu方法中进行回调,

@Override
 public boolean onMenuOpened(int featureId, Menu menu) {
  if (featureId == Window.FEATURE_ACTION_BAR && menu != null) {
   if (menu.getClass().getSimpleName().equals("MenuBuilder")) {
    try {
     Method m = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE);
     m.setAccessible(true);

//MenuBuilder实现Menu接口,创建菜单时,传进来的menu其实就是MenuBuilder对象(java的多态特征) 


     m.invoke(menu, true);
    } catch (Exception e) {
    }
   }
  }
  return super.onMenuOpened(featureId, menu);
 }

 

需要特别注意,在使用ActionBar时,如果版本不能高于11,那么需要使用v7兼容包,然后继承ActionBarActivity,然后调用getSupportActionBar方法而不是getActionBar方法,但是使用了ActionBarActivity就意味着需要使用兼容包的theme作为风格,否则就会报错,这点需要特别注意!


        最后,需要注意,Activity中的onCreateOptionsMenu与onOptionsItemSelected方法是对应的app bar的item项的,同时由于item项太多而使用overflow的话,那么overflow里面的item项也算是app bar的item项的。这是我容易混淆的地方。



       回到ToolBar,使用ToolBar代替ActionBar可知,ToolBar有SearchView,下面是SearchView作为app bar的item项代码:

< item
         android:id = "@+id/action_search"
         android:icon = "@drawable/ic_search"
         app:actionViewClass = "android.support.v7.widget.SearchView"
         app:showAsAction = "ifRoom|collapseActionView"
         android:inputType = "textCapWords"
         android:imeOptions = "actionSearch"
         android:title = "search" />
这里ifRoom表示如果空间足够则显示,如果不够则只显示标题在overflow中。collapseActionView表示当前空间点开之后占据整个ToolBar空间。always表示总是以标题方式显示,当我们长按则以Toast方式显示标题。never表示总是显示在overflow中。

        下面是代码部分:

public boolean onCreateOptionsMenu(Menu menu) {
   MenuInflater inflater = getMenuInflater();
   inflater.inflate(R.menu.menu_main, menu);
   MenuItem menuItem = menu.findItem(R.id.action_search); //在菜单中找到对应控件的item
   SearchView searchView = (SearchView) MenuItemCompat.getActionView(menuItem);
   Log.d( "Tag" , "menu create" );
   MenuItemCompat.setOnActionExpandListener(menuItem, new MenuItemCompat.OnActionExpandListener() { //设置打开关闭动作监听
     @Override
     public boolean onMenuItemActionExpand(MenuItem item) {
       Toast.makeText(MainActivity. this , "onExpand" , Toast.LENGTH_LONG).show();
       return true ;
     }
     @Override
     public boolean onMenuItemActionCollapse(MenuItem item) {
       Toast.makeText(MainActivity. this , "Collapse" , Toast.LENGTH_LONG).show();
       return true ;
     }
   });
   return super .onCreateOptionsMenu(menu);
}
        以上是ToolBar中使用SearchView的方式。


        另外,ToolBar不作为ActionBar使用时,item项的点击监听使用setOnMenuItemListener方法监听。这点注意!


        ToolBar的overflow使用方式跟ActionBar是一样的。目前还没有发现ToolBar的overflow有什么问题。


        在Theme.Appcompat.Light风格中,style里面的item项如果添加一个colorAccent,那么所有的控件的强调颜色都可以变成指定的颜色,例如RadioButton的checked状态,EditText的输入状态。另外,在该风格中RadioButton的checked状态是绿色的。另外需要注意的是,backgroundTint这个属性实际上限制非常大,可以不用使用了,因为需要高版本,而且高版本中不同版本支持程度不一样,所以最好不要使用。

        在ToolBar的style中,colorPrimary是高版本才能使用的,但是在低版本中,我们可以直接在ToolBar控件下使用android:background="?attr/colorPrimary"引用android内部特征,而这个特征正是style中定义的colorPrimary!


        如果想要掌握好ToolBar,其实很大程度上需要参照旧版本的ActionBar,因为google开发出ToolBar很多都是参照ActionBar的。


        ToolBar自己的控件风格时可以修改的,这里以修改navigationIcon的图片的缩放方式为例,首先需要在ToolBar的style中添加一项

<item name="toolbarNavigationButtonStyle">@style/myToolbarNavigationButtonStyle</item>
这里引用的风格时自定义风格,如下所示:

<style name="myToolbarNavigationButtonStyle" parent="@style/Widget.AppCompat.Toolbar.Button.Navigation">
    <item name="android:scaleType">fitCenter</item>
</style>
这样就能修改navigationIcon的图片的缩放方式了。另外,可以直接在SDK->Extras->android->support-v7->res->values的attrs.xml和styles.xml文件中查看用到的属性。


        需要注意,在Toolbar的使用中,控制Toolbar本身的按钮一般都是通过属性以及风格实现的,这里按钮的点击变色需要非常注意,因为ToolBar本身的按钮其实是一个ImageButton,所以其实点击的时候背景使用的是android系统本身的点击变色,也就是背景会有蓝色出现,对于这一点,如果需要更改颜色,那么就需要使用风格控制相应的按钮。

        这里返回按钮部分对应的是toolbarNavigationButtonStyle,而overflow按钮对应的是actionOverflowButtonStyle,所有的按钮可以使用actionButtonStyle。在我们的style中添加项:

<item name="toolbarNavigationButtonStyle">@style/NavigationButton</item>
<item name="actionButtonStyle">@style/actionButton</item>
<item name="actionOverflowButtonStyle">@style/overflowButton</item>
然后这里对应的style为:

<style name="actionButton" parent="@style/Widget.AppCompat.ActionButton">
</style>
<style name="overflowButton" parent="@style/Widget.AppCompat.ActionButton.Overflow">
</style>

<!--修改ToolBar中navigationIcon的风格-->
<!--在ToolBar的风格中添加<item name="toolbarNavigationButtonStyle">@style/myToolbarNavigationButtonStyle</item>
可以修改控件风格,这里修改了navigationIcon的图片的对齐方式-->
<style name="NavigationButton" parent="@style/Widget.AppCompat.Toolbar.Button.Navigation">
    <!--<item name="android:scaleType">fitCenter</item>-->
    <item name="android:width">50dp</item>
    <item name="android:height">50dp</item>
    <item name="android:background">@null</item>
</style>

这里需要注意,在NavigationButton中,android:background对应的是按钮的背景,这里设置为null之后,按钮点击就不会变色了!

        总的来说就是针对ToolBar中不同的按钮,我们使用不同的item使用不同的style对按钮进行控制。



        

ps:对于ToolBar如果仅仅作为一个控件在XML中使用时,最左边的控件是无法对其最左边的,也就是说最左边的控件离ToolBar最左边有一定的空隙。我们需要设置app:contentInsetStart="0dp"才可以消除这个间隙,这点需要特别注意!

ps:在AndroidManifest中添加android:parentActivityName可以让ToolBar的返回按钮自动有点击返回上一个Activity的功能。但是如果需要监听这个按钮,需要使用setNavigationOnClickListener()方法。

ps:使用app:maxButtonHeight可以设置ToolBar所有的按钮的高度,但是并没有提供宽度设置,同时这个属性设置高度仅仅是截取,并不能实现像ImageVIew一样的缩放效果,这点需要注意,另外,在在ToolBar高度wrap_content时,app:maxButtonHeight大于56dp时,ToolBar高度会随之变大,但是如果ToolBar指定了高度,那么那么app:maxButtonHeight设置的再大也没用,所以其实这个属性并没有什么用。

ps:ToolBar里面的NavigationIcon等控件如果修改了图片,那么效果并不能像ImageView那样有自动缩放效果,如果尺寸没定好,会出现截取的现象,这点需要注意!

ps:对于ToolBar的高度需要注意,默认是56dp,也就是?attr/actionBarSize的高度。ToolBar添加的控件在ToolBar中是居中对齐的。ToolBar的高度为wrap_content表示高度值大于等于56dp,也就是说添加到ToolBar的控件大于56dp则ToolBar的高度为添加的控件中最高的控件的高度,否则为56dp。ToolBar的高度设置为除56dp之外的值,则无论app:maxButtonHeight怎么设置,ToolBar自身的控件跟ToolBar之间之中都会有间隙,例如NavigationIcon控件。总的来说就是,在ToolBar中添加控件基本可以正常使用,但是如果要使用ToolBar自身的控件则会受到高度56dp的影响!如果需要设置app bar的高度,正确的做法应该是在style里面的item中设置actionBarSize数值,这才是最正确的做法!高度引用?attr/ActionBarSize中?意思是使用android内部特征,从ToolBar使用这个属性作为高度可以看出,我们在style中定义actionBarSize是最正规的做法。

ps:在ToolBar中添加控件,给ToolBar添加android:gravity属性中,bottom属性起作用,而top属性不起作用。

ps:在旧版本的ActionBar里面,在设置getSupportActionBar().setDisplayHomeAsUpEnabled(true)之后,需要在Activity里面设置android:parentActivity之后,然后返回按钮才会生效,但是需要在android 4.0之后才会生效。而在oolBar里面根本就不需要配置android:parentActivity这个属性就可以生效。

ps:对于ToolBar,如果没有在Activity里面设置setSupportActionBar(ToolBar)这个属性,那么ToolBar的点击时不会生效的,控件的点击也就不会变色了,因为这个时候ToolBar就仅仅是一个控件而已!如果需要点击变色以及返回按钮,overflow按钮就必须要加上setSupportActionBar(ToolBar)这个属性,如果返回按钮需要可以返回上一个Activity的话,还需要在AndroidManifest中声明android:parentActivity才行,不然不会返回。







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值