更多关于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)) {
//title不为null
if(this.mTitleTextView == null) {
//如果主标题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) {
//设置字体颜色
this.mTitleTextView.setTextColor(this.mTitleTextColor);
}
}
if(this.mTitleTextView.getParent() == null) {
//若父窗体为null,则添加主标题TextView,同导航图标
this.addSystemView(this.mTitleTextView);
//同样更新为可见状态
this.updateChildVisibilityForExpandedActionView(this.mTitleTextView);
}
} else if(this.mTitleTextView != null && this.mTitleTextView.getParent() != null) {
//title为null则移除主标题的TextView
this.removeView(this.mTitleTextView);
}
if(this.mTitleTextView != null) {
//存在主标题TextView则设置文字
this.mTitleTextView.setText(title);
}
//设置当前文件
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)) {
//getMenu方法下面介绍,先记住getMenu返回的是SupportMenu的实现类
super.inflate(menuRes, menu);
} else {
XmlResourceParser parser = null;
try {
parser = this.mContext.getResources().getLayout(menuRes);
AttributeSet e = Xml.asAttributeSet(parser);
//分析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) {
//沉浸式菜单为空
MenuBuilder menu = (MenuBuilder)this.mMenuView.getMenu();
if(this.mExpandedMenuPresenter == null) {
//创建沉浸式菜单的每一个菜单项
this.mExpandedMenuPresenter = new Toolbar.ExpandedActionViewMenuPresenter(null);
}
//显示菜单
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;
//找到
//添加菜单项
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中。
欢迎大家讨论,纯属抛砖引玉。