您的位置:首页 > 移动开发 > 微信开发

Android 仿微信TabHost使用方法详解

2018-02-07 11:31 375 查看
 

一、TabHost简介

Container for a tabbed window view. Thisobject holds two children: a set of tab labels that the 

user clicks toselect a specific tab, and a FrameLayout object that displays the contents ofthat 

page. Theindividual elements are typically controlled using this container object,rather than 

setting values onthe child elements themselves. 

TabHost ,标签视图的容器。容器包含两个孩子节点,一个用来存放一系列的标签,点击来选择对应的窗口;一个是FrameLayout用来存放页面具体内容。这些独立的元素通常用TabHost来控制,而不是在视图内部通过设置值来实现。

 

 

二、TabHost常用组件

 

方法

意义

addTab

添加一个tab

clearAllTabs

移除所有的tab

dispatchKeyEvent

下发keyevent

dispatchWindowFocusChanged

下发windowsfocusChanged事件

newTabSpec

创建一个新的TabSpec,关联到具体内容

onTouchModeChanged

NA

setup()

不和TabActivity关联,通过findViewById获取的TabHost需要调用setup(),如果是在TabActivity中通过getTabHost()的方式获取的不需要调用这个方法

setup(LocalActivityManager activityGroup)

setContent中传入intent的时候才关注下这个方法

getCurrentTab()/setCurrentTab()

获取/设置当前需要显示的tab,通过index

setCurrentTabByTag/getCurrentTabTag

通过tag设置当前需要显示的Tab,tag就是创建TabSpec的时候传入的字符串

getCurrentTabView

设置/获取当前在TabWidget中显示的View,也就是作为标签的View而非内容

getCurrentView

获取当前显示的内容

setOnTabChangedListener

设置标签页切换事件监听

getTabContentView

获取内容页面的容器FrameLayout

getTabWidget

获取TabWidget

 

 

三、TabHost使用步骤

1.主页UI布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<TabHost
android:id="@+id/tabhost"
android:layout_width="match_parent"
android:layout_height="match_parent">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="9">

<TextView
android:id="@+id/tv_one"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="This is one"
android:textColor="@color/colorAccent"
android:textSize="20sp" />

<TextView
android:id="@+id/tv_two"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="This is two"
android:textColor="@color/colorPrimary"
android:textSize="25sp" />

<TextView
android:id="@+id/tv_three"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="This is three"
android:textSize="30sp" />

<TextView
android:id="@+id/tv_four"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="This is Four"
android:textSize="35sp" />
</FrameLayout>

<TabWidget
android:id="@android:id/tabs"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:padding="5dp"
android:showDividers="none"></TabWidget>
</LinearLayout>
</TabHost>
</LinearLayout>

注意:在自定义自己的TabHost时,TabWiget和FrameLayout不可以自定义id,

TabHost的id定义为:android:id="@+id/tabhost"

FrameLayout的id定义为android:id="@android:id/tabcontent"

需在setup里面进行实例化,因此需要早addTab添加内容之前调用setup方法。

 

2.初始化UI

tabHost = (TabHost) findViewById(R.id.tabhost);
tabHost.setup();//初始化TabHost

 

3.初始化数据

/*添加tab*/
for (int i = 0; i < 4; i++) {
View view = LayoutInflater.from(this).inflate(R.layout.myindicator, null, false);
TextView textView = (TextView) view.findViewById(R.id.tv_indicator);
ImageView imageView = (ImageView) view.findViewById(R.id.iv_indicator);

switch (i) {
case 0:
textView.setText("微信");
imageView.setImageResource(R.mipmap.ic_launcher);
tabHost.addTab(tabHost.newTabSpec("1").setIndicator(view).setContent(R.id.tv_one));
break;
case 1:
textView.setText("通讯录");
imageView.setImageResource(R.mipmap.ic_launcher);
tabHost.addTab(tabHost.newTabSpec("2").setIndicator(view).setContent(R.id.tv_two));
break;
case 2:
textView.setText("发现");
imageView.setImageResource(R.mipmap.ic_launcher);
tabHost.addTab(tabHost.newTabSpec("3").setIndicator(view).setContent(R.id.tv_three));
break;
case 3:
textView.setText("我的");
imageView.setImageResource(R.mipmap.ic_launcher);
tabHost.addTab(tabHost.newTabSpec("4").setIndicator(view).setContent(R.id.tv_four));
break;
}

}

 

4.设置监听器

/*设置标签切换监听器*/
tabHost.setOnTabChangedListener(new TabHost.OnTabChangeListener() {
@Override
public void onTabChanged(String tabId) {
for (int i = 0; i < 4; i++) {//颜色全部重置
((TextView) tabHost.getTabWidget().getChildTabViewAt(i).findViewById(R.id.tv_indicator))
.setTextColor(getResources().getColor(R.color.colorAccent));
}
if (tabHost.getCurrentTabTag() == tabId) {
((TextView) tabHost.getCurrentTabView().findViewById(R.id.tv_indicator))
.setTextColor(getResources().getColor(R.color.colorPrimary));
}//选中的那个Tab文字颜色修改
}
});
((TextView) tabHost.getCurrentTabView().findViewById(R.id.tv_indicator))
.setTextColor(getResources().getColor(R.color.colorPrimary));//第一次进入的时候讲选中的Tab修改文字颜色

5.滑动事件

@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
initx = event.getX();
break;
case MotionEvent.ACTION_MOVE:
currentx = event.getX();
break;
case MotionEvent.ACTION_UP:
/*左右滑动事件处理*/
if ((currentx - initx) > 25) {
if (tabHost.getCurrentTab() != 0) {
tabHost.setCurrentTab(tabHost.getCurrentTab() - 1);
}
} else if ((currentx - initx) < -25) {
if (tabHost.getCurrentTab() != tabHost.getTabContentView().getChildCount()) {
tabHost.setCurrentTab(tabHost.getCurrentTab() + 1);
}
}
break;

}

return true;
}

6.另解:继承TabActivity

TabActivity已经被废弃很久了,但是还是可以使用,在布局中将TabHost的id改成android:id=”@android:id/tabhost”,然后在继承了TabActivity的MainActivity.java中使用 tabHost = getTabHost(); 然后基本使用方法就和上面一样了。

7.注意:
使用TabHost的时候,当你页面内有输入框的时候你会发现输入法会把底部tabWeight顶起来。我们可以在注册activity的时候对输入法做一些限制。

<activity android:name=".MainActivity"

android:windowSoftInputMode="stateHidden|adjustPan"/>

8.android:windowSoftInputMode一些属性的介绍

·“stateUnspecified” 软键盘的状态(是否它是隐藏或可见)没有被指定。系统将选择一个合适的状态或依赖于主题的设置。这个是为了软件盘行为默认的设置。
·“stateUnchanged” 软键盘被保持无论它上次是什么状态,是否可见或隐藏,当主窗口出现在前面时。
·“stateHidden” 当用户选择该Activity时,软键盘被隐藏——也就是,当用户确定导航到该Activity时,而不是返回到它由于离开另一个Activity。
·“stateAlwaysHidden” 软键盘总是被隐藏的,当该Activity主窗口获取焦点时。
·“stateVisible” 软键盘是可见的,当那个是正常合适的时(当用户导航到Activity主窗口时)。
·“stateAlwaysVisible” 当用户选择这个Activity时,软键盘是可见的——也就是,也就是,当用户确定导航到该Activity时,而不是返回到它由于离开另一个Activity。
·“adjustUnspecified” 它不被指定是否该Activity主窗口调整大小以便留出软键盘的空间,或是否窗口上的内容得到屏幕上当前的焦点是可见的。系统将自动选择这些模式中一种主要依赖于是否窗口的内容有任何布局视图能够滚动他们的内容。如果有这样的一个视图,这个窗口将调整大小,这样的假设可以使滚动窗口的内容在一个较小的区域中可见的。这个是主窗口默认的行为设置。
·“adjustResize” 该Activity主窗口总是被调整屏幕的大小以便留出软键盘的空间。
·“adjustPan” 该Activity主窗口并不调整屏幕的大小以便留出软键盘的空间。相反,当前窗口的内容将自动移动以便当前焦点从不被键盘覆盖和用户能总是看到输入内容的部分。这个通常是不期望比调整大小,因为用户可能关闭软键盘以便获得与被覆盖内容的交互操作。
 

 

四、效果图

 

 
   


 

 

五、续言

Fragment是Android 3.0 引入的新API,他使开发的效率更加高效,在前面的例子我们也看到Fragment不止能解决Android Pad屏幕比较大,空间不能充分利用的问题,即使只是在手机上,也有很多的场景可以运用到Fragment,我们可能会注意到很多手机应用都会有一个非常类似的功能——即屏幕的下方显示一行Tab标签选项,点击不同的标签就可以切换到不同的界面,例如微信、QQ、支付宝等。大家可能马上就想到了TabHost,但是殊不知,TabHost并非是那么的简单,它的可扩展性非常的差,不能随意地定制Tab项显示的内容,而且运行还要依赖于ActivityGroup。ActivityGroup原本主要是用于为每一个TabHost的子项管理一个单独的Activity,但目前已经被废弃了。为什么呢?当然就是因为Fragment的出现了!查看Android官方文档中ActivityGroup的描述,如下所示:



可以看到,在API 13的时候Android就已经将ActivityGroup废弃掉了,并且官方推荐的替代方式就是使用Fragment,因为它使用起来更加的灵活。

 

六、源码下载

地址:http://download.csdn.net/download/u012721519/10243603

 

Good luck!

Write by Jimmy.li
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息