android选项卡左右滑动切换,TabHost通过手势切换Activity,滑动效果

一、自定义一个AnimationTabHost组件

----------------------------------------------------------------------------------------------

AnimationTabHost.java代码

/**继承TabHost组件,带有切入切出的滑动动画效果。*/

publicclassAnimationTabHostextendsTabHost {

privateAnimationslideLeftIn;

privateAnimationslideLeftOut;

privateAnimationslideRightIn;

privateAnimationslideRightOut;

/**记录是否打开动画效果*/

privatebooleanisOpenAnimation;

/**记录当前标签页的总数*/

privateintmTabCount;

publicAnimationTabHost(Context

context, AttributeSet attrs) {

super(context, attrs);

slideLeftIn= AnimationUtils.loadAnimation(context,

R.anim.slide_left_in);

slideLeftOut= AnimationUtils.loadAnimation(context,

R.anim.slide_left_out);

slideRightIn= AnimationUtils.loadAnimation(context,

R.anim.slide_right_in);

slideRightOut= AnimationUtils.loadAnimation(context,

R.anim.slide_right_out);

isOpenAnimation=false;

}

/**

*设置是否打开动画效果

*@paramisOpenAnimation

*            true:打开

*/

publicvoidsetOpenAnimation(booleanisOpenAnimation) {

this.isOpenAnimation= isOpenAnimation;

}

说明:这里的Animation都是自定义的动画效果,可以在res/anim中找到对应的XML文件,下面用slide_left_in.xml来说明定义的大概用法

slide_left_in.xml

android:toXDelta="0"

android:duration="800"/>

android:toAlpha="1.0"

android:duration="300"/>

说明:

①因为这个动画是由几个动画复合组成的,所以外围就用一个set标签括起来,组成一个AnimationSet。

②Translate标签内主要定义位置的变化情况,fromXDelta="100%p",为动画起始时,X坐标上的伸缩尺寸。是指正下方刚好一个View的高度的距离的地方开始出现,100%p是一个相对值,大于0为下方,小于0为上方。toXDelta="0",为动画结束时,X坐标上的伸缩尺寸。另:0.0表示收缩到没有(即刚好达到布局文件的原始位置停止),1.0表示正常无伸缩,值小于1.0表示收缩,值大于1.0表示放大。

③参数fromXDelta和toXDelta都是指控件相对于parent的偏移距离,100%p就是正好在parent外面。左右是from和to来决定的(就是在根的左和右)。

④duration="800",是指整个动作的时间用时为800毫秒,系统会根据这个时间自动调整速度。

⑤alpha标签内定义的是透明度,0为全透明,1.0为不透明,过程为300毫秒,让View为逐渐出现的过程。

/**

*设置标签滑动动画。

*动画顺序为“左进——>左出——>右进——>右出”

*

*@paramanimationResIDs

*动画的资源文件ID

*@returntrue:四个动画文件;

*         false:非四个动画文件(无法匹配,采用默认动画)

*/

publicbooleansetTabAnimation(int[] animationResIDs) {

if(3 == animationResIDs.length) {

slideLeftIn= AnimationUtils.loadAnimation(getContext(),

animationResIDs[0]);

slideLeftOut= AnimationUtils.loadAnimation(getContext(),

animationResIDs[1]);

slideRightIn= AnimationUtils.loadAnimation(getContext(),

animationResIDs[2]);

slideRightOut=AnimationUtils.loadAnimation(getContext(),

animationResIDs[3]);

returntrue;

}else{

returnfalse;

}

}

/**

*@return返回当前标签页的总数

*/

publicintgetTabCount() {

returnmTabCount;

}

@Override

publicvoidaddTab(TabSpec tabSpec) {

mTabCount++;

super.addTab(tabSpec);

}

@Override

publicvoidsetCurrentTab(intindex) {

intmCurrentTabID = getCurrentTab();

if(null!= getCurrentView()) {

//第一次设置Tab时,该值为null。

if(isOpenAnimation) {

if(mCurrentTabID == (mTabCount- 1) && index == 0) {

getCurrentView().startAnimation(slideLeftOut);

}elseif(mCurrentTabID == 0

&& index == (mTabCount- 1)) {

getCurrentView().startAnimation(slideRightOut);

}elseif(index > mCurrentTabID)

{

getCurrentView().startAnimation(slideLeftOut);

}elseif(index < mCurrentTabID)

{

getCurrentView().startAnimation(slideRightOut);

}

}

}

super.setCurrentTab(index);

if(isOpenAnimation) {

if(mCurrentTabID == (mTabCount- 1) && index ==

0) {

getCurrentView().startAnimation(slideLeftIn);

}elseif(mCurrentTabID == 0 && index == (mTabCount- 1)) {

getCurrentView().startAnimation(slideRightIn);

}elseif(index > mCurrentTabID) {

getCurrentView().startAnimation(slideLeftIn);

}elseif(index < mCurrentTabID) {

getCurrentView().startAnimation(slideRightIn);

}

}

}

}

说明:mTabCount为当前标签页的总数。setCurrentTab设置当前标签页。index可以理解为:需要显示的那个标签页。

--------------------------------------------------------------------------------------------

二、TabHost选项卡

TabHostActivity.java代码

publicclassTabHostActivityextendsTabActivityimplementsOnTabChangeListener {

privateGestureDetectorgestureDetector;

privateFrameLayoutframeLayout;

privateAnimationTabHostmTabHost;

privateTabWidgetmTabWidget;

/**记录当前分页ID */

privateintcurrentTabID= 0;

@Override

protectedvoidonCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.tab_host_test_view);

说明:

①OnTabChangeListener接口,标签切换事件监听

②使用TabHost有两种方法,一种是继承TabActivity;一种是不继承TabActivity;在这里是继承TabActivity的;首先我们得写好tab_host_test_view.xml布局文件,在写这个布局文件时要注意,使用TabHost一定要有TabWidget、FramLayout这两个控件,并且TabWidget必须使用系统ID @android:id/tabs;FrameLayout作为标签内容的基本框架,也必须使用系统ID

@android:id/tabcontent;而TabHost可以自定义ID,这是为了在系统初始化时能够使用,否则会报错!布局文件tab_host_test_view.xml如下:

-------

tab_host_test_view.xml

xmlns:android="http://schemas.android.com/apk/res/android"android:id="@android:id/tabhost"

android:layout_width="fill_parent"

android:layout_height="fill_parent"android:background="@drawable/default_bg">

android:layout_width="fill_parent"android:layout_height="fill_parent">

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:layout_weight="1.0"

/>

android:padding="3.0dip"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:layout_weight="0.0"

/>

----------

mTabHost=(AnimationTabHost)findViewById(android.R.id.tabhost);

mTabWidget= (TabWidget) findViewById(android.R.id.tabs);

mTabHost.setOnTabChangedListener(this);

init();

gestureDetector=newGestureDetector(newTabHostTouch());

newView.OnTouchListener() {

publicbooleanonTouch(View v, MotionEvent event) {

if(gestureDetector.onTouchEvent(event)) {

returntrue;

}

returnfalse;

}

};

frameLayout=mTabHost.getTabContentView();

Log.i("TabHostActivity",

"TabHostActivity====>>>onCreate()===>>>>frameLayout:

"

+frameLayout.getChildCount());

}

privatevoidinit() {

setIndicator(R.drawable.tab_logo_0, 0,newIntent(this,

TabHostTestOne.class));

setIndicator(R.drawable.tab_logo_1, 1,newIntent(this,

TabHostTestTwo.class));

setIndicator(R.drawable.tab_logo_2, 2,newIntent(this,

TabHostTestThree.class));

setIndicator(R.drawable.tab_logo_3, 3,newIntent(this,

TabHostTestFour.class));

mTabHost.setOpenAnimation(true);

}

privatevoidsetIndicator(inticon,inttabId, Intent intent) {

View localView =

LayoutInflater.from(this.mTabHost.getContext())

.inflate(R.layout.tab_widget_view,null);

((ImageView)

localView.findViewById(R.id.main_activity_tab_image))

.setBackgroundResource(icon);

String str = String.valueOf(tabId);

TabHost.TabSpec

localTabSpec=mTabHost.newTabSpec(str).setIndicator(

localView).setContent(intent);

mTabHost.addTab(localTabSpec);

}

说明:

①mTabHost = (AnimationTabHost) findViewById(android.R.id.tabhost);

mTabWidget = (TabWidget)

findViewById(android.R.id.tabs);

系统自带

②init():初始化。设置各选项卡的icon、id、intent。

③GestureDetector手势识别类。通过GestureDetector.OnGestureListener来获取当前被触发的操作手势。另:使用OnTouchListener可以比OnClickListener获得更细的控制粒度,例如涉及down-touch/up-touch/no-drag,多点,触摸的强度,按下,松开,拖动等。。。。,而OnClickListener只是点击,只适用于组件的事件触发。

④使用setIndicator(localView)把localView添加进去。

publicvoidonTabChanged(String tabId) {

inttabID = Integer.valueOf(tabId);

for(inti = 0; i

if(i == tabID) {

mTabWidget.getChildAt(Integer.valueOf(i)).setBackgroundColor(

R.color.bule);

}else{

mTabWidget.getChildAt(Integer.valueOf(i))

.setBackgroundResource(R.drawable.main_meun_bg);

}

}

}

说明:标签切换事件,使用getChildAt(int i)来取得每个标签

publicbooleandispatchTouchEvent(MotionEvent event) {

if(gestureDetector.onTouchEvent(event)) {

event.setAction(MotionEvent.ACTION_CANCEL);

}

returnsuper.dispatchTouchEvent(event);

}

说明:

dispatchOnTouchEvent()时派发事件,从最上层View开始派发,dispatchOnTouchEvent()返回true时,View将事件派发给自己onTouchEvent()方法处理,如果返回false,则交给interceptTouchEvent来决定是否要拦截,如果返回false,则传给子View,由子View的dispatchTouchEvent()方法再来派发。因此,要清楚自己的view的继承关系,不要派发到父类的窗口就可以了。

如果没有此段代码,点击各Tab,各页面之间跳转会有滑动动画效果,但是无法实现拖动页面时的动画效果。

privateclassTabHostTouchextendsSimpleOnGestureListener {

/**滑动翻页所需距离*/

privatestaticfinalintON_TOUCH_DISTANCE= 80;

publicbooleanonFling(MotionEvent e1,

MotionEvent e2,floatvelocityX,

floatvelocityY) {

if(e1.getX() - e2.getX()

<= (-ON_TOUCH_DISTANCE)) {

currentTabID=mTabHost.getCurrentTab() - 1;

if(currentTabID< 0) {

currentTabID=mTabHost.getTabCount() - 1;

}

}elseif(e1.getX() - e2.getX() >=ON_TOUCH_DISTANCE) {

currentTabID=mTabHost.getCurrentTab() + 1;

if(currentTabID>=mTabHost.getTabCount()) {

currentTabID= 0;

}

}

mTabHost.setCurrentTab(currentTabID);

returnfalse;

}

}

}

说明:

boolean  onFling(MotionEvent e1, MotionEvent e2, float

velocityX, float velocityY)

Touch了滑动一点距离后,up时触发。即用户按下屏幕,快速移动后松开(就是在屏幕上滑动)

e1:第一个ACTION_DOWN事件(手指按下的那一点)

e2:最后一个ACTION_MOVE事件(手指松开的那一点)

velocityX:手指在x轴移动的速度单位:像素/秒

velocityY:手指在y轴移动的速度单位:像素/秒

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值