android--解决方案--自定义tabhost(动态添加选项+带自动水平滑动选项卡+手势切换选项卡及内容功能)

本文主要解决自定义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;
	}

至此,一个完美的tabhost自定义解决方案完成。

时间: 2024-11-05 12:09:48

android--解决方案--自定义tabhost(动态添加选项+带自动水平滑动选项卡+手势切换选项卡及内容功能)的相关文章

android 在布局中动态添加控件

第一步 Java代码 final LayoutInflater inflater = LayoutInflater.from(this); 第二步:获取需要被添加控件的布局 Java代码 final LinearLayout lin = (LinearLayout) findViewById(R.id.LinearLayout01); 第三步:获取需要添加的布局(控件) Java代码 LinearLayout layout = (LinearLayout) inflater.inflate( R

Android在布局中动态添加view的两种方法

一.说明 添加视图文件的时候有两种方式:1.通过在xml文件定义layout:2.java代码编写 二.前言说明 1.构造xml文件 2.LayoutInflater 提到addview,首先要了解一下LayoutInflater类.这个类最主要的功能就是实现将xml表述的layout转化为View的功能.为了便于理解,我们可以将它与findViewById()作一比较,二者都是实例化某一对象,不同的是findViewById()是找xml布局文件下的具体widget控件实例化,而LayoutI

Android ListView分页,动态添加数据

1.ListView分页的实现,重点在于实现OnScrollListener接口,判断滑动到最后一项时,是否还有数据可以加载, 我们可以利用listView.addFootView(View v)方法进行提示 自定义一个ListView(这里本来想进行一些自定已修改的...实际代码并没有做)CornerListView package com.example.testlistview; import android.widget.AbsListView; import android.conte

Android 4.4.2 动态添加JNI库方法记录 (一 JNI库层)

欢迎转载,但必须注明出处.http://blog.csdn.net/wang_shuai_ww/article/details/44456755 本篇是继<s5p4418 Android 4.4.2 驱动层 HAL层 服务层 应用层 开发流程记录>之后的另外一种添加JNI和服务的方法. 前面的方法是直接把HAL和服务层添加到了,Android的api中,这样的方式好处是操作系统已开发完成,剩下做APP的开发,那么我们只需要一个classes.jar文件即可使用我们自己Android系统的被隐藏

easyui-combobox 动态添加选项option

根据后台数据添加: $("#themecombo").combobox({ url:'<%=basePath%>analysis/getactivit.action', valueField:'id', textField:'title', editable:false }); 然后想在最前面添加一个空选项: $(document).ready( function(){ $.ajax({ url:'<%=basePath%>analysis/getactivit

select框动态添加选项

$.ajax({ url : "${staticServer }/ywgl/zkpzgl/zkfkgl/showBillType.htm", //ajax请求路径 type : "post", //请求方式 data : "", //请求时发送的数据 async:true, //是否异步 dataType : "json", //数据格式 success : function(r){ //访问成功时调用的方法(其中r时是返回的

Android 4.4.2 动态添加JNI库方法记录 (二 app应用层)

欢迎转载,务必注明出处:http://blog.csdn.net/wang_shuai_ww/article/details/44458553 源码下载地址:http://download.csdn.net/detail/u010406724/8515377 本篇介绍怎么使用前面建立好的库文件. 要使用JNI库文件,那么首先我们是需要把它加载到系统中,并对其定义接口,供给应用来调用. 建立一个工程,我的工程名为RealArmTest,过程就省略了,完成后再在src下建立一个类,不继承其他类,包名

【Android】自定义相机的实现(支持连续拍照、前后摄像头切换、连续对焦)

~转载请注明http://blog.csdn.net/u013015161/article/details/46921257 介绍 这几天,写了一个自定义照相机的demo,支持连续拍照和摄像头切换.由于自己以前没接触过相关的编程,也算是一个学习的过程,在这里做一下记录,同时也分享出来,并附上源码和工程. 效果如图: 左上角switch切换摄像头,右边snap按钮进行拍照. 一般流程 Android进行拍照,需要调用摄像头类android.hardware.Camera.而要进行预览,则需要用an

【Android】自定义ImageView实现图片的平移、缩放、旋转(手势操作)

http://blog.csdn.net/happy_bug/article/details/7895244 在网上搜到很多都是一样的版本,只有平移和缩放的功能.我在搜到的源代码基础上添加了旋转和边界检查的功能.