安卓選項卡——FragmentTabHost

TabHost之外另一種實現選項卡的方式


TabHost實現的時候有幾個界面要切換,就需要在XML中寫幾個,過多時候會顯得冗餘,用FragmentTabHost在XML文件中只需要一個FrameLayout,不需要在裏面寫更多的佈局

<?xml version="1.0" encoding="utf-8"?>
<androidx.fragment.app.FragmentTabHost
    android:id="@android:id/tabhost"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:android="http://schemas.android.com/apk/res/android" >

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <TabWidget
            android:id="@android:id/tabs"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"/>
        <FrameLayout
            android:id="@android:id/tabcontent"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_above="@android:id/tabs"/>
    </RelativeLayout>
</androidx.fragment.app.FragmentTabHost>

不在XML中寫是不寫在一起(不都放在FrameLayout裏),但是還是要有佈局文件。

所以單獨寫一個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/tv_content"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="30sp"
        android:textColor="#008577"/>

</LinearLayout>

FragmentTabHost的寫法和TabHost不一樣

  • 啓動 => TabHost直接setup(),FragmentTabHost需要有參數
  • 創建內容頁面 => TabHost需要一個setContent來指定該選項對應哪個界面,FragmentTabHost不需要
  • 添加 => TabHost使用addTabSpec()只有一個參數,FragmentTabHost有三個參數
  • 上條其中的第二個參數是個class字節碼,java類內實現的最重要的是佈局填充
package net.onest.fragmenttabhostch0203;

import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentTabHost;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TabHost;
import android.widget.TextView;

import net.onest.fragmenttabhostch0203.fragment.FirstFragment;
import net.onest.fragmenttabhostch0203.fragment.SecondFragment;

import java.util.HashMap;
import java.util.Map;

public class MainActivity extends AppCompatActivity {

    private Map<String, ImageView> imageViewMap = new HashMap<>();
    private Map<String, TextView> textViewMap = new HashMap<>();

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

        //獲取FragmentTabHost的引用
        FragmentTabHost fragmentTabHost = findViewById(android.R.id.tabhost);
        //初始化
        fragmentTabHost.setup(this,
                getSupportFragmentManager(),//管理多個Fragment對象的管理器
                android.R.id.tabcontent);//顯示內容頁面的控件的id

        //創建內容頁面TabSpec對象
        TabHost.TabSpec tab1 = fragmentTabHost.newTabSpec("first_tab")
                .setIndicator(getTabSpecView("first_tab","短信",R.drawable.message));
//                .setIndicator("短信");
        //Class參數:類名.class,對象.getClass()
        fragmentTabHost.addTab(tab1,
                FirstFragment.class,//FristFragment類的Class(字節碼)對象
                null);//傳遞數據時使用,不需要傳遞數據直接傳null

        TabHost.TabSpec tab2 = fragmentTabHost.newTabSpec("second_tab")
                .setIndicator(getTabSpecView("second_tab","聯繫人",R.drawable.contact));
//                .setIndicator("聯繫人");
        fragmentTabHost.addTab(tab2,
                SecondFragment.class,//SecondFragment類的Class對象
                null);

        //處理fragmentTabHost的選項切換事件
        fragmentTabHost.setOnTabChangedListener(new TabHost.OnTabChangeListener() {
            @Override
            public void onTabChanged(String tabId) {
                //修改圖片和文字的顏色
                switch (tabId){
                    case "first_tab"://選中了短信
                        imageViewMap.get("first_tab").setImageResource(R.drawable.message1);
                        imageViewMap.get("second_tab").setImageResource(R.drawable.contact);
                        break;
                    case "second_tab"://選中了聯繫人
                        imageViewMap.get("first_tab").setImageResource(R.drawable.message);
                        imageViewMap.get("second_tab").setImageResource(R.drawable.contact1);
                        break;
                }
            }
        });

        //設置默認選中的標籤頁:參數是下標
        fragmentTabHost.setCurrentTab(0);
        imageViewMap.get("first_tab").setImageResource(R.drawable.message1);
        //setTextColor不能直接傳入color資源的id號
        textViewMap.get("first_tab").setTextColor(getResources().getColor(android.R.color.black));
    }

    public View getTabSpecView(String tag, String tilte, int drawable){
        View view = getLayoutInflater().inflate(R.layout.tab_spec_layout,null);

        //獲取tab_spec_layout佈局當中視圖控件的引用
        ImageView icon = view.findViewById(R.id.icon);
        icon.setImageResource(drawable);

        //將ImageView對象存儲到Map中
        imageViewMap.put(tag,icon);

        TextView tvTitle = view.findViewById(R.id.title);
        tvTitle.setText(tilte);

        textViewMap.put(tag,tvTitle);

        return view;
    }
}


java字節碼那裏對應的代碼

package net.onest.fragmenttabhostch0203.fragment;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

import net.onest.fragmenttabhostch0203.R;

//第一個內容頁面對應的Fragment類
public class FirstFragment extends Fragment {
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        //加載內容頁面的佈局文件(將內容頁面的XML佈局文件轉成View類型的對象)
        View view = inflater.inflate(R.layout.fragment_layout,//內容頁面的佈局文件
                container,//根視圖對象
                false);//false表示需要手動調用addView方法將view添加到container
                                     //true表示不需要手動調用addView方法

        //獲取內容頁面當中控件的引用
        TextView tvContent = view.findViewById(R.id.tv_content);
        tvContent.setText("這是第一個內容頁面");

        return view;
    }
}


在java代碼設置指示器的地方(setIndicator)可以設置字符串也可以是自定義的view,上面代碼的佈局文件如下

<?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:gravity="center">

    <ImageView
        android:id="@+id/icon"
        android:layout_width="40dp"
        android:layout_height="40dp"/>
    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</LinearLayout>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章