Android 제스처 슬라이딩 멀 티 터치 크기 조정 그림 효과 구현(2)

지난 편 에 서 는 자 유 롭 게 확대 축소 사진 을 실 현 했 고 Matrix 를 간단하게 소개 했다.구체 적 인 것 은 참고 하 시기 바 랍 니 다.안 드 로 이 드 는 제스처 슬라이딩 다 중 터치 확대 그림 효 과 를 실현 하고 이 편 은 우리 의 ImageView 를 계속 보완 합 니 다.
우선 확대 후의 이동 을 넣는다.
1.자 유 롭 게 이동
저 희 는 onTouchEvent 에 이동 코드 를 추가 합 니 다.물론 화면 보다 길 거나 넓 어야 이동 할 수 있 습 니 다~~

@Override
 public boolean onTouch(View v, MotionEvent event)
 {
  mScaleGestureDetector.onTouchEvent(event);
 
  float x = 0, y = 0;
  //         
  final int pointerCount = event.getPointerCount();
  //         x y  
  for (int i = 0; i < pointerCount; i++)
  {
   x += event.getX(i);
   y += event.getY(i);
  }
  x = x / pointerCount;
  y = y / pointerCount;
 
  /**
   *           ,  mLasX , mLastY 
   */
  if (pointerCount != lastPointerCount)
  {
   isCanDrag = false;
   mLastX = x;
   mLastY = y;
  }
   
 
  lastPointerCount = pointerCount;
 
  switch (event.getAction())
  {
  case MotionEvent.ACTION_MOVE:
   Log.e(TAG, "ACTION_MOVE");
   float dx = x - mLastX;
   float dy = y - mLastY;
    
   if (!isCanDrag)
   {
    isCanDrag = isCanDrag(dx, dy);
   }
   if (isCanDrag)
   {
    RectF rectF = getMatrixRectF();
    if (getDrawable() != null)
    {
     isCheckLeftAndRight = isCheckTopAndBottom = true;
     //           ,       
     if (rectF.width() < getWidth())
     {
      dx = 0;
      isCheckLeftAndRight = false;
     }
     //           ,       
     if (rectF.height() < getHeight())
     {
      dy = 0;
      isCheckTopAndBottom = false;
     }
     mScaleMatrix.postTranslate(dx, dy);
     checkMatrixBounds();
     setImageMatrix(mScaleMatrix);
    }
   }
   mLastX = x;
   mLastY = y;
   break;
 
  case MotionEvent.ACTION_UP:
  case MotionEvent.ACTION_CANCEL:
   Log.e(TAG, "ACTION_UP");
   lastPointerCount = 0;
   break;
  }
 
  return true;
 }
먼저 우 리 는 터치 점 의 수량 을 얻 은 다음 에 여러 개의 터치 점 의 평균 값 을 구하 고 우리 에 게 mLastX,mLastY 를 설정 한 다음 에 이동 할 때 dx,dy 를 받 아 범위 검 사 를 한 후에 mScale Matrix.post Translate 를 호출 하여 오프셋 을 설정 해 야 합 니 다.물론 설정 이 완 료 된 후에 다시 한 번 확인 해 야 합 니 다.그림 을 화면 경계 와 흰색 으로 이동 할 수 없습니다.검사 가 완료 되면 setImageMatrix 를 호출 합 니 다.
여기:주의해 야 합 니 다.저 희 는 ACTION 을 복사 하지 않 았 습 니 다.DOWM,왜냐하면,ACTIONDOWN 은 다 중 터치 가 있 는 상태 에서 한 손가락 만 누 른 상태 라면 다른 손가락 을 누 르 면 다시 ACTION 을 터치 하지 않 습 니 다.DOWN,하지만 여러 손가락 이후 터치 포인트 의 평균 값 이 크게 달라 질 수 있 기 때문에 우 리 는 ACTION 을 사용 하지 않 았 습 니 다.DOWN。터치 포인트 의 수량 이 변 할 때마다 우 리 는 새로운 현재 mLastX,mLasty 와 함께 합 니 다.
다음은 위 에서 사용 하 는 두 가지 개인 적 인 방법 입 니 다.하 나 는 경 계 를 검사 하 는 데 사용 되 고 하 나 는 드래그 여 부 를 판단 하 는 데 사 용 됩 니 다.

/**
  *    ,      ,            
  */
 private void checkMatrixBounds()
 {
  RectF rect = getMatrixRectF();
 
  float deltaX = 0, deltaY = 0;
  final float viewWidth = getWidth();
  final float viewHeight = getHeight();
  //         ,            
  if (rect.top > 0 && isCheckTopAndBottom)
  {
   deltaY = -rect.top;
  }
  if (rect.bottom < viewHeight && isCheckTopAndBottom)
  {
   deltaY = viewHeight - rect.bottom;
  }
  if (rect.left > 0 && isCheckLeftAndRight)
  {
   deltaX = -rect.left;
  }
  if (rect.right < viewWidth && isCheckLeftAndRight)
  {
   deltaX = viewWidth - rect.right;
  }
  mScaleMatrix.postTranslate(deltaX, deltaY);
 }
 
 /**
  *        
  * 
  * @param dx
  * @param dy
  * @return
  */
 private boolean isCanDrag(float dx, float dy)
 {
  return Math.sqrt((dx * dx) + (dy * dy)) >= mTouchSlop;
 }
이렇게 하면 우 리 는 즐겁게 확대 하고 축소 하 며 이동 할 수 있다.
효과 도:이번에 남자 로 바 뀐 사진,우리 탈옥 의 주인공 중 한 명,TBug~

우리 의 크기 조정+이동 이 완료 되 었 습 니 다.
2.더 블 클릭 확대 와 축소
더 블 클릭 사건 에 대해 서 는 저희 Gesture Detector 가 드디어 등장 합 니 다.이 친구 가 더 블 클릭 사건 을 잡 을 수 있 습 니 다~~
1)、Gesture Detector 의 사용
Gesture Detector 가 감청 기 를 설정 하면 방법 이 한 줄 씩 있 습 니 다.우 리 는 onDoubleTap 이라는 리 셋 만 필요 하기 때문에 내부 클래스 인 Simple OnGesture Listener 를 사용 하여 인터페이스의 다른 방법 을 실현 하려 고 합 니 다.
그러나 몇 가지 문 제 를 토론 해 야 우리 의 코드 를 시작 할 수 있 습 니 다.
우리 더 블 클릭 사 이 즈 는 어떻게 변화 합 니까?
저 는 이 렇 습 니 다.현재 크기 에 따라 2 보다 작 으 면 원 그림 의 2 배 까지 두 번 누 르 십시오.만약 2,4 사이 의 것 이 라면,우 리 는 두 번 눌 러 서 바로 원 그림 의 4 배 이다.다른 상 태 는 4 배,더 블 클릭 후 최초 사이즈 로 복원 한다.
만약 네가 이렇게 하 는 것 이 적합 하지 않다 고 생각한다 면,자신의 취미 에 따라 조정 할 수 있다.
우 리 는 두 번 눌 러 서 변 화 를 하려 면 애니메이션 이 필요 합 니 다.예 를 들 어 우리 가 예 를 들 어 프 리 젠 테 이 션 그림 이 매우 크 고 전체 화면 이 표 시 될 때 initScale=0.5 왼쪽 이후 에 두 번 눌 러 서 2,즉 순간 이 네 배 커 졌 습 니 다.과도 효과 가 없 으 면 사용자 에 게 매우 나 쁜 느낌 을 줄 수 있 습 니 다.그래서 저 희 는 potDelay 를 사용 하여 Runnable 을 실행 하려 고 합 니 다.Runnable 에서 다시 당연한 크기 조정 값 에 따라 계속 실행 하려 고 합 니 다.
우선,저 희 는 구조 방법 에서 Gesture Detector 에 대한 초기 화 와 onDoubleTap 감청 설정 을 완 료 했 습 니 다.

public ZoomImageView(Context context, AttributeSet attrs)
 {
  super(context, attrs);
  mScaleGestureDetector = new ScaleGestureDetector(context, this);
  mGestureDetector = new GestureDetector(context,
    new SimpleOnGestureListener()
    {
     @Override
     public boolean onDoubleTap(MotionEvent e)
     {
      if (isAutoScale == true)
       return true;
 
      float x = e.getX();
      float y = e.getY();
      Log.e("DoubleTap", getScale() + " , " + initScale);
      if (getScale() < SCALE_MID)
      {
       ZoomImageView.this.postDelayed(
         new AutoScaleRunnable(SCALE_MID, x, y), 16);
       isAutoScale = true;
      } else if (getScale() >= SCALE_MID
        && getScale() < SCALE_MAX)
      {
       ZoomImageView.this.postDelayed(
         new AutoScaleRunnable(SCALE_MAX, x, y), 16);
       isAutoScale = true;
      } else
      {
       ZoomImageView.this.postDelayed(
         new AutoScaleRunnable(initScale, x, y), 16);
       isAutoScale = true;
      }
 
      return true;
     }
    });
  mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
  super.setScaleType(ScaleType.MATRIX);
  this.setOnTouchListener(this);
 }
  • 1.더 블 클릭 할 때 자동 크기 조정 여 부 를 먼저 판단 하고 있 으 면 retrun 을 직접 판단 합 니 다.
  • 2.그리고 우리 의 if 에 들 어 왔 습 니 다.물론 scale 이 2 보다 작 으 면 view 를 통 해 Runnable 을 보 내 서 실행 합 니 다.기타 유사;
  • 다음은 우리 Runnable 의 코드 를 보 겠 습 니 다.
    
    /**
      *        
      * 
      * @author zhy
      * 
      */
     private class AutoScaleRunnable implements Runnable
     {
      static final float BIGGER = 1.07f;
      static final float SMALLER = 0.93f;
      private float mTargetScale;
      private float tmpScale;
     
      /**
       *      
       */
      private float x;
      private float y;
     
      /**
       *        ,         ,          
       * 
       * @param targetScale
       */
      public AutoScaleRunnable(float targetScale, float x, float y)
      {
       this.mTargetScale = targetScale;
       this.x = x;
       this.y = y;
       if (getScale() < mTargetScale)
       {
        tmpScale = BIGGER;
       } else
       {
        tmpScale = SMALLER;
       }
     
      }
     
      @Override
      public void run()
      {
       //     
       mScaleMatrix.postScale(tmpScale, tmpScale, x, y);
       checkBorderAndCenterWhenScale();
       setImageMatrix(mScaleMatrix);
     
       final float currentScale = getScale();
       //         ,    
       if (((tmpScale > 1f) && (currentScale < mTargetScale))
         || ((tmpScale < 1f) && (mTargetScale < currentScale)))
       {
        ZoomImageView.this.postDelayed(this, 16);
       } else//          
       {
        final float deltaScale = mTargetScale / currentScale;
        mScaleMatrix.postScale(deltaScale, deltaScale, x, y);
        checkBorderAndCenterWhenScale();
        setImageMatrix(mScaleMatrix);
        isAutoScale = false;
       }
     
      }
     }
    
    코드 를 다 썼 습 니 다.우 리 는 여전히 우리 의 이 벤트 를 그것 에 게 전달 해 야 합 니 다.여전히 onTouch 방법 입 니 다.
    
    @Override
     public boolean onTouch(View v, MotionEvent event)
     {
      if (mGestureDetector.onTouchEvent(event))
       return true;
    
    자,확대 와 축소 기능 을 더 블 클릭 하면 됩 니 다.
    3.ViewPager 와 의 충돌 처리
    우리 의 그림 을 ViewPager 의 Item 으로 직접 사용 하 는 것 은 분명 충돌 이 있 을 것 입 니 다~~
    1)레이아웃 파일
    
    <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">
     
      
     </android.support.v4.view.viewpager>
     
    </relativelayout>
    
    2),Activity 코드
    
    package com.zhy.zhy_scalegesturedetector02;
     
    import android.app.Activity;
    import android.os.Bundle;
    import android.support.v4.view.PagerAdapter;
    import android.support.v4.view.ViewPager;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ImageView;
     
    import com.zhy.view.ZoomImageView;
     
    public class MainActivity extends Activity
    {
     private ViewPager mViewPager;
     private int[] mImgs = new int[] { R.drawable.tbug, R.drawable.a,
       R.drawable.xx };
     private ImageView[] mImageViews = new ImageView[mImgs.length];
     
     @Override
     protected void onCreate(Bundle savedInstanceState)
     {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.vp);
       
      mViewPager = (ViewPager) findViewById(R.id.id_viewpager);
      mViewPager.setAdapter(new PagerAdapter()
      {
     
       @Override
       public Object instantiateItem(ViewGroup container, int position)
       {
        ZoomImageView imageView = new ZoomImageView(
          getApplicationContext());
        imageView.setImageResource(mImgs[position]);
        container.addView(imageView);
        mImageViews[position] = imageView;
        return imageView;
       }
     
       @Override
       public void destroyItem(ViewGroup container, int position,
         Object object)
       {
        container.removeView(mImageViews[position]);
       }
     
       @Override
       public boolean isViewFromObject(View arg0, Object arg1)
       {
        return arg0 == arg1;
       }
     
       @Override
       public int getCount()
       {
        return mImgs.length;
       }
      });
     
     }
    }
    
    지금 바로 실행 중 입 니 다.ViewPager 가 괜 찮 은 것 을 발 견 했 습 니 다.하지만 우리 의 그림 이 확대 되면 서 이동 과 ViewPager 가 충돌 하여 이동 할 수 없습니다~.닦 아,닦 아.
    3)、충돌 처리
    지금 우 리 는 신속하게 생각해 보 겠 습 니 다.이전에 사건 배포 체 제 를 배 웠 던 것 을 기억 합 니 다.우리 의 ZoomImageView 는 ViewPager 에서 우리 가 차단 되 고 싶 지 않다 면 어떻게 합 니까?
    우선 차단 되 고 싶 지 않 은 조건 은 우리 의 너비 나 높이 가 화면 너비 나 높이 보다 클 때 이동 할 수 있 기 때문에 차단 되 고 싶 지 않다 는 것 이다.다음은 차단 되 고 싶 지 않 습 니 다.
    getParent().requestDisallowInterceptTouchEvent(true);
    한 줄 의 코드 가 충분 합 니 다.만약 에 사건 배포 에서 차단 되 지 않 고 명확 하지 않 으 면 참고 할 수 있 습 니 다.어떻게 차단 되 지 않 습 니까?
    함께 놓 으 면 우리 의 코드 는:
    
    switch (event.getAction())
      {
      case MotionEvent.ACTION_DOWN:
       if (rectF.width() > getWidth() || rectF.height() > getHeight())
       {
        getParent().requestDisallowInterceptTouchEvent(true);
       }
       break;
      case MotionEvent.ACTION_MOVE:
       if (rectF.width() > getWidth() || rectF.height() > getHeight())
       {
        getParent().requestDisallowInterceptTouchEvent(true);
       }
    
    화면 너비 나 높이 보다 크 거나 넓 을 때 드래그 효 과 는 그림 을 이동 하 는 것 으로 간주 하고,반대로 ViewPager 에 게 처리 하도록 합 니 다.
    현재 효과:

    ok,이제 ViewPager 와 의 충돌 이 해결 되 었 습 니 다.
    4、경계 에 도달 한 사건 은 ViewPager 에 게 처리
    일부 사용자 들 은 그림 이 경계 에 도 착 했 을 때 더 이상 끌 수 없 을 때 ViewPager 에 이 벤트 를 줄 수 있 기 를 바 랄 수도 있 습 니 다.
    그럼 ACTION 에서MOVE 에서 현재 경계 에 도 달 했 고 끌 고 있 을 때 이 벤트 를 ViewPager 에 게 전달 합 니 다.
    
    if (isCanDrag)
       {
     
        if (getDrawable() != null)
        {
         if (getMatrixRectF().left == 0 && dx > 0)
         {
          getParent().requestDisallowInterceptTouchEvent(false);
         }
     
         if (getMatrixRectF().right == getWidth() && dx < 0)
         {
          getParent().requestDisallowInterceptTouchEvent(false);
         }
    
    현재 효과:

    이 쯤 에서,우리 안 드 로 이 드 제스처 검 측 실전 만 들 기 크기 조정 을 지원 하 는 그림 미리보기 효과 가 끝 났 습 니 다~~!
    더 블 클릭 을 4 배로 확대 하고 If 를 주석 하 는 것 을 권장 합 니 다.
    
    //      else if (getScale() >= SCALE_MID
    //        && getScale() < SCALE_MAX)
    //      {
    //       ZoomImageView.this.postDelayed(
    //         new AutoScaleRunnable(SCALE_MAX, x, y), 16);
    //       isAutoScale = true;
    //      }
    이상 은 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 기 를 바 랍 니 다.여러분 도 안 드 로 이 드 를 실천 하여 제스처 슬라이딩 다 중 터치 확대 와 그림 이동 효 과 를 실현 할 수 있 습 니 다.

    좋은 웹페이지 즐겨찾기