Android應(yīng)用中使用TabHost組件繼承TabActivity的布局方法
繼承TabActivity并以activity布局
先查看下最終效果圖:

再看下代碼結(jié)構(gòu):

其中black.gif顧名思義就是一個(gè)黑背景圖片,grey.gif就是一張灰色的背景圖片
然后直接上代碼:
ArtistActivity.java
package cn.com.tagview;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class ArtistActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView textView = new TextView(this);
// 該文檔將會(huì)作為標(biāo)簽的內(nèi)容進(jìn)行顯示
textView.setText("藝術(shù)內(nèi)容");
setContentView(textView);
}
}
MusicActivity.java
package cn.com.tagview;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class MusicActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView textView = new TextView(this);
// 該文檔將會(huì)作為標(biāo)簽的內(nèi)容進(jìn)行顯示
textView.setText("音樂(lè)內(nèi)容");
setContentView(textView);
}
}
SportActivity.java
package cn.com.tagview;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class SportActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView textView = new TextView(this);
// 該文檔將會(huì)作為標(biāo)簽的內(nèi)容進(jìn)行顯示
textView.setText("運(yùn)動(dòng)內(nèi)容");
setContentView(textView);
}
}
ArtistActivity.java MusicActivity.java SportActivity.java三個(gè)activity是用做標(biāo)簽內(nèi)容的activity。即當(dāng)用戶(hù)點(diǎn)擊相應(yīng)的標(biāo)簽時(shí),下邊會(huì)顯示相應(yīng)的activity內(nèi)容。
ic_tab.xml代碼
<?xml version="1.0" encoding="utf-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android"
>
<item android:drawable="@drawable/grey"
android:state_selected="true"
></item>
<item android:drawable="@drawable/black"
></item>
</selector>
這里一定要注意ic_tab.xml文件的位置,是放在res/drawable文件夾下的。有些朋友說(shuō)怎么沒(méi)有這個(gè)文件夾啊,實(shí)際上大家看到了我將它放在了drawable-hdpi中了,實(shí)際上drawable-hdpi、drawable-ldpi、drawable-mdpi三個(gè)文件夾都屬于drawable文件夾的哦。該文件它規(guī)定了,當(dāng)標(biāo)簽獲得焦點(diǎn)和失去焦點(diǎn)時(shí),標(biāo)簽上顯示什么圖片。
例如本例中,就是當(dāng)state_selected="true"(當(dāng)標(biāo)簽被選中時(shí)),顯示@drawable/grey指定的資源圖片。當(dāng)未被選中時(shí),顯示@drawable/black指定的資源圖片。
tagView.java代碼:
package cn.com.tagview;
import android.app.TabActivity;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
import android.widget.TabHost;
/**
* @author chenzheng_Java
* @description 注意,該類(lèi)一定要繼承TabActivity
*/
public class TagView extends TabActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.main);
// android代碼中訪(fǎng)問(wèn)application資源的一個(gè)類(lèi)
Resources resources = getResources();
// 獲取當(dāng)前activity的標(biāo)簽,該方法的實(shí)現(xiàn)中已經(jīng)執(zhí)行了setContentView(com.android.internal.R.layout.tab_content);
TabHost tabHost = getTabHost();
// 每一個(gè)標(biāo)簽項(xiàng)
TabHost.TabSpec spec;
// 聲明一個(gè)意圖,該意圖告訴我們,下一個(gè)跳轉(zhuǎn)到的activity是ArtistActivity。
Intent intent = new Intent(this, ArtistActivity.class);
/**
* tabHost.newTabSpec("artist")創(chuàng)建一個(gè)標(biāo)簽項(xiàng),其中artist為它的標(biāo)簽標(biāo)識(shí)符,相當(dāng)于jsp頁(yè)面標(biāo)簽的name屬性
* setIndicator("藝術(shù)標(biāo)簽",resources.getDrawable(R.drawable.ic_tab))設(shè)置標(biāo)簽顯示文本以及標(biāo)簽上的圖標(biāo)(該圖標(biāo)并不是一個(gè)圖片,而是一個(gè)xml文件哦)
* setContent(intent)為當(dāng)前標(biāo)簽指定一個(gè)意圖
* tabHost.addTab(spec); 將標(biāo)簽項(xiàng)添加到標(biāo)簽中
*/
spec = tabHost.newTabSpec("artist").setIndicator("藝術(shù)標(biāo)簽",
resources.getDrawable(R.drawable.ic_tab)).setContent(intent);
tabHost.addTab(spec);
Intent intent2 = new Intent(this, MusicActivity.class);
spec = tabHost.newTabSpec("music").setIndicator("音樂(lè)標(biāo)簽",
resources.getDrawable(R.drawable.ic_tab)).setContent(intent2);
tabHost.addTab(spec);
Intent intent3 = new Intent(this, SportActivity.class);
spec = tabHost.newTabSpec("sport").setIndicator("體育標(biāo)簽",
resources.getDrawable(R.drawable.ic_tab)).setContent(intent3);
tabHost.addTab(spec);
// tabHost.setCurrentTabByTag("music");設(shè)置第一次打開(kāi)時(shí)默認(rèn)顯示的標(biāo)簽,該參數(shù)與tabHost.newTabSpec("music")的參數(shù)相同
tabHost.setCurrentTab(1);//設(shè)置第一次打開(kāi)時(shí)默認(rèn)顯示的標(biāo)簽,參數(shù)代表其添加到標(biāo)簽中的順序,位置是從0開(kāi)始的哦。
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cn.com.tagview"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="8" />
<application android:icon="@drawable/icon" android:label="@string/app_name">
<!-- android:theme="@android:style/Theme.NoTitleBar" 的意思是將系統(tǒng)默認(rèn)的tag標(biāo)簽去掉,為咱們自己的標(biāo)簽空出位置-->
<activity android:name=".TagView"
android:label="@string/app_name"
android:theme="@android:style/Theme.NoTitleBar"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- 在主配置文件中聲明用于標(biāo)簽切換的3個(gè)activity,記住此處一定要聲明,否則會(huì)出錯(cuò)
android:name="ArtistActivity"里面ArtistActivity前面是否有.都可以,你只需要保證該類(lèi)是在manifest標(biāo)簽下package屬性的包中即可。
-->
<activity android:name="ArtistActivity" android:label="@string/app_name"></activity>
<activity android:name="MusicActivity" android:label="@string/app_name"></activity>
<activity android:name="SportActivity" android:label="@string/app_name"></activity>
</application>
</manifest>
一切都弄好之后,運(yùn)行,就出現(xiàn)了最終效果。這里要注意,main.xml是一直都沒(méi)有用到的哦。
廢話(huà)連篇:
其實(shí),利用TabHost布局與ListView有很多相似之處,系統(tǒng)也同樣為他們提供了幫助類(lèi),TabHost-TabActivity ListView-ListActivity .當(dāng)我們的activity集成了這些類(lèi)之后,一般在里面我們只需要整理綁定下數(shù)據(jù)就可以。
再次聲明一下,代碼中是存在setContentView方法的調(diào)用的,只不過(guò)因?yàn)槲覀兗闪薚abActivity,TabActivity的getTabHost方法中已經(jīng)進(jìn)行了實(shí)現(xiàn)而已。對(duì)用戶(hù)隱藏了,并不代表沒(méi)有。
項(xiàng)目中為了簡(jiǎn)單易懂,我們只是在每個(gè)標(biāo)簽的內(nèi)容部分添加了一個(gè)文本。實(shí)際上,我們完全可以在里面添加圖片、視頻等等。只要在相應(yīng)的activity中實(shí)現(xiàn)就行了。我們可以看到,這種方式其實(shí)有很好的分層結(jié)構(gòu),activity與activity之間沒(méi)有太多耦合。
可能一直到現(xiàn)在,有些朋友對(duì)TabActivity和ListActivity這種實(shí)現(xiàn)都特別的別扭。我這里就簡(jiǎn)單的說(shuō)一下,實(shí)際上這其實(shí)是一種設(shè)計(jì)模式,模板模式。系統(tǒng)給你提供了一個(gè)實(shí)現(xiàn)了大部分內(nèi)容的模板,然后你通過(guò)繼承模板,去做修改(例如模板中有一個(gè)方法沒(méi)有任何實(shí)現(xiàn),你重寫(xiě)該方法并對(duì)其進(jìn)行具體實(shí)現(xiàn)),讓其符合你的要求。這就是模板模式的原理。
繼承TabActivity并以布局文件進(jìn)行布局
然后再來(lái)看以XML布局文件進(jìn)行布局的方法,先上效果圖:

上面的是最終效果圖。
代碼結(jié)構(gòu)如下。

main.xml代碼:
<?xml version="1.0" encoding="utf-8"?>
<!-- 該布局文件定義了標(biāo)簽的內(nèi)容部分,該布局文件一定要以FrameLayout為根元素 -->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent">
<!-- 第一個(gè)標(biāo)簽內(nèi)容 -->
<LinearLayout android:id="@+id/widget_layout_Blue"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:orientation="vertical" >
<EditText android:id="@+id/widget34" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:text="EditText"
android:textSize="18sp">
</EditText>
<Button android:id="@+id/widget30" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="Button">
</Button>
</LinearLayout>
<!-- 第二個(gè)標(biāo)簽內(nèi)容 AnalogClock為鐘表組件-->
<LinearLayout android:id="@+id/widget_layout_red"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:orientation="vertical" >
<AnalogClock android:id="@+id/widget36"
android:layout_width="wrap_content" android:layout_height="wrap_content">
</AnalogClock>
</LinearLayout>
<!-- 第三個(gè)標(biāo)簽內(nèi)容 RadioButton必須在RadioGroup中哦 -->
<LinearLayout android:id="@+id/widget_layout_green"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:orientation="vertical">
<RadioGroup android:id="@+id/widget43"
android:layout_width="166px" android:layout_height="98px"
android:orientation="vertical">
<RadioButton android:id="@+id/widget44"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="RadioButton">
</RadioButton>
<RadioButton android:id="@+id/widget45"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="RadioButton">
</RadioButton>
</RadioGroup>
</LinearLayout>
</FrameLayout>
TagHostTest.java的代碼:
package cn.com.tagHost.test;
import android.app.TabActivity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.widget.TabHost;
public class TagHostTest extends TabActivity {
private TabHost myTabhost;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myTabhost = this.getTabHost();
/**
* inflate(int resource, ViewGroup root, boolean attachToRoot)
* resource 很顯然是一個(gè)資源索引id
* 當(dāng)attachToRoot為true時(shí),root代表一個(gè)可放置于容器中的組件
* 當(dāng)attachToRoot為false時(shí),root僅代表一個(gè)存儲(chǔ)值的對(duì)象
* 該方法的意思是,將根據(jù)R.layout.main生成的標(biāo)簽View,添加到由myTabhost.getTabContentView()獲得的父容器中
* LayoutInflater類(lèi)的inflate方法中有如下片段
* if (root != null && attachToRoot) {
root.addView(temp, params);
}
其中temp是根據(jù)resource指定的資源生成的一個(gè)和標(biāo)簽有關(guān)的view
*/
LayoutInflater.from(this).inflate(R.layout.main,
myTabhost.getTabContentView(), true);
myTabhost.setBackgroundColor(Color.argb(150, 22, 70, 150));
myTabhost.addTab(myTabhost.newTabSpec("One")
.setIndicator("A").setContent(R.id.widget_layout_Blue));
myTabhost.addTab(myTabhost.newTabSpec("Two")
.setIndicator("B", getResources().getDrawable(R.drawable.icon))
.setContent(R.id.widget_layout_green));
myTabhost.addTab(myTabhost.newTabSpec("Three")
.setIndicator("C", getResources().getDrawable(R.drawable.icon))
.setContent(R.id.widget_layout_red));
}
}
這種方法實(shí)現(xiàn)起來(lái)比較簡(jiǎn)單,看看我們都做了些什么。
第一步:定義標(biāo)簽內(nèi)容部分的布局文件,該布局文件必須以FrameLayout為根節(jié)點(diǎn)。
第二步:讓activity繼承TabActivity,然后實(shí)現(xiàn)自己的代碼。
- Android中BroadcastReceiver(異步接收廣播Intent)的使用
- Android的Service應(yīng)用程序組件基本編寫(xiě)方法
- 淺談Android Content Provider的使用
- Android開(kāi)發(fā)之ContentProvider的使用詳解
- Android中自定義ContentProvider實(shí)例
- Android提高之BroadcastReceiver實(shí)例詳解
- Android編程四大組件之Activity用法實(shí)例分析
- Android實(shí)現(xiàn)Activity、Service與Broadcaster三大組件之間互相調(diào)用的方法詳解
- 通過(guò)實(shí)例簡(jiǎn)單講解Android App中的Activity組件
- Android編程四大組件分別是什么
相關(guān)文章
基于Android FileProvider 屬性配置詳解及FileProvider多節(jié)點(diǎn)問(wèn)題
這篇文章主要介紹了基于Android FileProvider 屬性配置詳解及FileProvider多節(jié)點(diǎn)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-03-03
Android基于高德地圖完全自定義Marker的實(shí)現(xiàn)方法
這篇文章主要給大家介紹了關(guān)于Android基于高德地圖完全自定義Marker的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-07-07
Android實(shí)現(xiàn)文件上傳和下載倒計(jì)時(shí)功能的圓形進(jìn)度條
這篇文章主要介紹了Android實(shí)現(xiàn)文件上傳和下載倒計(jì)時(shí)功能的圓形進(jìn)度條,需要的朋友可以參考下2017-09-09
Android自定義scrollview實(shí)現(xiàn)回彈效果
這篇文章主要為大家詳細(xì)介紹了Android自定義scrollview實(shí)現(xiàn)回彈效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04
Android應(yīng)用自動(dòng)更新功能實(shí)現(xiàn)的方法
這篇文章主要為大家詳細(xì)介紹了Android應(yīng)用自動(dòng)更新功能實(shí)現(xiàn)的方法,感興趣的小伙伴們可以參考一下2016-06-06
解決Android Studio sdk emulator directory is missing問(wèn)題
這篇文章主要介紹了解決Android Studio sdk emulator directory is missing問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11
android 自定義TabActivity的實(shí)例方法
系統(tǒng)自帶的TabActivity的效果不甚理想。開(kāi)發(fā)中對(duì)TabActivity自定義可能有兩種:第一種:改變TAB行的位置,如放到頁(yè)面下方。第二種:對(duì)TabHost圖片的自定義2013-11-11
Android中通知欄跳動(dòng)問(wèn)題解決方法
這篇文章主要介紹了Android中通知欄跳動(dòng)問(wèn)題解決方法,導(dǎo)致這個(gè)問(wèn)題的原因是when這個(gè)屬性值,默認(rèn)它是使用的系統(tǒng)當(dāng)前時(shí)間,這就是導(dǎo)致跳動(dòng)問(wèn)題的原因,指定一個(gè)固定時(shí)間即可解決這個(gè)問(wèn)題,需要的朋友可以參考下2015-01-01

