1. 程式人生 > >Android UI 之選項卡

Android UI 之選項卡

當應用的內容過多時,我們可以通過選項卡的方式把應用的內容分類到每個選項下,讓使用者有更好的體驗。下面會介紹三種選項卡的實現方式。
一、TabHost實現選項卡
佈局檔案

<?xml version="1.0" encoding="utf-8"?>
    <TabHost
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@android:id/tabhost"
        android:layout_width="match_parent"
        android:layout_height
="match_parent">
<RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <TabWidget android:layout_alignParentBottom="true" android:id="@android:id/tabs" android:layout_width
="match_parent" android:layout_height="wrap_content">
</TabWidget> <FrameLayout android:layout_alignParentTop="true" android:id="@android:id/tabcontent" android:layout_width="match_parent" android:layout_height
="match_parent" android:paddingBottom="50dp">
</FrameLayout> </RelativeLayout> </TabHost>

在TabHost新增一個相對佈局(這個非必要),在相對佈局裡新增一個TabWidget和一個FrameLayout(這兩個是必要的),TabHost、TabWidget、FrameLayout的id分別為@android:id/tabhost、@android:id/tabs、@android:id/tabcontent這些安卓自帶的id。
Activity的程式碼:

package com.example.yougel.tabdemo;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.widget.TabHost;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class TabdemoActivity extends AppCompatActivity {

    TabHost tabHost;
    List<Map<String,Object>> tabData;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_tabdemo);
        tabHost= (TabHost) findViewById(android.R.id.tabhost);
        //裝載
        tabHost.setup();
        tabData=getTabData();
        initTabs();
    }

    protected void initTabs(){
        //動態載入佈局到指定選項
        LayoutInflater inflater=LayoutInflater.from(this);
        inflater.inflate(R.layout.tab1,tabHost.getTabContentView());
        inflater.inflate(R.layout.tab2,tabHost.getTabContentView());
        inflater.inflate(R.layout.tab3,tabHost.getTabContentView());
        inflater.inflate(R.layout.tab4,tabHost.getTabContentView());

        //新增選項
        for (int i=0;i<tabData.size();i++){
            Map<String,Object> data=tabData.get(i);
            tabHost.addTab(buildSpec(data.get("tag").toString(),data.get("text").toString(),(int)data.get("viewId"),(int)data.get("resId")));
        }
        //設定當前所在選項
        tabHost.setCurrentTab(3);
    }


    //類似ListView中的資料來源,就是匹配每個選項內容
    private List<Map<String,Object>> getTabData(){
        List<Map<String,Object>> tabData=new ArrayList<>();
        Map<String,Object> tab=new HashMap<>();
        tab.put("tag","tab1");
        tab.put("text","精選");
        tab.put("viewId",R.id.tab1);
        tab.put("resId",R.mipmap.icon_broswer_gray);
        tabData.add(tab);

        tab=new HashMap<>();
        tab.put("tag","tab2");
        tab.put("text","動態");
        tab.put("viewId",R.id.tab2);
        tab.put("resId",R.mipmap.icon_debug_gray);
        tabData.add(tab);

        tab=new HashMap<>();
        tab.put("tag","tab3");
        tab.put("text","發現");
        tab.put("viewId",R.id.tab3);
        tab.put("resId",R.mipmap.icon_refresh_gray);
        tabData.add(tab);

        tab=new HashMap<>();
        tab.put("tag","tab4");
        tab.put("text","我的");
        tab.put("viewId",R.id.tab4);
        tab.put("resId",R.mipmap.icon_share_gray);
        tabData.add(tab);

        return tabData;
    }

    //建立TabSpec
    private TabHost.TabSpec buildSpec(String tag,String text,int viewid ,int resId){
        TabHost.TabSpec ts1=tabHost.newTabSpec(tag);
        ts1.setContent(viewid);
        ts1.setIndicator("",getResources().getDrawable(resId));
        return ts1;
    }
}

如果不是繼承TabActivity,那麼關聯了TabHost後必須使用setup方法裝載。
通過佈局inflater將多個佈局載入到TabHost的tabcontent裡
inflater.inflate(指定佈局,tabHost.getTabContentView())
通過addTab方法把選項卡的內容匹配到WidgetTab中,因為addTab要傳遞一個TabHost.TabSpec物件,所以自定義了一個buildSpec方法,主要內容如下:
TabHost.TabSpec ts1=tabHost.newTabSpec(tag);
獲取TabSpec物件
ts1.setContent(viewid);
設定內容(為佈局的id)
ts1.setIndicator(“”,getResources().getDrawable(resId));
設定選項卡的,上面只有圖片的選項卡,由於這種方式實現的選項卡無法文字和圖片同時顯現,所以可以使用第二種方式

二、TabHost+RadioGroup實現較複雜的選項卡
佈局檔案:

<?xml version="1.0" encoding="utf-8"?>
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@android:id/tabhost"
    >
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <TabWidget
            android:id="@android:id/tabs"
            android:visibility="invisible"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"></TabWidget>
        <!--中間佈局-->
        <TextView
            android:id="@+id/the_title"
            android:layout_alignParentTop="true"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@android:id/tabs"
            android:background="@color/colorPrimary"
            android:paddingTop="10dp"
            android:paddingBottom="10dp"
            android:textSize="20sp"
            android:textColor="@color/title"
            android:gravity="center"
            />
        <FrameLayout
            android:layout_below="@id/the_title"
            android:id="@android:id/tabcontent"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            >
        </FrameLayout>
        <!--底部佈局-->
        <RelativeLayout
            android:layout_alignParentBottom="true"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <RadioGroup
                android:id="@+id/rgTabs"
                android:orientation="horizontal"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">
                <RadioButton
                    android:checked="true"
                    android:id="@+id/rbjingxuan"
                    android:text="精選"
                    style="@style/radio_button_style"
                    android:drawableTop="@drawable/rb_top1"
                    />
                <RadioButton
                    android:id="@+id/rbdonngtai"
                    android:text="動態"
                    style="@style/radio_button_style"
                    android:drawableTop="@drawable/rb_top2"
                    />
                <RadioButton
                    android:id="@+id/rbfaxian"
                    android:text="發現"
                    style="@style/radio_button_style"
                    android:drawableTop="@drawable/rb_top3"
                    />
                <RadioButton
                    android:id="@+id/rbwode"
                    android:text="我的"
                    style="@style/radio_button_style"
                    android:drawableTop="@drawable/rb_top4"/>
            </RadioGroup>
        </RelativeLayout>
    </RelativeLayout>
</TabHost>

佈局的變化主要是TabWidget隱藏起來,然後在底部新增一組Radiobutton
Activity程式碼:

package com.example.yougel.tabdemo;

import android.app.TabActivity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TabHost;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class TouTiaoActivity extends TabActivity {

    List<Map<String,Object>> tabsData;
    TabHost tabHost;
    RadioGroup rgTabs;
    TextView title;
    RadioButton rbjingxuan,rbdonngtai,rbfaxian,rbwode;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_tou_tiao);

        tabsData=getTabData();
        //獲取tabHost物件
        tabHost=getTabHost();
        title= (TextView) findViewById(R.id.the_title);
        rgTabs= (RadioGroup) findViewById(R.id.rgTabs);
        rbjingxuan= (RadioButton) findViewById(R.id.rbjingxuan);
        rbdonngtai= (RadioButton) findViewById(R.id.rbdonngtai);
        rbfaxian= (RadioButton) findViewById(R.id.rbfaxian);
        rbwode= (RadioButton) findViewById(R.id.rbwode);
        title.setText(rbjingxuan.getText());

        //為tabhost新增tab選項
        for (int i=0;i<tabsData.size();i++){
            Map<String,Object> data=tabsData.get(i);
            tabHost.addTab(buildSpec(
                    data.get("tag").toString(),
                    data.get("text").toString(),
                    (Intent) data.get("intent")));
        }
//        tabHost.setCurrentTab(1);

        rgTabs.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                switch (checkedId){
                    case R.id.rbjingxuan:
                        title.setText(rbjingxuan.getText());
                        tabHost.setCurrentTab(0);
                        break;
                    case R.id.rbdonngtai:
                        title.setText(rbdonngtai.getText());
                        tabHost.setCurrentTab(1);
                        break;
                    case R.id.rbfaxian:
                        title.setText(rbfaxian.getText());
                        tabHost.setCurrentTab(2);
                        break;
                    case R.id.rbwode:
                        title.setText(rbwode.getText());
                        tabHost.setCurrentTab(3);
                        break;
                }
            }
        });

    }
    private List<Map<String,Object>> getTabData(){
        List<Map<String,Object>> tabData=new ArrayList<>();
        Map<String,Object> tab=new HashMap<>();
        tab.put("tag","tab1");
        tab.put("text","精選");
        tab.put("intent",new Intent(this,Activity1.class));
        tabData.add(tab);

        tab=new HashMap<>();
        tab.put("tag","tab2");
        tab.put("text","動態");
        tab.put("intent",new Intent(this,Activity2.class));
        tabData.add(tab);

        tab=new HashMap<>();
        tab.put("tag","tab3");
        tab.put("text","發現");
        tab.put("intent",new Intent(this,Activity3.class));
        tabData.add(tab);

        tab=new HashMap<>();
        tab.put("tag","tab4");
        tab.put("text","我的");
        tab.put("intent",new Intent(this,Activity4.class));
        tabData.add(tab);

        return tabData;
    }

    private TabHost.TabSpec buildSpec(String tag,String text,Intent intent){
        TabHost.TabSpec ts1=tabHost.newTabSpec(tag);
        ts1.setContent(intent);
        ts1.setIndicator(text);
        return ts1;
    }
}

在這裡繼承的是TabActivity,所以TabHost不用裝載,並且用getTabHost方法獲取,其他方法基本和第一種方式相同。但是這種方式實現的選項卡是無法滑動切換頁面,所以可以使用ViewPager+RadioGroup的方式來實現,這種方法主要是定義一個PagerAdapter來實現選項卡,具體的實現就不展示出來,實現的方法可以參考以下網址通過的例項
https://yq.aliyun.com/articles/36036