Android ToolBar/App bar

2014 google i/o发表令多数人为之一亮的 material design toolbar,这是用来取代过去 actionbar 的控件,而现在于 material design中也对之有一个统一名称:app bar,在未来的 android app 中,就以 toolbar这个元件来实作之。概述 Android 3.0 Android推了 ActionBar这个控件,而到了2013 Google开始大力地推动所谓的 android style,想要逐渐改善过去 android 纷乱的界面设计,希望让终端使用者尽可能在 android手机有个一致的操作体验。ActionBar过去最多人使用的两大套件就是 ActionBarSherlock以及官方提供在 support library v 7里的 AppCompat Toolbar的诞生,也意味着官方在某些程度上认为 ActionBar 限制了 android app的开发与设计的弹性,而在 material design也对之做了名称的定义:App bar

Material DesignTheme

  • @android:style/Theme.Material (dark version)
  • @android:style/Theme.Material.Light (light version)
  • @android:style/Theme.Material.Light.DarkActionBar

与之对应的Compat Theme:

  • Theme.AppCompat
  • Theme.AppCompat.Light
  • Theme.AppCompat.Light.DarkActionBar

示例:https://github.com/mengdd/HelloActivityAndFragmenthttps://github.com/hongyangAndroid/Android_Blog_Demos/tree/master/blogcodes/src/main/java/com/zhy/blogcodes/toolbarhttps://github.com/tekinarslan/AndroidMaterialDesignToolbarhttps://github.com/mosil/Android-Mosil-Sample-Toolbarhttps://github.com/hanks-zyh/ToolBar

基础

1.首先项目gradle中添加:appcompat-v7依赖 2.确保Activity继承AppCompatActivity 3.application设置中使用NoActionBar的主题:

<application
android:theme="@style/Theme.AppCompat.Light.NoActionBar"
/>

4.Toolbar写在布局中

<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
android:layout_width="match_parent"
android:background="?attr/colorPrimary"
android:elevation="4dp"
android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>

请记得用 support v7里的 toolbar,不然然只有 API Level 21也就是 Android 5.0以上的版本才能使用。程序 (Java) MainActivity.javaonCreate中加入 Toolbar的声明:

Toolbar toolbar=(Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);//声明后,再将之用 setSupportActionBar 设定,Toolbar即能取代原本的 actionbar 了

定义menu:

<?xmlversion="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/action_android"
android:icon="@drawable/ic_android_black_24dp"
android:title="@string/action_android"
app:showAsAction="always"/>
<item
android:id="@+id/action_favourite"
android:icon="@drawable/ic_favorite_black_24dp"
android:title="@string/action_favourite"
app:showAsAction="ifRoom"/>
<item
android:id="@+id/action_settings"
android:title="@string/action_settings"
app:showAsAction="never"/>
</menu>

然后在代码中inflate和处理它的点击事件:

@Override
publicboolean onCreateOptionsMenu(Menu menu){
Log.i(TAG, "onCreateOptionsMenu()");
getMenuInflater().inflate(R.menu
.menu_activity_main, menu);
returnsuper.onCreateOptionsMenu(menu);
}
 
@Override
publicboolean onOptionsItemSelected(MenuItem item){
switch(item.getItemId()){
case R.id.action_android:
Log.i(TAG, "action android selected");
returntrue;
case R.id
.action_favourite:
Log.i(TAG, "action favourite selected");
returntrue;
case R.id
.action_settings:
Log.i(TAG, "action settings selected");
returntrue;
default:
returnsuper.onOptionsItemSelected(item);
}
}

Menu Item,依然支持在menu/menu_main.xml去声明,然后复写onCreateOptionsMenuonOptionsItemSelected即可。可选方案也可以通过toolbar.setOnMenuItemClickListener实现点击MenuItem的回调。

toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener(){
@Override

publicboolean onMenuItemClick(MenuItem item){
returnfalse;
}
});

添加向上返回的action添加向上返回parentaction:

@Override
protectedvoid onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_toolbar_demo);
setSupportActionBar(toolbar);
 
// add a left arrow to back to parent activity,
// no need to handle action selected event, this is handled by super
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}

然后只需要在manifest中指定parent:

<activity
android:name=".toolbar.ToolbarDemoActivity"
android:parentActivityName=".MainActivity">
<!--
Parent activity meta-data to support4.0 and lower -->
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".MainActivity" />
</activity>

自定义颜色(Customization color)

  • colorPrimaryDark(状态栏底色):在风格 (styles)或是主题 (themes)里进行设定。
  • App bar底色。这个设定分为二,若你的 android app仍是使用 actionbar,则直接在风格 (styles)或是主题 (themes)里进行设定 colorPrimary参数即可;

可若是采用 toolbar的话,则要在界面 (layout)里面设定 toolbar控件的background属性。

  • navigationBarColor(导航栏底色):仅能在 API v21也就是 Android 5以后的版本中使用,因此要将之设定在 res/values-v21/styles.xml里面。

也因此在这个阶段,我们需要设定的地方有三,一是 style(res/values/styles.xml)

<stylename="AppTheme.Base"parent="Theme.AppCompat.Light.NoActionBar">
<!-- <item name="windowActionBar">false</item> -->
<!-- <item name="android:windowNoTitle">true</item> -->
<!-- Actionbar color -->
<itemname="colorPrimary">@color/accent_material_dark</item>
<!--Status bar color-->
<itemname="colorPrimaryDark">@color/accent_material_light</item>
<!--Window color-->
<itemname="android:windowBackground">@color/dim_foreground_material_dark</item>
</style>

再来是 v21style (res/values-v21/styles.xml)

<stylename="AppTheme"parent="AppTheme.Base">
<!--Navigation bar color-->
<itemname="android:navigationBarColor">@color/accent_material_light</item>
</style>

最后,就是为了本篇的主角 – Toolbar background进行设定。

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

控件 (component)

在还未于 <android.support.v7.widget.Toolbar/>标签中,自行添加元件的 toolbar有几个大家常用的元素可以使用,请先见下图:

Toolbar toolbar=(Toolbar) findViewById(R.id.toolbar);
 
// App Logo
toolbar.setLogo(R.drawable.ic_launcher);
// Title
toolbar.setTitle("My Title");
// Sub Title
toolbar.setSubtitle("Sub title");
 

setSupportActionBar(
toolbar);
 
// Navigation Icon 要設定在 setSupoortActionBar之后才有作用
// 否則會出現 back button
toolbar.setNavigationIcon(R.drawable.ab_android);

这边要留意的是setNavigationIcon需要放在 setSupportActionBar之后才会生效。可选方案当然如果你喜欢,也可以在布局文件中去设置部分属性:

<android.support.v7.widget.Toolbar
android:id="@+id/id_toolbar"
app:title="App Title"
app:subtitle="Sub Title"
app:navigationIcon="@drawable/ic_toc_white_24dp"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
android:layout_width="match_parent"
android:background="?attr/colorPrimary"/>

Action Views and Action Providers To add an action view, create an <item> element in the toolbar's menu resource, as Add Action Buttons describes. Add one of the following two attributes to the <item> element:

  • actionViewClass: The class of a widget that implements the action.
  • actionLayout: A layout resource describing the action's components.

<itemandroid:id="@+id/action_search"
android:title="@string/action_search"
android:icon="@drawable/ic_search"
<!-- app: -->
app:showAsAction="ifRoom|collapseActionView"
app:actionViewClass="android.support.v7.widget.SearchView" />

getActionView的正确操作方式:

@Override
publicboolean onCreateOptionsMenu(Menu menu){
getMenuInflater().inflate(R.menu.main_activity_actions, menu);
 
MenuItem searchItem= menu.findItem(R.id.action_search);
SearchView searchView =
(SearchView) MenuItemCompat.getActionView(searchItem);
 
// Configure the search info and add any event listeners...
 
returnsuper.onCreateOptionsMenu(menu);
}

Add an Action Provider

<itemandroid:id="@+id/action_share"
android:title="@string/share"
app:showAsAction="ifRoom"
app:actionProviderClass="android.support.v7.widget.ShareActionProvider"/>

在这样的架构设计下,ToolBar直接成了Layout中可以控制的东西,相对于过去的actionbar来说,设计与可操控性大幅提升。最后再附上一个界面上常用的属性说明图:这里按照图中从上到下的顺序做个简单的说明:

colorPrimaryDark

状态栏背景色。 style的属性中设置。 textColorPrimary

App bar上的标题与更多菜单中的文字颜色。 style的属性中设置。 App bar的背景色

Actionbar的背景色设定在 style中的 colorPrimary Toolbar的背景色在layout文件中设置background属性。 colorAccent

各控制元件(如:check boxswitch或是 radoi)被勾选 (checked)或是选定 (selected)的颜色。 style的属性中设置。 colorControlNormal

各控制元件的预设颜色。 style的属性中设置 windowBackground

App 的背景色。 style的属性中设置 navigationBarColor

导航栏的背景色,但只能用在 API Level 21 (Android 5)以上的版本 style的属性中设置

最后需要注意的是:使用material主题的时候,必须设定targetSdkVersion = 21,否则界面看起来是模糊的

在Fragment中使用Toolbar:

Fragment中使用Toolbar的步骤和Activity差不多.Fragment布局中添加一个Toolbar,然后find,然后调用Activity的方法来把它设置成ActionBar:

((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);

注意此处有一个强转,必须是AppCompatActivity才有这个方法.但是此时运行到Fragment之后,发现Toolbar上的文字和按钮全是Activity传过来的,这是因为只有ActivityonCreateOptionsMenu()被调用了,但是Fragment的并没有被调用.Fragment中加上这句:

setHasOptionsMenu(true);

此时FragmentonCreateOptionsMenu()回调会被调到了,但是inflate出的按钮和Activity中的actions加在一起显示出来了.因为ActivityonCreateOptionsMenu()会在之前调用到.于是Fragment中的写成这样:

@Override
publicvoid onCreateOptionsMenu(Menu menu, MenuInflater inflater){
Log.e(TAG, "onCreateOptionsMenu()");
menu.clear();
inflater.inflate(R.menu.menu_parent_fragment, menu);
}

即先clear()一下,这样按钮就只有Fragment中设置的自己的了,不会有Activity中的按钮.

在嵌套的子Fragment中使用Toolbar

前面已经介绍过, Fragment可以嵌套使用:Android Fragment使用()嵌套Fragments (Nested Fragments)的使用及常见错误那么在前面的Fragment中再显示一个子Fragment,并且又带有一个不一样的Toolbar,还需要哪些处理呢?首先, java代码中还是需要有:

setHasOptionsMenu(true)
((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);

然后根据是否需要菜单按钮,覆写onCreateOptionsMenu()方法来inflate自己的menu文件即可.感觉和在普通的Fragment中使用Toolbar作为ActionBar并没有什么区别.但是如果你的多个Fragment有不同的Toolbar菜单选项,如果你没有懂得其中的原理,可能就会出现一些混乱.下面来解说一下相关的方法.onCreateOptionsMenu()方法的调用一旦调用.setSupportActionBar(toolbar);就会导致Activity.onCreateOptionsMenu()方法的调用,Activity会根据其中Fragment是否设置了setHasOptionsMenu(true)来调用FragmentonCreateOptionsMenu()方法,调用顺序是树形的,按层级调用,中间如果有false则跳过.

假设当前Activity, Parent FragmentChild Fragment中都设置了自己的ToolbarActionBar.在打开Child fragment的时候, onCreateOptionsMenu()的调用顺序是.Activity → Parent → Child. 此时parentchild fragment都设置了setHasOptionsMenu(true).

关于这个,还有以下几种情况: -如果Parent`setHasOptionsMenu(false)`, Childtrue,Parent`onCreateOptionsMenu()`不会调用,打开Child的时候Activity → Child. -如果Child`setHasOptionsMenu(false)`, Parenttrue,则打开Child的时候仍然会调用ActivityParentonCreateOptionsMenu()方法. - 如果ParentChild都置为false,打开ParentChild Fragment的时候都会调用ActivityonCreateOptionsMenu()方法.仅仅是child Fragmentshow() hide()的切换, activityparent FragmentonCreateOptionsMenu()也会重新进入.

上面的机制常常是导致Toolbar上面的按钮混淆错乱的原因.举个例子:如果我们现在ActivityParent Fragment有不同的Toolbar按钮,但是Child只有文字,没有按钮.很显然我们不需要给childmenu文件,也不需要覆写child里的onCreateOptionsMenu()方法.但是此时不管怎样, parentonCreateOptionsMenu()方法都会被调用,这样我们打开child的时候, toolbar上就神奇地出现了parent里的按钮.这种情况如何解决呢?可以在parent中加一个条件,当没有child fragment的时候才做inflate的工作:

@Override
publicvoid onCreateOptionsMenu(Menu menu, MenuInflater inflater){
Log.e(TAG, "onCreateOptionsMenu()");
menu.clear();
if(getChildFragmentManager().getBackStackEntryCount()==0){
inflater.inflate(R.menu
.menu_parent_fragment, menu);
}
}

另外,除了setSupportActionBar()之外,如果我们想主动触发 onCreateOptionsMenu()方法的调用,可以用invalidateOptionsMenu()方法.

onOptionsItemSelected()方法的调用Activity和其中的Fragment都有options menu的时候,需要注意menu itemid不要重复.因为点击事件的分发也是从Activity开始分发下去的,如果child fragment中有个选项的idActivity中一个选项的id重复了,则在Activity中就会将其处理,不会继续分发.

有嵌套Fragment Back键处理之前没有嵌套Fragment的情况下,只要将Fragment加入到Back Stack,那么按下Back键的时候pop动作是系统自动做好的.虽然在添加child fragment的时候将其加入到back stack,但是按back键的时候仍然是将parent fragment弹出,只剩下Activity.这是因为back键只检查第一层Fragmentback stack, 对于child fragment,需要在其parent中自己处理.比如这样处理:Activity

@Override
publicvoid onBackPressed(){
Fragment fragment = getSupportFragmentManager().findFragmentById(android.R.id.content);
if(fragmentinstanceof ToolbarFragment){
if(((ToolbarFragment) fragment).onBackPressed()){
return;
}
}
super.onBackPressed();
}

其中ToolbarFragment是直接加在Activity中作为parent fragment.parent fragment(ToolbarFragment):

publicboolean onBackPressed(){
return getChildFragmentManager().popBackStackImmediate();

Fragment单独使用Toolbar而不与ActionBar进行关联

对于Fragment使用Toolbar思维被局限了,Menu的操作也不用在onCreateOptionsMenu方法,直接使用ToolBarinflateMenu方法Menu的事件也是独立的,需要通过设置ToolBarsetOnMenuItemClickListener来实现

Toolbar toolbar=(Toolbar) findViewById(R.id.toolbar);
 
// App Logo
toolbar.setLogo(R.drawable.ic_launcher);
// Title
toolbar.setTitle("My Title");
// Sub Title
toolbar.setSubtitle("Sub title");
 

//setSupportActionBar(toolbar);
toolbar.inflateMenu(R.menu.activity_main);
// Navigation Icon 要設定在 setSupoortActionBar后 才有作用
// 否則會出現 back button
toolbar.setNavigationIcon(R.drawable.ab_android);
toolbar.setNavigationOnClickListener(newView.OnClickListener(){
@Override

publicvoid onClick(View v){
 
}
});
// Menu item click 设定在 setSupportActionBar 之后才有作用
toolbar.setOnMenuItemClickListener(onMenuItemClick);
private Toolbar.OnMenuItemClickListener
onMenuItemClick=new Toolbar.OnMenuItemClickListener(){
@Override
publicboolean onMenuItemClick(MenuItem menuItem){
String msg="";
switch(menuItem.getItemId()){
case R.id.action_edit:
break;
}
returntrue;
}
};

自定义布局 title修改为居中

<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/toolbar"
android:layout_width="match_parent"
    android:layout_height="wrap_content"
android:background="@mipmap/bg_title"
android:minHeight="?actionBarSize">
<TextView
android:id="@+id/toolbar_title"
style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"/>
</android.support.v7.widget.Toolbar>

禁用系统的title显示,即setDisplayShowTitleEnabled方法实现将布局的内容延伸到状态栏 styles.xml <item name="android:windowTranslucentStatus" tools:targetApi="19">true</item>

整合ToolBar,DrawerLayout,ActionBarDrawerToggle

大致思路整体实现还是比较容易的,首先需要引入DrawerLayout(如果你对DrawerLayout不了解,可以参考Android DrawerLayout 高仿QQ5.2双向侧滑菜单),然后去初始化mActionBarDrawerTogglemActionBarDrawerToggle实际上是个DrawerListener,设置mDrawerLayout.setDrawerListener(mActionBarDrawerToggle);就已经能够实现上面点击Nav Icon切换效果了。当然了细节还是挺多的。我们的效果图,左侧菜单为Fragment,内容区域为Fragment,点击左侧菜单切换内容区域的Fragment即可。 activity_main.xml

<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent"
android:background="#ffffffff"
xmlns:app="http://schemas.android.com/apk/res-auto">
 
<!--app:subtitle="Sub Title"-->
<android.support.v7.widget.Toolbar
android:id="@+id/id_toolbar"
app:title="App Title"
app:navigationIcon="@drawable/ic_toc_white_24dp"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
android:layout_width="match_parent"
android:background="?attr/colorPrimary"/>
 
<android.support.v4.widget.DrawerLayout
android:id="@+id/id_drawerlayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
 
<FrameLayout
android:id="@+id/id_content_container"
android:layout_width="match_parent"
android:layout_height="match_parent"></FrameLayout>
 

<FrameLayout
android:id="@+id/id_left_menu_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="left"
android:background="#ffffffff"></FrameLayout>
 

 
</android.support.v4.widget.DrawerLayout>
 
 
</LinearLayout>

DrawerLayout中包含两个FrameLayout,分别放内容区域和左侧菜单的Fragment LeftMenuFragment

packagecom.zhy.toolbar;
 
importandroid.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.ListFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
 
/**
* Created by zhy on 15/4/26.
*/

publicclass LeftMenuFragmentextends ListFragment {
 
privatestaticfinalint SIZE_MENU_ITEM=3;
 
privateMenuItem[] mItems=newMenuItem[SIZE_MENU_ITEM];
 
private LeftMenuAdapter mAdapter;
 
private LayoutInflater mInflater;
 
@Override
publicvoid onCreate(@Nullable Bundle savedInstanceState){
super.onCreate(savedInstanceState);
 
mInflater = LayoutInflater.from(getActivity());
 
MenuItem menuItem=null;
for(int i =0; i< SIZE_MENU_ITEM; i++){
menuItem =newMenuItem(getResources().getStringArray(R.array.array_left_menu)[i],false, R.drawable.music_36px, R.drawable.music_36px_light);
mItems[i]= menuItem;
}
}
 
@Override
publicView onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
returnsuper.onCreateView(inflater, container, savedInstanceState);
}
 
@Override
publicvoid onViewCreated(View view, @Nullable Bundle savedInstanceState){
super.onViewCreated(view, savedInstanceState);
 
setListAdapter(mAdapter =new LeftMenuAdapter(getActivity(), mItems));
 
}
 
@Override
publicvoid onListItemClick(ListView l, View v, int position,long id){
super.onListItemClick(l, v, position, id);
 
if(mMenuItemSelectedListener!=null){
mMenuItemSelectedListener.menuItemSelected(((MenuItem) getListAdapter().getItem(position)).text);
}
 
mAdapter.setSelected(position);
 
}
 
 
//选择回调的接口
publicinterface OnMenuItemSelectedListener{
void menuItemSelected(String title);
}
private OnMenuItemSelectedListener mMenuItemSelectedListener;
 
publicvoid setOnMenuItemSelectedListener(OnMenuItemSelectedListener menuItemSelectedListener){
this.mMenuItemSelectedListener= menuItemSelectedListener;
}
 
 
 
}

继承自ListFragment,主要用于展示各个Item,提供了一个选择Item的回调,这个需要在Activity中去注册处理。 LeftMenuAdapter

packagecom.zhy.toolbar;
 
importandroid.content.Context;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
 
/**
* Created by zhy on 15/4/26.
*/

publicclass LeftMenuAdapterextends ArrayAdapter<MenuItem>{
 
 
private LayoutInflater mInflater;
 
privateint mSelected;
 
 
public LeftMenuAdapter(Context context,MenuItem[] objects){
super(context, -1, objects);
 
mInflater = LayoutInflater.from(context);
 
}
 
@Override
publicView getView(int position, View convertView, ViewGroup parent){
 
 
if(convertView==null){
convertView = mInflater.inflate(R.layout.item_left_menu, parent,false);
}
 
ImageView iv =(ImageView) convertView.findViewById(R.id.id_item_icon);
TextView title =(TextView) convertView.findViewById(R.id.id_item_title);
title.setText(getItem(position).text);
iv.setImageResource(getItem(position).icon);
convertView.setBackgroundColor(Color.TRANSPARENT);
 
if(position== mSelected){
iv.setImageResource(getItem(position).iconSelected);
convertView.setBackgroundColor(getContext().getResources().getColor(R.color.state_menu_item_selected));
}
 
return convertView;
}
 
publicvoid setSelected(int position){
this.mSelected= position;
notifyDataSetChanged();
}
 
 
}
 
 
packagecom.zhy.toolbar;
 
publicclassMenuItem{
 
publicMenuItem(String text, boolean isSelected, int icon, int iconSelected){
this.text= text;
this.isSelected= isSelected;
this.icon= icon;
this.iconSelected= iconSelected;
}
 
boolean isSelected;
String text;
int icon;
int iconSelected;
}

Adapter没撒说的~~提供了一个setSection方法用于设置选中Item的样式什么的。接下来看ContentFragment,仅仅只是一个TextView而已,所以代码也比较easy

packagecom.zhy.toolbar;
 
importandroid.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
 
/**
* Created by zhy on 15/4/26.
*/

publicclass ContentFragmentextends Fragment {
 
publicstaticfinalString KEY_TITLE ="key_title";
privateString mTitle;
 
publicstatic ContentFragment newInstance(String title){
ContentFragment fragment =new ContentFragment();
Bundle bundle =new Bundle();
bundle.putString(KEY_TITLE, title);
fragment.setArguments(bundle);
return fragment;
}
 
@Nullable
@Override
publicView onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState){
 
TextView tv =new TextView(getActivity());
String title=(String) getArguments().get(KEY_TITLE);
if(!TextUtils.isEmpty(title))
{
tv.setGravity(Gravity.CENTER);
tv.setTextSize(40);
tv.setText(title);
}

 
return tv;
}
}

提供newInstance接收一个title参数去实例化它。最后就是我们的MainActivity了,负责管理各种Fragment

MainActivity
packagecom.zhy.toolbar;importandroid.os.Bundle;importandroid.support.v4.app.Fragment;importandroid.support.v4.app.FragmentManager;importandroid.support.v4.app.FragmentTransaction;importandroid.support.v4.widget.DrawerLayout;importandroid.support.v7.app.ActionBarDrawerToggle;importandroid.support.v7.app.AppCompatActivity;importandroid.support.v7.widget.Toolbar;importandroid.text.TextUtils;importandroid.view.Gravity;importjava.util.List;publicclass MainActivity extends AppCompatActivity {
 

private ActionBarDrawerToggle mActionBarDrawerToggle;
private DrawerLayout mDrawerLayout;private Toolbar mToolbar;private LeftMenuFragment mLeftMenuFragment;private ContentFragment mCurrentFragment;privateString
mTitle;
privatestaticfinalString
TAG =
"com.zhy.toolbar";privatestaticfinalString KEY_TITLLE ="key_title"; @Override
protectedvoid onCreate(
Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(
R.layout.activity_main);
 

initToolBar();
initViews();
//恢复title
restoreTitle(
savedInstanceState);
 

FragmentManager fm =
getSupportFragmentManager();
//查找当前显示的Fragment
mCurrentFragment =(ContentFragment) fm.findFragmentByTag(mTitle);if(mCurrentFragment==null){
mCurrentFragment = ContentFragment.newInstance(mTitle);
fm.beginTransaction().add(R.id.id_content_container, mCurrentFragment, mTitle).commit();
}
 
mLeftMenuFragment =(LeftMenuFragment) fm.findFragmentById(R.id.id_left_menu_container);if(mLeftMenuFragment==null){
mLeftMenuFragment =new LeftMenuFragment();
fm.beginTransaction().add(R.id.id_left_menu_container, mLeftMenuFragment).commit();
}//隐藏别的Fragment,如果存在的话
List<Fragment> fragments= fm.getFragments();if(fragments!=null)for(Fragment fragment: fragments){if(fragment== mCurrentFragment || fragment == mLeftMenuFragment)continue;
fm.beginTransaction().hide(fragment).commit();
}//设置MenuItem的选择回调
mLeftMenuFragment.setOnMenuItemSelectedListener(new LeftMenuFragment.OnMenuItemSelectedListener(){ @Override
publicvoid menuItemSelected(String title){
 
FragmentManager fm = getSupportFragmentManager();
ContentFragment fragment =(ContentFragment) getSupportFragmentManager().findFragmentByTag(title);if(fragment== mCurrentFragment){
mDrawerLayout.closeDrawer(Gravity.LEFT);return;
}
 
FragmentTransaction transaction = fm.beginTransaction();
transaction.hide(mCurrentFragment);if(fragment==null){
fragment = ContentFragment.newInstance(title);
transaction.add(R.id.id_content_container, fragment, title);
}else{
transaction.show(fragment);
}
transaction.commit();
 
mCurrentFragment = fragment;
mTitle = title;
mToolbar.setTitle(mTitle);
mDrawerLayout.closeDrawer(Gravity.LEFT);
 
 
}
});
 
}privatevoid restoreTitle(Bundle savedInstanceState){if(savedInstanceState!=null)
mTitle = savedInstanceState.getString(KEY_TITLLE);if(TextUtils.isEmpty(mTitle)){
mTitle = getResources().getStringArray(
R.array.array_left_menu)[0];
}
 
mToolbar.setTitle(mTitle);
} @Override
protectedvoid onSaveInstanceState(Bundle outState){super.onSaveInstanceState(outState);
outState.putString(KEY_TITLLE, mTitle);
}privatevoid initToolBar(){
 
Toolbar toolbar = mToolbar =(Toolbar) findViewById(R.id.id_toolbar);// App Logo
// toolbar.setLogo(R.mipmap.ic_launcher);
// Title
toolbar.setTitle(getResources().getStringArray(R.array.array_left_menu)[0]);// Sub Title
// toolbar.setSubtitle("Sub title");// toolbar.setTitleTextAppearance();
 

 
setSupportActionBar(toolbar);//Navigation Icon
toolbar.setNavigationIcon(R.drawable.ic_toc_white_24dp);/*
toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
return false;
}
});*/

 
}privatevoid initViews(){
 
mDrawerLayout =(DrawerLayout) findViewById(R.id.id_drawerlayout);
 
mActionBarDrawerToggle =new ActionBarDrawerToggle(this,
mDrawerLayout, mToolbar, R.string.open, R.string.close);
mActionBarDrawerToggle.syncState();
mDrawerLayout.setDrawerListener(mActionBarDrawerToggle);
 
 
}
}

内容区域的切换是通过Fragment hideshow实现的,毕竟如果用replace,如果Fragmentview结构比较复杂,可能会有卡顿。当然了,注意每个Fragment占据的内存情况,如果内存不足,可能需要改变实现方式。对于旋转屏幕或者应用长时间置于后台,Activity重建的问题,做了简单的处理。

参考:https://developer.android.com/training/appbar/setting-up.htmlhttp://www.cnblogs.com/mengdd/p/5590634.html

http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0430/2814.html

http://wuxiaolong.me/2015/12/21/fragmentToolbar/http://wuxiaolong.me/2015/11/10/toolbar/

http://blog.csdn.net/a553181867/article/details/51336899

http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1118/2006.html

http://m.blog.csdn.net/article/details?id=51965925

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值