Android 는 그림 확대,이동,회전 기능 을 실현 합 니 다.
설명 에서 그림 그리 기의 원리 에 관 한 지식 을 미리 알 아야 한다.
실현 에 관 한 절차
1.사용자 정의
View
2,조작 이미지 획득Bitmap
3.복사View
의onTouchEvent()
방법 중의ACTION_DOWN
,ACTION_POINTER_DOWN
,ACTION_MOVE
,ACTION_POINTER_UP
및ACTION_UP
사건.4.해당 이미지 의 변화
Matrix
행렬 을 정의 하고 제스처 작업 의 변 화 를 통 해 해당 하 는Matrix
을 설정한다.5.최종
Matrix
설정 을 완성 할 때invalidate()
방법 으로 페이지 를 다시 그립 니 다.그러면 다음 에 우 리 는 상기 절차 에 따라 한 걸음 한 걸음 코드 를 실현 한다.
코드 데모
/**
* :ZhouYou
* :2016/8/23.
*/
public class TouchImageView extends View {
//
private Paint paintEdge;
//
private Matrix matrix = new Matrix();
//
private Matrix downMatrix = new Matrix();
//
private Matrix moveMatrix = new Matrix();
//
private Bitmap srcImage;
//
private PointF midPoint = new PointF();
//
private int mode;
private static final int NONE = 0; //
private static final int TRANS = 1; //
private static final int ZOOM = 2; //
//
private boolean withinBorder;
public TouchImageView(Context context) {
this(context, null);
}
public TouchImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public TouchImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
paintEdge = new Paint();
paintEdge.setColor(Color.BLACK);
paintEdge.setAlpha(170);
paintEdge.setAntiAlias(true);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
srcImage = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_avatar_1);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
float[] points = getBitmapPoints(srcImage, matrix);
float x1 = points[0];
float y1 = points[1];
float x2 = points[2];
float y2 = points[3];
float x3 = points[4];
float y3 = points[5];
float x4 = points[6];
float y4 = points[7];
//
canvas.drawLine(x1, y1, x2, y2, paintEdge);
canvas.drawLine(x2, y2, x4, y4, paintEdge);
canvas.drawLine(x4, y4, x3, y3, paintEdge);
canvas.drawLine(x3, y3, x1, y1, paintEdge);
//
canvas.drawBitmap(srcImage, matrix, null);
}
// X
private float downX;
// Y
private float downY;
//
private float oldDistance;
//
private float oldRotation;
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = MotionEventCompat.getActionMasked(event);
switch (action) {
case MotionEvent.ACTION_DOWN:
mode = TRANS;
downX = event.getX();
downY = event.getY();
downMatrix.set(matrix);
break;
case MotionEvent.ACTION_POINTER_DOWN: //
mode = ZOOM;
oldDistance = getSpaceDistance(event);
oldRotation = getSpaceRotation(event);
downMatrix.set(matrix);
midPoint = getMidPoint(event);
break;
case MotionEvent.ACTION_MOVE:
//
if (mode == ZOOM) {
moveMatrix.set(downMatrix);
float deltaRotation = getSpaceRotation(event) - oldRotation;
float scale = getSpaceDistance(event) / oldDistance;
moveMatrix.postScale(scale, scale, midPoint.x, midPoint.y);
moveMatrix.postRotate(deltaRotation, midPoint.x, midPoint.y);
withinBorder = getMatrixBorderCheck(srcImage, event.getX(), event.getY());
if (withinBorder) {
matrix.set(moveMatrix);
invalidate();
}
}
//
else if (mode == TRANS) {
moveMatrix.set(downMatrix);
moveMatrix.postTranslate(event.getX() - downX, event.getY() - downY);
withinBorder = getMatrixBorderCheck(srcImage, event.getX(), event.getY());
if (withinBorder) {
matrix.set(moveMatrix);
invalidate();
}
}
break;
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_UP:
mode = NONE;
break;
default:
break;
}
return true;
}
/**
*
*
* @param event
* @return
*/
private float getSpaceRotation(MotionEvent event) {
double deltaX = event.getX(0) - event.getX(1);
double deltaY = event.getY(0) - event.getY(1);
double radians = Math.atan2(deltaY, deltaX);
return (float) Math.toDegrees(radians);
}
/**
*
*
* @param event
* @return
*/
private float getSpaceDistance(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return (float) Math.sqrt(x * x + y * y);
}
/**
*
*
* @param event
*/
private PointF getMidPoint(MotionEvent event) {
PointF point = new PointF();
float x = event.getX(0) + event.getX(1);
float y = event.getY(0) + event.getY(1);
point.set(x / 2, y / 2);
return point;
}
/**
* matrix
*
* @return
*/
protected float[] getBitmapPoints(Bitmap bitmap, Matrix matrix) {
float[] dst = new float[8];
float[] src = new float[]{
0, 0,
bitmap.getWidth(), 0,
0, bitmap.getHeight(),
bitmap.getWidth(), bitmap.getHeight()
};
matrix.mapPoints(dst, src);
return dst;
}
/**
*
*
* @param x
* @param y
* @return true - | false -
*/
private boolean getMatrixBorderCheck(Bitmap bitmap, float x, float y) {
if (bitmap == null) return false;
float[] points = getBitmapPoints(bitmap, moveMatrix);
float x1 = points[0];
float y1 = points[1];
float x2 = points[2];
float y2 = points[3];
float x3 = points[4];
float y3 = points[5];
float x4 = points[6];
float y4 = points[7];
float edge = (float) Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
if ((2 + Math.sqrt(2)) * edge >= Math.sqrt(Math.pow(x - x1, 2) + Math.pow(y - y1, 2))
+ Math.sqrt(Math.pow(x - x2, 2) + Math.pow(y - y2, 2))
+ Math.sqrt(Math.pow(x - x3, 2) + Math.pow(y - y3, 2))
+ Math.sqrt(Math.pow(x - x4, 2) + Math.pow(y - y4, 2))) {
return true;
}
return false;
}
}
나 는 코드 에서 발생 할 수 있 는 문제 에 대해 상세 한 설명 을 했다.1. Matrix
//
private Matrix matrix = new Matrix();
//
private Matrix downMatrix = new Matrix();
//
private Matrix moveMatrix = new Matrix();
먼저 저 는 세 개의Matrix
변 수 를 정 의 했 습 니 다.서로 다른 제스처 로 그림 을 조작 하 는Matrix
을 통 해 최종 적 으로 그림 을 그 리 는Matrix
에 의 해 수신 되 기 때문에 서로 다른 조작 에서 서로 다른Matrix
을 사용 하여 도형 변환 데 이 터 를 전달 하고 렌 더 링 페이지 에서 최종Matrix
을 그림 으로 전달 해 야 합 니 다Matrix
.2. PointF
//
private PointF midPoint = new PointF();
그림 의 회전 과 확대 작업 이 라면 두 손가락 을 통 해 제어 해 야 하기 때문에 여러 손가락 이 화면 을 만 질 때의 중심 점 좌 표를 알 아야 한다.3.터치 모드
//
private int mode;
private static final int NONE = 0; //
private static final int TRANS = 1; //
private static final int ZOOM = 2; //
onTouchEvent()
사건 에서 서로 다른 사건 에 따라 터치 제어 모델 을 바 꾸 어 서로 다른 그림 변환 작업 을 한다.4. onTouchEvent()
우선,저 희 는 사용자 정의
View
이기 때문에 이 사건 을 소비 하려 면 반환 값 을true
로 설정 해 야 합 니 다.(1)ACTION_DOWN-이 사건 은 단일 터치 스크린 의 사건 입 니 다.즉,손가락 하나 가 화면 을 누 르 면 이 사건 을 반전 시 키 는 것 입 니 다.그러면 이 이벤트 에서 터치 모드 를 드래그 모드(TRANS)로 설정 하고 화면 을 누 른 xy 좌 표를 기록 하 며 이 이벤트 에서 그림 을 그린 Matrix 를 누 른 Matrix 에 복사 합 니 다.
case MotionEvent.ACTION_DOWN:
mode = TRANS;
downX = event.getX();
downY = event.getY();
downMatrix.set(matrix);
break;
(2)ACTION_POINTER_DOWN-이 사건 은 손가락 하나 이상 이 화면 을 만 졌 을 때 발생 했다.우 리 는 이 사건 에서 멀 티 터치 스크린 의 조작 에 대해 초기 화 설정 을 할 수 있다.이 이벤트 에서 터치 모드 를 다시(ZOOM)로 설정 하고 두 손가락 사이 의 터치 스크린 거리 와 두 손가락 사이 의 회전 각 도 를 초기 화하 고 두 손가락 사이 의 중심 점 좌 표를 초기 화 합 니 다.마지막 으로 그림 을 그린 Matrix 를 화면 을 누 른 Matrix 에 복사 합 니 다.
case MotionEvent.ACTION_POINTER_DOWN: //
mode = ZOOM;
oldDistance = getSpaceDistance(event);
oldRotation = getSpaceRotation(event);
midPoint = getMidPoint(event);
downMatrix.set(matrix);
break;
(3)ACTION_MOVE-움 직 이 는 이벤트 에 이 르 러 이전의 터치 모드 에 따라 판단 한다.우선 이 벤트 를 누 른 Matrix 를 이동 이벤트 의 Matrix 에 복사 합 니 다.만약(ZOOM)모드 라면 우 리 는 사건 에 따라 손가락 회전 각도 의 차이 와 손가락 사이 의 거리의 차 이 를 얻 을 수 있 습 니 다.이 두 가지 차이 에 따라,그리고 ACTION 에서DOWN 이벤트 에서 얻 은 중점 좌 표를 사용 하면 MOVE 이벤트 의 크기 조정 과 회전 을 설정 할 수 있 습 니 다.(TRANS)모드 도 마찬가지다.마지막 으로 그림 변환 의 경계 값 을 가 져 와 그림 렌 더 링 을 할 지 여 부 를 판단 합 니 다.
case MotionEvent.ACTION_MOVE:
//
if (mode == ZOOM) {
moveMatrix.set(downMatrix);
float deltaRotation = getSpaceRotation(event) - oldRotation;
float scale = getSpaceDistance(event) / oldDistance;
moveMatrix.postScale(scale, scale, midPoint.x, midPoint.y);
moveMatrix.postRotate(deltaRotation, midPoint.x, midPoint.y);
withinBorder = getMatrixBorderCheck(srcImage, event.getX(), event.getY());
if (withinBorder) {
matrix.set(moveMatrix);
invalidate();
}
}
//
else if (mode == TRANS) {
moveMatrix.set(downMatrix);
moveMatrix.postTranslate(event.getX() - downX, event.getY() - downY);
withinBorder = getMatrixBorderCheck(srcImage, event.getX(), event.getY());
if (withinBorder) {
matrix.set(moveMatrix);
invalidate();
}
}
break;
(4)ACTION_POINTER_UP 와 ACTIONUP-이 두 이벤트 에서 터치 스크린 모드 를 다시 설정 하면 NONE 가 됩 니 다.5.경계 판단
다음은 경계 판단 의 논 리 는 정사각형 그림 에 대한 것 이다.먼저 원본 그림 을 통 해 자신의 네 개의 좌 표를 상대 적 으로 매 핑 하여 Matrix 가 화면 에 대응 하 는 점 좌표 가 됩 니 다.4 개의 점 의 좌 표를 얻 으 면 우 리 는 손가락 으로 그림 을 만 질 때의 좌표 와 그림 의 4 개의 점 좌 표를 연결 할 수 있다.
경계 판단 의 논 리 는 손가락 으로 그림 을 만 지 는 점 에서 4 개의 정점 까지 의 거 리 를 합 친 것 이다.
/**
* matrix
*
* @return
*/
protected float[] getBitmapPoints(Bitmap bitmap, Matrix matrix) {
float[] dst = new float[8];
float[] src = new float[]{
0, 0,
bitmap.getWidth(), 0,
0, bitmap.getHeight(),
bitmap.getWidth(), bitmap.getHeight()
};
matrix.mapPoints(dst, src);
return dst;
}
/**
*
*
* @param x
* @param y
* @return true - | false -
*/
private boolean getMatrixBorderCheck(Bitmap bitmap, float x, float y) {
if (bitmap == null) return false;
float[] points = getBitmapPoints(bitmap, moveMatrix);
float x1 = points[0];
float y1 = points[1];
float x2 = points[2];
float y2 = points[3];
float x3 = points[4];
float y3 = points[5];
float x4 = points[6];
float y4 = points[7];
float edge = (float) Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
if ((2 + Math.sqrt(2)) * edge >= Math.sqrt(Math.pow(x - x1, 2) + Math.pow(y - y1, 2))
+ Math.sqrt(Math.pow(x - x2, 2) + Math.pow(y - y2, 2))
+ Math.sqrt(Math.pow(x - x3, 2) + Math.pow(y - y3, 2))
+ Math.sqrt(Math.pow(x - x4, 2) + Math.pow(y - y4, 2))) {
return true;
}
return false;
}
총결산자,본 고의 내용 은 여기까지 입 니 다.상기 절 차 를 완성 하면 그림 이 화면 에서 의 확대,이동 과 회전 에 대한 조작 을 완성 할 수 있 습 니 다.그 렇 죠?쉽 죠?관심 이 있 는 사람 은 스스로 조작 할 수 있 습 니 다.이 글 이 여러분 의 학습 과 업무 에 도움 이 되 기 를 바 랍 니 다.궁금 한 점 이 있 으 면 댓 글 을 달 아 교류 할 수 있 습 니 다.저희 에 대한 지지 에 감 사 드 립 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Kotlin의 기초 - 2부지난 글에서는 Kotlin이 무엇인지, Kotlin의 특징, Kotlin에서 변수 및 데이터 유형을 선언하는 방법과 같은 Kotlin의 기본 개념에 대해 배웠습니다. 유형 변환은 데이터 변수의 한 유형을 다른 데이터...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.