2018年8月30日 星期四

[Android] 使用兩指旋轉圖片

本篇文章說明怎麼在android上開發『用兩隻手指頭旋轉圖片』功能

縮放一樣,繼承原生的ImageView,在由onTouchEvent去控制

程式碼如下:


package com.distudio.learn.demo.touch;
import
android.content.Context;
import
android.graphics.Canvas;
import
android.graphics.PointF;
import
android.graphics.drawable.Drawable;
import
android.util.AttributeSet;
import
android.view.MotionEvent;
import
com.distudio.learn.demo.R;


public class
RotateWith2Fingers  extends android.support.v7.widget.AppCompatImageView{
    private Drawable mIcon;

    private float
newRot = 0f;
    private float
d = 0f;
    private float
r = 0f;
   
    public
RotateWith2Fingers(Context context) {
        this(context, null, 0);
   
}

    public RotateWith2Fingers(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
   
}

    public RotateWith2Fingers(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
       
mIcon = context.getResources().getDrawable(R.drawable.duran);
       
mIcon.setBounds(0, 0, mIcon.getIntrinsicWidth(), mIcon.getIntrinsicHeight());
   
}

    @Override
   
public void onDraw(Canvas canvas) {
        super.onDraw(canvas);
       
canvas.save();
       
canvas.rotate(r);
       
mIcon.draw(canvas);
       
canvas.restore();
   
}

    @Override
   
public boolean onTouchEvent(MotionEvent ev) {
        final int action = ev.getAction();
        switch
(action & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_POINTER_DOWN: // first and second finger down
               
d = rotation(ev);
                break;
            case
MotionEvent.ACTION_MOVE: {
                if(ev.getPointerCount() == 2){
                    newRot = rotation(ev);
                   
r = newRot - d;
                   
invalidate();
                    break;
               
}
                break;
           
}
        }

        return true;
   
}



    private float rotation(MotionEvent event) {
        double delta_x = (event.getX(0) - event.getX(1));
        double
delta_y = (event.getY(0) - event.getY(1));
        double
radians = Math.atan2(delta_y, delta_x);
        return
(float) Math.toDegrees(radians);
   
}
}

逐步解析

1. 一樣先把該寫的東西都寫完

package com.distudio.learn.demo.touch;
import
android.content.Context;
import
android.graphics.Canvas;
import
android.graphics.PointF;
import
android.graphics.drawable.Drawable;
import
android.util.AttributeSet;
import
android.view.MotionEvent;
import
com.distudio.learn.demo.R;


public class
RotateWith2Fingers  extends android.support.v7.widget.AppCompatImageView{
    private Drawable mIcon;
    private float
r = 0f;
   
    public
RotateWith2Fingers(Context context) {
        this(context, null, 0);
   
}

    public RotateWith2Fingers(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
   
}

    public RotateWith2Fingers(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
       
mIcon = context.getResources().getDrawable(R.drawable.duran);
       
mIcon.setBounds(0, 0, mIcon.getIntrinsicWidth(), mIcon.getIntrinsicHeight());
   
}

    @Override
   
public void onDraw(Canvas canvas) {
        super.onDraw(canvas);
       
canvas.save();
       
canvas.rotate(r);
       
mIcon.draw(canvas);
       
canvas.restore();
   
}

}

其中宣告參數 r 為旋轉角度

private float 0f;

onDraw中設定圖片選轉角度為r

canvas.rotate(r);


2. 旋轉邏輯程式,計算兩個手指的角度,有請數學老師幫忙解答

private float rotation(MotionEvent event) {
    double delta_x = (event.getX(0) - event.getX(1));
    double 
delta_y = (event.getY(0) - event.getY(1));
    double 
radians = Math.atan2(delta_ydelta_x);
    return 
(float) Math.toDegrees(radians);}


3. override onTouchEvent

@Override
public boolean onTouchEvent(MotionEvent ev) {
    final int action = ev.getAction();
    switch
(action & MotionEvent.ACTION_MASK) {

        case MotionEvent.ACTION_POINTER_DOWN: // first and second finger down
           
d = rotation(ev);
            break;
        case
MotionEvent.ACTION_MOVE: {
            if(ev.getPointerCount() == 2){
                newRot = rotation(ev);
               
r = newRot - d;
               
invalidate();
                break;
           
}
            break;
       
}
    }

    return true;
}

當兩隻手指都放上去時,用上面寫的rotation紀錄 = d

case MotionEvent.ACTION_POINTER_DOWN: // first and second finger down
    d = rotation(ev);
    break;

當監聽到移動事件時,在取得一次手指新位置的角度 = newRot
移動前後的值相減就是整張圖片要移動的角度 = r

case MotionEvent.ACTION_MOVE: {
    if(ev.getPointerCount() == 2){
        newRot = rotation(ev);
       
r = newRot - d;
       
invalidate();
        break;
   
}
    break;
}

4. 前端使用

<com.distudio.learn.demo.touch.RotateWith2Fingers
    android:layout_width="match_parent"
   
android:layout_height="match_parent"
   
android:gravity="center"/>


原始碼位置

activity_rotate_with_2_fingers.xml
整包下載

安裝完成之後點選『兩指旋轉』就可以demo效果囉




沒有留言:

張貼留言