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. android桌面小火箭升空动画

    public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceS ...

  2. Delphi 712操作word

    //导出Wordprocedure TFrm_Computing.ExportWord;var wordApp, WordDoc, WrdSelection, wrdtable, wrdtable1, ...

  3. [irving] C# Windows Beep 调用声音文件

    方法一:Console.Beep(); 方法二:可以用Console.WriteLine("/a");来代替Beep(). MSDN:http://msdn.microsoft.c ...

  4. Web自动化框架搭建——前言

    1.web测试功能特性 a.功能逻辑测试(功能测试),这一块所有系统都是一致的,比如数据的添加.删除.修改:功能测试案例设计感兴趣和有时间的话可以另外专题探讨: b.浏览器兼容性测试,更重要的是体验这 ...

  5. 国内外开源与 SaaS ,团队协作平台、项目管理工具整理

    整理一些开源与 SaaS ,团队协作平台.项目管理工具.还有哪些比较好的工具,可以推荐下? 名称 地址 备注 asana https://asana.com/ 国外 basecamp https:// ...

  6. ASP.NET Session丢失的解决方案

    正常操作情况下会有ASP.NET Session丢失的情况出现.因为程序是在不停的被操作,排除Session超时的可能.另外,Session超时时间被设定成60分钟,不会这么快就超时的.现在我就把原因 ...

  7. kendoui-在线文本编辑器

    文本编辑器用过很多,fckeditor是我之前用的最多的,但是问题也有很多,诸如安全问题,浏览器兼容问题..所以最近也一直在找替代产品,正好在研究kendo,所以就尝试了下kendo提供的edit控件 ...

  8. Tkinter教程之Radiobutton篇

    本文转载自:http://blog.csdn.net/jcodeer/article/details/1811308 #Tkinter教程之Radiobutton篇#Radiobutton为单选按钮, ...

  9. 优秀java开源项目与解决方案推荐与概论

    http://www.oschina.net/project/lang/19/java http://www.open-open.com/ http://java-source.net/ https: ...

  10. Failed to allocate the network(s), not rescheduling

    Failed to allocate the network(s), not rescheduling 在计算节点的/etc/nova/nova.conf中添加下面两句 #Fail instance ...