Android TabHost的使用
1. 写在前面
出于对新事物的好奇, 接触了一下Android, 主要是看书(《Anroid应用开发深入学习实录》 关立勋)、Google和看文档。使用的android-sdk的platform最低是android-14, 然后有android-17,android-20以及android-L(电脑配置暂时比较低,没法把每个版本都测试一遍)
此时此刻Intellij IDEA社区版还没法渲染出android-20和android-L,所以我基本都是用的android-17
虽然书的出版日期比较新, 但其中有些内容还是已经过时了
2. TabHost的使用详解
2.1 项目结构
先新建一个项目,使用以前构建项目的方法(虽然现在有了Gradle, 但是对于初学者来说学习成本稍高, 暂时搁置):
MySetting.java在这里没用,忽略它……
2.2 App布局
布局main.xml:
<?xml version="1.0" encoding="utf-8"?>
<TabHost
android:layout_width="fill_parent"
android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/tabHost">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<TabWidget
android:id="@android:id/tabs"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
</TabWidget>
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/textview1"
android:id="@+id/textView1" android:layout_gravity="left|top"/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/textview2"
android:id="@+id/textView2" android:layout_gravity="center_horizontal|top"/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/textview3"
android:id="@+id/textView3" android:layout_gravity="right|top"/>
</FrameLayout>
</LinearLayout>
</TabHost>
strings.xml不放了, 随便什么字符串无所谓
2.3 逻辑代码
想要实现的就是添加三个Tab标签, 改变Tab标签的时候会弹出一个对话框, 按照书上及网上搜到的大部分代码, MyActivity.java应该是:
public class MyActivity extends Activity {
@Override
public void onCreate( Bundle savedInstanceState ) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mTabHost = getTabHost();
mTabHost.addTab...
}
}
这样的话有个问题: 查文档发现TabActivity在API Level 13中已经被弃用了。有:
This class was deprecated in API level 13. New applications should use Fragments instead of this class; to continue to run on older devices, you can use the v4 support library which provides a version of theFragment API that is compatible down to DONUT.
还有一句:
A replacement for TabActivity can also be implemented by directly using TabHost.
这其实意味着如果我们不考虑向下兼容的问题, 其实可以直接将上述代码写成:
package com.hecate.Apollo;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.widget.TabHost;
public class MyActivity extends Activity {
/**
* Called when the activity is first created.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TabHost mTabHost = (TabHost) findViewById(R.id.tabHost);
mTabHost.setup();
mTabHost.addTab( mTabHost.newTabSpec("first").setIndicator("Tab 1",getResources().getDrawable(R.drawable.img1)).setContent(R.id.textView1) );
mTabHost.addTab( mTabHost.newTabSpec("second").setIndicator("Tab 2",getResources().getDrawable(R.drawable.img2)).setContent(R.id.textView2) );
mTabHost.addTab( mTabHost.newTabSpec("third").setIndicator("Tab 3",getResources().getDrawable(R.drawable.img3)).setContent(R.id.textView3) );
mTabHost.setBackgroundColor(Color.parseColor("blue"));
mTabHost.setBackgroundResource(R.drawable.background);
mTabHost.setCurrentTab(0);
mTabHost.setOnTabChangedListener( new TabHost.OnTabChangeListener() {
@Override
public void onTabChanged( String tabId ) {
Dialog dialog = new AlertDialog.Builder( MyActivity.this )
.setTitle("Change Tabs")
.setMessage("You chosen "+tabId+" Tab")
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick( DialogInterface dialogInterface, int whichButton ) {
dialogInterface.cancel();
}
}).create();
dialog.show();
}
});
}
}
也就是直接继承Activity, 然后不使用getTabHost()方法而是findViewById(), 这时候又有一个注意点, 在TabHost文档的setup()方法中有:
Call setup() before adding tabs if loading TabHost using findViewById().
就是说如果你不是用getTabHost而是findViewById获取的TabHost,那在使用addTab()方法前要使用setup()方法。
2.4 运行测试
按照以上完成之后, 再添加相应的资源文件就可以成功运行了(在API Level 13以上):
原谅我的背景图片、、、点击TAB2后弹窗:
2.5 向下兼容
说完了不向下兼容的方法, 那如果需要向下兼容呢? 正如一开始的文档所说, 使用Fragments和android.support.v4 library即可, 具体可以去查看详细的文档, 里面给了一个示例, 我把示例代码贴出来, 就不分析了:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.app.FragmentTabHost
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TabWidget
android:id="@android:id/tabs"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0"/>
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="0"/>
<FrameLayout
android:id="@+id/realtabcontent"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
</LinearLayout>
</android.support.v4.app.FragmentTabHost>
Java代码:
import com.example.android.supportv4.R;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTabHost;
/**
* This demonstrates how you can implement switching between the tabs of a
* TabHost through fragments, using FragmentTabHost.
*/
public class FragmentTabs extends FragmentActivity {
private FragmentTabHost mTabHost;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_tabs);
mTabHost = (FragmentTabHost)findViewById(android.R.id.tabhost);
mTabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent);
mTabHost.addTab(mTabHost.newTabSpec("simple").setIndicator("Simple"),
FragmentStackSupport.CountingFragment.class, null);
mTabHost.addTab(mTabHost.newTabSpec("contacts").setIndicator("Contacts"),
LoaderCursorSupport.CursorLoaderListFragment.class, null);
mTabHost.addTab(mTabHost.newTabSpec("custom").setIndicator("Custom"),
LoaderCustomSupport.AppListFragment.class, null);
mTabHost.addTab(mTabHost.newTabSpec("throttle").setIndicator("Throttle"),
LoaderThrottleSupport.ThrottledLoaderListFragment.class, null);
}
}