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