Android开发Android知识Android技术知识

Android TextView实现底部导航栏

2017-07-14  本文已影响258人  Android开发666

前言

底部导航栏在App开发中是经常碰到的,国内的app大部分都有底部导航栏(QQ、微信、支付宝),我的手机一直都用的Android原生操作系统(从nexus系列到pxiel系列)。可以看出其实google推荐用侧滑菜单,google自带的app基本都使用侧滑菜单。但是我刚刚看的时候YouTube居然使用底部导航了。

分析需求

从效果图中我们可以看到底部有四个按钮,还有中间有个图片。

BottomNavigation

代码实现

先看布局文件activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <FrameLayout
        android:id="@+id/main_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/view_line"/>

    <View
        android:id="@+id/view_line"
        android:layout_height="1dp"
        android:layout_width="match_parent"
        android:background="#DCDBDB"
        android:layout_above="@+id/rl_bottom"/>
    
    <LinearLayout
        android:id="@+id/rl_bottom"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:paddingTop="5dp"
        android:paddingBottom="5dp"
        android:background="#F2F2F2"
        android:orientation="horizontal" >

        <TextView
            android:id="@+id/tv_main"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_weight="1"
            android:drawableTop="@drawable/tab_item_main_img_selector"
            android:drawablePadding="@dimen/main_tab_item_image_and_text"
            android:focusable="true"
            android:gravity="center"
            android:text="@string/main"
            android:textColor="@drawable/tabitem_txt_sel" />

        <TextView
            android:id="@+id/tv_dynamic"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_weight="1"
            android:drawableTop="@drawable/tab_item_dynamic_img_selector"
            android:drawablePadding="@dimen/main_tab_item_image_and_text"
            android:focusable="true"
            android:gravity="center"
            android:text="@string/dynamic"
            android:textColor="@drawable/tabitem_txt_sel" />

        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1" />

        <TextView
            android:id="@+id/tv_message"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_weight="1"
            android:drawableTop="@drawable/tab_item_message_img_selector"
            android:drawablePadding="@dimen/main_tab_item_image_and_text"
            android:focusable="true"
            android:gravity="center"
            android:text="@string/message"
            android:textColor="@drawable/tabitem_txt_sel" />

        <TextView
            android:id="@+id/tv_person"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_weight="1"
            android:drawableTop="@drawable/tab_item_person_img_selector"
            android:drawablePadding="@dimen/main_tab_item_image_and_text"
            android:focusable="true"
            android:gravity="center"
            android:text="@string/person"
            android:textColor="@drawable/tabitem_txt_sel"/>
    </LinearLayout>

    <ImageView
        android:id="@+id/iv_make"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:paddingBottom="10dp"
        android:src="@drawable/icon_tab_make_select"/>
</RelativeLayout>

最外层用用RelativeLayout。

我们看到给每个TextView设置了android:drawableTop属性,这个属性就是在TextView的文本上面放一张图片。我们看看首页的TextView的android:drawableTop属性对应的drawable文件。

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 选中状态显示 -->
    <item android:drawable="@drawable/icon_tab_main_select" android:state_selected="true"/>

    <!--非选中状态显示-->
    <item android:drawable="@drawable/icon_tab_main_normal"/>
</selector>

最外层是一个selector,里面有两个item(item可以有多个),我们看到第一个item是选中状态的情况,item有一个属性叫android:state_selected="true",就是View选中状态时显示android:drawable对应的图片。第二个item就是默认情况,就是非选中的情况显示。在java代码中TextView.setSelected(true)对应第一个item。

不只是图片,还有TextView设置文字颜色也是通过selector来控制的。我们可以看到底部的四个TextView的android:textColor属性都引用了drawable/tabitem_txt_sel文件。

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 选中状态 -->
    <item android:color="@color/main_tab_item_text_select" android:state_selected="true"/>

    <!--非选中状态-->
    <item android:color="@color/main_tab_item_text_normal"/>
</selector>

跟图片的选择器有点类似,只不过把android:drawable换成了android:color。

接下来看MainActivity代码,继承自FragmentActivity,这是android-support-v4.jar包里面的一个类,可以兼容3.0以下版本使用Fragment。

public class MainActivity extends FragmentActivity {
    //要切换显示的四个Fragment
    private HomeFragment homeFragment;
    private DynamicFragment dynamicFragment;
    private MessageFragment messageFragment;
    private PersonFragment personFragment;

    private int currentId = R.id.tv_main;// 当前选中id,默认是主页

    private TextView tvMain, tvDynamic, tvMessage, tvPerson;//底部四个TextView

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tvMain = (TextView) findViewById(R.id.tv_main);
        tvMain.setSelected(true);//首页默认选中
        tvDynamic = (TextView) findViewById(R.id.tv_dynamic);
        tvMessage = (TextView) findViewById(R.id.tv_message);
        tvPerson = (TextView) findViewById(R.id.tv_person);

        //默认加载首页
        homeFragment = new HomeFragment();
        getSupportFragmentManager().beginTransaction().add(R.id.main_container,homeFragment).commit();

        tvMain.setOnClickListener(tabClickListener);
        tvDynamic.setOnClickListener(tabClickListener);
        tvMessage.setOnClickListener(tabClickListener);
        tvPerson.setOnClickListener(tabClickListener);
        findViewById(R.id.iv_make).setOnClickListener(onClickListener);
    }
    
    private OnClickListener onClickListener=new OnClickListener() {
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
            case R.id.iv_make:
                Toast.makeText(MainActivity.this,"点击了制作按钮",Toast.LENGTH_SHORT).show();
                break;
            }
        }
    };

    private OnClickListener tabClickListener = new OnClickListener() {
        @Override
        public void onClick(View v) {
            if (v.getId() != currentId) {//如果当前选中跟上次选中的一样,不需要处理
                changeSelect(v.getId());//改变图标跟文字颜色的选中 
                changeFragment(v.getId());//fragment的切换
                currentId = v.getId();//设置选中id
            }
        }
    };

    /**
     * 改变fragment的显示
     * @param resId
     */
    private void changeFragment(int resId) {
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();//开启一个Fragment事务
        
        hideFragments(transaction);//隐藏所有fragment
        if(resId==R.id.tv_main){//主页
            if(homeFragment==null){//如果为空先添加进来.不为空直接显示
                homeFragment = new HomeFragment();
                transaction.add(R.id.main_container,homeFragment);
            }else {
                transaction.show(homeFragment);
            }
        }else if(resId==R.id.tv_dynamic){//动态
            if(dynamicFragment==null){
                dynamicFragment = new DynamicFragment();
                transaction.add(R.id.main_container,dynamicFragment);
            }else {
                transaction.show(dynamicFragment);
            }
        }else if(resId==R.id.tv_message){//消息中心
            if(messageFragment==null){
                messageFragment = new MessageFragment();
                transaction.add(R.id.main_container,messageFragment);
            }else {
                transaction.show(messageFragment);
            }
        }else if(resId==R.id.tv_person){//我
            if(personFragment==null){
                personFragment = new PersonFragment();
                transaction.add(R.id.main_container,personFragment);
            }else {
                transaction.show(personFragment);
            }
        }
        transaction.commit();//一定要记得提交事务
    }
    
    /**
     * 显示之前隐藏所有fragment
     * @param transaction
     */
    private void hideFragments(FragmentTransaction transaction){
        if (homeFragment != null)//不为空才隐藏,如果不判断第一次会有空指针异常
            transaction.hide(homeFragment);
        if (dynamicFragment != null)
            transaction.hide(dynamicFragment);
        if (messageFragment != null)
            transaction.hide(messageFragment);
        if (personFragment != null)
            transaction.hide(personFragment);
    }

    /**
     * 改变TextView选中颜色
     * @param resId
     */
    private void changeSelect(int resId){
        tvMain.setSelected(false);
        tvDynamic.setSelected(false);
        tvMessage.setSelected(false);
        tvPerson.setSelected(false);

        switch (resId) {
        case R.id.tv_main:
            tvMain.setSelected(true);
            break;
        case R.id.tv_dynamic:
            tvDynamic.setSelected(true);
            break;
        case R.id.tv_message:
            tvMessage.setSelected(true);
            break;
        case R.id.tv_person:
            tvPerson.setSelected(true);
            break;
        }
    }
}

在onCreate方法中设置布局文件,查找底部的四个TextView,给首页的TextView设置为选中状态,并且默认加载首页的Fragment,最后给底部的四个Tab设置点击事件。还有最中间的那个ImageView。

tabClickListener处理Tab点击事件,先判断这次点击的Tab跟上次点击的是否一致,如果跟当前的是一样的那就不需要处理。否则的话需要改变图标跟文字选中状态。还有Fragment的切换。并且把当前点击的View的id设置成当前选中的id。

changeSelect方法改变TextView选中颜色,首先全部设置成未选中,然后再来判断当前选中的那个。

changeFragment改变Fragment的显示,首先调用hideFragments方法隐藏所有的Fragment,然后根据当前选中的Tab来决定显示那个Fragment。显示的时候需要先判断这个Fragment有没有显示过,如果没有现实过需要new一个新的Fragment,然后调用FragmentTransaction的add方法添加进去。如果之前有添加过的,直接调用show方法就行。

hideFragments方法就是隐藏所有的Fragment。先判断Fragment是否为null,不为null,就调用transaction.hide方法隐藏Fragment。

底部的四个Tab(TextView)对应四个Fragment。分别是HomeFragment、DynamicFragment、MessageFragment、PersonFragment。因为是Demo所以都只显示了一个TextView。我们看看首页的Fragment。其他三个就不贴代码了。

HomeFragment显示的布局文件fragment_home.xml,里面就一个TextView

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="这是首页"
        android:textSize="20sp"/>
</RelativeLayout>

HomeFragment.java

public class HomeFragment extends Fragment{
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_home, null);
        return rootView;
    }
}

源码下载

源码下载

      Android开发666 - 安卓开发技术分享
             扫描二维码加关注
Android开发666
上一篇下一篇

猜你喜欢

热点阅读