更多关于Toolbar的使用请移步Toolbar使用详解系列
从Toolbar的使用一步步解析Toolbar源码
大体架构
mToolbar.setNavigationIcon(R.drawable.ic_actionbar_flow);源码如下
public void setNavigationIcon(int resId) { this.setNavigationIcon(this.mTintManager.getDrawable(resId)); }
public void setNavigationIcon(@Nullable Drawable icon) { if(icon != null) { this.ensureNavButtonView(); if(this.mNavButtonView.getParent() == null) { this.addSystemView(this.mNavButtonView); this.updateChildVisibilityForExpandedActionView(this.mNavButtonView); } } else if(this.mNavButtonView != null && this.mNavButtonView.getParent() != null) { this.removeView(this.mNavButtonView); } if(this.mNavButtonView != null) { this.mNavButtonView.setImageDrawable(icon); } }
先判断传入图片参数是否为null
private void ensureNavButtonView() { if(this.mNavButtonView == null) { this.mNavButtonView = new ImageButton(this.getContext(), (AttributeSet)null, attr.toolbarNavigationButtonStyle); Toolbar.LayoutParams lp = this.generateDefaultLayoutParams(); lp.gravity = 8388611 | this.mButtonGravity & 112; this.mNavButtonView.setLayoutParams(lp); } }设置导航图标,通过LayoutParams.gravity
lp.gravity=8388611设置gravity=start即左边开始位置
在Toolbar构造函数内对gravity进行了初始化
this.mButtonGravity = 48;48:gravity = top
&112 = 得到gravity的纵向位置
综上,即设置导航坐标处于左上位置
关于gravity的详细说明
继续往下判断父窗体是否为null
private void addSystemView(View v) { android.view.ViewGroup.LayoutParams vlp = v.getLayoutParams(); Toolbar.LayoutParams lp; if(vlp == null) { lp = this.generateDefaultLayoutParams(); } else if(!this.checkLayoutParams(vlp)) { lp = this.generateLayoutParams(vlp); } else { lp = (Toolbar.LayoutParams)vlp; } lp.mViewType = 1; this.addView(v, lp); }因为Toolbar继承自ViewGroup,当导航图标的父窗体为null时,将图标添加到Toolbar上。
public void setNavigationOnClickListener(OnClickListener listener) { this.ensureNavButtonView(); this.mNavButtonView.setOnClickListener(listener); }ensureNavButtonView上面已作出说明
public void setTitle(CharSequence title) { if(!TextUtils.isEmpty(title)) {
<span style="white-space:pre"> </span>//title不为null if(this.mTitleTextView == null) {
<span style="white-space:pre"> </span>//如果主标题TextView不存在则新建 Context context = this.getContext(); this.mTitleTextView = new TextView(context); this.mTitleTextView.setSingleLine(); this.mTitleTextView.setEllipsize(TruncateAt.END); if(this.mTitleTextAppearance != 0) { this.mTitleTextView.setTextAppearance(context, this.mTitleTextAppearance); } if(this.mTitleTextColor != 0) {
<span style="white-space:pre"> </span>//设置字体颜色 this.mTitleTextView.setTextColor(this.mTitleTextColor); } } if(this.mTitleTextView.getParent() == null) {
<span style="white-space:pre"> </span>//若父窗体为null,则添加主标题TextView,同导航图标 this.addSystemView(this.mTitleTextView);
<span style="white-space:pre"> </span>//同样更新为可见状态 this.updateChildVisibilityForExpandedActionView(this.mTitleTextView); } } else if(this.mTitleTextView != null && this.mTitleTextView.getParent() != null) {
<span style="white-space:pre"> </span>//title为null则移除主标题的TextView this.removeView(this.mTitleTextView); } if(this.mTitleTextView != null) {
<span style="white-space:pre"> </span>//存在主标题TextView则设置文字 this.mTitleTextView.setText(title); }
<span style="white-space:pre"> </span>//设置当前文件 this.mTitleText = title;
public void inflateMenu(int resId) { this.getMenuInflater().inflate(resId, this.getMenu()); }最终调用的是SupportMenuInflater.inflate方法
public void inflate(int menuRes, Menu menu) { if(!(menu instanceof SupportMenu)) {
<span style="white-space:pre"> </span>//getMenu方法下面介绍,先记住getMenu返回的是SupportMenu的实现类 super.inflate(menuRes, menu); } else { XmlResourceParser parser = null; try { parser = this.mContext.getResources().getLayout(menuRes); AttributeSet e = Xml.asAttributeSet(parser);
<span style="white-space:pre"> </span>//分析menu.xml文件,往menu里添加menuItem this.parseMenu(parser, e, menu); } catch (XmlPullParserException var9) { throw new InflateException("Error inflating menu XML", var9); } catch (IOException var10) { throw new InflateException("Error inflating menu XML", var10); } finally { if(parser != null) { parser.close(); } } } }
public Menu getMenu() { this.ensureMenu(); return this.mMenuView.getMenu(); }
private void ensureMenu() { this.ensureMenuView(); if(this.mMenuView.peekMenu() == null) {
<span style="white-space:pre"> </span>//沉浸式菜单为空 MenuBuilder menu = (MenuBuilder)this.mMenuView.getMenu(); if(this.mExpandedMenuPresenter == null) {
<span style="white-space:pre"> </span>//创建沉浸式菜单的每一个菜单项 this.mExpandedMenuPresenter = new Toolbar.ExpandedActionViewMenuPresenter(null); } <span style="white-space:pre"> </span>//显示菜单 this.mMenuView.setExpandedActionViewsExclusive(true); menu.addMenuPresenter(this.mExpandedMenuPresenter, this.mPopupContext); } }
private void ensureMenuView() { if(this.mMenuView == null) { this.mMenuView = new ActionMenuView(this.getContext()); this.mMenuView.setPopupTheme(this.mPopupTheme); this.mMenuView.setOnMenuItemClickListener(this.mMenuViewItemClickListener); this.mMenuView.setMenuCallbacks(this.mActionMenuPresenterCallback, this.mMenuBuilderCallback); Toolbar.LayoutParams lp = this.generateDefaultLayoutParams(); lp.gravity = 8388613 | this.mButtonGravity & 112; this.mMenuView.setLayoutParams(lp); this.addSystemView(this.mMenuView); } }这里很重要,功能是新建这个Toolbar菜单栏。实现在ActionMenuView,ActionMenuView的实现不再本文的讨论范围,只要知道ActionMenuView继承LinearLayoutCompat。
private void parseMenu(XmlPullParser parser, AttributeSet attrs, Menu menu) throws XmlPullParserException, IOException { SupportMenuInflater.MenuState menuState = new SupportMenuInflater.MenuState(menu); int eventType = parser.getEventType(); boolean lookingForEndOfUnknownTag = false; String unknownTagName = null; String tagName;
<span style="white-space:pre"> </span>//找到<menu> do { if(eventType == 2) { tagName = parser.getName(); if(!tagName.equals("menu")) { throw new RuntimeException("Expecting menu, got " + tagName); } eventType = parser.next(); break; } eventType = parser.next(); } while(eventType != 1); <span style="white-space:pre"> </span>//开始遍历 for(boolean reachedEndOfMenu = false; !reachedEndOfMenu; eventType = parser.next()) { switch(eventType) { case 1: throw new RuntimeException("Unexpected end of document"); case 2: if(!lookingForEndOfUnknownTag) { tagName = parser.getName(); if(tagName.equals("group")) { menuState.readGroup(attrs); } else if(tagName.equals("item")) {</span>
<span style="white-space:pre"> </span>//添加菜单项 menuState.readItem(attrs); } else if(tagName.equals("menu")) { SubMenu subMenu = menuState.addSubMenuItem(); this.parseMenu(parser, attrs, subMenu); } else { lookingForEndOfUnknownTag = true; unknownTagName = tagName; } } break; case 3: tagName = parser.getName(); if(lookingForEndOfUnknownTag && tagName.equals(unknownTagName)) { lookingForEndOfUnknownTag = false; unknownTagName = null; } else if(tagName.equals("group")) { menuState.resetGroup(); } else if(tagName.equals("item")) { if(!menuState.hasAddedItem()) { if(menuState.itemActionProvider != null && menuState.itemActionProvider.hasSubMenu()) { menuState.addSubMenuItem(); } else { menuState.addItem(); } } } else if(tagName.equals("menu")) { reachedEndOfMenu = true; } } } }分析完毕后就把MenuItem显示到Menu上。
private final ActionMenuView.OnMenuItemClickListener mMenuViewItemClickListener = new ActionMenuView.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { if (mOnMenuItemClickListener != null) { return mOnMenuItemClickListener.onMenuItemClick(item); } return false; } };最后实现是在ActionMenuView中。
欢迎大家讨论,纯属抛砖引玉。
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/qq284565035/article/details/47107821