现在不少Android APP应用底部都会有一个底部导航栏。做法很简单,之前做法是 RadioGroup+RadioButton实现这一效果。但是这种做法必须要给每一个RadioButton设置一个id值,做出的效果也很棒。可是当某一天项目需求发生了改变,导航栏由起始的四个变成了五个。是不是又要在RadioGroup中嵌套一个RadioButton,设置id,然后。。。 

在Java中强调的一点是低耦合,高内聚。在Android中也不例外。所以我感觉有必要写出一个通用的底部导航。在不通过id的状态下一样可以快速实现需求。首先  xml布局  activity_main

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.ouxun.demo.basetabdemo.MainActivity">
<FrameLayout
        android:id="@+id/main_flvessel"
        android:layout_weight="1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
<!--底部导航栏-->
    <LinearLayout
        android:id="@+id/main_tab_llvessel"
        android:background="@color/colorGray"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:orientation="horizontal">
        <LinearLayout
            android:orientation="vertical"
            android:gravity="center"
            android:layout_weight="1"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <ImageView
                android:layout_width="30dp"
                android:layout_height="30dp"
                android:background="@drawable/home_selector"/>
            <TextView
                android:layout_marginBottom="3dp"
                android:layout_marginTop="2dp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="首页"
                android:textColor="@color/color_main_tab"/>
        </LinearLayout>
        <LinearLayout
            android:orientation="vertical"
            android:gravity="center"
            android:layout_weight="1"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <ImageView
                android:layout_width="30dp"
                android:layout_height="30dp"
                android:background="@drawable/home3_selector"/>
            <TextView
                android:layout_marginBottom="3dp"
                android:layout_marginTop="2dp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="商城"
                android:textColor="@color/color_main_tab"/>
        </LinearLayout>
        <LinearLayout
            android:orientation="vertical"
            android:gravity="center"
            android:layout_weight="1"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <ImageView
                android:layout_width="30dp"
                android:layout_height="30dp"
                android:background="@drawable/home2_selector"/>
            <TextView
                android:layout_marginBottom="3dp"
                android:layout_marginTop="2dp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="圈子"
                android:textColor="@color/color_main_tab"/>
        </LinearLayout>
        <LinearLayout
            android:orientation="vertical"
            android:gravity="center"
            android:layout_weight="1"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <ImageView
                android:layout_width="30dp"
                android:layout_height="30dp"
                android:background="@drawable/home4_selector"/>
            <TextView
                android:layout_marginBottom="3dp"
                android:layout_marginTop="2dp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="个人"
                android:textColor="@color/color_main_tab"
                />
        </LinearLayout>
    </LinearLayout>

</LinearLayout>

activity 代码

private void initView() {
        // 初始化 底部父控件LinearLayout
        tabBottomParent_ll = (LinearLayout) findViewById(R.id.main_tab_llvessel);
    }


该方法在onCreate方法中调用, 其实就是初始化导航栏 LinearLayout父控件。导航栏肯定是要执行点击事件的,所以下步执行监听


private void initLinener() {
        /*监听底部控件被点击事件,但是整体是被LinearLayout父控件所包裹,
            1.获取该父控件所有的子控件的个数
            2·遍历父控件,获取子控件,监听子控件点击事件
        **/
        int childCount = tabBottomParent_ll.getChildCount();
        for (int i = 0; i <childCount ; i++) {
            LinearLayout tabSonControl_ll = (LinearLayout) tabBottomParent_ll.getChildAt(i);
            tabSonControl_ll.setOnClickListener(onClicklistener);
        }
    }


这个方法也是在onCreate方法中调用的,写到这里我们已经拿到每一个父控件 LinearLayout中的子孩子 tabSonControl_ll当然这个东西也是LinearLayout。

/**
     * 监听取出子控件被点击事件。根据点击对应的view取出被点击的角标,判断是否要更改状态
     * */
    private View.OnClickListener onClicklistener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            int sonItem = tabBottomParent_ll.indexOfChild(v);
            changUi(sonItem);
        }
    };


我们之所以要取出这个item是因为我们要判断点击的是不是当前这个item,从而改变控件状态

即:点击自身的时候,为不可用状态 enable = false。

反之 enable = true;

·

private void changUi(int item) {
        int childCount = tabBottomParent_ll.getChildCount();
        for (int i = 0; i <childCount ; i++) {
            if (item == i) {                //当前被点击的view 为不可用状态
                tabBottomParent_ll.getChildAt(i).setEnabled(false);
                setEnable(tabBottomParent_ll.getChildAt(i),false);
            }else {
                tabBottomParent_ll.getChildAt(i).setEnabled(true);
                setEnable(tabBottomParent_ll.getChildAt(i),true);
            }
        }
        
    }
现在我们回想一下我们一开始写的布局整个导航栏是被LinearLayout所包裹的,直接子孩子还是一个LinearLayout,我们之前的操作都是针对于这个LinearLayout的,所以我们通过setEnable方法去同步这组控件的状态
/**
     * 因为这个子孩子是一个 LinearLayout,可以会包裹其他的控件,所以这个控件整体要同步其状态,递归
     * 判断孙子是否是ViewGroup,
     * */
    private void setEnable(View childAt, boolean b) {
        childAt.setEnabled(b);                  // 改变状态
        if(childAt instanceof ViewGroup) {
            int grandSonCount = ((ViewGroup) childAt).getChildCount();
            for (int i = 0; i <grandSonCount ; i++) {
                setEnable(((ViewGroup) childAt).getChildAt(i),b);
            }
        } 
    }
好了 一步步写下来,通用的导航栏就写好了  是不是棒棒哒。