这篇文章主要是分析网易主页的tabhost的制作和动态的移动背景实现,首先说一下tabhost这个组件,android原生的tabhost的tab导航是在屏幕上方显示显示的,如果要使tab导航在屏幕下方需要在xml布局文件中把TabWidget布局到tabcontent下方即可,下面来看下具体是怎样布局的:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TabHost android:id="@+id/tabhost" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_below="@id/column_navi" > <FrameLayout android:id="@android:id/tabcontent" android:layout_width="fill_parent" android:layout_height="fill_parent" android:paddingBottom="41.0dip" > <LinearLayout android:id="@+id/tab_news" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > </LinearLayout> <FrameLayout android:id="@+id/tab_topic" android:layout_width="fill_parent" android:layout_height="fill_parent" > </FrameLayout> <LinearLayout android:id="@+id/tab_images" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/pictures_bg" android:gravity="center" android:orientation="vertical" > </LinearLayout> <LinearLayout android:id="@+id/tab_notes" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > </LinearLayout> <RelativeLayout android:id="@+id/tab_vote" android:layout_width="fill_parent" android:layout_height="fill_parent" > <ImageView android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="@drawable/top_weight_bg" /> </RelativeLayout> <include android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_gravity="center" layout="@layout/loadingbar" /> </FrameLayout> <RelativeLayout android:layout_width="fill_parent" android:layout_height="fill_parent" > <TabWidget android:id="@android:id/tabs" android:layout_width="fill_parent" android:layout_height="43.0dip" android:layout_alignParentBottom="true" android:background="@drawable/tab_bg" /> <ImageView android:id="@+id/tab_front_bg" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="@android:id/tabs" android:layout_alignLeft="@android:id/tabs" android:src="@drawable/tab_front_bg" /> <ImageView android:id="@+id/tab_bg_bg" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_above="@android:id/tabs" android:background="@drawable/bottom_weight_bg" /> </RelativeLayout> </TabHost> </LinearLayout>
大家可以看到在TabWidget标签下面放了2张图片,这2张图片分别是实现动态移动的背景图片和TabWidget的整体背景图片,通过分析这2张图片的布局方式大家应该可以看得出来,这里都不多说。
现在布局弄好了,现在的问题就是怎样让我们选着一个tab项后面的背景也跟这移动到我选择的位置呢?
其实很简单,我是这样实现的,首先在给tab标签添加setIndicator(View view)的时候加入自定义的view,然后分别给自定义view控件添加onTouch()监听,监听的作用就是每次手指点击到这个控件时,就获取这个控件在屏幕上的坐标位置,然后让tab_front_bg图片移动到当前坐标即可。具体实现背景移动的细节可以参考我的另一片文章http://blog.csdn.net/yaoyeyzq/article/details/7579938
下面是实现的部分源码:
import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.Window; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TabHost; import android.widget.TextView; import com.yzq.text.custom.TabListener; public class TestActivity extends Activity { /** Called when the activity is first created. */ // private ScrollLayout scroll; private ImageView tab_front_bg; private TabHost host; private TabListener tabListener; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.main); initView(); } private void initView() { host = (TabHost) findViewById(R.id.tabhost); tab_front_bg = (ImageView) findViewById(R.id.tab_front_bg); host.setup(); tabListener = new TabListener(tab_front_bg, this, host); host.addTab(host.newTabSpec("xw").setIndicator(getIndicatorView(1)) .setContent(R.id.tab_news)); host.addTab(host.newTabSpec("ht").setIndicator(getIndicatorView(2)) .setContent(R.id.tab_topic)); host.addTab(host.newTabSpec("tp").setIndicator(getIndicatorView(3)) .setContent(R.id.tab_images)); host.addTab(host.newTabSpec("gt").setIndicator(getIndicatorView(4)) .setContent(R.id.tab_notes)); host.addTab(host.newTabSpec("tp").setIndicator(getIndicatorView(5)) .setContent(R.id.tab_vote)); host.setCurrentTab(0); } private View getIndicatorView(int location) { LinearLayout layout = new LinearLayout(this); TextView textView = new TextView(this); switch (location) { case 1: textView.setId(R.id.news); textView.setBackgroundDrawable(getResources().getDrawable( R.drawable.current_news_tab)); break; case 2: textView.setId(R.id.topic); textView.setBackgroundDrawable(getResources().getDrawable( R.drawable.back_topic_tab)); break; case 3: textView.setId(R.id.picture); textView.setBackgroundDrawable(getResources().getDrawable( R.drawable.back_picture_tab)); break; case 4: textView.setId(R.id.comment); textView.setBackgroundDrawable(getResources().getDrawable( R.drawable.back_comment_tab)); break; case 5: textView.setId(R.id.vote); textView.setBackgroundDrawable(getResources().getDrawable( R.drawable.back_vote_tab)); break; } LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(-1, -1); textView.setOnTouchListener(tabListener); layout.addView(textView, params); return layout; } }
下面是移动背景和动态改变tab图片状态的具体实现源码:
import android.app.Activity; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import android.view.animation.Animation; import android.view.animation.Animation.AnimationListener; import android.view.animation.TranslateAnimation; import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.RelativeLayout.LayoutParams; import android.widget.TabHost; import android.widget.TextView; import com.yzq.test.R; /** * @author Administrator * */ public class TabListener implements OnTouchListener { private int lastX = 0; private TextView up_text; private ImageView column_slide_bar; private Activity cotext; private TabHost host; public TabListener(ImageView column_slide_bar, Activity cotext, TabHost host) { super(); this.column_slide_bar = column_slide_bar; this.cotext = cotext; this.host = host; } /* * (non-Javadoc) * * @see android.view.View.OnTouchListener#onTouch(android.view.View, * android.view.MotionEvent) */ @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { if (up_text != null) { switch (up_text.getId()) { case R.id.news: up_text.setBackgroundDrawable(cotext.getResources() .getDrawable(R.drawable.back_news_tab)); break; case R.id.topic: up_text.setBackgroundDrawable(cotext.getResources() .getDrawable(R.drawable.back_topic_tab)); break; case R.id.picture: up_text.setBackgroundDrawable(cotext.getResources() .getDrawable(R.drawable.back_picture_tab)); break; case R.id.comment: up_text.setBackgroundDrawable(cotext.getResources() .getDrawable(R.drawable.back_comment_tab)); break; case R.id.vote: up_text.setBackgroundDrawable(cotext.getResources() .getDrawable(R.drawable.back_vote_tab)); break; } } else { TextView news = (TextView) cotext.findViewById(R.id.news); news.setBackgroundDrawable(cotext.getResources().getDrawable( R.drawable.back_news_tab)); } translateImage(event); TextView tv = (TextView) v; switch (tv.getId()) { case R.id.news: tv.setBackgroundDrawable(cotext.getResources().getDrawable( R.drawable.current_news_tab)); host.setCurrentTab(0); break; case R.id.topic: tv.setBackgroundDrawable(cotext.getResources().getDrawable( R.drawable.current_topic_tab)); host.setCurrentTab(1); break; case R.id.picture: tv.setBackgroundDrawable(cotext.getResources().getDrawable( R.drawable.current_picture_tab)); host.setCurrentTab(2); break; case R.id.comment: tv.setBackgroundDrawable(cotext.getResources().getDrawable( R.drawable.current_comment_tab)); host.setCurrentTab(3); break; case R.id.vote: tv.setBackgroundDrawable(cotext.getResources().getDrawable( R.drawable.current_vote_tab)); host.setCurrentTab(4); break; } up_text = tv; } return true; } private void translateImage(MotionEvent event) { float x = event.getX(); float rx = event.getRawX(); final float nx = rx - x; TranslateAnimation trans = null; if (nx > lastX) { trans = new TranslateAnimation(0, nx - lastX, 0, 0); } else if (nx < lastX) { trans = new TranslateAnimation(0, (lastX - nx) * -1, 0, 0); } else { return; } trans.setDuration(300); trans.setAnimationListener(new AnimationListener() { @Override public void onAnimationStart(Animation animation) { // TODO Auto-generated method stub } @Override public void onAnimationRepeat(Animation animation) { // TODO Auto-generated method stub } @Override public void onAnimationEnd(Animation animation) { RelativeLayout.LayoutParams params = (LayoutParams) column_slide_bar .getLayoutParams(); params.leftMargin = (int) nx; column_slide_bar.setLayoutParams(params); } }); trans.setFillEnabled(true); column_slide_bar.startAnimation(trans); lastX = (int) nx; } }