Toolbar使用说明

转载请注明出处:http://blog.youkuaiyun.com/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属性的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值