2017-11-11 19 views
13

Tôi đang cố gắng để làm một cái nhìn theo ngón tay của tôi và làm một số luân chuyển và mở rộng quy mô trong cảm ứng đa điểm với đoạn mã sauKéo một cái nhìn xoay bằng cách điều chỉnh bố trí params

@Override 
public boolean onTouch(View view, MotionEvent motionEvent) { 

    final int action = motionEvent.getActionMasked(); 
    int newPosX,newPosY; 
    switch (action) { 
     case MotionEvent.ACTION_DOWN: { 
      final int pointerIndex = motionEvent.getActionIndex(); 
      final float x = motionEvent.getX(pointerIndex); 
      final float y = motionEvent.getY(pointerIndex); 

      RelativeLayout.LayoutParams parms = (RelativeLayout.LayoutParams) view.getLayoutParams(); 

      // Remember where we started (for dragging) 
      mLastTouchX = (int) x; 
      mLastTouchY = (int) y; 
      // Save the ID of this pointer (for dragging) 
      mActivePointerId = motionEvent.getPointerId(0); 
      break; 
     } 

     case MotionEvent.ACTION_MOVE: { 
      if(motionEvent.getPointerCount()==2){ 
       float newDist = spacing(motionEvent); 
       float scale = newDist/oldDist * view.getScaleX(); 
       view.setScaleY(scale); 
       view.setScaleX(scale); 

       float newAngle = rotation(motionEvent); 
       float a = newAngle - oldAngle; 
       view.animate().rotationBy(a).setDuration(0).setInterpolator(new LinearInterpolator()).start(); 
      } 
      // Find the index of the active pointer and fetch its position 
      final int pointerIndex = 
        motionEvent.findPointerIndex(mActivePointerId); 

      final float x = motionEvent.getX(pointerIndex); 
      final float y = motionEvent.getY(pointerIndex); 

      // Calculate the distance moved 
      final float dx = x - mLastTouchX; 
      final float dy = y - mLastTouchY; 
      RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view.getLayoutParams(); 

      layoutParams.leftMargin += dx; 
      layoutParams.topMargin += dy; 

      view.setLayoutParams(layoutParams); 

      break; 
     } 
     case MotionEvent.ACTION_POINTER_DOWN:{ 
      oldDist = spacing(motionEvent); 
      oldAngle = rotation(motionEvent); 
      break; 
     } 

     case MotionEvent.ACTION_UP: { 
      mActivePointerId = INVALID_POINTER_ID; 
      break; 
     } 

     case MotionEvent.ACTION_CANCEL: { 
      mActivePointerId = INVALID_POINTER_ID; 
      break; 
     } 

     case MotionEvent.ACTION_POINTER_UP: { 

      final int pointerIndex = motionEvent.getActionIndex(); 
      final int pointerId = motionEvent.getPointerId(pointerIndex); 

      if (pointerId == mActivePointerId) { 
       // This was our active pointer going up. Choose a new 
       // active pointer and adjust accordingly. 
       final int newPointerIndex = pointerIndex == 0 ? 1 : 0; 
       mLastTouchX = (int) motionEvent.getX(newPointerIndex); 
       mLastTouchY = (int) motionEvent.getY(newPointerIndex); 
       mActivePointerId = motionEvent.getPointerId(newPointerIndex); 
      } 
      break; 
     } 
    } 
    return true; 

} 
    private float spacing(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); 
} 

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); 
} 

Tất cả mọi thứ đang làm việc tốt cho đến khi xem được quay. Khi nó được xoay trên 90 độ và chúng tôi cố gắng kéo nó nhảy xung quanh điểm tiếp xúc. Tôi nghĩ rằng nó có liên quan đến

layoutParams.leftMargin += dx; 
layoutParams.topMargin += dy; 

setLayoutParams(layoutParams); 

Tôi đang làm việc để thực hiện công việc này trong hai ngày qua không thành công.

LƯU Ý: những gì tôi đang cố gắng đạt được là làm cho chế độ xem xoay và xoay với 2 ngón tay (kéo bằng một ngón tay) Tôi đã theo mã kéo từ tài liệu của Google để không nhảy khi đang chuyển ngón tay . Tôi đang sử dụng điều này để xoay view.animate(). RotationBy (a) .setDuration (0) .setInterpolator (new LinearInterpolator()). Start();

vì khi tôi sử dụng view.setRotate(), chế độ xem đang rung.

EDIT 1: Tôi đã gỡ bỏ

layoutParams.leftMargin += dx; 
layoutParams.topMargin += dy; 

và thay thế nó bằng:

//To get the moved distance of the finger(X and Y) 

float diffX = motionEvent.getX(pointerIndex) - mLastTouchX; 
        float diffY = motionEvent.getY(pointerIndex) - mLastTouchY; 

//to get the distance from touch point and the top or left of the view 
        final float dx = motionEvent.getRawX() - (motionEvent.getRawX()-motionEvent.getX()); 
        final float dy = motionEvent.getRawY() - (motionEvent.getRawY()-motionEvent.getY()); 
        RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view.getLayoutParams(); 

//Settings appropriate value for the margin top and margin left. 

        layoutParams.leftMargin = (int) (((motionEvent.getRawX())-dx)+ diffX); 
        layoutParams.topMargin = (int) (((motionEvent.getRawY())-dy)+ diffY); 

Bây giờ ngay cả sau khi quay chế độ xem không được di chuyển xung quanh. nhưng khi tôi chuyển ngón tay hoạt động của nó nhảy xung quanh từ vị trí thực tế.

On ACTION_POINTER_UP tôi đang làm điều này để thay đổi chuyển các ngón tay hoạt động

case MotionEvent.ACTION_POINTER_UP: { 

       final int pointerIndex = motionEvent.getActionIndex(); 
       final int pointerId = motionEvent.getPointerId(pointerIndex); 

       if (pointerId == mActivePointerId) { 
        // This was our active pointer going up. Choose a new 
        // active pointer and adjust accordingly. 
        final int newPointerIndex = pointerIndex == 0 ? 1 : 0; 
        Log.d(TAG,"New pointer index :"+newPointerIndex); 
        mLastTouchX = (int) motionEvent.getX(newPointerIndex); 
        mLastTouchY = (int) motionEvent.getY(newPointerIndex); 
        mActivePointerId = motionEvent.getPointerId(newPointerIndex); 
       } 
       break; 
      } 
+1

Tôi gặp vấn đề tương tự. Sau đó tôi tìm thấy bài viết tuyệt vời và mẫu trên Medium. Vui lòng tham khảo những điều sau đây. https://blog.uptech.team/how-to-create-snapchat-like-stickers-for-android-50512957c351. Kính trọng Preethi –

Trả lời

1

Thông thường tôi sẽ tham mưu chống thao túng vị trí và kích thước của cái nhìn quá nhiều vào thời gian chạy, nó sẽ cập nhật cách bố trí không cần thiết làm giảm hiệu suất, khó kiểm soát và hiếm khi có vẻ tốt.

Thay vào đó, nếu bạn không muốn đi sâu vào OpenGL, sau đó lời khuyên của tôi sẽ là một Custom View, tạo ra một lớp mà extend View mà sau này bạn thêm trong XML layout của bạn, <com.packagename.MyCustomView ... />. chế độ xem này sẽ có kích thước toàn bộ màn hình của bạn. Bạn @Override phương thức onDraw(Canvas canvas), nó sẽ cung cấp cho bạn canvas của chế độ xem, bạn có thể sử dụng Canvas để vẽ đồ họa trong Chế độ xem.

viết vào cuối bạn onDraw() để yêu cầu Chế độ xem thử lại và gọi onDraw() một lần nữa khi có, bạn nên ngừng gọi khi người dùng dừng chạm vào chế độ xem của bạn để thêm một số boolean vào nó.

hiện đang chạm, bạn có thể đăng ký để chạm vào các sự kiện như bạn đã làm nhưng bên trong chế độ xem tùy chỉnh và sử dụng x, y và kích thước của chế độ xem từ canvas.getWidth()canvas.getHeight() để xác định việc cần làm.

nếu bạn cần kích thước của chế độ xem trước khi bạn tiếp cận onDraw() ghi đè onMeasure().

Summery

Điều này có thể không nhìn thấy dễ dàng nhưng nó là, và nó nhanh chóng và bỏ hiệu quả, đồ họa sẽ được mịn màng, nếu bạn muốn kết quả tốt nhất có thể và không sợ rất nhiều mã sau đó bạn có thể nhìn vào bản vẽ bằng cách sử dụng OpenGl nhưng tôi sẽ không khuyên bạn rằng cho những gì bạn đang cố gắng làm.

Hy vọng tôi hiểu vấn đề và giúp bạn - Chúc may mắn!

Các vấn đề liên quan