Fragment+FrameLayout實現Tab切換

前言

底部切換效果已經很常見了,本文介紹其中的一種實現方法:FrameLayout+Fragment
本案例已上傳至Github,你可以查看完整源碼,也可以下載demo apk體驗一下
實現效果如下:

這裏寫圖片描述

Tab切換

Step1:創建Fragment
創建四個頁卡所表示的Fragment以及其佈局文件,圖中每個頁卡都是一個Fragment(碎片)

先創建第一個頁卡的Fragment以及佈局文件
fragment_tab1.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.zhuangfei.fragment.TabFragment1"
    android:orientation="vertical">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="第一個頁卡" />

    <Button
        android:id="@+id/tab1_btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textAllCaps="false"
        android:text="Fragment交互"/>

</LinearLayout>

TabFragment1.java


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

/**
 *第一個頁卡
 * A simple {@link Fragment} subclass.
 */
public class TabFragment1 extends Fragment {

    View view;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        view=inflater.inflate(R.layout.fragment_tab1, container, false);

        Button button=view.findViewById(R.id.tab1_btn);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(getContext(),"findViewById()時不要忘了前邊的view."
                        ,Toast.LENGTH_SHORT).show();
            }
        });
        return view;
    }
}

以下copy3份,並簡單的修改一下顯示的文字
fragment_tab2.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.zhuangfei.fragment.TabFragment1">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="第二個頁卡" />

</LinearLayout>

TabFragment2.java

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

/**
 *第二個頁卡
 * A simple {@link Fragment} subclass.
 */
public class TabFragment2 extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_tab2, container, false);
    }
}

fragment_tab3.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.zhuangfei.fragment.TabFragment1">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="第三個頁卡" />

</LinearLayout>

TabFragment3.java

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

/**
 *第三個頁卡
 * A simple {@link Fragment} subclass.
 */
public class TabFragment3 extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_tab3, container, false);
    }
}

fragment_tab4.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.zhuangfei.fragment.TabFragment1">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="第四個頁卡" />

</LinearLayout>

TabFragment4.java

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

/**
 *第四個頁卡
 * A simple {@link Fragment} subclass.
 */
public class TabFragment4 extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_tab4, container, false);
    }
}

創建主頁面

四個Fragment應該怎麼顯示在主頁面上呢,這裏用到了幀佈局,主頁面的底部是底部導航的佈局,中間是一個幀佈局

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <!--幀佈局,承載四個TAB的Fragment-->
    <FrameLayout
        android:id="@+id/id_framelayout"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:background="@color/app_white" />

    <View
        android:layout_width="match_parent"
        android:layout_height="1px"
        android:background="@color/app_line"/>

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

</LinearLayout>

view_bottom.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/bottomLayout"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:background="@color/app_white"
    android:orientation="horizontal">

    <!-- 主界面底部4個TAB -->

    <LinearLayout
        android:id="@+id/id_tab1_layout"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:gravity="center"
        android:orientation="vertical">

        <ImageView
            android:id="@+id/id_tab1_imageview"
            android:layout_width="25dp"
            android:layout_height="25dp"
            android:src="@drawable/ic_tab1" />
    </LinearLayout>

    <LinearLayout
        android:id="@+id/id_tab2_layout"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:gravity="center"
        android:orientation="vertical">

        <ImageView
            android:id="@+id/id_tab2_imageview"
            android:layout_width="25dp"
            android:layout_height="25dp"
            android:src="@drawable/ic_tab2" />
    </LinearLayout>

    <LinearLayout
        android:id="@+id/id_tab3_layout"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:gravity="center"
        android:orientation="vertical">

        <ImageView
            android:id="@+id/id_tab3_imageview"
            android:layout_width="25dp"
            android:layout_height="25dp"
            android:src="@drawable/ic_tab3" />
    </LinearLayout>

    <LinearLayout
        android:id="@+id/id_tab4_layout"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:gravity="center"
        android:orientation="vertical">

        <ImageView
            android:id="@+id/id_tab4_imageview"
            android:layout_width="25dp"
            android:layout_height="25dp"
            android:src="@drawable/ic_tab4" />
    </LinearLayout>

</LinearLayout>

MainActivity.java

package com.zhuangfei.fragment;

import android.media.Image;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;

/**
 * 主頁面,顯示多個Fragment
 */
public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    // 創建Fragment對象
    private TabFragment1 tabFragment1;
    private TabFragment2 tabFragment2;
    private TabFragment3 tabFragment3;
    private TabFragment4 tabFragment4;

    private ImageView tabImageView1;
    private ImageView tabImageView2;
    private ImageView tabImageView3;
    private ImageView tabImageView4;

    private LinearLayout tabLayout1;
    private LinearLayout tabLayout2;
    private LinearLayout tabLayout3;
    private LinearLayout tabLayout4;

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

    private void initView() {
        tabImageView1=findViewById(R.id.id_tab1_imageview);
        tabImageView2=findViewById(R.id.id_tab2_imageview);
        tabImageView3=findViewById(R.id.id_tab3_imageview);
        tabImageView4=findViewById(R.id.id_tab4_imageview);

        tabLayout1=findViewById(R.id.id_tab1_layout);
        tabLayout2=findViewById(R.id.id_tab2_layout);
        tabLayout3=findViewById(R.id.id_tab3_layout);
        tabLayout4=findViewById(R.id.id_tab4_layout);

        tabLayout1.setOnClickListener(this);
        tabLayout2.setOnClickListener(this);
        tabLayout3.setOnClickListener(this);
        tabLayout4.setOnClickListener(this);
    }

    /**
     * 初始化Tab的狀態
     */
    public void initTab() {
        int color = getResources().getColor(R.color.app_gray);
        // 更改圖片顏色爲暗色
        tabImageView1.setColorFilter(color);
        tabImageView2.setColorFilter(color);
        tabImageView3.setColorFilter(color);
        tabImageView4.setColorFilter(color);
    }

    /**
     * 選中第i個Tab時的處理
     *
     * @param i
     */
    public void select(int i) {
        // 得到Fragment管理器以及事務
        FragmentManager manager = getSupportFragmentManager();
        FragmentTransaction transaction = manager.beginTransaction();
        initTab();
        int color = getResources().getColor(R.color.app_orange);
        switch (i) {
            case 0:
                tabImageView1.setColorFilter(color);

                if (tabFragment1 == null) {
                    tabFragment1 = new TabFragment1();
                }
                transaction.replace(R.id.id_framelayout, tabFragment1);

                break;
            case 1:
                tabImageView2.setColorFilter(color);

                if (tabFragment2 == null) {
                    tabFragment2 = new TabFragment2();
                }
                transaction.replace(R.id.id_framelayout, tabFragment2);
                break;
            case 2:
                tabImageView3.setColorFilter(color);

                if (tabFragment3 == null) {
                    tabFragment3 = new TabFragment3();
                }
                transaction.replace(R.id.id_framelayout, tabFragment3);
                break;
            case 3:
                tabImageView4.setColorFilter(color);

                if (tabFragment4 == null) {
                    tabFragment4 = new TabFragment4();
                }
                transaction.replace(R.id.id_framelayout, tabFragment4);
                break;
            default:
                break;
        }
        transaction.commit();
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.id_tab1_layout:
                select(0);
                break;
            case R.id.id_tab2_layout:
                select(1);
                break;
            case R.id.id_tab3_layout:
                select(2);
                break;
            case R.id.id_tab4_layout:
                select(3);
                break;
        }
    }
}

本文用的是replace()方法來替換顯示的Fargment,這種方法的優缺點:
優點:使用簡單
缺點:會導致Fargment在每次切換時都實例化一個對象,性能有影響,並且Fargment有嵌套時會出現內部數據消失的問題

還可以使用add()、show()、hide()實現Fragment切換,該方法的優缺點:
優點:提升性能
缺點:可能會出現重影問題

當然,上面提到的兩個問題都是有解決方法的,後續的文章中將使用add()、show()、hide()實現Fragment切換,敬請期待…

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章