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. 通过简单的Linux内核启动程序代码窥探操作系统的启动原理

    作者:吴乐  山东师范大学 <Linux内核分析> 孟宁 MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.程序设计与分析 ...

  2. 大话细说ORM

    什么是ORM? ORM,即对象关系映射(Object Relational Mapping)表示一种技术,用来把(对象模型)表示的对象映射到基于SQL的(关系模型)数据结构中去. 说得通俗点,就是在对 ...

  3. 机器学习真的可以起作用吗?(3)(以二维PLA为例)

    前两篇文章已经完成了大部分的工作,这篇文章主要是讲VC bound和 VC dimension这两个概念. (一)前文的一点补充 根据前面的讨论,我们似乎只需要用来替代来源的M就可以了,但是实际公式却 ...

  4. bzoj 4006 [JLOI2015]管道连接(斯坦纳树+状压DP)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4006 [题意] 给定n点m边的图,连接边(u,v)需要花费w,问满足使k个点中同颜色的 ...

  5. C++11 之 " = delete "

    1  缺省函数 设计一个类,没有成员函数 (member function),只有成员数据 (member data) class DataOnly { private: std::string st ...

  6. [算法] 插入排序 Insertion Sort

    插入排序(Insertion Sort)是一种简单直观的排序算法.它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入.插入排序在实现上,通常采用in-pla ...

  7. Unity中的单实例

    static GUIManager myInstance; public static GUIManager Instance { get { if (myInstance == null) myIn ...

  8. linux下开发c第一弹--相关环境需求

    我用的是mac,mac和linux一般集成了一定的开发环境,基本上需要gcc.vim.gdb之类的,linux下需要apt-get,mac下homebrew的brew install都可以解决问题.同 ...

  9. zznu 1914 asd的甩锅计划

    http://acm.zznu.edu.cn/problem.php?id=1914 asd的甩锅计划 时间限制: 1 Sec  内存限制: 128 MB提交: 114  解决: 10[提交][状态] ...

  10. eclispe输入@注解时提示所有注解的设置

    修改输入@提示所有的注解提示方法 eclipse下windows-->preference-->java-->editor-->Content Assist下的Enable a ...