1. 程式人生 > >首頁-底部Tab導航(選單欄)的實現:FragmentTabHost+ViewPager+Fragment

首頁-底部Tab導航(選單欄)的實現:FragmentTabHost+ViewPager+Fragment

前言

Android開發中使用底部選單欄的頻次非常高,主要的實現手段有以下:
- TabWidget
- 隱藏TabWidget,使用RadioGroup和RadioButton
- FragmentTabHost
- 5.0以後的TabLayout
- 最近推出的 Bottom navigation

今天帶大家來探索下如何用Fragment+FragmentTabHost++ViewPager
實現底部選單欄

目錄

目錄

總體設計思路

  • Fragment:存放不同選項的頁面內容
  • FragmentTabHost:點選切換選項卡
  • ViewPager:實現頁面的左右滑動效果

概念介紹

1. FragmentTabHost
用於實現點選選項進行切換選項卡的自定義效果

使用FragmentTabHost,就是先用TabHost“裝著”Fragment,然後放進MainActivity裡面

2. ViewPager
- 定義
ViewPager是android擴充套件包v4包中的類

android.support.v4.view.ViewPager
  • 作用
    左右切換當前的view,實現滑動切換的效果。

    注:
    1.ViewPager類直接繼承了ViewGroup類,和LinearLayout等佈局一樣,都是一個容器,需要在裡面新增我們想要顯示的內容。
    2.ViewPager類需要PagerAdapter介面卡類提供資料,與ListView類似 3.Google官方建議ViewPager配合Fragment使用


具體使用請參考我寫的另外一篇文章:Android開發:ViewPage的介紹
3. Fragment
- 定義
Fragment是activity的介面中的一部分或一種行為
1.把Fragment認為模組化的一段activity
2.它具有自己的生命週期,接收它自己的事件,並可以在activity執行時被新增或刪除
3.Fragment不能獨立存在,它必須嵌入到activity中,而且Fragment的生命週期直接受所在的activity的影響。例如:當activity暫停時,它擁有的所有的Fragment們都暫停了,當activity銷燬時,它擁有的所有Fragment們都被銷燬。
  • 作用
    主要是為了支援更動態、更靈活的介面設計(從3.0開始引入)

底部選單欄實現步驟

  1. 在主xml佈局裡面定義一個FragmentTabHost控制元件
  2. 定義底部選單欄佈局
  3. 定義每個Fragment佈局
  4. 定義每個Fragment的Java類
  5. 定義介面卡以關聯頁卡和ViewPage
  6. 定義MainActivity(具體實現請看註釋)

具體實現例項

1. 完整Demo下載地址

2. 工程檔案目錄

工程檔案目錄

3. 具體實現步驟

步驟1:在主xml佈局裡面定義一個FragmentTabHost控制元件

主xml佈局:Main_tab_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <include layout="@layout/main_top" />

    <android.support.v4.view.ViewPager
        android:id="@+id/pager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" /><!--裝4個Fragment-->

    <FrameLayout
        android:visibility="gone"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

    <!--定義FragmentTabHost控制元件-->
    <android.support.v4.app.FragmentTabHost
        android:id="@android:id/tabhost"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="@android:color/black" ><!--裝4個Fragment-->

        <FrameLayout
            android:id="@android:id/tabcontent"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_weight="0" /><!--裝Tab的內容-->
    </android.support.v4.app.FragmentTabHost>
</RelativeLayout>

步驟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:gravity="center"   
android:orientation="vertical"    
android:background="#ffffff">    
<ImageView        
android:id="@+id/tab_imageview"        
android:layout_width="wrap_content"        
android:layout_height="wrap_content"        
/>    
<TextView        
android:id="@+id/tab_textview"        
android:layout_width="wrap_content"        
android:layout_height="wrap_content"        
android:text=""        
android:textColor="@drawable/selector_text_background" />
</LinearLayout>

步驟3:定義Fragment佈局
fragment_item1.xml&fragment_item2.xml

這裡使用兩個選項,由於fragment_item1.xml與fragment_item2.xml相同,這裡只貼出一個

fragment_item1.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">

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="fragment1"
        android:textSize="20sp"/>

</LinearLayout>

步驟4: 定義每個Fragment的Java類

  1. 這裡使用兩個選項:Fragment1.java&fragmen2.java
  2. 由於Fragment1.java&fragmen2.java相同,這裡只貼出一個

Fragment1.java

package com.example.carson_ho.tab_menu_demo;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/**
 * Created by Carson_Ho on 16/5/23.
 */
public class Fragment1 extends Fragment

    {
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_item1, null);
        return view;
    }
    }

步驟5: 定義介面卡關聯頁卡和ViewPage
MyFragmentAdapter.java

package com.example.carson_ho.tab_menu_demo;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;

import java.util.List;

/**
 * Created by Carson_Ho on 16/5/23.
 */
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 arg0) {
        return list.get(arg0);
    }//根據Item的位置返回對應位置的Fragment,繫結item和Fragment

        @Override
        public int getCount() {
        return list.size();
    }//設定Item的數量

    }


步驟6: 定義MainActivity
具體實現看註釋
MainActivity.java

package com.example.carson_ho.tab_menu_demo;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
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 java.util.ArrayList;
import java.util.List;

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

    private FragmentTabHost mTabHost;
    private LayoutInflater layoutInflater;
    private Class fragmentArray[] = { Fragment1.class, Fragment2.class };
    private int imageViewArray[] = { R.drawable.tab_home_btn, R.drawable.tab_view_btn };
    private String textViewArray[] = { "首頁", "分類"};
    private List<Fragment> list = new ArrayList<Fragment>();
    private ViewPager vp;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();//初始化控制元件
        initPage();//初始化頁面
    }

    //    控制元件初始化控制元件
    private void initView() {
        vp = (ViewPager) findViewById(R.id.pager);

        /*實現OnPageChangeListener介面,目的是監聽Tab選項卡的變化,然後通知ViewPager介面卡切換介面*/
        /*簡單來說,是為了讓ViewPager滑動的時候能夠帶著底部選單聯動*/

        vp.addOnPageChangeListener(this);//設定頁面切換時的監聽器
        layoutInflater = LayoutInflater.from(this);//載入佈局管理器

        /*例項化FragmentTabHost物件並進行繫結*/
        mTabHost = (FragmentTabHost) findViewById(android.R.id.tabhost);//繫結tahost
        mTabHost.setup(this, getSupportFragmentManager(), R.id.pager);//繫結viewpager

        /*實現setOnTabChangedListener介面,目的是為監聽介面切換),然後實現TabHost裡面圖片文字的選中狀態切換*/
        /*簡單來說,是為了當點選下面選單時,上面的ViewPager能滑動到對應的Fragment*/
        mTabHost.setOnTabChangedListener(this);

        int count = textViewArray.length;

        /*新建Tabspec選項卡並設定Tab選單欄的內容和繫結對應的Fragment*/
        for (int i = 0; i < count; i++) {
            // 給每個Tab按鈕設定標籤、圖示和文字
            TabHost.TabSpec tabSpec = mTabHost.newTabSpec(textViewArray[i])
                    .setIndicator(getTabItemView(i));
            // 將Tab按鈕新增進Tab選項卡中,並繫結Fragment
            mTabHost.addTab(tabSpec, fragmentArray[i], null);
            mTabHost.setTag(i);
            mTabHost.getTabWidget().getChildAt(i)
                    .setBackgroundResource(R.drawable.selector_tab_background);//設定Tab被選中的時候顏色改變
        }
    }

    /*初始化Fragment*/
    private void initPage() {
        Fragment1 fragment1 = new Fragment1();
        Fragment2 fragment2 = new Fragment2();

        list.add(fragment1);
        list.add(fragment2);

        //繫結Fragment介面卡
        vp.setAdapter(new MyFragmentAdapter(getSupportFragmentManager(), list));
        mTabHost.getTabWidget().setDividerDrawable(null);
    }

    private View getTabItemView(int i) {
        //將xml佈局轉換為view物件
        View view = layoutInflater.inflate(R.layout.tab_content, null);
        //利用view物件,找到佈局中的元件,並設定內容,然後返回檢視
        ImageView mImageView = (ImageView) view
                .findViewById(R.id.tab_imageview);
        TextView mTextView = (TextView) view.findViewById(R.id.tab_textview);
        mImageView.setBackgroundResource(imageViewArray[i]);
        mTextView.setText(textViewArray[i]);
        return view;
    }


    @Override
    public void onPageScrollStateChanged(int arg0) {

    }//arg0 ==1的時候表示正在滑動,arg0==2的時候表示滑動完畢了,arg0==0的時候表示什麼都沒做,就是停在那。

    @Override
    public void onPageScrolled(int arg0, float arg1, int arg2) {

    }//表示在前一個頁面滑動到後一個頁面的時候,在前一個頁面滑動前呼叫的方法

    @Override
    public void onPageSelected(int arg0) {//arg0是表示你當前選中的頁面位置Postion,這事件是在你頁面跳轉完畢的時候呼叫的。
        TabWidget widget = mTabHost.getTabWidget();
        int oldFocusability = widget.getDescendantFocusability();
        widget.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);//設定View覆蓋子類控制元件而直接獲得焦點
        mTabHost.setCurrentTab(arg0);//根據位置Postion設定當前的Tab
        widget.setDescendantFocusability(oldFocusability);//設定取消分割線

    }

    @Override
    public void onTabChanged(String tabId) {//Tab改變的時候呼叫
        int position = mTabHost.getCurrentTab();
        vp.setCurrentItem(position);//把選中的Tab的位置賦給介面卡,讓它控制頁面切換
    }

}

效果圖
經過上述6個步驟就完成了可滑動的底部選單欄了,效果圖如下:

預設第一個Tab
點選或滑動到第二個Tab

實現步驟彙總

底部選單欄實現步驟:
1. 在主xml佈局裡面定義一個FragmentTabHost控制元件
2. 定義底部選單欄佈局
3. 定義每個Fragment佈局
4. 定義每個Fragment的Java類
5. 定義介面卡以關聯頁卡和ViewPage
6. 定義具體實現的MainActivity

完整Demo下載地址

總結

本文對底部選單欄進行了全面的實現,也講解得非常詳細,有不懂的可以直接在下面留言給我哦!接下來我會介紹繼續介紹Android開發中的相關知識,有興趣可以繼續關注Carson_Ho的安卓部落格

請幫頂 / 評論點贊!

因為你的鼓勵是我寫作的最大動力!