Toolbar使用说明

来源:互联网 发布:淘宝客服差评处理技巧 编辑:程序博客网 时间:2024/05/22 12:42

转载请注明出处:http://blog.csdn.net/forevercbb/article/details/50889282
由于ActionBar的局限性,Google引进Toolbar取代ActionBar,Toolbar可以更方便及更大程度的进行自定义。最近也是粗浅的使用了一下Toolbar,也遇到一些问题,这里分享一下Toolbar的正确使用姿势。

Toolbar的基本使用

1.调整styles.xml

<style name="AppBaseTheme" parent="Theme.AppCompat">    <item name="windowActionBar">false</item>    <item name="windowNoTitle">true</item></style>

使用Theme.AppCompat系列主题,如果应用是白色主题,可以使用Theme.AppCompat.Light.DarkActionBar

2.在布局文件中定义Toolbar控件,跟定义TextView一样,增加app命名空间,一般控件的属性如background、layout属性用android的,Toolbar特有的属性用app命名空间的。

<android.support.v7.widget.Toolbar 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="?attr/actionBarSize"    android:background="@drawable/toolbar_bg"    app:navigationIcon="@drawable/icon_back_new"    app:titleTextColor="#787878"    ></android.support.v7.widget.Toolbar>

属性不多,通过属性名基本可以看懂作用。由于应用风格的一致,Toolbar会有较多的相同或相似,因此建议将Toolbar单独定义在一个layout里面,使用时通过include导入即可,既避免重复劳动,日后修改也比较方便。
Background可以设置toolbar的背景,navigationIcon定义返回按钮,只需要在布局文件中设置这个属性,就会出现返回按钮了,无需像Actionbar一样在代码中set个什么鬼的。

3.在代码中获取Toolbar,可以通过代码继续定义toolbar,最后调用setSupportActionBar(),就能用Toolbar替代ActionBar了。

Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);toolbar.setTitle(R.string.music);setSupportActionBar(toolbar);

这里需要注意,Activity需要继承v7包的AppCompatActivity才能调用setSupportActionBar()方法。同时Toolbar要导入v7包的,否则只有在API Level 21,也就是Android 5.0以上版本才能使用。

其它还有什么设置logo啊,title啊,subTitle啊,都太简单了,使用任何语言进行描述都显得苍白无力。

这里介绍一下Toolbar的一些自定义颜色属性。

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

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

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

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

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

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

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

AppCompatActivity中的菜单使用问题

1.AppCompatActivity菜单不会加载Icon。
解决方案:

@Override 
protected boolean onPrepareOptionsPanel(View view, Menu menu) {
if (menu != null) {
if (menu.getClass() == MenuBuilder.class) {
try {
Method m = menu.getClass().getDeclaredMethod(“setOptionalIconsVisible”, Boolean.TYPE);
m.setAccessible(true);
m.invoke(menu, true);
} catch (Exception e) {
}
}
}
return super.onPrepareOptionsPanel(view, menu);
}
 
2.使用onPrepareOptionsMenu()会重复加载菜单
解决方法:在onPrepareOptionsMenu方法中调用invalidateOptionsMenu()方法使原来填充的menu无效。

最后说一下setSupportActionBar()方法和getSupportActionBar()方法
setSupportActionBar的参数是Toolbar,而getSupportActionBar取回的却是ActionBar

public abstract void setSupportActionBar(Toolbar toolbar); public abstract ActionBar getSupportActionBar();

跟踪一下源码,由setSupportActionBar()的注释可以知道,Toolbar to set as the Activity’s action bar,该方法实际将Toolbar设置成了Actionbar。但是Toolbar继承于GroupView,而ActionBar没有父类,又是怎么设置的呢。
继续跟踪,在AppCompatDelegateImplV7类找到setSupportActionBar()方法的实现,

 public void setSupportActionBar(Toolbar toolbar) {        if (!(mOriginalWindowCallback instanceof Activity)) {            // Only Activities support custom Action Bars            return;        }        final ActionBar ab = getSupportActionBar();        if (ab instanceof WindowDecorActionBar) {            throw new IllegalStateException("This Activity already has an action bar supplied " +                    "by the window decor. Do not request Window.FEATURE_SUPPORT_ACTION_BAR and set " +                    "windowActionBar to false in your theme to use a Toolbar instead.");        }        // Clear out the MenuInflater to make sure that it is valid for the new Action Bar        mMenuInflater = null;        ToolbarActionBar tbab = new ToolbarActionBar(toolbar, ((Activity) mContext).getTitle(),                mAppCompatWindowCallback);        mActionBar = tbab;        mWindow.setCallback(tbab.getWrappedWindowCallback());        tbab.invalidateOptionsMenu();    }

可以知道Toolbar到ActionBar的转换通过ToolbarActionBar类完成,跟进ToolbarActionBar类,可以看到ToolbarActionBar是ActionBar的子类,并且有个成员变量private DecorToolbar mDecorToolbar,

    public ToolbarActionBar(Toolbar toolbar, CharSequence title, Window.Callback callback) {        mDecorToolbar = new ToolbarWidgetWrapper(toolbar, false);        mWindowCallback = new ToolbarCallbackWrapper(callback);        mDecorToolbar.setWindowCallback(mWindowCallback);        toolbar.setOnMenuItemClickListener(mMenuClicker);        mDecorToolbar.setWindowTitle(title);    }

在以上的代码中,toolbar作为参数完成成员变量mDecorToolbar的初始化。并在以下的代码中得到Toolbar的属性。

 public ToolbarWidgetWrapper(Toolbar toolbar, boolean style,            int defaultNavigationContentDescription, int defaultNavigationIcon) {        mToolbar = toolbar;        mTitle = toolbar.getTitle();        mSubtitle = toolbar.getSubtitle();        mTitleSet = mTitle != null;        mNavIcon = toolbar.getNavigationIcon();        if (style) {            final TintTypedArray a = TintTypedArray.obtainStyledAttributes(toolbar.getContext(),                    null, R.styleable.ActionBar, R.attr.actionBarStyle, 0);            final CharSequence title = a.getText(R.styleable.ActionBar_title);            if (!TextUtils.isEmpty(title)) {                setTitle(title);            }            final CharSequence subtitle = a.getText(R.styleable.ActionBar_subtitle);            if (!TextUtils.isEmpty(subtitle)) {                setSubtitle(subtitle);            }            final Drawable logo = a.getDrawable(R.styleable.ActionBar_logo);            if (logo != null) {                setLogo(logo);            }            final Drawable icon = a.getDrawable(R.styleable.ActionBar_icon);            if (mNavIcon == null && icon != null) {                setIcon(icon);            }            final Drawable navIcon = a.getDrawable(R.styleable.ActionBar_homeAsUpIndicator);            if (navIcon != null) {                setNavigationIcon(navIcon);            }            setDisplayOptions(a.getInt(R.styleable.ActionBar_displayOptions, 0));            final int customNavId = a.getResourceId(                    R.styleable.ActionBar_customNavigationLayout, 0);            if (customNavId != 0) {                setCustomView(LayoutInflater.from(mToolbar.getContext()).inflate(customNavId,                        mToolbar, false));                setDisplayOptions(mDisplayOpts | ActionBar.DISPLAY_SHOW_CUSTOM);            }            final int height = a.getLayoutDimension(R.styleable.ActionBar_height, 0);            if (height > 0) {                final ViewGroup.LayoutParams lp = mToolbar.getLayoutParams();                lp.height = height;                mToolbar.setLayoutParams(lp);            }            final int contentInsetStart = a.getDimensionPixelOffset(                    R.styleable.ActionBar_contentInsetStart, -1);            final int contentInsetEnd = a.getDimensionPixelOffset(                    R.styleable.ActionBar_contentInsetEnd, -1);            if (contentInsetStart >= 0 || contentInsetEnd >= 0) {                mToolbar.setContentInsetsRelative(Math.max(contentInsetStart, 0),                        Math.max(contentInsetEnd, 0));            }            final int titleTextStyle = a.getResourceId(R.styleable.ActionBar_titleTextStyle, 0);            if (titleTextStyle != 0) {                mToolbar.setTitleTextAppearance(mToolbar.getContext(), titleTextStyle);            }            final int subtitleTextStyle = a.getResourceId(                    R.styleable.ActionBar_subtitleTextStyle, 0);            if (subtitleTextStyle != 0) {                mToolbar.setSubtitleTextAppearance(mToolbar.getContext(), subtitleTextStyle);            }            final int popupTheme = a.getResourceId(R.styleable.ActionBar_popupTheme, 0);            if (popupTheme != 0) {                mToolbar.setPopupTheme(popupTheme);            }            a.recycle();            // Keep the TintManager in case we need it later            mTintManager = a.getTintManager();        } else {            mDisplayOpts = detectDisplayOptions();            // Create a TintManager in case we need it later            mTintManager = TintManager.get(toolbar.getContext());        }        setDefaultNavigationContentDescription(defaultNavigationContentDescription);        mHomeDescription = mToolbar.getNavigationContentDescription();        setDefaultNavigationIcon(mTintManager.getDrawable(defaultNavigationIcon));        mToolbar.setNavigationOnClickListener(new View.OnClickListener() {            final ActionMenuItem mNavItem = new ActionMenuItem(mToolbar.getContext(),                    0, android.R.id.home, 0, 0, mTitle);            @Override            public void onClick(View v) {                if (mWindowCallback != null && mMenuPrepared) {                    mWindowCallback.onMenuItemSelected(Window.FEATURE_OPTIONS_PANEL, mNavItem);                }            }        });    }

由于Toolbar最后还是设置给了ActionBar,因此在v7包中,通过Activity的对象activity.getSupportActionBar()方法取得的ActionBar对象是能够正常使用并修改ActionBar属性的。

0 0
原创粉丝点击