跟縮放一樣,繼承原生的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);
}
}
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();
}
}
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 r = 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_y, delta_x);
return (float) Math.toDegrees(radians);}
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);}
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;
}
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;
d = rotation(ev);
break;
當監聽到移動事件時,在取得一次手指新位置的角度 = newRot
移動前後的值相減就是整張圖片要移動的角度 = r
case MotionEvent.ACTION_MOVE: {
if(ev.getPointerCount() == 2){
newRot = rotation(ev);
r = newRot - d;
invalidate();
break;
}
break;
}
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"/>
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"/>
沒有留言:
張貼留言