1.TabActivity、视图树、动画
整个页面为TabActivity, 其中对TabWidget进行了一些改变,当切换页签时页签后面红色背景会以Translate动画形式移动到相对应的页签后。
布局
TabHost、TabWidget、FrameLayout的id必须是系统定义的,
因为可以直接get获取控件,上面的Tab标签一般不写原生的,自己写。
把原生的TabWidget隐藏,用了个垂直的LinearLayout写,
下面是FrameLayout,也是TabHost必须写的
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<TabHost
android:id="@android: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" >
<TabWidget
android:id="@android:id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone" >
</TabWidget>
<!-- 自定义导航 -->
<RelativeLayout
android:layout_width="match_parent"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:layout_height="wrap_content"
android:background="@android:color/darker_gray"
>
<ImageView
android:id="@+id/iv_slide_backgrounp"//阴影图片
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/slide_background" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<!-- 第一个三分之一 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:gravity="center_horizontal"
android:orientation="horizontal" >
<!-- 会话标签 -->
<LinearLayout
android:id="@+id/ll_conversation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingLeft="10dp"
android:paddingRight="10dp" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/tab_conversation" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="会话" />
</LinearLayout>
</LinearLayout>
<!-- 第二个三分之一 -->
。。。。。。。
<!-- 第三个三分之一 -->
- 。。。。。。。。跟上面一样
</LinearLayout>
</RelativeLayout>
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</FrameLayout>
</LinearLayout>
</TabHost>
</RelativeLayout>
代码:
阴影图片默认是这样的,用动画去动态的变化位置,其实图片还是在那了,只是个动画
public class MainActivity extends TabActivity implements OnClickListener {
private TabHost tabHost;
private LinearLayout llConversation;//会话
private LinearLayout llFolder;//文件夹
private LinearLayout llGroup;//群组
private ImageView slideBackGround;//导航图片
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tabHost = getTabHost();//直接get获取
addTab("conversation","会话",R.drawable.tab_conversation,ConversationUI.class);
addTab("folder","文件夹",R.drawable.tab_folder,FolderUI.class);
addTab("group","群组",R.drawable.tab_group,GroupUI.class);
//都是activity
llConversation = (LinearLayout) findViewById(R.id.ll_conversation);
llFolder = (LinearLayout) findViewById(R.id.ll_folder);
llGroup = (LinearLayout) findViewById(R.id.ll_group);
llConversation.setOnClickListener(this);
llFolder.setOnClickListener(this);
llGroup.setOnClickListener(this);
slideBackGround = (ImageView) findViewById(R.id.iv_slide_backgrounp);
// 此时 llConversation 仅仅创建了对象,还没有执行onMeasure 和 onLayout 方法 ,所以,此时 getWidth 返回值是0
//System.out.println("llConversation.getWidth()::"+llConversation.getWidth());
// 获得全局viewTree的观察者,并添加 全局的layout监听
llConversation.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
//由于此方法会执行多次,而我们只需要执行一次就可以了,
//所以,在执行一次的时候,将全局的layout监听取消,,此处 this 指的是,内部的匿名对象
llConversation.getViewTreeObserver().removeGlobalOnLayoutListener(this);
System.out.println("llConversation.getWidth()::"+llConversation.getWidth());
//设置图片的宽高,与会话标签相同
int width = llConversation.getWidth();
int height = llConversation.getHeight();
//
slideBackGround的layoutParams 是没有leftMargin这个属性的,所以强转RelativeLayout.LayoutParams layoutParams = (android.widget.RelativeLayout.LayoutParams) slideBackGround.getLayoutParams();
layoutParams.width = width;
layoutParams.height = height;
//设置图片的左边距与会话的左边距相同
int left = llConversation.getLeft();// 获得llConversation 在他的父view中左边距
layoutParams.leftMargin =left;
// 将 llConversation的父view的宽度,设置给 itemLength,需要动态的变化
itemLength = ((ViewGroup)llConversation.getParent()).getWidth();
}
});
}
/**
* 背景图片移动的单位宽度,即,屏幕的1/3
*/
private int itemLength;
/**
* 给tabHost添加标签
* @param tag 标签的命名
* @param label 标签显示的文字
* @param iconId 标签显示的图标
* @param clazz 该标签对应的显示内容
*/
private void addTab(String tag, CharSequence label, int iconId, Class<?> clazz){
//创建新的 标签 tag 是该标签的命名,此命名是tabHost用来管理标签的标示。
TabSpec tabSpec =tabHost.newTabSpec(tag);
//给标签添加 文字,和图标
tabSpec.setIndicator(label, getResources().getDrawable(iconId));
// 给标签添加对应的显示内容
Intent intent = new Intent(this,clazz);
tabSpec.setContent(intent);
tabHost.addTab(tabSpec);
}
/**
* 滑动背景的上一个位置
*/
private int lastPosition;
@Override
/**
* 响应标签的点击事件
*/
public void onClick(View v) {
switch (v.getId()) {
case R.id.ll_conversation:// 会话标签
// 判断当前页面是否是 会话页面,如果不是,切换至会话页面,
if(!"conversation".equals(tabHost.getCurrentTabTag())){
tabHost.setCurrentTabByTag("conversation");
slideBackGround.startAnimation(getAnim(0));
lastPosition = 0;
}
break;
case R.id.ll_folder:// 文件夹标签
// 判断当前页面是否是文件夹页面,如果不是,切换至
if(!"folder".equals(tabHost.getCurrentTabTag())){
tabHost.setCurrentTabByTag("folder");
slideBackGround.startAnimation(getAnim(itemLength));
lastPosition = itemLength;
}
break;
case R.id.ll_group:// 群组标签
// 判断当前页面是否是文件夹页面,如果不是,切换至
if(!"group".equals(tabHost.getCurrentTabTag())){
tabHost.setCurrentTabByTag("group");
slideBackGround.startAnimation(getAnim(itemLength*2));
lastPosition = itemLength*2;
}
break;
}
}
private TranslateAnimation getAnim(int destPosition) {
TranslateAnimation anim = new TranslateAnimation(lastPosition, destPosition, 0, 0);
anim.setDuration(500);
anim.setFillAfter(true);
return anim;
}
}