2015-08-27 23 views
11

Tôi đang làm việc trên một ứng dụng đọc sách đơn giản dành cho Android. Tôi đã sử dụng listview cho việc này.Cách phóng to mục danh sách từ trung tâm của pinch

Những gì tôi đang làm đang tải hình ảnh từ xa từ máy chủ vào Listview của tôi (Sử dụng thư viện picasso) và đang hoạt động tốt.

Tôi cũng muốn thu phóng chức năng trong Reader của mình, tôi cũng sử dụng lớp ZoomListView để đạt được điều này.

public class ZoomListView extends ListView { 
private static final int INVALID_POINTER_ID = -1; 
private int mActivePointerId = INVALID_POINTER_ID; 
private ScaleGestureDetector mScaleDetector; 

private float mScaleFactor = 1.f; 
private float maxWidth = 0.0f; 
private float maxHeight = 0.0f; 
private float mLastTouchX; 
private float mLastTouchY; 
private float mPosX; 
private float mPosY; 
private float width; 
private float height; 

public ZoomListView(Context context) { 
    super(context); 
    mScaleDetector = new ScaleGestureDetector(getContext(), 
      new ScaleListener()); 
} 

public ZoomListView(Context context, AttributeSet attrs) { 
    super(context, attrs); 
    mScaleDetector = new ScaleGestureDetector(getContext(), 
      new ScaleListener()); 
} 

public ZoomListView(Context context, AttributeSet attrs, int defStyleAttr) { 
    super(context, attrs, defStyleAttr); 
    mScaleDetector = new ScaleGestureDetector(getContext(), 
      new ScaleListener()); 
} 

@Override 
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
    width = MeasureSpec.getSize(widthMeasureSpec); 
    height = MeasureSpec.getSize(heightMeasureSpec); 
    super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
} 

@Override 
public boolean onTouchEvent(@NonNull MotionEvent ev) { 
    super.onTouchEvent(ev); 
    final int action = ev.getAction(); 
    mScaleDetector.onTouchEvent(ev); 
    switch (action & MotionEvent.ACTION_MASK) { 
    case MotionEvent.ACTION_DOWN: { 
     final float x = ev.getX(); 
     final float y = ev.getY(); 

     mLastTouchX = x; 
     mLastTouchY = y; 

     mActivePointerId = ev.getPointerId(0); 
     break; 
    } 

    case MotionEvent.ACTION_MOVE: { 
     final int pointerIndex = ev.findPointerIndex(mActivePointerId); 
     final float x = ev.getX(pointerIndex); 
     final float y = ev.getY(pointerIndex); 
     final float dx = x - mLastTouchX; 
     final float dy = y - mLastTouchY; 

     mPosX += dx; 
     mPosY += dy; 

     if (mPosX > 0.0f) 
      mPosX = 0.0f; 
     else if (mPosX < maxWidth) 
      mPosX = maxWidth; 

     if (mPosY > 0.0f) 
      mPosY = 0.0f; 
     else if (mPosY < maxHeight) 
      mPosY = maxHeight; 

     mLastTouchX = x; 
     mLastTouchY = y; 

     invalidate(); 
     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 = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; 
     final int pointerId = ev.getPointerId(pointerIndex); 
     if (pointerId == mActivePointerId) { 
      final int newPointerIndex = pointerIndex == 0 ? 1 : 0; 
      mLastTouchX = ev.getX(newPointerIndex); 
      mLastTouchY = ev.getY(newPointerIndex); 
      mActivePointerId = ev.getPointerId(newPointerIndex); 
     } 
     break; 
    } 
    } 

    return true; 
} 

@Override 
public void onDraw(Canvas canvas) { 
    super.onDraw(canvas); 
    canvas.save(Canvas.MATRIX_SAVE_FLAG); 
    canvas.translate(mPosX, mPosY); 
    canvas.scale(mScaleFactor, mScaleFactor); 
    canvas.restore(); 
} 

@Override 
protected void dispatchDraw(@NonNull Canvas canvas) { 
    canvas.save(Canvas.MATRIX_SAVE_FLAG); 
    if (mScaleFactor == 1.0f) { 
     mPosX = 0.0f; 
     mPosY = 0.0f; 
    } 
    canvas.translate(mPosX, mPosY); 
    canvas.scale(mScaleFactor, mScaleFactor); 
    super.dispatchDraw(canvas); 
    canvas.restore(); 
    invalidate(); 
} 

private class ScaleListener extends 
     ScaleGestureDetector.SimpleOnScaleGestureListener { 
    @Override 
    public boolean onScale(ScaleGestureDetector detector) { 
     mScaleFactor *= detector.getScaleFactor(); 
     mScaleFactor = Math.max(1.0f, Math.min(mScaleFactor, 4.0f)); 
     maxWidth = width - (width * mScaleFactor); 
     maxHeight = height - (height * mScaleFactor); 
     invalidate(); 
     return true; 
    } 
} 

} 

Đây là layout XML của tôi (tôi đã cho thấy chỉ ZoomListView):

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:tools="http://schemas.android.com/tools" 
android:layout_width="match_parent" 
android:layout_height="match_parent" > 

<RelativeLayout 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:background="#ffffff" 
    android:gravity="top" 
    android:visibility="visible" > 

    <libraries.ZoomListView 
     android:id="@+id/lstv_book_reader" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:layout_marginTop="0dp" 
     android:paddingTop="0dp" > 
    </libraries.ZoomListView> 
</RelativeLayout> 
</RelativeLayout> 

Điều này cho phép tôi để zoom đọc cuốn sách của tôi. đọc cuốn sách của tôi trông giống như

enter image description here

Vấn đề: Tôi nhận được vấn đề trong zoom nhúm của tôi. Khi tôi đang thu nhỏ, thu phóng sẽ bắt đầu từ trên cùng bên trái của chế độ xem danh sách.

Hãy để tôi mô tả với hình ảnh

1 Pinch

enter image description here

2 Output Current

Lưu ý: Đây Đã phóng listview từ góc topleft

enter image description here

3 Đề xuất Output

enter image description here

+0

Làm theo hướng dẫn http://android-er.blogspot.com/2011/11/implement-pinch-zoom-in-ontouchlistener.html –

+0

Bạn có thể biện minh cho các câu sau: 'if (mPosX> 0.0f) mPosX = 0,0f; else if (mPosX maxWidth) mPosX = maxWidth; '. Tôi có những lo ngại tương tự về các điều kiện kiểm tra ranh giới của bạn cho 'mPosY'. – Vikram

+0

@Vikram Tôi đã thay đổi như bạn đã đề xuất ở trên, nhưng vấn đề của tôi vẫn còn đó. –

Trả lời

1

nó có nghĩa là bạn muốn thay đổi thuộc tính mặc định đó là zoom (rộng) luôn luôn bắt đầu từ (0,0) đó là:

_____________ 
|0,0 x  | 
|y   | 
|   | Suppose this the device screen 
|   | 
|   | 
______________ 

Và bạn muốn quy mô nó từ:

_____________ 
|   | 
|   | 
|   | Suppose this the device screen 
|   y | 
|  X 0,0| 
______________ 

Vì vậy, để đạt được điều này: Thay đổi bạn mã từ này:

canvas.scale(mScaleFactor, mScaleFactor); 

này:

canvas.scale(mScaleFactor, -mScaleFactor); 

cũng thấy câu hỏi này có liên quan với câu hỏi của bạn: Android: Drawing to canvas, way to make bottom left correspond to (0,0)? Tôi có i bạn nhận giải pháp của bạn từ ví dụ này và đoạn mã.

+0

vui lòng đọc lại bài kiểm tra. Tôi không muốn điều này như đề xuất câu trả lời của bạn thay vì tôi cần phải phóng to mục danh sách từ trung tâm của pinch nhưng nó luôn luôn phóng to từ trên cùng bên trái của mục –

+0

@All: làm thế nào để phóng to điểm tôi chạm vào nó – abcd1234

1

Hãy thử sử dụng getPivotX()getPivotY(). Bởi def họ là 0, 0 đó là lý do tại sao nó bắt đầu thu nhỏ từ góc trên bên trái.
Hãy thử để có được trục từ nơi nó chạm vào và thay đổi của bạn
canvas.scale(...) để
canvas.scale(mScaleFactor, mScaleFactor, pivotx, pivoty);

+0

@All: how to điểm zoom Tôi chạm vào nó – abcd1234

2

Cách tiếp cận một:

Để phóng to từ trung tâm của danh sách, có trung tâm zoom bằng cách gọi detector.getFocusX();detector.getFocusY(); Now sử dụng trung tâm này trong logic mở rộng của bạn.

Thay đổi onScale() thi-một cái gì đó của bạn như dưới đây:

mPosX = detector.getFocusX(); 
    mPosY = detector.getFocusY(); 

Cách tiếp cận hai (mà tôi hiện đang sử dụng):

  • Đặt cái nhìn của bạn theo quan điểm di chuyển.
  • Đổi kích thước chế độ xem của bạn.
  • Tính toán mức độ di chuyển của trung tâm. (Lấy điểm khác của detector.getFocusX() và detector.getFocusY() trước và sau khi thay đổi kích thước)
  • sử dụng parent.scrollBy (dx, dy) để xem lại.

Nếu trợ giúp - đây là một phần trong mã trung tâm của tôi.

if (isZoomOnGoing && mPreviousWidth != 0 && Math.abs(mCenterDiff) > 0) { 
     float ratioBeforeAdjustment = mCurrentZoomFocus/(float) (mTotalWidth - mCurrentZoomFocus);// 
     float ratioDiff = reducePrecision(mStartZoomRatio) - reducePrecision(ratioBeforeAdjustment); 
     float x1 = mStartZoomRatio * mTotalWidth/(1.0f + mStartZoomRatio); 
     float y1 = mTotalWidth - x1; 
     float currentRatio = x1/y1;// 
     int currentScrollBy = (int) (x1 - mCurrentZoomFocus); 
     int scrollDiff = 0; 
     if (mPreviousScrollBy != 0 && Math.abs(ratioDiff) > 1) { 
      scrollDiff = currentScrollBy - mPreviousScrollBy; 
     } 
     // if (scrollDiff>5) {//To avoid flickering//TODO do we need this 
     parent.scrollBy(currentScrollBy, 0); 

//} else {// Log.d (TAG, "drawActualGraph bỏ qua cuộn vì scrollDiff < 5"); //} mPreviousScrollBy = currentScrollBy;

+0

@Tất cả: cách thu phóng điểm tôi chạm vào nó – abcd1234

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