Android系统自带一个Gallery浏览图片的应用,通过手指拖动时能够非常流畅的显示图片,用户交互和体验都很好。

本示例就是通过Gallery和自定义的View,模仿实现一个仿Gallery图像集的图片浏览效果。效果图如下:

1、基本原理

在 Activity 中实现 OnGestureListener 的接口 onFling() 手势事件,通过自定义的 View 绘制draw() 图片

2、Activity

Activity中,通过onTouchEvent() 注册 myGesture.onTouchEvent(event)

  1. @Override
  2. public boolean onTouchEvent(MotionEvent event) {
  3. switch (event.getAction()) {
  4. case MotionEvent.ACTION_UP:
  5. flingView.onFling(0);           // 手指抬起后,重置滑动距离offsetX = 0
  6. break;
  7. }
  8. return myGesture.onTouchEvent(event);
  9. }

接着实现接口OnGestureListener 的 onScroll()方法,给继承自View的 FlingView 的handleScroll()成员方法传递滑动参数,获取滑动的x轴距离

  1. @Override
  2. public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
  3. flingView.handleScroll(-1 * (int) distanceX);
  4. return true;
  5. }

接着实现接口OnGestureListener 的 OnFling()方法,给继承自View的 FlingView 的onFling()成员方法传递滑动参数,获取手势的速度

  1. @Override
  2. public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
  3. flingView.onFling((int) - velocityX);
  4. return true;
  5. }

3、FlingView

FlingView中,获取来自Activity中的手势速度

  1. public void onFling(int paramFloat1) {
  2. if (offsetX > GalleryDemoActivity.deviceScreenWidth / 5) {
  3. if (fBitmap != null) {
  4. isFling = true;
  5. isFlingRight = true;
  6. }
  7. } else if (offsetX < -GalleryDemoActivity.deviceScreenWidth / 5) {
  8. if (nBitmap != null) {
  9. isFling = true;
  10. isFlingLeft = true;
  11. }
  12. }
  13. // 开始动画效果
  14. startAnimation(new MyAnimation());
  15. }

在滑动过程中,通过实现View的Draw()方法绘制图片,注意:此时需要同时绘制当前图片(获取焦点)和下一张图片(即将获取焦点)共两张图片

  1. @Override
  2. public void draw(Canvas canvas) {
  3. Paint paint = new Paint();
  4. Rect rect = new Rect();
  5. canvas.drawColor(Color.BLACK);
  6. // 绘制当前图片
  7. if (bitmap != null) {
  8. int left = offsetX;
  9. int top = offsetY;
  10. int right = offsetX + GalleryDemoActivity.deviceScreenWidth;
  11. int bottom = offsetY + GalleryDemoActivity.deviceScreenHeight;
  12. rect.set(left, top, right, bottom);
  13. canvas.drawBitmap(bitmap, null, rect, paint);
  14. }
  15. // 绘制下一张图片
  16. if (offsetX < 0) {           // 向左滑动
  17. if (nBitmap != null) {
  18. int left = GalleryDemoActivity.deviceScreenWidth + 15 + offsetX;
  19. int top = 0;
  20. int right = left + GalleryDemoActivity.deviceScreenWidth;
  21. int bottom = GalleryDemoActivity.deviceScreenHeight;
  22. rect.set(left, top, right, bottom);
  23. canvas.drawBitmap(nBitmap, null, rect, paint);
  24. }
  25. } else if (offsetX > 0) {        // 向右滑动
  26. if (fBitmap != null) {
  27. int left = -GalleryDemoActivity.deviceScreenWidth - 15 + offsetX;
  28. int top = 0;
  29. int right = left + GalleryDemoActivity.deviceScreenWidth;
  30. int bottom = GalleryDemoActivity.deviceScreenHeight;
  31. rect.set(left, top, right, bottom);
  32. canvas.drawBitmap(fBitmap, null, rect, paint);
  33. }
  34. }
  35. }

在滑动图片结束后,需要做滑动动画后的处理,重新设置当前图片和当前图片的上一张和下一张的状态,为下次滑动做准备

  1. @Override
  2. protected void onAnimationEnd() {
  3. if (isFlingRight) {         // 向右滑动,position减1
  4. nBitmap = bitmap;
  5. bitmap = fBitmap;
  6. fBitmap = null;
  7. postion = postion - 1;
  8. } else if (isFlingLeft) {       // 向左滑动,position加1
  9. fBitmap = bitmap;
  10. bitmap = nBitmap;
  11. nBitmap = null;
  12. postion = postion + 1;
  13. }
  14. isFlingRight = false;
  15. isFlingLeft = false;
  16. isFling = false;
  17. offsetX = 0;
  18. if (fBitmap == null && offsetX == 0) {          // 如果前一张图片为空(向右滑),则重置前一张图片(position - 1)
  19. if (postion > 0) {
  20. fBitmap = getBitmap(postion - 1);
  21. }
  22. } else if (nBitmap == null && offsetX == 0) {       // 如果后一张图片为空(向左滑),则重置后一张图片(position + 1)
  23. if (postion < bitmaps.length - 1) {
  24. nBitmap = getBitmap(postion + 1);
  25. }
  26. }
  27. clearAnimation();
  28. }

4、手势坐标介绍
本示例中,用到了OnGestureListener接口的onScroll()和OnFling()方法,涉及到了Android系统坐标及触摸MotionEvent e1和e2、速度velocityX、velocityY等值

Android屏幕坐标系如下图(左)

(1)MotionEvent中 e1是手指第一次按上屏幕的起点,e2是抬起手指离开屏幕的终点,根据上图Android屏幕坐标系可知:

手指向右滑动,终点(e2)在起点(e1)的右侧,有e2.getX() - e1.getX() 大于0
手指向左滑动,终点(e2)在起点(e1)的左侧,有e2.getX() - e1.getX() 小于0
手指向下滑动,终点(e2)在起点(e1)的下侧,有e2.getY() - e1.getY() 大于0
手指向上滑动,终点(e2)在起点(e1)的上侧,有e2.getY() - e1.getY() 小于0

(2)onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)

distanceX,是前后两次call的X距离,不是e2与e1的水平距离

distanceX,是前后两次call的Y距离,不是e2与e1的垂直距离

具体数值的方向,请详见上图(中)

(3)onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)

velocityX,是X轴的每秒速度

velocityY,是Y轴的每秒速度

具体数值的方向,请详见上图(右)

仔细观察可以发现:velocityX、velocityY的方向与distanceX、distanceY方向正好相反

Android 滑动效果基础篇(三)—— Gallery仿图像集浏览的更多相关文章

  1. Android 滑动效果基础篇(四)—— Gallery + GridView

    Android系统自带一个GridView和Gallery两个控件,GridView网格显示,Gallery单个浏览,两者结合起来可以真正实现Gallery浏览图片效果. 本示例通过GridView和 ...

  2. Android 滑动效果进阶篇(六)—— 倒影效果

    上篇介绍了使用Animation实现3D动画旋转翻页效果,现在介绍图片倒影实现,先看效果图 本示例主要通过自定义Gallery和ImageAdapter(继承自BaseAdapter)实现 1.倒影绘 ...

  3. Android 滑动效果入门篇(二)—— Gallery

    Gallery 是Android官方提供的一个View容器类,继承于AbsSpinner类,用于实现页面滑动效果. 从上面的继承关系可以看出,AbsSpinner类继承自AdapterView,因此我 ...

  4. Android 滑动效果高级篇(八)—— 自定义控件

    自定义控件,较常用View.ViewGroup.Scroller三个类,其继承关系如下: 本示例自定义控件,实现一个Gallery效果,并添加了一个显示View个数和位置的bar条,效果图: 自定义控 ...

  5. Android 滑动效果入门篇(一)—— ViewFlipper

    ViewFilpper 是Android官方提供的一个View容器类,继承于ViewAnimator类,用于实现页面切换,也可以设定时间间隔,让它自动播放.又ViewAnimator继承至于Frame ...

  6. Android 滑动效果进阶篇(五)—— 3D旋转

    前面介绍了利用Android自带的控件,进行滑动翻页制作效果,现在我们通过代码实现一些滑动翻页的动画效果. Animation实现动画有两个方式:帧动画(frame-by-frame animatio ...

  7. Android 滑动效果高级篇(七)—— 华丽翻页效果

    By 何明桂(http://blog.csdn.net/hmg25) 转载请注明出处 之前看到像ipad上的ibook的模拟书籍翻页的特效感觉很炫,在android上也有像laputa和ireader ...

  8. 十六、Android 滑动效果汇总

    Android 滑动效果入门篇(一)—— ViewFlipper Android 滑动效果入门篇(二)—— Gallery Android 滑动效果基础篇(三)—— Gallery仿图像集浏览 And ...

  9. Android 滑动效果汇总

    Android 滑动效果入门篇(一)—— ViewFlipper Android 滑动效果入门篇(二)—— Gallery Android 滑动效果基础篇(三)—— Gallery仿图像集浏览 And ...

随机推荐

  1. POJ 1573 Robot Motion

    Robot Motion Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 12978   Accepted: 6290 Des ...

  2. bjfu1099 度度熊大战僵尸

    这也是2011年百度之星的一道题. 这题我就是乱搞搞过的,打代码之前自己心里也没底,不知道能不能过的. 我的做法很简单,就是按时间顺序依次构造能杀死的僵尸血量,找到第k小的.构造的方法也很暴力:对t时 ...

  3. WiFi Test Entity

    项目要结了,总结下每次新版本WiFi需要测试的内容 1 IOT1.1     connect target[Connected];    modify wifi pwd to wrong pwd[Au ...

  4. java Ant 的使用

    Apache Ant 1.7.0 is the best available version的下载地址:http://ant.apache.org/bindownload.cgi 部署: 参考JAVA ...

  5. 你今天Python了吗?(下)

    在体验了wxPython的强大之后,让我们把注意力集中到Twisted上来.在C++的世界里,你会发现一个很棒的网络应用框架,那就是ACE了:在Python的地盘,Twisted则是在网络应用框架中当 ...

  6. 基于GPL329xx linux平台电容屏gsl1680的驱动调试分析

    因客户有用到了gsl1680 7寸电容屏,所以拿了一块过来,便在329xx的平台上面开始调试了. 大概浏览了一下所提供的资料,只有介绍模组的资料跟一份中文版的datasheet,datasheet只是 ...

  7. 二分+最短路 uvalive 3270 Simplified GSM Network(推荐)

    // 二分+最短路 uvalive 3270 Simplified GSM Network(推荐) // 题意:已知B(1≤B≤50)个信号站和C(1≤C≤50)座城市的坐标,坐标的绝对值不大于100 ...

  8. vi--文本编辑常用快捷键之光标移动

    再来一发! 上一篇关于vi/vim的文章中,主要介绍了文本的复制粘贴删除替换等操作,在慢慢的适应vim的过程中,我发现有很多时间实际上是浪费在移动光标上的,特别是行内移动光标.这篇文章就主要是介绍vi ...

  9. javadoc注释规范

    javadoc做注释 一. Java 文档 // 注释一行 /* ...... */ 注释若干行 /** ...... */ 注释若干行,并写入 javadoc 文档 通常这种注释的多行写法如下: / ...

  10. DedeCMS Error:Tag disabled:"php"的解决办法