android控件随手势旋转

作者:某人_Valar
如需转载请保留原文链接
android随手势旋转的控件

相关文章

  • android图片的缩放,移动
  • android控件的缩放,移动
  • android控件随手势旋转

本文结构

  • 1.简介
  • 2.使用步骤
  • 3.源码
1 简介

前面两篇文章分别介绍了对图片和控件的缩放、移动,这次就是对控件的旋转了。


控件的旋转
2 使用步骤

旋转控件的原理其实是和上一篇 android控件的缩放,移动一样的。
不过旋转的重点在于角度的计算,只要我们将手指旋转的角度计算处理,再调用android view自带的setRotation()方法就行了。

android控件随手势旋转_第1张图片
image.png

图中绿色小框就是一个要旋转的view,中间的红点为view的中心点,当我们从触摸点1滑到触摸点2时,两条线中的夹角就是我们需要的。

/**
*根据坐标系中的3点确定夹角的方法(注意:夹角是有正负的)
*/
public float angle(Point cen, Point first, Point second)
    {
        float dx1, dx2, dy1, dy2;

        dx1 = first.x - cen.x;
        dy1 = first.y - cen.y;
        dx2 = second.x - cen.x;
        dy2 = second.y - cen.y;

        // 计算三边的平方
        float ab2 = (second.x - first.x) * (second.x - first.x) + (second.y - first.y) * (second.y - first.y);
        float oa2 = dx1*dx1 + dy1*dy1;
        float ob2 = dx2 * dx2 + dy2 *dy2;

        // 根据两向量的叉乘来判断顺逆时针
        boolean isClockwise = ((first.x - cen.x) * (second.y - cen.y) - (first.y - cen.y) * (second.x - cen.x)) > 0;

        // 根据余弦定理计算旋转角的余弦值
        double cosDegree = (oa2 + ob2 - ab2) / (2 * Math.sqrt(oa2) * Math.sqrt(ob2));

        // 异常处理,因为算出来会有误差绝对值可能会超过一,所以需要处理一下
        if (cosDegree > 1) {
            cosDegree = 1;
        } else if (cosDegree < -1) {
            cosDegree = -1;
        }

        // 计算弧度
        double radian = Math.acos(cosDegree);

        // 计算旋转过的角度,顺时针为正,逆时针为负
       return (float) (isClockwise ? Math.toDegrees(radian) : -Math.toDegrees(radian));
   
    }

当我们计算出夹角之后,只需要在手势监听中给view设置setRotation()既可以了。

3 DragScaleView 的完整代码
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;


public class DragScaleView extends android.support.v7.widget.AppCompatImageView implements View.OnTouchListener {
    protected int lastX;
    protected int lastY;

    //初始的旋转角度
    private float oriRotation = 0;
    private static String TAG = "sxlwof";
   
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        int action = event.getAction()& MotionEvent.ACTION_MASK;
        if (action == MotionEvent.ACTION_DOWN) {
            oriLeft = v.getLeft();
            oriRight = v.getRight();
            oriTop = v.getTop();
            oriBottom = v.getBottom();
            lastY = (int) event.getRawY();
            lastX = (int) event.getRawX();
          
            oriRotation = v.getRotation();
            Log.d(TAG, "ACTION_DOWN: "+oriRotation);
        }
   
        delDrag(v, event, action);
        invalidate();
        return false;
    }

    /**
     * 处理拖动事件
     *
     * @param v
     * @param event
     * @param action
     */
    protected void delDrag(View v, MotionEvent event, int action) {
        switch (action) {
            case MotionEvent.ACTION_MOVE:
                int dx = (int) event.getRawX() - lastX;
                int dy = (int) event.getRawY() - lastY;
                Point center = new Point(oriLeft+(oriRight-oriLeft)/2,oriTop+(oriBottom-oriTop)/2);
               Point first = new Point(lastX,lastY);
               Point second = new Point((int) event.getRawX(),(int) event.getRawY());
               oriRotation += angle(center,first,second);
                 
                v.setRotation(oriRotation);
                lastX = (int) event.getRawX();
                lastY = (int) event.getRawY();
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_POINTER_UP:
                break;
        }
    }

    public float angle(Point cen, Point first, Point second)
    {
        float dx1, dx2, dy1, dy2;

        dx1 = first.x - cen.x;
        dy1 = first.y - cen.y;
        dx2 = second.x - cen.x;
        dy2 = second.y - cen.y;

        // 计算三边的平方
        float ab2 = (second.x - first.x) * (second.x - first.x) + (second.y - first.y) * (second.y - first.y);
        float oa2 = dx1*dx1 + dy1*dy1;
        float ob2 = dx2 * dx2 + dy2 *dy2;

        // 根据两向量的叉乘来判断顺逆时针
        boolean isClockwise = ((first.x - cen.x) * (second.y - cen.y) - (first.y - cen.y) * (second.x - cen.x)) > 0;

        // 根据余弦定理计算旋转角的余弦值
        double cosDegree = (oa2 + ob2 - ab2) / (2 * Math.sqrt(oa2) * Math.sqrt(ob2));

        // 异常处理,因为算出来会有误差绝对值可能会超过一,所以需要处理一下
        if (cosDegree > 1) {
            cosDegree = 1;
        } else if (cosDegree < -1) {
            cosDegree = -1;
        }

        // 计算弧度
        double radian = Math.acos(cosDegree);

        // 计算旋转过的角度,顺时针为正,逆时针为负
       return (float) (isClockwise ? Math.toDegrees(radian) : -Math.toDegrees(radian));
   
    }
}

你可能感兴趣的:(android控件随手势旋转)