Fragment + TextView 实现底部导航栏

经过前几章节的学习,我们对 Fragment 已经有了很深的了解,本章开始,我们将利用一些范例来加深对 Fragment 的印象

我们将使用 Fragment 来实现一个底部导航栏

实现底部导航栏方法有很多,比如全用 TextView 做,或者用 RadioButton,又或者使用 TabLayout + RadioButton 但本章节使用 TextView 来实现

我们先来看看最后的效果图


  1. 创建一个 空的 Android 项目 cn.twle.android.FragmentTextView

  2. 下载解压 /static/i/android/fragment_tab_demo.zip,并把所有的图片拖到 res/drawable 目录下

  3. 从效果图上可以看到,底部的每一项点击的时候都有不同的效果,这些效果是通过判定是否 selected 来实现的,所以我们要对每一个 tab 创建 TextView 状态的资源文件

    res/drawable 目录下新建四个文件

    tab_menu_home.xml

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:drawable="@drawable/tab_home_pressed" android:state_selected="true" />
        <item android:drawable="@drawable/tab_home" />
    </selector>
    

    tab_menu_category.xml

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:drawable="@drawable/tab_category_pressed" android:state_selected="true" />
        <item android:drawable="@drawable/tab_category" />
    </selector>
    

    tab_menu_cart.xml

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:drawable="@drawable/tab_cart_pressed" android:state_selected="true" />
        <item android:drawable="@drawable/tab_cart" />
    </selector>
    

    tab_menu_discover.xml

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:drawable="@drawable/tab_discover_pressed" android:state_selected="true" />
        <item android:drawable="@drawable/tab_discover" />
    </selector>
    
  4. res/drawable 目录下新建文件 tab_menu_text.xml 创建文字资源

    因为文字也会根据是否选中而改变颜色

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:color="#1296db" android:state_selected="true" />
        <item android:color="#515151" />
    </selector>
    
  5. res/drawable 目录下新建文件 tab_menu_bg.xml 创建背景资源

    选中的 tab 背景会有点灰色

        <?xml version="1.0" encoding="utf-8"?>
        <selector xmlns:android="http://schemas.android.com/apk/res/android">
            <item android:state_selected="true">
                <shape>
                    <solid android:color="#ffdddddd" />
                </shape>
            </item>
            <item>
                <shape>
                    <solid android:color="#00FFFFFF" />
                </shape>
            </item>
        </selector>
    
  6. res/layout 目录下创建一个 Fragment 的简单布局 fg_content.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#ffffff">
    
        <TextView
            android:id="@+id/ms_txt_content"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:text="简单教程,简单编程"
            android:textColor="#333333"
            android:textSize="20sp"/>
    
    </LinearLayout>
    
  7. 资源方面我们已经准备的差不多了,现在开始添加布局

    仔细看效果图,我们可以把整个页面分成三大块

    1. 顶部的 title 栏
    2. 中间的具体页面
    3. 底部的 tabbar
  8. 修改 activity_main.xml 添加布局布局

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <RelativeLayout
            android:id="@+id/ms_topbar"
            android:layout_width="match_parent"
            android:layout_height="48dp"
            android:background="#FCFCFC">
    
            <TextView
                android:id="@+id/ms_topbar_title"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_centerInParent="true"
                android:gravity="center"
                android:textSize="18sp"
                android:textColor="#694E42"
                android:text="信息"/>
    
            <View
                android:layout_width="match_parent"
                android:layout_height="2px"
                android:background="#E5E5E5"
                android:layout_alignParentBottom="true"/>
    
        </RelativeLayout>
    
        <LinearLayout
            android:id="@+id/ms_tab_bar"
            android:layout_width="match_parent"
            android:layout_height="56dp"
            android:layout_alignParentBottom="true"
            android:background="#ffffff"
            android:orientation="horizontal">
    
            <TextView
                android:id="@+id/ms_tab_home"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="@drawable/tab_menu_bg"
                android:drawablePadding="3dp"
                android:drawableTop="@drawable/tab_menu_home"
                android:gravity="center"
                android:padding="5dp"
                android:text="首页"
                android:textColor="@drawable/tab_menu_text"
                android:textSize="16sp" />
    
            <TextView
                android:id="@+id/ms_tab_category"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="@drawable/tab_menu_bg"
                android:drawablePadding="3dp"
                android:drawableTop="@drawable/tab_menu_category"
                android:gravity="center"
                android:padding="5dp"
                android:text="分类"
                android:textColor="@drawable/tab_menu_text"
                android:textSize="16sp" />
    
            <TextView
                android:id="@+id/ms_tab_discover"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="@drawable/tab_menu_bg"
                android:drawablePadding="3dp"
                android:drawableTop="@drawable/tab_menu_discover"
                android:gravity="center"
                android:padding="5dp"
                android:text="发现"
                android:textColor="@drawable/tab_menu_text"
                android:textSize="16sp" />
    
            <TextView
                android:id="@+id/ms_tab_cart"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="@drawable/tab_menu_bg"
                android:drawablePadding="3dp"
                android:drawableTop="@drawable/tab_menu_cart"
                android:gravity="center"
                android:padding="5dp"
                android:text="购物车"
                android:textColor="@drawable/tab_menu_text"
                android:textSize="16sp"/>
    
        </LinearLayout>
    
        <View
            android:id="@+id/div_tab_bar"
            android:layout_width="match_parent"
            android:layout_height="2px"
            android:background="#E5E5E5"
            android:layout_above="@id/ms_tab_bar"/>
    
        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@id/ms_topbar"
            android:layout_above="@id/div_tab_bar"
            android:id="@+id/ms_content">
    
        </FrameLayout>
    
    </RelativeLayout>
    
    1. 首先定义顶部标题栏的样式,48dpLinearLayout 中间加上一个 TextView 作为标题

    2. 接着定义一个大小为 56dpLinerLayout 对齐底部,在这个里面加入四个 `TextView,比例 1:1:1:1 并且设置相关属性

    3. 接着在这个 LinearLayout 上加一条线段

    4. 最后以标题栏和底部导航栏为边界,写一个 FrameLayout,宽高 match_parent,用做 Fragment 的容器

  9. 隐藏顶部导航栏

    修改 MainActivity.java 继承自 Activity 而非 AppCompatActivity

    然后在 onCreate() 方法中的 super.onCreate(savedInstanceState); 之前加上下列代码

    requestWindowFeature(Window.FEATURE_NO_TITLE);
    

    最后在 AndroidManifest.xml 设置下 theme 属性

    android:theme="@style/Theme.AppCompat.NoActionBar"
    

    注意

    requestWindowFeature(Window.FEATURE_NO_TITLE); 放在 super.onCreate(savedInstanceState); 前面就可以隐藏 ActionBar 而不报错

  10. MainActivity.java 同一目录下新建文件 MsFragment.java

    package cn.twle.android.fragmenttextview;
    
    import android.annotation.SuppressLint;
    import android.app.Fragment;
    import android.os.Bundle;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.TextView;
    
    @SuppressLint("ValidFragment")
    public class MsFragment extends Fragment {
    
        private String content;
    
        public MsFragment(String content) {
            this.content = content;
        }
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            View view = inflater.inflate(R.layout.fg_content,container,false);
            TextView txt_content = (TextView) view.findViewById(R.id.ms_txt_content);
            txt_content.setText(content);
            return view;
        }
    }
    
  11. 继续修改 MainActivity.java

    继续修改代码之前,我们先问自己几个问题

    • Fragment 什么时候初始化和添加到容器中?什么时候 hide 和 show ?
    • 如何让 TextView 被选中?选中一个 TextView 后,要做一些什么操作?
    • 刚进入 MainActivity 怎么样让一个 TextView 处于 Selected 的状态 ?

    这都是好问题,我们一一来解答

    • 我们选中 TextView 后对对应的 Fragment 进行判空,如果为空,初始化,并添加到容器中

      而 hide 的话,我们定义一个方法 hide() 所有的 Fragment,每次触发点击事件就先调用这个 hideAll() 方法隐藏所有 Fragment,然后如果 TextView 对应的 Fragment 不为空,我们就将这个 Fragment 显示出来

    • 通过点击事件来实现,点击 TextView 后先重置所有 TextView 的选中状态为 false,然后设置点击的 TextView的选中状态为 true

    • 通过点击事件来设置选中的,那么在 onCreate() 方法里加个触发点击事件的 方法 txt_channel.performClick();

  12. 继续修改 MainActivity.java

    package cn.twle.android.fragmenttextview;
    
    import android.app.Activity;
    import android.app.FragmentManager;
    import android.app.FragmentTransaction;
    import android.os.Bundle;
    import android.view.View;
    import android.view.Window;
    import android.widget.FrameLayout;
    import android.widget.TextView;
    
    public class MainActivity extends Activity implements View.OnClickListener{
    
        //UI Object
        private TextView ms_topbar_title;
        private TextView ms_tab_home;
        private TextView ms_tab_category;
        private TextView ms_tab_discover;
        private TextView ms_tab_cart;
        private FrameLayout ms_content;
    
        //Fragment Object
        private MsFragment fg1,fg2,fg3,fg4;
        private FragmentManager fManager;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            requestWindowFeature(Window.FEATURE_NO_TITLE);
            setContentView(R.layout.activity_main);
            fManager = getFragmentManager();
            bindViews();
    
            ms_tab_home.performClick();   //模拟一次点击,既进去后选择第一项
        }
    
        //UI组件初始化与事件绑定
        private void bindViews() {
            ms_topbar_title = (TextView) findViewById(R.id.ms_topbar_title);
            ms_tab_home = (TextView) findViewById(R.id.ms_tab_home);
            ms_tab_category = (TextView) findViewById(R.id.ms_tab_category);
            ms_tab_discover = (TextView) findViewById(R.id.ms_tab_discover);
            ms_tab_cart = (TextView) findViewById(R.id.ms_tab_cart);
            ms_content = (FrameLayout) findViewById(R.id.ms_content);
    
            ms_tab_home.setOnClickListener(this);
            ms_tab_category.setOnClickListener(this);
            ms_tab_discover.setOnClickListener(this);
            ms_tab_cart.setOnClickListener(this);
        }
    
        //重置所有文本的选中状态
        private void setSelected(){
    
            ms_tab_home.setSelected(false);
            ms_tab_category.setSelected(false);
            ms_tab_discover.setSelected(false);
            ms_tab_cart.setSelected(false);
        }
    
        //隐藏所有 Fragment
        private void hideAllFragment(FragmentTransaction fragmentTransaction){
            if(fg1 != null) fragmentTransaction.hide(fg1);
            if(fg2 != null) fragmentTransaction.hide(fg2);
            if(fg3 != null) fragmentTransaction.hide(fg3);
            if(fg4 != null) fragmentTransaction.hide(fg4);
        }
    
        @Override
        public void onClick(View v) {
            FragmentTransaction fTransaction = fManager.beginTransaction();
            hideAllFragment(fTransaction);
            switch (v.getId()){
                case R.id.ms_tab_home:
                    setSelected();
                    ms_tab_home.setSelected(true);
                    if(fg1 == null){
                        fg1 = new MsFragment("第一个 Fragment");
                        fTransaction.add(R.id.ms_content,fg1);
                    }else{
                        fTransaction.show(fg1);
                    }
                    break;
                case R.id.ms_tab_category:
                    setSelected();
                    ms_tab_category.setSelected(true);
                    if(fg2 == null){
                        fg2 = new MsFragment("第二个 Fragment");
                        fTransaction.add(R.id.ms_content,fg2);
                    }else{
                        fTransaction.show(fg2);
                    }
                    break;
                case R.id.ms_tab_discover:
                    setSelected();
                    ms_tab_discover.setSelected(true);
                    if(fg3 == null){
                        fg3 = new MsFragment("第三个 Fragment");
                        fTransaction.add(R.id.ms_content,fg3);
                    }else{
                        fTransaction.show(fg3);
                    }
                    break;
                case R.id.ms_tab_cart:
                    setSelected();
                    ms_tab_cart.setSelected(true);
                    if(fg4 == null){
                        fg4 = new MsFragment("第四个 Fragment");
                        fTransaction.add(R.id.ms_content,fg4);
                    }else{
                        fTransaction.show(fg4);
                    }
                    break;
            }
    
            fTransaction.commit();
        }
    }
    

注意: FragmentTransaction 只能使用一次,每次使用都要调用 FragmentManagerbeginTransaction() 方法获得 FragmentTransaction 事务对象

Android 基础教程

关于   |   FAQ   |   我们的愿景   |   广告投放   |  博客

  简单教程,简单编程 - IT 入门首选站

Copyright © 2013-2022 简单教程 twle.cn All Rights Reserved.