Android 는 그림 확대,이동,회전 기능 을 실현 합 니 다.

일단 이 룰 효과 도 를 살 펴 보 겠 습 니 다.

설명 에서 그림 그리 기의 원리 에 관 한 지식 을 미리 알 아야 한다.
실현 에 관 한 절차
     1.사용자 정의View     2,조작 이미지 획득Bitmap     3.복사ViewonTouchEvent()방법 중의ACTION_DOWN,ACTION_POINTER_DOWN,ACTION_MOVE,ACTION_POINTER_UPACTION_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;
  }
총결산
자,본 고의 내용 은 여기까지 입 니 다.상기 절 차 를 완성 하면 그림 이 화면 에서 의 확대,이동 과 회전 에 대한 조작 을 완성 할 수 있 습 니 다.그 렇 죠?쉽 죠?관심 이 있 는 사람 은 스스로 조작 할 수 있 습 니 다.이 글 이 여러분 의 학습 과 업무 에 도움 이 되 기 를 바 랍 니 다.궁금 한 점 이 있 으 면 댓 글 을 달 아 교류 할 수 있 습 니 다.저희 에 대한 지지 에 감 사 드 립 니 다.

좋은 웹페이지 즐겨찾기