在Android应用中,一般TabActivity和若干个Tab选项卡(TabWidget)。如果选项卡的数量超过了5个,就不适合放到一个屏幕中,这样可以让这些选项卡滑动起来。
滑动的选项卡的实现有好几种方式,在这些方式中,最简单也是我最满意的还是在原生的TabActivity上修改,将上面的选项卡改为可滑动的状态。这样既有新的滑动的效果,也保留了原有TabActivity的各项功能。
实现Tab可滑动基本的思路就是把上面的TabWidget放到一个HorizontalScrollView中,让TabWidget滑动起来。不过如果仅仅修改XML还是会产生问题,就是没有办法控制每个选项卡的宽度。所以还是需要在程序中设置每个选项卡的宽度。例如:
// 设置窗口的宽度 DisplayMetrics dm = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(dm); int screenWidth = dm.widthPixels; if (count < 4) { for (int i = 0; i < count; i++) { // 设置每个选项卡的宽度 tabWidget.getChildTabViewAt(i).setMinimumWidth(screenWidth / 4); } }
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <tabhost android:id="@android:id/tabhost" android:layout_width="fill_parent" android:layout_height="fill_parent"> <linearlayout android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <horizontalscrollview android:layout_height="wrap_content" android:layout_width="fill_parent" android:scrollbars="none"> <tabwidget android:id="@android:id/tabs" android:layout_width="fill_parent" android:layout_height="60dp" /> <framelayout android:id="@android:id/tabcontent" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" />
效果图如下:
package com.xu81.testflip; import java.util.Vector; import android.content.Context; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.widget.Scroller; public class ScrollLayout extends ViewGroup { private Scroller mScroller; private VelocityTracker mVelocityTracker; private int mCurScreen; private int mDefaultScreen = 0; private static final int TOUCH_STATE_REST = 0; private static final int TOUCH_STATE_SCROLLING = 1; private static final int SNAP_VELOCITY = 500; private int mTouchState = TOUCH_STATE_REST; private int mTouchSlop; private float mLastMotionX; private int sensitivity = 30; private boolean spring; private Vector listeners; public ScrollLayout(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub mScroller = new Scroller(context); mCurScreen = mDefaultScreen; mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); listeners = new Vector(); } public void addChangeListener(LayoutChangeListener listener) { listeners.add(listener); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { // TODO Auto-generated method stub int childLeft = 0; final int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { final View childView = getChildAt(i); if (childView.getVisibility() != View.GONE) { final int childWidth = childView.getMeasuredWidth(); childView.layout(childLeft, 0, childLeft + childWidth, childView.getMeasuredHeight()); childLeft += childWidth; } } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); final int width = MeasureSpec.getSize(widthMeasureSpec); final int widthMode = MeasureSpec.getMode(widthMeasureSpec); if (widthMode != MeasureSpec.EXACTLY) { throw new IllegalStateException( "ScrollLayout only canmCurScreen run at EXACTLY mode!"); } final int heightMode = MeasureSpec.getMode(heightMeasureSpec); if (heightMode != MeasureSpec.EXACTLY) { throw new IllegalStateException( "ScrollLayout only can run at EXACTLY mode!"); } // The children are given the same width and height as the scrollLayout final int count = getChildCount(); for (int i = 0; i < count; i++) { getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec); } scrollTo(mCurScreen * width, 0); } public void snapToDestination() { final int screenWidth = getWidth(); final int destScreen = (getScrollX() + screenWidth / 2) / screenWidth; snapToScreen(destScreen); } public void snapToScreen(int whichScreen) { // get the valid layout page int lastIndex = mCurScreen; whichScreen = Math.max(0, Math.min(whichScreen, getChildCount() - 1)); if (getScrollX() != (whichScreen * getWidth())) { final int delta = whichScreen * getWidth() - getScrollX(); mScroller.startScroll(getScrollX(), 0, delta, 0, Math.abs(delta) * 2); mCurScreen = whichScreen; invalidate(); // Redraw the layout } for (LayoutChangeListener listener : listeners) listener.doChange(lastIndex, whichScreen); } public void setToScreen(int whichScreen) { whichScreen = Math.max(0, Math.min(whichScreen, getChildCount() - 1)); mCurScreen = whichScreen; scrollTo(whichScreen * getWidth(), 0); } public int getCurScreen() { return mCurScreen; } @Override public void computeScroll() { // TODO Auto-generated method stub if (mScroller.computeScrollOffset()) { scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); postInvalidate(); } } public boolean isSpring() { return spring; } public void setSpring(boolean spring) { this.spring = spring; } @Override public boolean onTouchEvent(MotionEvent event) { // TODO Auto-generated method stub if (mVelocityTracker == null) mVelocityTracker = VelocityTracker.obtain(); mVelocityTracker.addMovement(event); final int action = event.getAction(); final float x = event.getX(); switch (action) { case MotionEvent.ACTION_DOWN: if (!mScroller.isFinished()) mScroller.abortAnimation(); mLastMotionX = x; break; case MotionEvent.ACTION_MOVE: int deltaX = (int) (mLastMotionX - x); if (Math.abs(deltaX) > sensitivity) { // 左滑动为正数、右为负数 if (spring) { scrollBy(deltaX, 0); mLastMotionX = x; } else { final int childCount = getChildCount(); boolean max = mCurScreen < childCount - 1; boolean min = mCurScreen > 0; boolean canMove = deltaX > 0 ? (max ? true : false) : (min ? true : false); if (canMove) { scrollBy(deltaX, 0); mLastMotionX = x; } } } break; case MotionEvent.ACTION_UP: final VelocityTracker velocityTracker = mVelocityTracker; velocityTracker.computeCurrentVelocity(1000); int velocityX = (int) velocityTracker.getXVelocity(); if (velocityX > SNAP_VELOCITY && mCurScreen > 0) { // Fling enough to move left snapToScreen(mCurScreen - 1); } else if (velocityX < -SNAP_VELOCITY && mCurScreen < getChildCount() - 1) { // Fling enough to move right snapToScreen(mCurScreen + 1); } else { snapToDestination(); } if (mVelocityTracker != null) { mVelocityTracker.recycle(); mVelocityTracker = null; } mTouchState = TOUCH_STATE_REST; break; case MotionEvent.ACTION_CANCEL: mTouchState = TOUCH_STATE_REST; break; } return true; } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { // TODO Auto-generated method stub final int action = ev.getAction(); if ((action == MotionEvent.ACTION_MOVE) && (mTouchState != TOUCH_STATE_REST)) return true; final float x = ev.getX(); switch (action) { case MotionEvent.ACTION_MOVE: final int xDiff = (int) Math.abs(mLastMotionX - x); if (xDiff > mTouchSlop) mTouchState = TOUCH_STATE_SCROLLING; break; case MotionEvent.ACTION_DOWN: mLastMotionX = x; mTouchState = mScroller.isFinished() ? TOUCH_STATE_REST : TOUCH_STATE_SCROLLING; break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: mTouchState = TOUCH_STATE_REST; break; } return mTouchState != TOUCH_STATE_REST; } }
这是模仿qq的滑动实现,和tab不是一个思路,也比较美观实用可以借鉴
附件源码下载...
相关推荐
需要导入一下jar包~在libs文件夹中
TabHostActivity在API 13之后就不能用了。 写了个Demo,用FragmentActivity + Tabhost实现多标签页,并添加滑动手势。 API=19,可运行
很多情况下,我们需要用到标签,类似于微末下面的标签效果,直接使用系统默认的往往不能满足项目的需求,就需要我们自定义一个TabHost。下面我把在项目的实现的效果分享给大家,希望能帮助需要的朋友!
以前做这种新闻标签页都是用...当把api升级到最新后发现这个LocalActivityManager已经被废弃了,取而代之的是FragmentManager,经过一下午的研究终于用FragmentManager实现了新闻滑动标签页的效果。
ListView +ViewPage+Fragmen+TabHost滑动效果,外加上拉刷新,下拉加载更多 按钮跳转
在Android下实现的tabhost的滑动翻页的效果。
Android可以点击切换和滑动切换的tabhost
android实现可滑动的tabhost,点击每一个tab,可进行页面的切换,也可以根据手势来滑动每一个页面。用户体验相当的好啊··
1.利用tabHost加ViewPager实现滑动的切换选项卡 2.有详细的注释,可自行修改界面风格 3.项目基于2.2开发,可兼容所有手机
安卓Android源码——ViewPager和Tabhost结合,可滑动的tabhost.rar
自定义Android中TabHost组件显示在屏幕底部,并实现滑动切换页面。在此基础上可以实现类似米聊等软件主界面的Tab效果。
android实现可滑动标签页有很多方法,这里给大家介绍一种官方推荐,性能最高,并且代码最少的方式,就是利用FragmentTabhost+ViewPager+FragmentPagerAdapter来实现。
最近在使用TabHost的时候遇到了一些奇怪的问题,在这里总结分享备忘一下。
安卓Android源码——ViewPager和Tabhost结合,可滑动的tabhost.zip
ListView +ViewPage+Fragmen+TabHost滑动效果,外加上拉刷新,下拉加载更多
简单的例子 能够运行流畅 是想手机一样的 通过手指左右滑动切换tabhost
利用Tabhost + Fragment实现android标签切换界面.
可以滑动的TabHost 基于ViewPaget实现 可能需要导入包,在libs中
viewPager和tabhost组合滑动,源码,代码详细,tabhost上有箭头随选择进行滑动,有注释,需有android-support-v4.jar包支持
前几年的Android应用源码Demo,主要面向的是学生毕业设计学习。