雖然已經(jīng)有了官方的BottomNavigationView币砂,但感覺用不慣,以我對其淺薄的了解(僅僅是在demo中用了下,沒為深入源碼),覺得BottomNavigationView不夠靈活卡骂,主要有一下幾個原因:
- 不能添加自己寫的view作為BottomNavigationView 的item,因為是時候有這樣的UI(簡書這種還是很常見的)
BottomNavigationView 的item不能超過五個,三個以上會有夸張的動畫(動畫可以用反射關(guān)閉形入,之前看過偿警,簡書上就有)
好像不能顯示消息數(shù)量角標
用法:
布局:
<com.nevermore.oceans.widget.BottomTabLayout
android:id="@+id/btl"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize">
<com.nevermore.oceans.widget.BottomTabView
android:layout_width="0dp"
app:tabText="首頁"
app:tabIconNormal="@mipmap/ic_launcher_round"
app:tabIconSelected="@mipmap/ic_launcher"
app:tabTextColorNormal="#999999"
app:tabTextColorSelected="#2c8bef"
android:layout_weight="1"
android:layout_height="match_parent"/>
<com.nevermore.oceans.widget.BottomTabView
android:layout_width="0dp"
android:layout_weight="1"
app:tabIconNormal="@mipmap/ic_launcher_round"
app:tabIconSelected="@mipmap/ic_launcher"
app:tabTextColorNormal="#999999"
app:tabTextColorSelected="#2c8bef"
app:tabText="購物車"
android:layout_height="match_parent"/>
<com.nevermore.oceans.widget.BottomTabView
app:tabText="我的"
android:layout_width="0dp"
app:tabIconNormal="@mipmap/ic_launcher_round"
app:tabIconSelected="@mipmap/ic_launcher"
app:tabTextColorNormal="#999999"
app:tabTextColorSelected="#2c8bef"
android:layout_weight="1"
android:layout_height="match_parent"/>
</com.nevermore.oceans.widget.BottomTabLayout>
代碼1:
public class MainActivity extends AppCompatActivity {
private TextView tv;
private BottomTabLayout btl;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btl = (BottomTabLayout) findViewById(R.id.btl);
tv = (TextView) findViewById(R.id.tv);
//底部每個標簽的點擊事件
btl.setOnItemTabClickListener(new BottomTabLayout.OnItemTabClickListener() {
@Override
public void onItemTabClick(int position, View itemView) {
if(itemView instanceof BottomTabView){
String tabText = ((BottomTabView) itemView).getTabText();
tv.setText(tabText);
}
//設(shè)為被選中
btl.selectItem(itemView);
}
});
//默認選中第一個tab
btl.selectItem(0);
}
}
BottomTabView:
/**
*
* author XuNeverMore
* create on 2017/5/16 0016
* github https://github.com/XuNeverMore
*/
public class BottomTabView extends FrameLayout {
private static final String TAG = "BottomTabView";
private Drawable drawableN;
private Drawable drawableS;
private ImageView tabIcon;
private TextView tabText;
private String text;
private TextView tvCount;
private int textColorNoraml = 0xff000000;
private int textColorSelected = 0xff4caf65;
public BottomTabView(@NonNull Context context) {
this(context, null);
}
public BottomTabView(@NonNull Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public BottomTabView(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
super(context, attrs, defStyleAttr);
//統(tǒng)一定制每個tab的布局,以便修改
LayoutInflater.from(context).inflate(R.layout.item_bottom, this, true);
//圖標
tabIcon = (ImageView) findViewById(R.id.tab_icon);
//文字
tabText = (TextView) findViewById(R.id.tab_text);
//顯示消息數(shù)
tvCount = (TextView) findViewById(R.id.tv_count);
//自定義一些屬性
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.BottomTabView);
drawableN = typedArray.getDrawable(R.styleable.BottomTabView_tabIconNormal);//正常狀態(tài)圖標
drawableS = typedArray.getDrawable(R.styleable.BottomTabView_tabIconSelected);//選中狀態(tài)圖標
textColorNoraml = typedArray.getColor(R.styleable.BottomTabView_tabTextColorNormal, textColorNoraml);//正常文字顏色
textColorSelected = typedArray.getColor(R.styleable.BottomTabView_tabTextColorSelected, textColorSelected);//選中狀態(tài)文字顏色
text = typedArray.getString(R.styleable.BottomTabView_tabText);
//默認都顯示未選中狀態(tài)的圖標
if (drawableN != null) {
tabIcon.setImageDrawable(drawableN);
}
if (!TextUtils.isEmpty(text)) {
tabText.setText(text);
tabText.setTextColor(textColorNoraml);
}
typedArray.recycle();
}
/**
* 切換 tab 選中狀態(tài)
* @param select
*/
public void setSelectState(boolean select){
setSelected(select);
tabIcon.setImageDrawable(select?drawableS:drawableN);
tabText.setTextColor(select?textColorSelected:textColorNoraml);
}
/**
* 獲取 tab 上的文字
* @return
*/
public String getTabText(){
return tabText.getText().toString().trim();
}
public void setTabText(String text){
tabText.setText(text);
}
/**
* 設(shè)置未讀消息數(shù)量
* @param count
*/
public void setCount(int count){
tvCount.setVisibility(count>0?VISIBLE:GONE);
tvCount.setText(""+count);
}
}
BottomTabView 就是封裝了一個布局:
R.layout.item_bottom
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/tab_icon"
android:scaleType="center"
android:layout_marginTop="8dp"
android:layout_centerHorizontal="true"
android:duplicateParentState="true"
android:layout_width="24dp"
android:layout_height="24dp" />
<TextView
android:id="@+id/tab_text"
android:layout_alignParentBottom="true"
android:layout_marginBottom="5dp"
android:text="folder"
android:layout_centerHorizontal="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:visibility="gone"
android:id="@+id/tv_count"
android:layout_toRightOf="@+id/tab_icon"
android:text="5"
android:layout_marginTop="2dp"
android:layout_marginLeft="-12dp"
android:textColor="#ffffff"
android:background="@drawable/rect_round_red"
android:textSize="12sp"
android:gravity="center"
android:paddingLeft="6dp"
android:paddingTop="1dp"
android:paddingBottom="1dp"
android:paddingRight="6dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</RelativeLayout>
這個item 布局可以根據(jù)需求自己修改唯笙,消息數(shù)量默認是gone,可以通過以下方法顯示:
public void setCount(int count){
tvCount.setVisibility(count>0?VISIBLE:GONE);
tvCount.setText(""+count);
}
幾個自定義屬性:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="BottomTabView">
<attr name="tabIconNormal" format="reference"/>
<attr name="tabIconSelected" format="reference"/>
<attr name="tabTextColorNormal" format="color"/>
<attr name="tabTextColorSelected" format="color"/>
<attr name="tabText" format="string"/>
</declare-styleable>
</resources>
BottomTabLayout :
繼承LinearLayout,用來管理每個tab的點擊盒使、選中崩掘,當然tab并不一定是BottomTabView類型的,
可以是自己寫的View
/**
*
* author XuNeverMore
* create on 2017/5/16 0016
* github https://github.com/XuNeverMore
*/
public class BottomTabLayout extends LinearLayout {
public BottomTabLayout(Context context) {
this(context, null);
}
public BottomTabLayout(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public BottomTabLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setOrientation(HORIZONTAL);//水平方向
}
private static final String TAG = "BottomTabLayout";
private View lastSelectedItemView;//上一個被選中的item
/**
* 每個tab 點擊事件 類似ListView的OnItemClickListener
*/
public interface OnItemTabClickListener {
void onItemTabClick(int position, View itemView);
}
private OnItemTabClickListener onItemTabClickListener;
public void setOnItemTabClickListener(OnItemTabClickListener onItemTabClickListener) {
this.onItemTabClickListener = onItemTabClickListener;
setListeners();
}
/**
* 為每個tab 設(shè)置點擊事件
*/
private void setListeners() {
int childCount = getChildCount();
Log.i(TAG, "setListeners: "+childCount);
//為BottmoTabLayout 的每個childView設(shè)置點擊事件
for (int i = 0; i < childCount; i++) {
final int position = i;
final View child = getChildAt(i);
child.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (onItemTabClickListener != null) {
//防止選中的tab被重復點擊
if(lastSelectedItemView!=null&&lastSelectedItemView==v){
return;
}
onItemTabClickListener.onItemTabClick(position, v);
}
}
});
}
}
//選中一個tab 并改變其狀態(tài)
public void selectItem(View itemView){
//讓上一個被選中的tab恢復原來狀態(tài)
if(lastSelectedItemView!=null){
changeItemSelectState(lastSelectedItemView,false);
}
//選中itemView
changeItemSelectState(itemView,true);
//保存itemView 下次切換修改
lastSelectedItemView = itemView;
}
public void selectItem(int position){
if(position<getChildCount()){
View childAt = getChildAt(position);
selectItem(childAt);
}
}
//改變tab 選中狀態(tài)
private void changeItemSelectState(View view,boolean selected){
if(view instanceof BottomTabView){//如果是tab 是BottomTabView類型的單獨設(shè)置
((BottomTabView) view).setSelectState(selected);
}else {
view.setSelected(selected);
}
}
}
主要用法就是代碼1
//底部每個標簽的點擊事件
btl.setOnItemTabClickListener(new BottomTabLayout.OnItemTabClickListener() {
@Override
public void onItemTabClick(int position, View itemView) {
if(itemView instanceof BottomTabView){
String tabText = ((BottomTabView) itemView).getTabText();
tv.setText(tabText);
}
//設(shè)為被選中
btl.selectItem(itemView);
}
});
因為現(xiàn)在做的項目少办,要判斷登錄狀態(tài)苞慢,在未登錄狀態(tài)下,點擊要調(diào)到登錄頁面英妓,所以沒有象TabLayout那樣寫一個setUpWithViewPager(viewpager);方法挽放,直接在OnItemTabClickListener里切換就可以了,這樣更靈活點蔓纠。
雖然更靈活了辑畦,但是要多寫一句btl.selectItem(itemView); 將你點擊的tab設(shè)為選中狀態(tài)
第一次完全用Markdown寫東西,瞬間覺得學了一門語言腿倚。