美文网首页Android知识库程序员Android知识
Toolbar中style的自定义及加载过程

Toolbar中style的自定义及加载过程

作者: imflyn | 来源:发表于2017-03-27 20:39 被阅读1166次

    Github Demo:https://github.com/imflyn/ActionBarStyle


    不久前,公司里设计师大大踌躇满志的说我们的app要改版。首当其冲的就是主题色的改变,由红色改为白色。并且界面改为扁平风格。那么意味着需要对所有界面里的ActionBar或者ToolBar都要进行主题样式与elevation的修改。最后的结果如下图:

    最简便的方法自然是定义style来更换,如果都在Java代码里去改的话工作量变多不说且都是重复的劳动。也不利于代码的维护。

    一.定义Style

    1.ActionBar的Style定义

    4.4及以下版本style.xml:

    <style name="AppTheme.ActionBar" parent="AppTheme">
        <!--ActionBar是否悬浮覆盖在你的布局上-->
        <item name="windowActionBarOverlay">false</item>
        <!--定义ActionBar窗体的背景-->
        <item name="android:windowContentOverlay">@null</item>
        <!--定义ActionBar的样式-->
        <item name="actionBarStyle">@style/AppTheme.ActionBarStyle</item>
        <!--定义Actionbar上Menu的字体样式-->
        <item name="actionMenuTextAppearance">@style/AppTheme.MyActionBarMenuTextStyle</item>
        <!--定义Actionbar上Menu的字体颜色-->
        <item name="actionMenuTextColor">@color/wechat_color</item>
        <!--定义Actionbar上回退按钮的图片-->
        <item name="homeAsUpIndicator">@drawable/icon_back_black</item>
    </style>
    
    <style name="AppTheme.ActionBarStyle" parent="Widget.AppCompat.Light.ActionBar">
        <!--定义Actionbar上Title的样式-->
        <item name="titleTextStyle">@style/AppTheme.ActionBarTitleTextStyle</item>
        <!--定义Actionbar的背景,R.drawable.bg_frame是最底部为横线,其余位置是透明的.9图片 -->
        <item name="background">@drawable/bg_frame</item>
    </style>
    
    

    5.0及以上版本的style.xml:

    <style name="AppTheme.ActionBar" parent="AppTheme">
        <!--ActionBar是否悬浮覆盖在你的布局上-->
        <item name="windowActionBarOverlay">false</item>
        <!--定义ActionBar的样式-->
        <item name="actionBarStyle">@style/AppTheme.ActionBarStyle</item>
        <!--定义Actionbar上Menu的字体样式-->
        <item name="actionMenuTextAppearance">@style/AppTheme.ActionBarMenuTextStyle</item>
        <!--定义Actionbar上Menu的字体颜色-->
        <item name="actionMenuTextColor">@color/wechat_color</item>
        <!--定义Actionbar上回退按钮的图片-->
        <item name="homeAsUpIndicator">@drawable/icon_back_black</item>
    </style>
    
    <style name="AppTheme.ActionBarStyle" parent="@style/Widget.AppCompat.Light.ActionBar">
        <item name="titleTextStyle">@style/AppTheme.ActionBarTitleTextStyle</item>
        <item name="background">@color/colorPrimary</item>
        <item name="elevation">1dp</item>
    </style>
    

    主题色:

    <style name="AppTheme" parent="Theme.AppCompat.Light">
        <!--主题色-->
        <item name="colorPrimary">@color/colorPrimary</item>
        <!--强调色-->
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <!--点缀色-->
        <item name="colorAccent">@color/colorAccent</item>
    </style>
    

    文字样式的定义:

    <style name="AppTheme.ActionBarTitleTextStyle" parent="TextAppearance.AppCompat.Widget.ActionBar.Title">
        <item name="android:textSize">16sp</item>
        <item name="android:textColor">@color/facebook_color</item>
    </style>
    
    <style name="AppTheme.ActionBarMenuTextStyle" parent="TextAppearance.AppCompat.Widget.ActionBar.Menu">
        <item name="android:textSize">12sp</item>
    </style>
    

    在Activity中引用style:

    <activity
        android:name=".ActionBarActivity"
        android:theme="@style/AppTheme.ActionBar" />
    

    注意:Android4.4版本及以下ActionBar取消elevation必须设置windowContentOverlay属性为null,这样背景就是默认的灰色了,所以还需要自己定义ActionBar的背景,如果在ActionBar底部需要分割线还要做一个.9的图片设置为ActionBar的背景。

    2.ToolBar的Style定义

    在style.xml中定义ToolBar样式:

    <style name="AppTheme.ToolBar" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <!--定义ToolBar上Menu的字体样式-->
        <item name="actionMenuTextAppearance">@style/AppTheme.MyActionBarMenuTextStyle</item>
        <!--定义ToolBar上Menu的字体颜色-->
        <item name="actionMenuTextColor">@color/wechat_color</item>
        <!--定义ToolBar上回退按钮的图片-->
        <item name="homeAsUpIndicator">@drawable/icon_back_black</item>
    </style>
    
    <!--定义ToolBar上Title的文字样式-->
    <style name="AppTheme.ToolbarTitleTextStyle" parent="TextAppearance.Widget.AppCompat.Toolbar.Title">
        <item name="android:textSize">16sp</item>
        <item name="android:textColor">@color/facebook_color</item>
    </style>
    

    在layout文件中设置ToolBar的文字样式:

    <LinearLayout 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:background="@android:color/white"
        android:orientation="vertical">
    
        <android.support.design.widget.AppBarLayout
            android:id="@+id/appbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:stateListAnimator="@animator/appbar_elevation">
    
            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:minHeight="?attr/actionBarSize"
                app:titleTextAppearance="@style/AppTheme.ToolbarTitleTextStyle" />
        </android.support.design.widget.AppBarLayout>
    </LinearLayout>
    

    在Activity中引用style,并且Activity继承supportV7包中的AppCompatActivity

    <activity
        android:name=".ToolBarActivity"
        android:theme="@style/AppTheme.ToolBar" />
    

    注意:Android4.4版本及以下因为不支持elevation属性,所以需要添加下面的代码才能显示ToolBar底部的横线。R.drawable.bg_frame是最底部为横线,背景透明的.9图片:

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
        ViewCompat.setBackground(findViewById(R.id.appbar), ContextCompat.getDrawable(this, R.drawable.bg_frame));
    }
    

    在Demo中最后的效果如下图,可以看到返回按钮、Title、Menu上的文字大小和颜色都是style定义后的。


    二.遇到的坑

    1. 定义ActionBar样式时,4.4及以下版本手机设置了<item name="android:windowContentOverlay">@null</item>后,必须为ActionBar设置背景,否则ActionBar是默认的颜色
    • 4.4及以下版本手机不支持elevation属性,所以在ActionBar底部的分割线或阴影效果需要自己做图片。
    • Menu菜单的文字颜色必须通过actionMenuTextColor属性设置,在actionMenuTextAppearance属性中设置textColor无效。
    • ToolBar的文字样式titleTextAppearance必须在layout布局文件中引用,如果像Actionbar一样只在style.xml中定义是无效的。
    • AppBarLayout的背景和elevation是由stateListAnimator控制的,如果需要改变elevation高度必须自定义stateListAnimator。因为stateListAnimator是5.0版本后的属性,4.4及以下版本手机必须重新设置AppBarLayout的background属性。

    三.源码之下,了无秘密

    修改Actionbar的样式固然很快,但是为了知道为什么会有上面写到的在定义style属性时遇到的坑,所以带着问题看看源码,在源码之下我们可以了解到ActionBar或ToolBar中的Style在AppCompatActivity中是如何被加载的。
    注意:下面贴出的源码不是完整的google官方代码,只截取了关键部分。

    首先AppCompatActivity在执行onCreate方法时创建了AppCompatDelegate对象,并进行了AppCompatDelegate的初始化。
    AppCompatDelegate相当于一个委托,appcompat适配包中一些方法委托AppCompatDelegate来调用。

    protected void onCreate(@Nullable Bundle savedInstanceState) {  
        final AppCompatDelegate delegate = getDelegate();//执行AppCompatDelegate.create();
        //初始化工作
        delegate.installViewFactory();
        delegate.onCreate(savedInstanceState);
        super.onCreate(savedInstanceState);
    }
    
    //根据Android系统版本创建AppCompatDelegate对象
    private static AppCompatDelegate create(Context context, Window window, AppCompatCallback callback) {
        final int sdk = Build.VERSION.SDK_INT;
        if (BuildCompat.isAtLeastN()) {
            return new AppCompatDelegateImplN(context, window, callback);
        } else if (sdk >= 23) {
            return new AppCompatDelegateImplV23(context, window, callback);
        } else if (sdk >= 14) {
            return new AppCompatDelegateImplV14(context, window, callback);
        } else if (sdk >= 11) {
            return new AppCompatDelegateImplV11(context, window, callback);
        } else {
            return new AppCompatDelegateImplV9(context, window, callback);
        }
    }
    

    onCreate结束之后,在Activity中调用setContentView()方法后,AppCompatActivity中会执行ensureSubDecor()方法,这个方法具体做了ActionBar窗体的创建,并使ActionBar依附到屏幕的Window中去。

    public void setContentView(int resId) {
        ensureSubDecor();
        ViewGroup contentParent = (ViewGroup) mSubDecor.findViewById(android.R.id.content);
        contentParent.removeAllViews();
        LayoutInflater.from(mContext).inflate(resId, contentParent);
        mOriginalWindowCallback.onContentChanged();
    }
    
    private void ensureSubDecor() {
        if (!mSubDecorInstalled) {
            mSubDecor = createSubDecor();
            onSubDecorInstalled(mSubDecor);
            mSubDecorInstalled = true;
        }
    }
    
    private ViewGroup createSubDecor() {
        //加载Activity的主题
        TypedArray a = mContext.obtainStyledAttributes(R.styleable.AppCompatTheme);
        if (!a.hasValue(R.styleable.AppCompatTheme_windowActionBar)) {
            a.recycle();
            throw new IllegalStateException(
                    "You need to use a Theme.AppCompat theme (or descendant) with this activity.");
        }
        //读取windowNoTitle属性,判断是否需要ActionBar
        if (a.getBoolean(R.styleable.AppCompatTheme_windowNoTitle, false)) {
            requestWindowFeature(Window.FEATURE_NO_TITLE);
        } else if (a.getBoolean(R.styleable.AppCompatTheme_windowActionBar, false)) {
            // Don't allow an action bar if there is no title.
            requestWindowFeature(FEATURE_SUPPORT_ACTION_BAR);
        }
        //读取windowActionBarOverlay属性
        if (a.getBoolean(R.styleable.AppCompatTheme_windowActionBarOverlay, false)) {
            requestWindowFeature(FEATURE_SUPPORT_ACTION_BAR_OVERLAY);
        }
        //读取windowActionModeOverlay属性
        if (a.getBoolean(R.styleable.AppCompatTheme_windowActionModeOverlay, false)) {
            requestWindowFeature(FEATURE_ACTION_MODE_OVERLAY);
        }
        //读取android:windowIsFloating属性
        mIsFloating = a.getBoolean(R.styleable.AppCompatTheme_android_windowIsFloating, false);
        a.recycle();
    
        // Now let's make sure that the Window has installed its decor by retrieving it
        mWindow.getDecorView();
    
        final LayoutInflater inflater = LayoutInflater.from(mContext);
        ViewGroup subDecor = null;
        
        if (!mWindowNoTitle) {
            //当需要ActionBar时执行下面的逻辑
            if (mIsFloating) {
                //省略
            } else if (mHasActionBar) {
                //读取ActionBar主题
                TypedValue outValue = new TypedValue();
                mContext.getTheme().resolveAttribute(R.attr.actionBarTheme, outValue, true);
                //加载ActionBar窗体的布局文件R.layout.abc_screen_toolbar
                subDecor = (ViewGroup) LayoutInflater.from(themedContext).inflate(R.layout.abc_screen_toolbar, null);
                mDecorContentParent = (DecorContentParent) subDecor.findViewById(R.id.decor_content_parent);
                mDecorContentParent.setWindowCallback(getWindowCallback());
            }
        } else {
            //省略
        }
    
        //在该方法的最后会把ActionBar的窗体加载到屏幕的整个Window中去
        mWindow.setContentView(subDecor);
        return subDecor;
    }
    

    上面的代码我们看到映射了一个名为abc_screen_toolbar.xml的布局文件,在这个xml布局文件中引用了Toolbar,并且可以看到声明了属性style="?attr/toolbarStyle",那么是不是这个toolBarStyle就决定了ToolBar的样式呢?我们继续往下看。

    <android.support.v7.widget.ActionBarOverlayLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:app="http://schemas.android.com/apk/res-auto"
            android:id="@+id/decor_content_parent"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true">
    
        <include layout="@layout/abc_screen_content_include"/>
    
        <android.support.v7.widget.ActionBarContainer
                android:id="@+id/action_bar_container"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentTop="true"
                style="?attr/actionBarStyle"
                android:touchscreenBlocksFocus="true"
                android:gravity="top">
    
            <android.support.v7.widget.Toolbar
                    android:id="@+id/action_bar"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    app:navigationContentDescription="@string/abc_action_bar_up_description"
                    style="?attr/toolbarStyle"/>
    
            <android.support.v7.widget.ActionBarContextView
                    android:id="@+id/action_context_bar"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:visibility="gone"
                    android:theme="?attr/actionBarTheme"
                    style="?attr/actionModeStyle"/>
    
        </android.support.v7.widget.ActionBarContainer>
    </android.support.v7.widget.ActionBarOverlayLayout>
    

    接下来会执行Toolbar的构造函数,其中引用的style也是在xml布局文件里所声明的。

    public Toolbar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        final TintTypedArray a = TintTypedArray.obtainStyledAttributes(getContext(), attrs,R.styleable.Toolbar, defStyleAttr, 0);    
        //标题文字样式
        mTitleTextAppearance = a.getResourceId(R.styleable.Toolbar_titleTextAppearance, 0);
        mSubtitleTextAppearance = a.getResourceId(R.styleable.Toolbar_subtitleTextAppearance, 0);   
        //标题
        final CharSequence title = a.getText(R.styleable.Toolbar_title);
        if (!TextUtils.isEmpty(title)) {
            setTitle(title);
        } 
        //设置返回按钮的Icon
        final Drawable navIcon = a.getDrawable(R.styleable.Toolbar_navigationIcon);
        if (navIcon != null) {
            setNavigationIcon(navIcon);
        }
        //设置title文字颜色
        if (a.hasValue(R.styleable.Toolbar_titleTextColor)) {
            setTitleTextColor(a.getColor(R.styleable.Toolbar_titleTextColor, 0xffffffff));
        }
        //设置subtitle文字颜色
        if (a.hasValue(R.styleable.Toolbar_subtitleTextColor)) {
            setSubtitleTextColor(a.getColor(R.styleable.Toolbar_subtitleTextColor, 0xffffffff));
        }
    }
    

    Toolbar构造完成后绘制ActionBarOverlayLayout时,会调用ActionBarOverlayLayout中的pullChildren()与getDecorToolbar()两个方法,在为全局变量mDecorToolbar 赋值时会创建一个Toolbar的包装器ToolbarWidgetWrapper

    void pullChildren() {
        if (mContent == null) {
            mContent = (ContentFrameLayout) findViewById(R.id.action_bar_activity_content);
            mActionBarTop = (ActionBarContainer) findViewById(R.id.action_bar_container);
            mDecorToolbar = getDecorToolbar(findViewById(R.id.action_bar));
        }
    }
    
    private DecorToolbar getDecorToolbar(View view) {
           if (view instanceof Toolbar) {
            return ((Toolbar) view).getWrapper();
           } 
    }
    
    public DecorToolbar getWrapper() {
        if (mWrapper == null) {
            mWrapper = new ToolbarWidgetWrapper(this, true);
        }
        return mWrapper;
    }
    

    在Toolbar的包装器ToolbarWidgetWrapper中,会加载actionBarStyle这个style中的属性,如homeAsUpIndicator定义了回退键的图片,titleTextStyle定义了Title的样式。所以ActionBar的样式最后加载的style都是在这个ToolbarWidgetWrapper中完成的。

    public ToolbarWidgetWrapper(Toolbar toolbar, boolean style,int defaultNavigationContentDescription, int defaultNavigationIcon) {
        mToolbar = toolbar;
        mTitle = toolbar.getTitle();
        mSubtitle = toolbar.getSubtitle();
        mTitleSet = mTitle != null;
        mNavIcon = toolbar.getNavigationIcon();
        final TintTypedArray a = TintTypedArray.obtainStyledAttributes(toolbar.getContext(), null, R.styleable.ActionBar, R.attr.actionBarStyle, 0);
        mDefaultNavigationIcon = a.getDrawable(R.styleable.ActionBar_homeAsUpIndicator);
        if (style) {
            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 (icon != null) {
                setIcon(icon);
            }
            if (mNavIcon == null && mDefaultNavigationIcon != null) {
                setNavigationIcon(mDefaultNavigationIcon);
            }
            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);
            }
        } else {
            mDisplayOpts = detectDisplayOptions();
        }
        a.recycle();
    }
    

    最后在调用getSupportActionBar()时会进入initWindowDecorActionBar()方法。ActionBar是一个抽象类,WindowDecorActionBar则是ActionBar的具体实现。在init过程中看到了对elevation的设置。

    public void initWindowDecorActionBar() {
        ensureSubDecor();
        if (!mHasActionBar || mActionBar != null) {
            return;
        }
        if (mOriginalWindowCallback instanceof Activity) {
            mActionBar = new WindowDecorActionBar((Activity) mOriginalWindowCallback,
                    mOverlayActionBar);
        }   
    }
    
    public WindowDecorActionBar(Activity activity, boolean overlayMode) {
        mActivity = activity;
        Window window = activity.getWindow();
        View decor = window.getDecorView();
        init(decor);
        if (!overlayMode) {
            mContentView = decor.findViewById(android.R.id.content);
        }
    }
    
    private void init(View decor) {
        mOverlayLayout = (ActionBarOverlayLayout) decor.findViewById(R.id.decor_content_parent);
    
        mDecorToolbar = getDecorToolbar(decor.findViewById(R.id.action_bar));
        mContextView = (ActionBarContextView) decor.findViewById(R.id.action_context_bar);
        mContainerView = (ActionBarContainer) decor.findViewById(R.id.action_bar_container);
    
        mContext = mDecorToolbar.getContext();
        
        final int elevation = a.getDimensionPixelSize(R.styleable.ActionBar_elevation, 0);
        if (elevation != 0) {
            setElevation(elevation);
        }
        a.recycle();
    }
    
    public void setElevation(float elevation) {
        ViewCompat.setElevation(mContainerView, elevation);
    }
    

    如果ActionBar上有Menu时,会调用ToolbarWidgetWrapper中setMenu方法,执行ActionMenuPresenter的构造函数,ActionMenuPresenter构造函数中第二个参数是每个menu item的父布局,第三个参数就对应某个menu item的布局。Menu item的xml布局中引用了actionMenuTextAppearance actionMenuTextColor两个属性,所以知道了,menu item的字体和颜色是由这两个属性控制的。

    public void setMenu(Menu menu, MenuPresenter.Callback cb) {
        if (mActionMenuPresenter == null) {
            mActionMenuPresenter = new ActionMenuPresenter(mToolbar.getContext());
            mActionMenuPresenter.setId(R.id.action_menu_presenter);
        }
        mActionMenuPresenter.setCallback(cb);
        mToolbar.setMenu((MenuBuilder) menu, mActionMenuPresenter);
    }
    
    public ActionMenuPresenter(Context context) {
        super(context, R.layout.abc_action_menu_layout, R.layout.abc_action_menu_item_layout);
    }
    
    <android.support.v7.internal.view.menu.ActionMenuItemView
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:gravity="center"
        android:focusable="true"
        android:paddingTop="4dip"
        android:paddingBottom="4dip"
        android:paddingLeft="8dip"
        android:paddingRight="8dip"
        android:textAppearance="?attr/actionMenuTextAppearance"
        android:textColor="?attr/actionMenuTextColor"
        style="?attr/actionButtonStyle"/>
    

    为什么在style.xml中定义toolbar的style无效,只能在toolbar的布局文件中引用呢?是因为Toolbar读取的是layout布局文件中的style,并且在构造ToolbarWidgetWrapper对象时也并不会和ActionBar一样去读取actionbar的属性。因为在调用setSupportActionBar()后会构造一个ToolbarActionBar,ToolbarActionBar中又会构造一个ToolbarWidgetWrapper,而ToolbarWidgetWrapper的构造函数中第二个参数在源码中传入的是false,所以不会在ToolbarWidgetWrapper进行style的加载,只会在创建Toolbar时进行style的加载。

    public void setSupportActionBar(Toolbar toolbar) {
        if (toolbar != null) {
            final ToolbarActionBar tbab = new ToolbarActionBar(toolbar,((Activity) mOriginalWindowCallback).getTitle(), mAppCompatWindowCallback);
        }
        invalidateOptionsMenu();
    }
    
    public ToolbarActionBar(Toolbar toolbar, CharSequence title, Window.Callback callback) {
        mDecorToolbar = new ToolbarWidgetWrapper(toolbar, false);
    }
    
    public ToolbarWidgetWrapper(Toolbar toolbar, boolean style,int defaultNavigationContentDescription, int defaultNavigationIcon) {   
        if (style) {
            //不执行
            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);
            }
           ...
        } else {
            mDisplayOpts = detectDisplayOptions();
        }
        a.recycle();
    }
    

    最后:

    更详细的参考Demo在github中,如果有错误也希望大家能够指出,觉得能帮到你的话给个Star吧。

    相关文章

      网友评论

        本文标题:Toolbar中style的自定义及加载过程

        本文链接:https://www.haomeiwen.com/subject/pbhfottx.html