双指旋转(以图片中心为旋转中心)

本文介绍了在Android平台上,如何实现以图片中心为旋转中心的双指旋转功能。通过View、ViewV2、RotateProcessor和ScaleCalcutor等关键组件,详细讲解了旋转操作的处理逻辑和坐标计算方法,辅助以Utils类提供的实用工具方法,帮助开发者实现平滑且精确的图片旋转交互体验。
摘要由CSDN通过智能技术生成

View

package com.hfengxiang.example.myphotoview;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import androidx.annotation.Nullable;

public class TestCanvasView extends View implements RotateProcessor.OnRotateListener {

    private Paint paint;
    private Bitmap bitmap;
    private int rotation = 0;
    private float currentScale = 1f;
    private RectF rectF;
    private RotateProcessor rotateProcessor;
    private boolean isRecover;
    private PointF translate = new PointF();

    public TestCanvasView setTranslate(float x,float y) {
        translate.set(x,y);
        return this;
    }

    public TestCanvasView(Context context) {
        this(context, null);
    }

    public TestCanvasView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, -1);
    }

    public TestCanvasView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        paint = new Paint();
        paint.setAntiAlias(true);
        bitmap = Utils.getPhoto(getResources(), getResources().getDisplayMetrics().widthPixels);
        rectF = new RectF();
        rotateProcessor = new RotateProcessor();
        rotateProcessor.setRotateListener(this);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.save();
//        canvas.translate(rotateProcessor.getRotateCenter().x-getWidth() / 2f,rotateProcessor.getRotateCenter().y-getHeight() / 2f);
        canvas.translate(translate.x,translate.y);
        canvas.translate(getWidth() / 2f, getHeight() / 2f);
//        canvas.rotate(rotation,rotateProcessor.getRotateCenter().x-getWidth() / 2f,rotateProcessor.getRotateCenter().y-getHeight() / 2f);
        canvas.rotate(rotation);
        rectF.set(-currentWidth()/2f,-currentHeight()/2f,
                currentWidth()/2f,currentHeight()/2f);
        canvas.drawBitmap(bitmap,null, rectF, paint);
        paint.setColor(Color.GREEN);
        canvas.drawCircle(0,0,15, paint);
        canvas.restore();
        paint.setColor(Color.RED);
        canvas.drawCircle(0,0,15, paint);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getActionMasked()) {
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_POINTER_DOWN:
                rotateProcessor.handleActionDown(event);
                break;
            case MotionEvent.ACTION_MOVE:
                rotateProcessor.handleActionMove(event);
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_POINTER_UP:
                rotateProcessor.handleActionUp(event);
                break;
        }
        return true;
    }

    private float currentWidth(){
        return bitmap.getWidth()* currentScale;
    }
    private float currentHeight(){
        return bitmap.getHeight()* currentScale;
    }

    @Override
    public void onRotate(float changeDegree, float totalDegree, float scale) {
        rotation = (int) totalDegree;
        Log.i("rotation","rotation="+rotation);
        if(scale!=-1){
            currentScale = scale;
//            Log.i("Scale","scale="+scale);
//            setTranslate(0,0);
//            setTranslate((rotateProcessor.getRotateCenter().x-getWidth() / 2f)*scale,(rotateProcessor.getRotateCenter().y-getHeight() / 2f)*scale);
        }else {
            setTranslate(0,0);
            Log.i("PADDING","rectF.left="+rectF.left);
            Log.i("PADDING","rectF.top="+rectF.top);
            Log.i("PADDING","rectF.right="+rectF.right);
            Log.i("PADDING","rectF.bottom="+rectF.bottom);
        }
        invalidate();
    }

    @Override
    public float[] onCalculateScale(float targetDegree) {
        targetDegree = computeTargetDegree(targetDegree);
        Log.i("onCalculateScale","targetScale="+targetDegree);
        float targetScale = ScaleCalculator.calculateScale(getWidth(), getHeight(), bitmap.getWidth(), bitmap.getHeight(),
                (int) targetDegree);
        isRecover = true;
        return new float[]{currentScale,targetScale};
    }

    @Override
    public void onRecoverEnd() {
        isRecover = false;
    }

    /**
     * 根据旋转的角度计算出图片复位应当到达的角度
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值