BottomNavigation的重新设计
今天写完了上周说要适用在印尼钱包中的「改进的」底部导航条SDK。
不仅是内部实现变得简洁高效,使用方法也有改进。
特性
有:
- 从以前的只支持2~5个tab到现在支持任意个数tab了
- 对于5.0以上机型适配
ripple effect
特效,点击放大/缩小的数值严格按照MD的规范 - 可以设置title文字大小和颜色
今天偶然听到刘炎说,「实现麻烦可以,用起来简单就行」,觉得很有道理,可以作为sdk的准则,当然,实现的「麻烦」不能是运行时时间/空间复杂度高的那种重复性劳动的麻烦。
有两个麻烦的细节需要注意:
-
View的构造函数
它的三个构造函数分别是在使用**new**创建实例的时候
/在xml中使用的时候
/在xml中使用并且有自定义Attr的时候
被用到。所以,如果只是在xml中用到,那么会发现只有第二个构造函数里的initView()
会执行!
//继承LinearLayout后覆写的方法
public BottomNav(Context context) {
super(context);
initView();
}
public BottomNav(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
public BottomNav(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
另外,我们发现父类的三个构造函数会一个个嵌套,最终调用的是参数最多的那个构造函数。
-
是否真的需要inflate
initView()中我写的是LayoutInflater
inflate操作,inflate有多种方式。
需要理解inflate的参数:
public View inflate(int resource, ViewGroup root)
public View inflate(int resource, ViewGroup root, boolean attachToRoot)
public View inflate(XmlPullParser parser, ViewGroup root)
public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot)
resource是布局资源id没问题,root是填充的根视图(指定的父view),attachToRoot代表 是否将载入的视图绑定到根视图中。
当我们给view传进来的root不是null,并且第三个参数是false
的时候,这个view就被加入到了root中,并且把root当作最终的返回值返回了。而当我们设置root为空的时候,没有设置LayoutParams参数的temp对象,作为返回值返回了。
举个例子,比如对于listView/recyclerView的单个item的布局,若才去这种方式填充视图,item布局中的根视图的layout_width之类的属性会被忽略掉,被设置成默认的包裹内容方式:
convertView = inflater.inflate(R.layout.item_list,null);
它的布局:
<!--?xml version="1.0" encoding="utf-8"?-->
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="60dp" android:background="@android:color/holo_orange_light" android:gravity="center" android:orientation="vertical">
<textview android:id="@+id/tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="11" android:textcolor="@android:color/black" android:textsize="22sp">
</textview></linearlayout>
所以,对于我现在用的把tab单独加入到线性布局的addView的方法,不需要设置parent view,因为我们addView进的view已经是最外层view了。
这个底部导航条的具体实现我不提了,可以到我的github上看,还是比较巧妙的,关键代码:
/**
* set up the selected and unselected tab's style
*
* @param tag tagName of the tab
*/
public void setCurrentSelectedTabByTag(String tag) {
for (ViewHolder holder : mViewHolderList) {
//traverse
if (tag.equals(holder.bottomNavItem.mTabTag)) {
holder.tabIcon.setImageResource(holder.bottomNavItem.mDrawableSelected);
holder.tabTitle.setTextColor(mSelectedTabTextColor);
mOnTabSelectedListener.onTabSelected(holder.bottomNavItem.mText);
holder.tabLinearLayout.setPadding(dp12, dp6, dp12, dp10);
holder.tabTitle.setTextSize(14);
} else {
holder.tabIcon.setImageResource(holder.bottomNavItem.mDrawableUnselected);
holder.tabTitle.setTextColor(mDefaultTabTextColor);
holder.tabLinearLayout.setPadding(dp12, dp8, dp12, dp10);
holder.tabTitle.setTextSize(12);
}
}
}
-Jan 4th