1》. TabHost

绿色整体是TabHost,橙色是页签,下面是内容部分,其实是个Activity,布局一般用FrameLayout.
在java中设置好Tabhost:
① 在create ()中调用 initTabHost(),
2》. 实现背景的滑动
绿色整体是TabHost,橙色是页签,下面是内容部分,其实是个Activity,布局一般用FrameLayout.
<TabHost
android:id="@android:id/tabhost"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<!---加入LinearLayout 让 TabWidget在上,FrameLayout在下->
<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"
android:visibility="gone" >
</TabWidget>
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
</FrameLayout>
</LinearLayout>
</TabHost>
小知识:Android:Layout_weight的深刻理解
在java中设置好Tabhost:
① 在create ()中调用 initTabHost(),
private void initTabHost() {
mTabHost = (TabHost) findViewById(android.R.id.tabhost);
addTabSpec("conversation", "会话", R.drawable.tab_conversation, new Intent(this, ConversationUI.class));
addTabSpec("folder", "文件夹", R.drawable.tab_folder, new Intent(this, FolderUI.class));
addTabSpec("group", "群组", R.drawable.tab_group, new Intent(this, GroupUI.class));
}
/**
* 添加一个页签
* @param tag 标记
* @param label 标题
* @param icon 图标
* @param intent 指向的activity
*/
private void addTabSpec(String tag, String label, int icon, Intent intent) {
TabSpec newTabSpec = mTabHost.newTabSpec(tag);
// 设置页签的标题和图标
newTabSpec.setIndicator(label, getResources().getDrawable(icon));
// 设置页签指向的显示内容问activity
newTabSpec.setContent(intent);
// 添加页签
mTabHost.addTab(newTabSpec);
}
它自带的页签不好看,把它的TabWidget Gone掉,然后在下面写上我们自己布局的页签。因为要分成3等分,用一个LinearLayout包裹起来,<LinearLayout> 3个都是相同的布局:
<LinearLayout android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<RelativeLayout
android:id="@+id/rl_conversation"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1" >
<LinearLayout
android:id="@+id/ll_conversation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center_horizontal"
android:orientation="vertical"
android:paddingBottom="5dip"
android:paddingLeft="15dip"
android:paddingRight="15dip"
android:paddingTop="5dip" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/tab_conversation" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dip"
android:text="会话"
android:textColor="@android:color/white" />
</LinearLayout>
</RelativeLayout>
.......
</LinearLayout>
为了增强效果,我们在给页签添加了一个整体背景,而且单个页签添加一个滑动背景,布局中把整个页签包裹下来。
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@android:color/darker_gray"
android:paddingBottom="5dip"
android:paddingTop="5dip" >
<View
android:id="@+id/slide_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/slide_background" />
..........
</RelativeLayout>
下面要获取移动背景的宽和高 ,让它正好包裹住页签中的元素。
private View mSlideView; // 页签的滑动背景
final View llConversation = findViewById(R.id.ll_conversation);
// 初始化滑动背景的宽和高
// 获得视图树的观察者对象, 添加一个当全部布局(layout)完成时的监听事件
llConversation.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
/*** 全局布局完成时回调. */
@Override
public void onGlobalLayout() {
// 移除全局布局的监听事件
llConversation.getViewTreeObserver().removeGlobalOnLayoutListener(this);
// 得到会话布局的参数, 设置给滑动块
LayoutParams lp = (LayoutParams) mSlideView.getLayoutParams();
lp.width = llConversation.getWidth();
lp.height = llConversation.getHeight();
lp.leftMargin = llConversation.getLeft();
mSlideView.setLayoutParams(lp);
}
});
其中 要移除他的监听事件,因为在 onGlobalLayout 设置布局,会调用 measure ---> layout -->draw. 又会触发OnGlobalLayoutListener事件,这样就形成了死循环,所以要移除它。
2》. 实现背景的滑动
private int basicWidth = 0; // 一等分的宽度
private int startX = 0; // 记住上一次移动完成之后的x轴的偏移量
basicWidth = findViewById(R.id.rl_conversation).getWidth();
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.ll_conversation: // 切换到会话页签
if(!"conversation".equals(mTabHost.getCurrentTabTag())) {
mTabHost.setCurrentTabByTag("conversation");
startTranslateAnimation(startX, 0);
startX = 0;
}
break;
case R.id.ll_folder: // 切换到文件夹页签
if(!"folder".equals(mTabHost.getCurrentTabTag())) {
mTabHost.setCurrentTabByTag("folder");
startTranslateAnimation(startX, basicWidth);
startX = basicWidth;
}
break;
case R.id.ll_group: // 切换到群组页签
if(!"group".equals(mTabHost.getCurrentTabTag())) {
mTabHost.setCurrentTabByTag("group");
startTranslateAnimation(startX, basicWidth * 2);
startX = basicWidth * 2;
}
break;
default:
break;
}
}
/**
* 给滑动块执行移动动画
* @param fromXDelta 开始位移x轴的偏移量(都是相对于自身来言的偏移量)
* @param toXDelta 结束位移x轴的偏移量
*/
private void startTranslateAnimation(int fromXDelta, int toXDelta) {
TranslateAnimation ta = new TranslateAnimation(
fromXDelta, toXDelta, 0, 0);
ta.setDuration(500);
ta.setFillAfter(true); // 停留在动画结束的位置上
mSlideView.startAnimation(ta);
}