第三部分 应用

在这一部分,我们会将前面两部分所了解到的内容和Android手势结合起来,利用各种不同的手势对图像进行平移、缩放和旋转,前面两项都是在实践中经常需要用到的功能,后一项据说苹果也是最近才加上的,而实际上在Android中,咱们通过自己的双手,也可以很轻松地实现之。

首先创建一个Android项目PatImageView,同时创建一个Activity:PatImageViewActivity。完成这一步后, 记得在AndroidManifest.xml中增加如下许可:

<uses-permissionandroid:name="android.permission.VIBRATE"/>

因为我们将要通过短按还是长按,来确定将图片到底是缩放还是旋转。

现在来创建一个ImageView的派生类:PatImageView,其代码(PatImageView.java)如下(2011-11-22 revised):

package com.pat.imageview;import android.app.Service;import android.content.Context;import android.graphics.Matrix;import android.graphics.PointF;import android.os.Vibrator;import android.util.FloatMath;import android.view.GestureDetector;import android.view.MotionEvent;import android.view.View;import android.widget.ImageView;public class PatImageView extends ImageView{private Matrix matrix;private Matrix savedMatrix;private boolean long_touch = false;private static int NONE = 0;private static int DRAG = 1;// 拖动private static int ZOOM = 2;// 缩放private static int ROTA = 3;// 旋转private int mode = NONE;private PointF startPoint;private PointF middlePoint;private float oldDistance;private float oldAngle;private Vibrator vibrator;private GestureDetector gdetector;public PatImageView(final Context context){super(context);matrix = new Matrix();savedMatrix = new Matrix();matrix.setTranslate(0f, 0f);setScaleType(ScaleType.MATRIX);setImageMatrix(matrix);startPoint = new PointF();middlePoint = new PointF();oldDistance = 1f;gdetector = new GestureDetector(context, new GestureDetector.OnGestureListener(){@Overridepublic boolean onSingleTapUp(MotionEvent e){return true;}@Overridepublic void onShowPress(MotionEvent e){}@Overridepublic boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY){return true;}@Overridepublic void onLongPress(MotionEvent e){long_touch = true;vibrator = (Vibrator) context.getSystemService(Service.VIBRATOR_SERVICE);// 振动50ms,提示后续的操作将是旋转图片,而非缩放图片vibrator.vibrate(50);}@Overridepublic boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY){return true;}@Overridepublic boolean onDown(MotionEvent e){return true;}});setOnTouchListener(new OnTouchListener(){public boolean onTouch(View view, MotionEvent event){switch(event.getAction() & MotionEvent.ACTION_MASK){case MotionEvent.ACTION_DOWN:// 第一个手指touchsavedMatrix.set(matrix);startPoint.set(event.getX(), event.getY());mode = DRAG;long_touch = false;break;case MotionEvent.ACTION_POINTER_DOWN:// 第二个手指toucholdDistance = getDistance(event);// 计算第二个手指touch时,两指之间的距离oldAngle = getDegree(event);// 计算第二个手指touch时,两指所形成的直线和x轴的角度if(oldDistance > 10f){savedMatrix.set(matrix);middlePoint = midPoint(event);if(!long_touch){mode = ZOOM;}else{mode = ROTA;}}break;case MotionEvent.ACTION_UP:mode = NONE;break;case MotionEvent.ACTION_POINTER_UP:mode = NONE;break;case MotionEvent.ACTION_MOVE:if(vibrator != null)vibrator.cancel();if(mode == DRAG){matrix.set(savedMatrix);matrix.postTranslate(event.getX() - startPoint.x, event.getY() - startPoint.y);}if(mode == ZOOM){float newDistance = getDistance(event);if(newDistance > 10f){matrix.set(savedMatrix);float scale = newDistance / oldDistance;matrix.postScale(scale, scale, middlePoint.x, middlePoint.y);}}if(mode == ROTA){float newAngle = getDegree(event);matrix.set(savedMatrix);float degrees = newAngle - oldAngle;matrix.postRotate(degrees, middlePoint.x, middlePoint.y);}break;}setImageMatrix(matrix);invalidate();gdetector.onTouchEvent(event);return true;}});}// 计算两个手指之间的距离    private float getDistance(MotionEvent event)    {        float x = event.getX(0) - event.getX(1);        float y = event.getY(0) - event.getY(1);        return FloatMath.sqrt(x * x + y * y);    }        // 计算两个手指所形成的直线和x轴的角度    private float getDegree(MotionEvent event)    {    return (float)(Math.atan((event.getY(1) - event.getY(0)) / (event.getX(1) - event.getX(0))) * 180f);    }    // 计算两个手指之间,中间点的坐标    private PointF midPoint( MotionEvent event)    {    PointF point = new PointF();        float x = event.getX(0) + event.getX(1);        float y = event.getY(0) + event.getY(1);        point.set(x / 2, y / 2);                return point;    }}


下面完善PatImageViewActivity.java的代码,使之如下:

package com.pat.imageview;import android.app.Activity;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.Bundle;import android.view.Window;import android.view.WindowManager;public class PatImageViewActivity extends Activity{    @Override    public void onCreate(Bundle savedInstanceState)    {        super.onCreate(savedInstanceState);                requestWindowFeature(Window.FEATURE_NO_TITLE);        this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,         WindowManager.LayoutParams.FLAG_FULLSCREEN);                PatImageView piv = new PatImageView(this);        Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.sophie);        piv.setImageBitmap(bmp);                setContentView(piv);    }}


由于有些手势在模拟器上无法模拟,所以就不上运行结果的图片了。本人在真机上运行后(照片就不拍了,有点累啦),可以轻松做到:

1. 很方便地拖动图片(比如,单指按住屏幕进行拖动)

2. 很方便地缩放图片(比如,双指按住屏幕进行分开或者并拢操作,可分别实现放大或者缩小图片的功能)

3. 长按出现振动后,可以很方便地旋转图片(一个手指固定,另外一个手指围绕那个固定的手指运动)。

更多相关文章

  1. Android 使用Glide4.9 压缩并保存图片(jpg/png/gif)到本地
  2. Android中ListView使用- 网络图片的异步加载
  3. Android带进度条的下载图片示例(AsyncTask异步任务)
  4. [置顶] android从图库(gallery)选择一张图片
  5. 【Android 内存优化】Android 工程中使用 libjpeg-turbo 压缩图
  6. Android中关于Volley的使用(四)利用NetworkImageView来加载图片
  7. Android中网络图片的异步加载
  8. Android拍照调用系统相册仿微信封装总结,治疗各种崩溃,图片横竖
  9. 【Android 工具】Android 点9图片制作及讲解

随机推荐

  1. android常用布局设置
  2. OpenGL ES教程III之移动变换(原文对照)
  3. Android自定义Dialog(zhuang)
  4. 列出Android设备中所有启动的服务,及判断
  5. Android常见问题(一点一点总结未完成)
  6. android studio gradle 配置修改
  7. Android 1.5 1.6 2.0 2.1 2.2的区别
  8. Android(安卓)SDK 更新太慢问题
  9. Android 学习笔记--android――listview
  10. android SQLite 原理