本文主要解决自定义tabhost的实现,以及集成通过代码动态添加选项卡功能、选项卡水平自动滑动功能、以及通过手势来切换选项卡功能。
下面跟我一起来完成这个完美的解决方案:
1、定义tabwidget选项卡的布局:tab_button.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="119dip" android:layout_height="wrap_content" android:orientation="vertical" > <TextView android:id="@+id/tv_tabs_tabHost" android:layout_width="119dip" android:layout_height="39dip" android:gravity="center" android:text="tab1" /> </LinearLayout>
2、主页面tab控件的布局文件:activity_tabhost.xml
<TabHost android:id="@+id/tabhost" android:layout_width="match_parent" android:layout_height="wrap_content" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <!-- 水平滚动 --> <RelativeLayout android:layout_width="fill_parent" android:layout_height="wrap_content" > <HorizontalScrollView android:id="@+id/hScroller_mytabhostactivity" android:layout_width="fill_parent" android:layout_height="wrap_content" android:fadingEdge="none" android:saveEnabled="false" android:scrollbars="none" > <TabWidget android:id="@android:id/tabs" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </HorizontalScrollView> </RelativeLayout> <FrameLayout android:id="@android:id/tabcontent" android:layout_width="match_parent" android:layout_height="0dip" android:layout_weight="1" /> </LinearLayout> </TabHost>
3、主页面MyTabHostActivity.java
首先定义如下变量:
// tabhost private static TabHost tbProductHost; // 滑动手势 private GestureDetector detector; // tab widget水平滑动条 private HorizontalScrollView hScroller; private int screenWidth;// 屏幕宽度 单位:dp
其中oncreate方法:
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_tabhost); // 初始化tabhost tbProductHost = (TabHost) findViewById(R.id.tabhost); tbProductHost.setup(CaptureMultiActivity.this.getLocalActivityManager()); // 获取手机屏幕的宽高 DisplayMetrics displayMetrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); screenWidth = Methods.px2dip(CaptureMultiActivity.this, displayMetrics.widthPixels);// dp // 初始化TabHost,根据arr for (int i=0;i<10;i++) { View view = LayoutInflater.from(MyTabHostActivity.this).inflate( R.layout.tab_button, null); TextView tView = (TextView) view.findViewById(R.id.tv_tabs_tabHost); tView.setText("tab"+i); tbProductHost.addTab("tab"+i) .setIndicator(view).setContent(MyTabHostActivity.this); updateTab(tbProductHost);//调用方法设置tabWidget选项卡的颜色 tbProductHost.setOnTabChangedListener(new OnTabChangedListener()); } hScroller = (HorizontalScrollView) findViewById(R.id.hScroller_scan); }
其中Methods类中的px2dip(int tt)方法为:
/** * px 转 dip * * @param context * @param pxValue * @return */ public static int px2dip(Context context, float pxValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (pxValue / scale + 0.5f); }
其中updateTab(Tabhost tb)方法主要用于设置tabwidget选项卡的颜色,以及选中时的颜色如下:
/** * 更新Tab标签的颜色,和字体的颜色 * * @param tabHost */ private void updateTab(final TabHost tabHost) { for (int i = 0; i < tabHost.getTabWidget().getChildCount(); i++) { View view = tabHost.getTabWidget().getChildAt(i); TextView tv = (TextView) tabHost.getTabWidget().getChildAt(i) .findViewById(R.id.tv_tabs_tabHost); tv.setTextSize(16); tv.setTypeface(Typeface.SERIF, 2); // 设置字体和风格 if (tabHost.getCurrentTab() == i) {// 选中 view.setBackgroundColor(getResources().getColor( R.color.color_text_red));// 选中后的背景 #eb037f tv.setTextColor(this.getResources().getColorStateList( android.R.color.black)); } else {// 不选中 view.setBackgroundColor(getResources().getColor( R.color.color_text_yellow));// 非选择的背景 #f8c514 tv.setTextColor(this.getResources().getColorStateList( android.R.color.white)); } } }
其中OnTabChangedListener类:
class OnTabChangedListener implements OnTabChangeListener { @Override public void onTabChanged(String tabId) { tbProductHost.setCurrentTabByTag(tabId); System.out.println("tabid " + tabId); System.out.println("curreny after: " + tbProductHost.getCurrentTabTag()); updateTab(tbProductHost); } }
另外MyTabHostActivity类要实现TabContentFactory, OnGestureListener共计两个接口,并实现里面的方法:
@Override public View createTabContent(String arg0) { // 初始化tabHost里面某一个选项卡的内容,可以通过Inflater来加载已经定义好的xml布局文件 //to-do return view; } public void flingLeft() { // 切换选项卡 int currentTab = tbProductHost.getCurrentTab(); if (currentTab != 0) { currentTab--; switchTab(currentTab); } // 水平滑动 hScrollManagment(true, currentTab); } public void flingRight() { // 切换选项卡 int currentTab = tbProductHost.getCurrentTab(); if (currentTab != tbProductHost.getTabWidget().getChildCount()) { currentTab++; switchTab(currentTab); } // 水平滑动 hScrollManagment(false, currentTab); } //用于在切换选项卡时自动居中所选中的选项卡的位置 private void hScrollManagment(boolean isToLeft, int currentTab) { int count = tbProductHost.getTabWidget().getChildCount(); System.out.println("000111:hScrollManagment count=" + count); if (179 * count > screenWidth) { int nextPosX = (int) (currentTab + 0.5) * 179 - screenWidth / 2;//此处的179可以自行修改 // hScroller.scrollTo(nextPosX, 0); hScroller.smoothScrollTo(nextPosX, 0); } } private static void switchTab(final int toTab) { new Thread(new Runnable() { @Override public void run() { tbProductHost.post(new Runnable() { @Override public void run() { tbProductHost.setCurrentTab(toTab); } }); } }).start(); } @Override public boolean onTouchEvent(MotionEvent event) { return this.detector.onTouchEvent(event); } @Override public boolean onDown(MotionEvent arg0) { // TODO Auto-generated method stub return false; } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { if (e1.getX() - e2.getX() < -120) { flingLeft(); return true; } else if (e1.getX() - e2.getX() > 120) { flingRight(); return true; } return false; } @Override public void onLongPress(MotionEvent e) { // TODO Auto-generated method stub } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { // TODO Auto-generated method stub return false; } @Override public void onShowPress(MotionEvent e) { // TODO Auto-generated method stub } @Override public boolean onSingleTapUp(MotionEvent e) { // TODO Auto-generated method stub return false; }