Android页面滑动加旋转特效总结 !!!!

ViewPage代码改写增加翻转和缩放效果

(本文属于个人经验总结,如有理解偏差,即使沟通)

 

1.     一般平移滑动效果原理:

拿ViewPager源码举例(ViewPager代码可以在新版SDK中找到),它继承了ViewGroup,如果实现3屏滑动,需将3个将要展示的页面添加到ViewGroup中去,通过触摸事件来计算滑动距离,使用scrollTo或者Scroller中的startScroll

方法将屏幕定位到需要展示的位置,达到滑动效果。如果将ViewGroup比喻成一个长长的卷轴,我们的手机屏幕就相当于放大镜,放大镜显示的区域有限,所以只能通过移动才能看到全部的卷轴内容。


2.     滑动过程中触摸事件分发:

在ViewGroup的子类中需要重写onInterceptTouchEvent和onTouch方法,onInterceptTouchEvent是对触摸事件进行拦截和分发。由于onInterceptTouchEvent()的机制比较复杂,上面的说明写的也比较复杂,总结一下,基本的规则是:

I.down事件首先会传递到onInterceptTouchEvent()方法

如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后returnfalse,那么后续的move,up等事件将继续会先传递给该ViewGroup,之后才和down事件一样传递给最终的目标view的onTouchEvent()处理。

 

II如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后returntrue,那么后续的move,up等事件将不再传递给onInterceptTouchEvent(),而是和down事件一样传递给该ViewGroup的onTouchEvent()处理,注意,目标view将接收不到任何事件。

 

III如果最终需要处理事件的view的onTouchEvent()返回了false,那么该事件将被传递至其上一层次的view的onTouchEvent()处理。

IV如果最终需要处理事件的view 的onTouchEvent()返回了true,那么后续事件将可以继续传递给该view的onTouchEvent()处理。

       如果传递到onTouchEvent方法,则主要是控制整个view的滑动,在onInterceptTouchEvent()down事件出发的时候记录x轴坐标,在onTouchEvent()move事件中记录x轴坐标,通过和onInterceptTouchEvent() down事件中记录的x轴坐标进行比对,从而得到屏幕是向右滑动还是像左滑动,滑动的距离则可通过减法获得。

怎样判断我是否滑动了一个屏幕呢?在viewpager中有两个标准,一个是手势滑动的速度还有一个就是手势滑动的距离,代码如下:

final VelocityTrackervelocityTracker = mVelocityTracker;

                    velocityTracker.computeCurrentVelocity(1000,mMaximumVelocity);

//得到x滑动速度

int initialVelocity = (int)VelocityTrackerCompat.getXVelocity();

 

//如果滑动速度大于4000像素每秒或者滑动的距离大于view的宽度的1/3

if ((Math.abs(initialVelocity) > 4000)

     || Math.abs(mInitialMotionX-mLastMotionX) >=(getWidth()/3)) {

 

表示滑动一屏幕(左屏幕还是右屏幕需要根据坐标去算)

}

 

至于一些细节的实现和状态控制请参考ViewPager源码

 

 

 

3.     dispatchDraw和onDraw方法区别:

 

常见的翻转变化的操作类是Camera,Matrix,然后通过Canvas画到页面上。滑动过程中要给view添加翻转效果,本人的思路是将本身的view隐藏掉然后得到viewcache中的bitmap图片通过对bitmap图片的操作来做相应的控制(如过想要更好的体验可以在view绘制的时候去操作,这样可能需要深度定制改写源代码)。重写dispatchDraw方法进行绘制,为什么不重写onDraw方法呢?主要原因是:draw过程会调用onDraw(Canvas canvas)方法,然后就是dispatchDraw(Canvas canvas)方法,dispatchDraw()主要是分发给子组件进行绘制,我们通常定制组件的时候重写的是onDraw()方法。值得注意的是ViewGroup容器组 件的绘制,当它没有背景时直接调用的是dispatchDraw()方法, 而绕过了draw()方法,当它有背景的时候就调用draw()方法,而draw()方法里包含了dispatchDraw()方法的调用。因此要在 ViewGroup上绘制东西的时候往往重写的是dispatchDraw()方法而不是onDraw()方法。

 

4.  View组件的cache机制:

 

  View组件显示的内容可以通过cache机制保存为bitmap, 使用到的api有

 void setDrawingCacheEnabled(booleanflag),

BitmapgetDrawingCache(boolean autoScale),

我们要获取它的cache先要通过setDrawingCacheEnable方法把cache开启,然后再调用getDrawingCache方法就可以获得view的cache图片了。buildDrawingCache方法可以不用调用,因为调用getDrawingCache方法时,若果cache没有建立,系统会自动调用buildDrawingCache方法生成cache。若果要更新cache, 必须要调用destoryDrawingCache方法把旧的cache销毁,才能建立新的。

当调用setDrawingCacheEnabled方法设置为false, 系统也会自动把原来的cache销毁。

获取cache通常会占用一定的内存,所以通常不需要的时候有必要对其进行清理,通过destroyDrawingCache或setDrawingCacheEnabled(false)实现。

示例代码:

currentView.clearFocus();//currentView表示设置的View对象

   currentView.setPressed(false);

   currentView.setDrawingCacheBackgroundColor(0);

   currentView.setDrawingCacheEnabled(true);

Bitmap viewBitmap = currentView.getDrawingCache();

currentView.setDrawingCacheEnabled(false);

 

5. 翻转和缩放:
得到bitmap对象后,我们利用Camera,Matrix对图片进行反转缩放
示例代码:

camera.save(); 

    //得到Y轴翻转角度 ,getTrangle方法获得角度,需要自定义

    float trangle = getTrangle(mPersonalDeltaX);

    //Y轴翻转 

    camera.rotateY(trangle);

//设置camera作用矩阵

Matrix matrix = new Matrix();

 

camera.getMatrix(matrix); 

 camera.restore(); 

   int width = viewBitmap.getWidth();

   int height = viewBitmap.getHeight();

       

    if(toLeft){

          //设置翻转中心点 

        matrix.preTranslate(-width, -height/2); 

        matrix.postTranslate(width, height/2); 

         

      }else if(toRight){

          //设置翻转中心点 

        matrix.preTranslate(0,-height/2); 

        matrix.postTranslate(0, height/2); 

        }

float scaleHeight =Math.abs(trangle/(MAX_TRANGLE*2));

float scaleWidth = scaleHeight;


//对图片进行缩放

matrix.postScale((1.0f - scaleWidth), (1.0f -scaleHeight), width/2, height/2);

   

//设置画布原点        canvas.translate(currentView.getWidth()*mCurItem,0);

//画图

    canvas.drawBitmap(viewBitmap, matrix,null);


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值