Android使用(TabLayout+ViewPager+fragment)與(FragmentTabHost+ViewPager+Fragment)實現底部狀態列切換

龍旋發表於2018-09-26

Android開發過程中,特別是新開的專案,底部狀態列的切換使用的頻率非常的高,主要的實現方式有:
(1)、TabLayout + Fragment
(2)、FragmentTabHost + Fragment
(3)、BottomNavigationView + Fragment
(4)、RidioGroup + Fragment

這裡我先介紹前面兩種實現方式,後面兩種後期再貼出實現方式。

一、使用TabLayout + Fragment + ViewPager實現

1、實現步驟:
(1)、佈局檔案中定義TabLayout控制元件
(2)、定義切換的每個Fragment佈局檔案
(3)、定義切換的每個Fragment的Java類
(4)、定義TabLayoutMainActivity類
(5)、效果圖演示

2、實現過程:

(1)、佈局檔案中定義TabLayout控制元件(activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.showly.bottomnavigationbardemo.TabLayoutMainActivity">

    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager_content_view"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:scrollbars="none" />

    <android.support.design.widget.TabLayout
        android:id="@+id/tab_layout_view"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        app:tabGravity="fill"
        app:tabIndicatorHeight="0dp"
        app:tabMode="fixed"
        app:tabSelectedTextColor="#FB8081"
        app:tabTextColor="#A0A0A0" />

</LinearLayout>

(2)、定義切換的每個Fragment佈局檔案(fragment_frist.xml)

這裡有四個Tab類別(首頁、娛樂、遊戲、我的),佈局都類似,這裡只貼出其中一個

<?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"
    android:background="#fff"
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="首頁"
        android:textColor="#000"/>
</RelativeLayout>

(3)、定義切換的每個Fragment的Java類(FristFragment.class)

這裡的Java 類實現方式也相似,貼出其中一個

package com.showly.bottomnavigationbardemo.fragment;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.showly.bottomnavigationbardemo.R;

public class FristFragment extends Fragment {

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment_frist, null);
        return view;
    }
}

(4)、定義TabLayoutMainActivity類(TabLayoutMainActivity.class)

package com.showly.bottomnavigationbardemo;


import android.os.Bundle;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;

import com.showly.bottomnavigationbardemo.fragment.FourthlyFragment;
import com.showly.bottomnavigationbardemo.fragment.FristFragment;
import com.showly.bottomnavigationbardemo.fragment.SecondFragment;
import com.showly.bottomnavigationbardemo.fragment.ThirtlyFragment;

public class TabLayoutMainActivity extends AppCompatActivity {

    //未選中的Tab圖片
    private int[] unSelectTabRes = new int[]{R.drawable.i8live_menu_home_normal
            , R.drawable.i8live_menu_information_normal, R.drawable.i8live_menu_game_normal, R.drawable.i8live_menu_personl_normal};
    //選中的Tab圖片
    private int[] selectTabRes = new int[]{R.drawable.i8live_menu_home_press, R.drawable.i8live_menu_information_press
            , R.drawable.i8live_menu_game_press, R.drawable.i8live_menu_personl_press};
    //Tab標題
    private String[] title = new String[]{"首頁", "娛樂", "遊戲", "我的"};
    private ViewPager viewPager;
    private TabLayout tabLayout;
    private TabLayout.Tab tabAtOne;
    private TabLayout.Tab tabAttwo;
    private TabLayout.Tab tabAtthree;
    private TabLayout.Tab tabAtfour;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getSupportActionBar().hide();//隱藏掉整個ActionBar
        setContentView(R.layout.activity_main);

        initView();
        initData();
        initListener();
    }

    private void initView() {
        viewPager = (ViewPager) findViewById(R.id.viewpager_content_view);
        tabLayout = (TabLayout) findViewById(R.id.tab_layout_view);

        //使用介面卡將ViewPager與Fragment繫結在一起
        viewPager.setAdapter(new MyFragmentPagerAdapter(getSupportFragmentManager()));
        //將TabLayout與ViewPager繫結
        tabLayout.setupWithViewPager(viewPager);

      /*  //設定方式一:
        //獲取底部的單個Tab
        tabAtOne = tabLayout.getTabAt(0);
        tabAttwo = tabLayout.getTabAt(1);
        tabAtthree = tabLayout.getTabAt(2);
        tabAtfour = tabLayout.getTabAt(3);

        //設定Tab圖片
        tabAtOne.setIcon(R.drawable.i8live_menu_home_press);
        tabAttwo.setIcon(R.drawable.i8live_menu_information_normal);
        tabAtthree.setIcon(R.drawable.i8live_menu_game_normal);
        tabAtfour.setIcon(R.drawable.i8live_menu_personl_normal);*/

        //設定方式二:
        for (int i = 0; i < title.length; i++) {
            if (i == 0) {
                tabLayout.getTabAt(0).setIcon(selectTabRes[0]);
            } else {
                tabLayout.getTabAt(i).setIcon(unSelectTabRes[i]);
            }
        }

    }

    private void initData() {

    }

    private void initListener() {
        //TabLayout切換時導航欄圖片處理
        tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {//選中圖片操作

                for (int i = 0; i < title.length; i++) {
                    if (tab == tabLayout.getTabAt(i)) {
                        tabLayout.getTabAt(i).setIcon(selectTabRes[i]);
                        viewPager.setCurrentItem(i);
                    }
                }

            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {//未選中圖片操作

                for (int i = 0; i < title.length; i++) {
                    if (tab == tabLayout.getTabAt(i)) {
                        tabLayout.getTabAt(i).setIcon(unSelectTabRes[i]);
                    }
                }

            }

            @Override
            public void onTabReselected(TabLayout.Tab tab) {

            }
        });
    }

	//自定義介面卡
    public class MyFragmentPagerAdapter extends FragmentPagerAdapter {

        public MyFragmentPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            if (position == 1) {
                return new SecondFragment();//娛樂
            } else if (position == 2) {
                return new ThirtlyFragment();//遊戲
            } else if (position == 3) {
                return new FourthlyFragment();//我的
            }
            return new FristFragment();//首頁
        }

        @Override
        public int getCount() {
            return title.length;
        }

        @Override
        public CharSequence getPageTitle(int position) {
            return title[position];
        }
    }
}

(5)、效果圖演示

在這裡插入圖片描述

二、使用FragmentTabHost+ Fragment + ViewPager實現

1、實現步驟:
(1)、佈局檔案中定義FragmentTabHost控制元件
(2)、定義底部選單欄佈局
(3)、定義切換的每個Fragment佈局檔案
(4)、定義切換的每個Fragment的Java類
(5)、切換按鈕的圖片
(6)、定義FragmentTabHostMainActivity類
(7)、效果圖演示

2、實現過程:

(1)、佈局檔案中定義FragmentTabHost控制元件(fragment_tabhost_activity.xml)

<?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="match_parent"
    android:background="#fff"
    android:orientation="vertical">

    <android.support.v4.view.ViewPager
        android:id="@+id/vp_pager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:scrollbars="none" />

    <android.support.v4.app.FragmentTabHost
        android:id="@android:id/tabhost"
        android:layout_width="match_parent"
        android:background="#3000"
        android:layout_height="65dp">

        <FrameLayout
            android:id="@android:id/tabcontent"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </android.support.v4.app.FragmentTabHost>
</LinearLayout>

(2)、定義底部選單欄佈局(tab_content.xml)

<?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="match_parent"
    android:padding="2dp"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/iv_imageview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:background="@drawable/i8live_menu_home_normal" />

    <TextView
        android:id="@+id/tv_item"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="5dp"
        android:text="首頁" />
</LinearLayout>

(3)、定義切換的每個Fragment佈局檔案(fragment_frist.xml)
這裡有四個Tab類別(首頁、娛樂、遊戲、我的),佈局都類似,這裡只貼出其中一個

<?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"
    android:background="#fff"
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="首頁"
        android:textColor="#000"/>
</RelativeLayout>

(4)、定義切換的每個Fragment的Java類(FristFragment.class)

這裡的Java 類實現方式也相似,貼出其中一個

package com.showly.bottomnavigationbardemo.fragment;


import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.showly.bottomnavigationbardemo.R;

public class FristFragment extends Fragment {

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment_frist, null);
        return view;
    }
}

(5)、切換按鈕的圖片(tab_main.xml)
這裡有四個是相似的,只貼出其中一個

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
   <!-- 切換選中之後的圖片-->
    <item android:drawable="@drawable/i8live_menu_home_press" android:state_selected="true"/>
    <!-- 未選中的圖片-->
    <item android:drawable="@drawable/i8live_menu_home_normal"/>
</selector

(6)、定義FragmentTabHostMainActivity類(FragmentTabHostMainActivity.class)

package com.showly.bottomnavigationbardemo;

import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentTabHost;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TabHost;
import android.widget.TabWidget;
import android.widget.TextView;

import com.showly.bottomnavigationbardemo.fragment.FourthlyFragment;
import com.showly.bottomnavigationbardemo.fragment.FristFragment;
import com.showly.bottomnavigationbardemo.fragment.SecondFragment;
import com.showly.bottomnavigationbardemo.fragment.ThirtlyFragment;

import java.util.ArrayList;
import java.util.List;


public class FragmentTabHostMainActivity extends FragmentActivity implements ViewPager.OnPageChangeListener, TabHost.OnTabChangeListener {

    private int[] selectTabRes = new int[]{R.drawable.tab_main, R.drawable.tab_infomation
            , R.drawable.tab_game, R.drawable.tab_personal};
    //Tab標題
    private String[] title = new String[]{"首頁", "娛樂", "遊戲", "我的"};
    private Class fragmentArry[] = {FristFragment.class, SecondFragment.class, ThirtlyFragment.class, FourthlyFragment.class};
    private List<Fragment> fragmentList = new ArrayList();

    private ViewPager viewPager;
    private FragmentTabHost tabHost;

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

        initView();
        initData();
        initListener();
    }

    /**
     * 初始化Fragment並給ViewPager新增介面卡
     */
    private void initVaper() {
        FristFragment fristFragment = new FristFragment();
        SecondFragment secondFragment = new SecondFragment();
        ThirtlyFragment thirtlyFragment = new ThirtlyFragment();
        FourthlyFragment fourthlyFragment = new FourthlyFragment();

        fragmentList.add(fristFragment);
        fragmentList.add(secondFragment);
        fragmentList.add(thirtlyFragment);
        fragmentList.add(fourthlyFragment);

        //ViewPager新增介面卡
        viewPager.setAdapter(new MyFragmentAdapter(getSupportFragmentManager(), fragmentList));
        tabHost.getTabWidget().setDividerDrawable(null);
    }

    private void initView() {
        viewPager = (ViewPager) findViewById(R.id.vp_pager);

        tabHost = (FragmentTabHost) findViewById(android.R.id.tabhost);//繫結tabhost
        tabHost.setup(this, getSupportFragmentManager(), R.id.vp_pager);//TabHost繫結viewpager

        //獲取item的個數
        int count = title.length;

        for (int i = 0; i < count; i++) {
            //設定每個TabHost佈局
            TabHost.TabSpec tabSpec = tabHost.newTabSpec(title[i])
                    .setIndicator(getTabItemView(i));

            //item與fragment關聯
            tabHost.addTab(tabSpec, fragmentArry[i], null);
            tabHost.setTag(i);
        }

        //初始化TabHost文字顏色
        upDateTab(tabHost);
        //給ViewPager設定介面卡
        initVaper();
    }

    /**
     * 更新文字顏色。
     *
     * @param mTabHost
     */
    private void upDateTab(FragmentTabHost mTabHost) {
        for (int i = 0; i < mTabHost.getTabWidget().getChildCount(); i++) {
            TextView tv = (TextView) mTabHost.getTabWidget().getChildAt(i).findViewById(R.id.tv_item);
            if (mTabHost.getCurrentTab() == i) {//選中
                tv.setTextColor(Color.parseColor("#FF5959"));
            } else {//不選中
                tv.setTextColor(Color.parseColor("#777777"));
            }
        }
    }

    /**
     * 設定每個Item佈局
     */
    private View getTabItemView(int i) {
        View view = LayoutInflater.from(this).inflate(R.layout.tab_content, null);

        ImageView itemImg = (ImageView) view.findViewById(R.id.iv_imageview);
        TextView itemText = (TextView) view.findViewById(R.id.tv_item);

        itemImg.setBackgroundResource(selectTabRes[i]);
        itemText.setText(title[i]);
        return view;
    }

    private void initData() {

    }

    private void initListener() {
        viewPager.addOnPageChangeListener(this);
        tabHost.setOnTabChangedListener(this);
    }

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }

    @Override
    public void onPageSelected(int position) {
        TabWidget widget = tabHost.getTabWidget();
        int oldFocusability = widget.getDescendantFocusability();
        widget.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);//設定View覆蓋子類控制元件而直接獲得焦點
        tabHost.setCurrentTab(position);//根據位置Postion設定當前的Tab
        widget.setDescendantFocusability(oldFocusability);//設定取消分割線
    }

    @Override
    public void onPageScrollStateChanged(int state) {

    }

    @Override
    public void onTabChanged(String tabId) {
        int position = tabHost.getCurrentTab();
        viewPager.setCurrentItem(position);//把選中的Tab的位置賦給介面卡,讓它控制頁面切換
        upDateTab(tabHost);//設定TabHost文字顏色
    }

    /**
     * 介面卡
     * */
    public class MyFragmentAdapter extends FragmentPagerAdapter {
        List<Fragment> list;

        public MyFragmentAdapter(FragmentManager fm, List<Fragment> list) {
            super(fm);
            this.list = list;
        }

        @Override
        public Fragment getItem(int position) {
            return list.get(position);
        }

        @Override
        public int getCount() {
            return list.size();
        }
    }
}

(7)、效果圖演示
在這裡插入圖片描述

三、總結
這兩種方式的實現已完成,實現起來相對還是比較簡單的,後期有時間會把後面兩種的實現方式補上。
Demo程式碼地址:底部公眾號回覆"底部狀態列切換"即可獲取。


以下是個人公眾號(longxuanzhigu),之後釋出的文章會同步到該公眾號,方便交流學習Android知識及分享個人愛好文章:
在這裡插入圖片描述

相關文章