Android:用TabHost做一个简单的多功能闹钟界面
话不多说直接上代码
activity_main.xml
在这里插<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<TabHost
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: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">
<LinearLayout
android:id="@+id/tab1"
android:layout_width="413dp"
android:layout_height="658dp"
android:orientation="vertical">
</LinearLayout>
<LinearLayout
android:id="@+id/tab2"
android:layout_width="413dp"
android:layout_height="658dp"
android:orientation="vertical">
</LinearLayout>
<LinearLayout
android:id="@+id/tab3"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
</LinearLayout>
<LinearLayout
android:id="@+id/tab4"
android:layout_width="413dp"
android:layout_height="658dp"
android:orientation="vertical">
</LinearLayout>
</FrameLayout>
</RelativeLayout>
</TabHost>
</FrameLayout>
MainActivity
package com.bignerdranch.android.zclock;
import android.os.Bundle;
import android.widget.TabHost;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tabHost = (TabHost)findViewById(android.R.id.tabhost);
tabHost.setup();
tabHost.addTab(tabHost.newTabSpec("tab1").setIndicator("时钟").setContent(R.id.tab1));
tabHost.addTab(tabHost.newTabSpec("tab2").setIndicator("闹钟").setContent(R.id.tab2));
tabHost.addTab(tabHost.newTabSpec("tab3").setIndicator("计时器").setContent(R.id.tab3));
tabHost.addTab(tabHost.newTabSpec("tab4").setIndicator("秒表").setContent(R.id.tab4));
}
private TabHost tabHost;
}
运行结果:
TabHost组件
TabHost继承自FrameLayout,它是个带Tab选项卡的容器,包含TabWidget和FrameLayout两个部分,TabWidget是每个Tab选项卡的标签按钮,FrameLayout是每个Tab选项卡的内容,在Android应用开发中提供了继承TabActivity和继承Activity两种实现方法,其中TabActivity已经过时,我主要学习Activity的实现方法。
Tab选项卡的UI布局文件的设计需要遵循下表的要求进行定义:
属性 | 方法名 说明 |
---|---|
TabHoste | 可自定义id |
TabWidget | 必须设置android:id为@android:id/tabs |
FrameLayout | 必须设置android:id为@android:id/tabcontent |
在使用组件中遇到的问题
1.在design界面并没有显示TabHost的组件只是个白色的按钮
原因是在design页面直接拖拽系统默认Tabwideget在底部。
解决方法是根据上面的实例代码直接放RelativeLayout的下面 。
TabWidget组件定义的选项标签按钮可以放在UI的上部或底部。本例中是在底部
因为在<TabWidget …/> 里边加了android:layout_alignParentBottom=“true”
默认是在顶部.
2.在运行的时候出现以下错误
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.bignerdranch.android.zclock, PID: 3100
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.bignerdranch.android.zclock/com.bignerdranch.android.zclock.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method ‘void android.widget.TabHost.setup()’ on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2646)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread
H
.
h
a
n
d
l
e
M
e
s
s
a
g
e
(
A
c
t
i
v
i
t
y
T
h
r
e
a
d
.
j
a
v
a
:
1460
)
a
t
a
n
d
r
o
i
d
.
o
s
.
H
a
n
d
l
e
r
.
d
i
s
p
a
t
c
h
M
e
s
s
a
g
e
(
H
a
n
d
l
e
r
.
j
a
v
a
:
102
)
a
t
a
n
d
r
o
i
d
.
o
s
.
L
o
o
p
e
r
.
l
o
o
p
(
L
o
o
p
e
r
.
j
a
v
a
:
154
)
a
t
a
n
d
r
o
i
d
.
a
p
p
.
A
c
t
i
v
i
t
y
T
h
r
e
a
d
.
m
a
i
n
(
A
c
t
i
v
i
t
y
T
h
r
e
a
d
.
j
a
v
a
:
6077
)
a
t
j
a
v
a
.
l
a
n
g
.
r
e
f
l
e
c
t
.
M
e
t
h
o
d
.
i
n
v
o
k
e
(
N
a
t
i
v
e
M
e
t
h
o
d
)
a
t
c
o
m
.
a
n
d
r
o
i
d
.
i
n
t
e
r
n
a
l
.
o
s
.
Z
y
g
o
t
e
I
n
i
t
H.handleMessage(ActivityThread.java:1460) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6077) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit
H.handleMessage(ActivityThread.java:1460)atandroid.os.Handler.dispatchMessage(Handler.java:102)atandroid.os.Looper.loop(Looper.java:154)atandroid.app.ActivityThread.main(ActivityThread.java:6077)atjava.lang.reflect.Method.invoke(NativeMethod)atcom.android.internal.os.ZygoteInitMethodAndArgsCaller.run(ZygoteInit.java:866)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method ‘void android.widget.TabHost.setup()’ on a null object reference
at com.bignerdranch.android.zclock.MainActivity.onCreate(MainActivity.java:16)
at android.app.Activity.performCreate(Activity.java:6662)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2599)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread
H
.
h
a
n
d
l
e
M
e
s
s
a
g
e
(
A
c
t
i
v
i
t
y
T
h
r
e
a
d
.
j
a
v
a
:
1460
)
a
t
a
n
d
r
o
i
d
.
o
s
.
H
a
n
d
l
e
r
.
d
i
s
p
a
t
c
h
M
e
s
s
a
g
e
(
H
a
n
d
l
e
r
.
j
a
v
a
:
102
)
a
t
a
n
d
r
o
i
d
.
o
s
.
L
o
o
p
e
r
.
l
o
o
p
(
L
o
o
p
e
r
.
j
a
v
a
:
154
)
a
t
a
n
d
r
o
i
d
.
a
p
p
.
A
c
t
i
v
i
t
y
T
h
r
e
a
d
.
m
a
i
n
(
A
c
t
i
v
i
t
y
T
h
r
e
a
d
.
j
a
v
a
:
6077
)
a
t
j
a
v
a
.
l
a
n
g
.
r
e
f
l
e
c
t
.
M
e
t
h
o
d
.
i
n
v
o
k
e
(
N
a
t
i
v
e
M
e
t
h
o
d
)
a
t
c
o
m
.
a
n
d
r
o
i
d
.
i
n
t
e
r
n
a
l
.
o
s
.
Z
y
g
o
t
e
I
n
i
t
H.handleMessage(ActivityThread.java:1460) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6077) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit
H.handleMessage(ActivityThread.java:1460)atandroid.os.Handler.dispatchMessage(Handler.java:102)atandroid.os.Looper.loop(Looper.java:154)atandroid.app.ActivityThread.main(ActivityThread.java:6077)atjava.lang.reflect.Method.invoke(NativeMethod)atcom.android.internal.os.ZygoteInitMethodAndArgsCaller.run(ZygoteInit.java:866)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)
检查发现是出现了空指针, at com.bignerdranch.android.zclock.MainActivity.onCreate(MainActivity.java:16)没有找的Tabhost的id。
下面也总结几点出现空指针的解决办法:
1:首先是查看报错的第一行(Androidstudio中打开run界面第一个可点击的地方),一般前几行都是比较关键的,我们一定要注意:
2:检查我们的XML文件里面定义的id(这个很关键),看看有没有对应的id,
3:检查代码中(对象,实例等)有没有初始化.
4:检查我们对应的事件(比如点击事件)有没有设置监听器。
一般能解决大部分出现java.lang.NullPointerException的问题。