Android中实现双指缩放的功能

安卓中实现将图片缩放的功能提供了一个很好的类:ScaleGestureDetector,本章就介绍使用canvas和ScaleGestureDetector类实现缩放的功能,如果要想详细了解ScaleGestureDetector请参考博文Android的ScaleGestureDetector缩放类详解
1. 先初始化缩放比和图片居中绘制的坐标点

float posX, posY;//图片的坐标    int viewWidth, viewHeight;//屏幕的宽高    float widthScale, heightScale;//宽高缩放比    boolean hasInitViewSize;//是否已经初始化视图    public void initSize() {        viewWidth = getWidth();//得到屏幕宽度        viewHeight = getHeight();//得到屏幕高度        if (viewWidth < 0 && viewHeight < 0) {            return;        }        hasInitViewSize = true;        widthScale = viewWidth / imgWidth;//宽高缩放比=屏幕的宽高/屏幕的宽高        heightScale = viewHeight / imgHeight;        scaleFactor = Math.min(widthScale, heightScale);//总缩放比取宽高缩放比中最小的        posX = viewWidth / 2 - imgWidth / 2;//使图片居中绘制        posY = viewHeight / 2 - imgHeight / 2;    }

2. 创建两个内部类分别继承SimpleOnScaleGestureListener和SimpleOnGestureListener来动态获取缩放比和坐标

class MySimpleOnGestureDetector extends GestureDetector.SimpleOnGestureListener {        @Override        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {            posX -= distanceX;//X轴的坐标=X轴的坐标-在X轴方向的移动距离            posY -= distanceY;//y轴的坐标=y轴的坐标-在y轴方向的移动距离            invalidate();//刷新view            return true;        }    }    class MySimpleScaleOnGestureDetector extends ScaleGestureDetector.SimpleOnScaleGestureListener {        @Override        public boolean onScale(ScaleGestureDetector detector) {            scaleFactor *= detector.getScaleFactor();//缩放比=缩放比*动态获取的缩放比            scaleFactor = scaleFactor < 0.75 ? (float) 0.75 : scaleFactor > 3 ? 3 : scaleFactor;//控制缩放倍率在0.75-3之间            invalidate();//刷新view            return true;        }    }

3. 为了移动图片时不超出屏幕,还得进行控制,原则是:图片较小时任意一条边都不能出了边界,图片较大任意一条边都不能进入边界。宽度和高度分别独立计算。

public void checkBounds() {        if (scaleFactor > widthScale) {//宽度方向已经填满            posX = Math.min(posX, (scaleFactor - 1) * (imgWidth / 2));            posX = Math.max(posX, viewWidth - imgWidth - (scaleFactor - 1) * (imgWidth / 2));        } else {            posX = Math.max(posX, (scaleFactor - 1) * (imgWidth / 2));            posX = Math.min(posX, viewWidth - imgWidth - (scaleFactor - 1) * (imgWidth / 2));        }        if (scaleFactor > heightScale) {//高度方向已经填满            posY = Math.min(posY, (scaleFactor - 1) * (imgHeight / 2));            posY = Math.max(posY, viewHeight - imgHeight - (scaleFactor - 1) * (imgHeight / 2));        } else {            posY = Math.max(posY, (scaleFactor - 1) * (imgHeight / 2));            posY = Math.min(posY, viewHeight - imgHeight - (scaleFactor - 1) * (imgHeight / 2));        }    }

4. 在类中实现onDraw方法进行绘制缩放

 @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        if (bitmap == null) {            return;        }        if (!hasInitViewSize) {            initSize();        }        canvas.save();//画布保存        checkBounds();//检查边界,使图片不能超出屏幕        canvas.scale(scaleFactor, scaleFactor, posX + imgWidth / 2, posY + imgHeight / 2);///以图片的中心为基点进行缩放        canvas.drawBitmap(bitmap, posX, posY, paint);//绘制图片        canvas.restore();//画布重绘    }

5. 关键点已经差不多写完了,现在将完整的类写上

package com.example.mygesture;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Paint;import android.support.annotation.Nullable;import android.util.AttributeSet;import android.view.GestureDetector;import android.view.MotionEvent;import android.view.ScaleGestureDetector;import android.view.View;public class MyScaleView extends View {    ScaleGestureDetector scaleGestureDetector;    float scaleFactor;    float posX, posY;    int viewWidth, viewHeight;    float widthScale, heightScale;    boolean hasInitViewSize;    Paint paint = new Paint();    Bitmap bitmap;    float imgWidth, imgHeight;    GestureDetector gestureDetector;    public MyScaleView(Context context, @Nullable AttributeSet attrs) {//注意:得在有两个参数的构造函数中实例化ScaleGestureDetector 和GestureDetector         super(context, attrs);        init(context);    }    private void init(Context context) {        scaleGestureDetector = new ScaleGestureDetector(context, new MySimpleScaleOnGestureDetector());        gestureDetector = new GestureDetector(context, new MySimpleOnGestureDetector());    }    class MySimpleOnGestureDetector extends GestureDetector.SimpleOnGestureListener {        @Override        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {            posX -= distanceX;            posY -= distanceY;            invalidate();            return true;        }    }    class MySimpleScaleOnGestureDetector extends ScaleGestureDetector.SimpleOnScaleGestureListener {        @Override        public boolean onScale(ScaleGestureDetector detector) {            scaleFactor *= detector.getScaleFactor();            scaleFactor = scaleFactor < 0.75 ? (float) 0.75 : scaleFactor > 3 ? 3 : scaleFactor;            invalidate();            return true;        }    }    public void initSize() {        viewWidth = getWidth();        viewHeight = getHeight();        if (viewWidth < 0 && viewHeight < 0) {            return;        }        hasInitViewSize = true;        widthScale = viewWidth / imgWidth;        heightScale = viewHeight / imgHeight;        scaleFactor = Math.min(widthScale, heightScale);        posX = viewWidth / 2 - imgWidth / 2;        posY = viewHeight / 2 - imgHeight / 2;    }    public void checkBounds() {//检查边界        if (scaleFactor > widthScale) {            posX = Math.min(posX, (scaleFactor - 1) * (imgWidth / 2));            posX = Math.max(posX, viewWidth - imgWidth - (scaleFactor - 1) * (imgWidth / 2));        } else {            posX = Math.max(posX, (scaleFactor - 1) * (imgWidth / 2));            posX = Math.min(posX, viewWidth - imgWidth - (scaleFactor - 1) * (imgWidth / 2));        }        if (scaleFactor > heightScale) {            posY = Math.min(posY, (scaleFactor - 1) * (imgHeight / 2));            posY = Math.max(posY, viewHeight - imgHeight - (scaleFactor - 1) * (imgHeight / 2));        } else {            posY = Math.max(posY, (scaleFactor - 1) * (imgHeight / 2));            posY = Math.min(posY, viewHeight - imgHeight - (scaleFactor - 1) * (imgHeight / 2));        }    }    @Override    public boolean onTouchEvent(MotionEvent event) {        scaleGestureDetector.onTouchEvent(event);//双指缩放        gestureDetector.onTouchEvent(event);//单指移动        return true;    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        if (bitmap == null) {            return;        }        if (!hasInitViewSize) {            initSize();        }        canvas.save();        checkBounds();        canvas.scale(scaleFactor, scaleFactor, posX + imgWidth / 2, posY + imgHeight / 2);        canvas.drawBitmap(bitmap, posX, posY, paint);        canvas.restore();    }    public void setImageResouse(int resID) {//设置图片        bitmap = BitmapFactory.decodeResource(getResources(), resID);        imgWidth = bitmap.getWidth();        imgHeight = bitmap.getHeight();        initSize();        invalidate();    }}

6. 类已经写好了,现在对其使用,创建一个新的Activity

6.1 构造布局文件

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    tools:context=".text.Main8Activity">    <com.example.mygesture.MyScaleView        android:id="@+id/activity_main8_myScaleView"        android:layout_width="match_parent"        android:layout_height="match_parent" /></LinearLayout>

6.2 对应的类中

package com.example.mygesture.text;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import com.example.mygesture.MyScaleView;import com.example.mygesture.R;public class Main8Activity extends AppCompatActivity {    MyScaleView myScaleView;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main8);        myScaleView = findViewById(R.id.activity_main8_myScaleView);        myScaleView.setImageResouse(R.drawable.q4);    }}

7. 所以使用还是很简单的,因为缩放操作模拟器上不好演示,效果图就省略了。

Tip: 小白,写得不好请见谅。若有不对的地方请留言。

关于手势方面的功能点还可以参考Android中实现自定义手势和识别手势的功能,Android中简单实现页面翻转和自动翻转的功能

更多相关文章

  1. Android的selector,背景选择器
  2. 浅谈android的selector背景选择器
  3. 浅谈android的selector背景选择器
  4. 【腾讯Bugly干货分享】Android动态布局入门及NinePatchChunk解密
  5. Android(安卓)上传头像(文件)到服务器
  6. Android的图像处理
  7. android的selector背景选择器
  8. Android开机动画bootanimation.zip
  9. React Native嵌入到Android原生应用中、组件的生命周期、颜色、

随机推荐

  1. PHP运行原理与变量类型
  2. 从农村盖三层小楼模板的使用,看周转材料消
  3. CSS基础2:伪类选择器,字体图标,盒模型
  4. 学习了php的赋值,声明,打印,输出,数组,关联数
  5. 基于EMR离线数据分析-反馈有礼
  6. 意派Epub360丨用一款音频录制H5开启线上
  7. MyCms 自媒体 CMS 系统 v2.8,支持织梦数据
  8. 人物肤色怎么上色?动漫人物手绘上色教程
  9. Grafana镜像在阿里云镜像站首发上线
  10. laravel_day5