Android 제스처 슬라이딩 멀 티 터치 확대 축소 이미지 효과 구현

인터넷 에 글 이 비록 많 지만,이러한 효 과 는 극히 적 으 므 로,나 는 진심으로 여러분 이 참고 하도록 바 칩 니 다.
실현 원리:ImageView 를 사용자 정의 하여 이 컨트롤 에 해당 하 는 layot(동적 레이아웃)를 진행 합 니 다.
여기 서 당신 은 몇 가지 방법 으로 집행 하 는 절 차 를 알 아야 합 니 다.
우선 ImageView 는 View 의 하위 클래스 를 계승 합 니 다.
onLayout 방법:리 셋 방법 입 니 다.이 방법 은 View 의 layot 방법 에서 실 행 됩 니 다.layot 방법 을 실행 하기 전에 setFrame 방법 을 먼저 실행 합 니 다.
setFrame 방법:우리 의 View 에 변화 가 있 는 지 판단 하고 변화 가 발생 하면 최신 l,t,r,b 를 View 에 전달 한 다음 동적 업데이트 UI 를 새로 고침 하고 ture 로 돌아 갑 니 다.변화 없 이 false 로 돌아 갑 니 다.
사용자 정의 컨트롤 을 소개 하기 전에 어떤 데 이 터 를 가 져 올 지 알 아야 합 니 다.화면의 너비,화면의 높이.
우선 setImageBitmap 방법 을 다시 써 야 합 니 다.역할:그림 의 너비 와 높이 를 얻 고 크기 를 조정 합 니 다.

/*** 
   *        
   */ 
  @Override 
  public void setImageBitmap(Bitmap bm) { 
    super.setImageBitmap(bm); 
    /**        **/ 
    bitmap_W = bm.getWidth(); 
    bitmap_H = bm.getHeight(); 
 
    MAX_W = bitmap_W * 3; 
    MAX_H = bitmap_H * 3; 
 
    MIN_W = bitmap_W / 2; 
    MIN_H = bitmap_H / 2; 
 
  }
이어서 우 리 는 onLayout 방법 에서 최초의 l,t,r,b 를 얻 었 다.

@Override 
  protected void onLayout(boolean changed, int left, int top, int right, 
      int bottom) { 
    super.onLayout(changed, left, top, right, bottom); 
    if (start_Top == -1) { 
      start_Top = top; 
      start_Left = left; 
      start_Bottom = bottom; 
      start_Right = right; 
    } 
 
  } 
다음은 중점 터치 방법 을 말씀 드 리 겠 습 니 다.사실 모두 가 알 고 있 었 습 니 다.어 려 운 말 을 하려 면 논리 가 실 현 된 것 같 습 니 다.
말 하기 전에 여러분 은 한 점 과 여러 점 의 차 이 를 알 아야 합 니 다.
한 손가락 조작:ACTIONDOWN---ACTION_MOVE----ACTION_UP
다 중 손가락 조작:ACTIONDOWN---ACTION_POINTER_DOWN---ACTION_MOVE--ACTION_POINTER_UP---ACTION_UP.
위 에 서 는 단지 절 차 를 간단하게 말 할 뿐 이 니,상세 한 것 은 모두 가 스스로 연구 하 시기 바 랍 니 다.여 기 는 단지 사용 하면 설명 할 뿐 입 니 다.

/*** 
   * touch    
   */ 
  @Override 
  public boolean onTouchEvent(MotionEvent event) { 
    /**     、     **/ 
    switch (event.getAction() & MotionEvent.ACTION_MASK) { 
    case MotionEvent.ACTION_DOWN: 
      onTouchDown(event); 
      break; 
    //      
    case MotionEvent.ACTION_POINTER_DOWN: 
      onPointerDown(event); 
      break; 
 
    case MotionEvent.ACTION_MOVE: 
      onTouchMove(event); 
      break; 
    case MotionEvent.ACTION_UP: 
      mode = MODE.NONE; 
      break; 
 
    //      
    case MotionEvent.ACTION_POINTER_UP: 
      mode = MODE.NONE; 
      /**        **/ 
      if (isScaleAnim) { 
        doScaleAnim(); 
      } 
      break; 
    } 
 
    return true; 
  } 
여기 서 의 실현 은 제 가 따로 썼 습 니 다.여러분 의 관람 에 유리 합 니 다.여기 서 저 는 사용자 정의 컨트롤 반환 값 을 말씀 드 리 겠 습 니 다.만약 에 아이 가 없 는 컨트롤 에 대해 Touch 처 리 를 하려 면 return true 를 하 는 것 이 좋 습 니 다.이것 도 게임 개발 에서 자주 사용 하 는 것 입 니 다.만약 에 이 컨트롤 에 아이 가 있다 면 이렇게 하지 마 세 요.그렇지 않 으 면 아이 가 Touch 사건 을 감청 하지 못 할 것 입 니 다.
다음은 우리 한 가지 방법 으로 보 자.
onTouchDown:손가락 클릭 시 시작 좌 표를 가 져 옵 니 다.

/**    **/ 
  void onTouchDown(MotionEvent event) { 
    mode = MODE.DRAG; 
 
    current_x = (int) event.getRawX(); 
    current_y = (int) event.getRawY(); 
 
    start_x = (int) event.getX(); 
    start_y = current_y - this.getTop(); 
 
  } 
여기 서 여러분 도 이벤트.getRawX()와 이벤트.getX()를 알 아야 합 니 다.하지만 저 는 모두 가 알 고 있 을 것 이 라 고 믿 습 니 다.제 앞의 ListView 드래그 도 언급 했 습 니 다.상대 화면,상대 부모 컨트롤 입 니 다.
onPointerDown:두 손가락 사이 의 거리.

/**             **/ 
  void onPointerDown(MotionEvent event) { 
    if (event.getPointerCount() == 2) { 
      mode = MODE.ZOOM; 
      beforeLenght = getDistance(event);//         
    } 
  } 
onTouch Move:이동 처리.

/**       **/ 
void onTouchMove(MotionEvent event) { 
  int left = 0, top = 0, right = 0, bottom = 0; 
  /**      **/ 
  if (mode == MODE.DRAG) { 
 
    /**           ,   drag     **/ 
 
    /**      l,t,r ,b **/ 
    left = current_x - start_x; 
    right = current_x + this.getWidth() - start_x; 
    top = current_y - start_y; 
    bottom = current_y - start_y + this.getHeight(); 
 
    /**        **/ 
    if (isControl_H) { 
      if (left >= 0) { 
        left = 0; 
        right = this.getWidth(); 
      } 
      if (right <= screen_W) { 
        left = screen_W - this.getWidth(); 
        right = screen_W; 
      } 
    } else { 
      left = this.getLeft(); 
      right = this.getRight(); 
    } 
    /**      **/ 
    if (isControl_V) { 
      if (top >= 0) { 
        top = 0; 
        bottom = this.getHeight(); 
      } 
 
      if (bottom <= screen_H) { 
        top = screen_H - this.getHeight(); 
        bottom = screen_H; 
      } 
    } else { 
      top = this.getTop(); 
      bottom = this.getBottom(); 
    } 
    if (isControl_H || isControl_V) 
      this.setPosition(left, top, right, bottom); 
 
    current_x = (int) event.getRawX(); 
    current_y = (int) event.getRawY(); 
 
  } 
  /**      **/ 
  else if (mode == MODE.ZOOM) { 
 
    afterLenght = getDistance(event);//         
 
    float gapLenght = afterLenght - beforeLenght;//       
 
    if (Math.abs(gapLenght) > 5f) { 
      scale_temp = afterLenght / beforeLenght;//         
 
      this.setScale(scale_temp); 
 
      beforeLenght = afterLenght; 
    } 
  } 
 
} 
처리 하 는 논리 가 비교적 많 지만 상소 코드 는 대부분 주석 이 달 려 있 습 니 다.저 는 모두 가 알 아 볼 수 있 고 원 리 를 파악 한 후에 자신의 논리 적 처 리 를 할 수 있다 고 믿 습 니 다.
월 계 여 부 를 고려 하여 크기 조정 처 리 를 보 겠 습 니 다.
setScale 방법:

/**      **/ 
  void setScale(float scale) { 
    int disX = (int) (this.getWidth() * Math.abs(1 - scale)) / 4;//          
    int disY = (int) (this.getHeight() * Math.abs(1 - scale)) / 4;//          
 
    //    
    if (scale > 1 && this.getWidth() <= MAX_W) { 
      current_Left = this.getLeft() - disX; 
      current_Top = this.getTop() - disY; 
      current_Right = this.getRight() + disX; 
      current_Bottom = this.getBottom() + disY; 
 
      this.setFrame(current_Left, current_Top, current_Right, 
          current_Bottom); 
      /*** 
       *          ,            。 
       */ 
      if (current_Top <= 0 && current_Bottom >= screen_H) { 
        Log.e("jj", "    =" + this.getHeight()); 
        isControl_V = true;//        
      } else { 
        isControl_V = false; 
      } 
      if (current_Left <= 0 && current_Right >= screen_W) { 
        isControl_H = true;//        
      } else { 
        isControl_H = false; 
      } 
 
    } 
    //    
    else if (scale < 1 && this.getWidth() >= MIN_W) { 
      current_Left = this.getLeft() + disX; 
      current_Top = this.getTop() + disY; 
      current_Right = this.getRight() - disX; 
      current_Bottom = this.getBottom() - disY; 
      /*** 
       *            
       */ 
      //      
      if (isControl_V && current_Top > 0) { 
        current_Top = 0; 
        current_Bottom = this.getBottom() - 2 * disY; 
        if (current_Bottom < screen_H) { 
          current_Bottom = screen_H; 
          isControl_V = false;//        
        } 
      } 
      //      
      if (isControl_V && current_Bottom < screen_H) { 
        current_Bottom = screen_H; 
        current_Top = this.getTop() + 2 * disY; 
        if (current_Top > 0) { 
          current_Top = 0; 
          isControl_V = false;//        
        } 
      } 
 
      //      
      if (isControl_H && current_Left >= 0) { 
        current_Left = 0; 
        current_Right = this.getRight() - 2 * disX; 
        if (current_Right <= screen_W) { 
          current_Right = screen_W; 
          isControl_H = false;//    
        } 
      } 
      //      
      if (isControl_H && current_Right <= screen_W) { 
        current_Right = screen_W; 
        current_Left = this.getLeft() + 2 * disX; 
        if (current_Left >= 0) { 
          current_Left = 0; 
          isControl_H = false;//    
        } 
      } 
 
      if (isControl_H || isControl_V) { 
        this.setFrame(current_Left, current_Top, current_Right, 
            current_Bottom); 
      } else { 
        this.setFrame(current_Left, current_Top, current_Right, 
            current_Bottom); 
        isScaleAnim = true;//        
      } 
 
    } 
 
  } 
먼저 확대 방법 을 살 펴 보 겠 습 니 다.이 안 에는 수평 이나 수직 이 깔 려 있 는 지 확인 해 야 합 니 다.
이어서 우 리 는 축 소 를 보 자.이것 은 상대 적 으로 좀 복잡 하 다.먼저 우 리 는 확대 후의 탁 이 를 고려 해 야 한다.그러면 우 리 는 축 소 를 할 때 l,t,r,b 그들 이 동시에 화면 경계 로 움 츠 러 들 지 않 을 것 이다.따라서 이때 처 리 를 해 야 한다.만약 에 한 측 이 먼저 화면 경계 로 움 츠 러 들 면 멈 춰 서서 당신 의 맞은편 을 기 다 려 야 한다.(이때 당신 의 맞은편 확대 속 도 는 원래 의 2 배 라 는 것 을 기억 하 세 요.그렇지 않 으 면 그림 이 변 형 될 것 입 니 다.여러분 스스로 생각해 보 세 요.)맞은편 에 도 화면 경계 로 움 츠 러 들 면 감청 을 닫 아야 합 니 다.그리고 두 사람 이 함께 움 츠 러 들 어야 합 니 다.원 리 는 바로 이 렇 습 니 다.
잘 모 르 겠 으 면 위 코드 를 보 셔 도 됩 니 다.다 들 잘 보 실 거 라 고 믿 습 니 다.
마지막 으로 우 리 는 축소 효 과 를 실현 해 야 한다(비교적 인성 화 된.)
처음에 나 는 Scale Animation 을 생각 했 지만 절반 의 문제 가 발생 했다.내 가 애니메이션 을 축소 한 후에 그녀 는 자동 으로 최초의 크기 로 돌 아 왔 다.아마도 너 는 setFill After(true)를 적 게 넣 었 다 고 말 할 것 이다.그러나 추 가 된 후에 기괴 한 현상 이 나타 날 수 있 습 니 다.다시 한 층 덮 을 것 입 니 다.원인 이 불분명 합 니 다.여러분 이 한번 해 보 세 요.API 가 준 애니메이션 이 실현 되 지 못 하 는 이상 제 가 직접 하 겠 습 니 다.다음은 구체 적 인 실현 을 보 겠 습 니 다.
MyAsyncTask 비동기 류.

/*** 
   *       
   */ 
  class MyAsyncTask extends AsyncTask<Void, Integer, Void> { 
    private int screen_W, current_Width, current_Height; 
 
    private int left, top, right, bottom; 
 
    private float scale_WH;//       
 
    /**         **/ 
    public void setLTRB(int left, int top, int right, int bottom) { 
      this.left = left; 
      this.top = top; 
      this.right = right; 
      this.bottom = bottom; 
    } 
 
    private float STEP = 5f;//    
 
    private float step_H, step_V;//     ,     
 
    public MyAsyncTask(int screen_W, int current_Width, int current_Height) { 
      super(); 
      this.screen_W = screen_W; 
      this.current_Width = current_Width; 
      this.current_Height = current_Height; 
      scale_WH = (float) current_Height / current_Width; 
      step_H = STEP; 
      step_V = scale_WH * STEP; 
    } 
 
    @Override 
    protected Void doInBackground(Void... params) { 
 
      while (current_Width <= screen_W) { 
 
        left -= step_H; 
        top -= step_V; 
        right += step_H; 
        bottom += step_V; 
 
        current_Width += 2 * step_H; 
 
        left = Math.max(left, start_Left); 
        top = Math.max(top, start_Top); 
        right = Math.min(right, start_Right); 
        bottom = Math.min(bottom, start_Bottom); 
 
        onProgressUpdate(new Integer[] { left, top, right, bottom }); 
        try { 
          Thread.sleep(10); 
        } catch (InterruptedException e) { 
          e.printStackTrace(); 
        } 
      } 
 
      return null; 
    } 
 
    @Override 
    protected void onProgressUpdate(final Integer... values) { 
      super.onProgressUpdate(values); 
      mActivity.runOnUiThread(new Runnable() { 
        @Override 
        public void run() { 
          setFrame(values[0], values[1], values[2], values[3]); 
        } 
      }); 
 
    } 
 
  } 
이것 은 제 가 상세 하 게 설명 하지 않 겠 습 니 다.여러분 이 주의해 야 할 것 은 수평 과 수직 방향의 속도 입 니 다.
마지막 으로 레이아웃 을 보면 호출 도 상당히 간단 하고 보조 UI 를 추가 하 는 데 도움 이 됩 니 다.android:scaleType="fitXY"라 는 말 을 쓰 는 것 을 잊 지 마 세 요.그렇지 않 으 면 가끔 이상 한 현상 이 발생 할 수 있 습 니 다.

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  android:layout_width="fill_parent" 
  android:layout_height="fill_parent" 
  android:gravity="center" > 
 
  <com.jj.drag.DragImageView 
    android:id="@+id/div_main" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content"  
    android:scaleType="fitXY" 
    /> 
 
</LinearLayout> 
Acitivity 에서 호출:

/**         **/ 
    viewTreeObserver = dragImageView.getViewTreeObserver(); 
    viewTreeObserver 
        .addOnGlobalLayoutListener(new OnGlobalLayoutListener() { 
 
          @Override 
          public void onGlobalLayout() { 
            if (state_height == 0) { 
              //         
              Rect frame = new Rect(); 
              getWindow().getDecorView() 
                  .getWindowVisibleDisplayFrame(frame); 
              state_height = frame.top; 
              dragImageView.setScreen_H(window_height-state_height); 
              dragImageView.setScreen_W(window_width); 
            } 
 
          } 
        }); 
이상 은 모두 이 루어 진 것 이다.마지막 으로 이 루어 진 효 과 를 살 펴 보 자.
원본 크기  
    
확대 해서 왼쪽으로 끌 어 당 겨 주세요.  
    
축소 후  

너 그 럽 게 자라다

운행 효과 가 괜 찮 은 것 같 습 니 다.텐 센트 시 나 닷 컴 과 차이 가 많 지 않 습 니 다.보조 UI 요 소 는 여러분 이 직접 수정 하여 추가 할 수 있 습 니 다.여기 서 저 는 이런 형식의 실현 을 여러분 에 게 바 칠 뿐 입 니 다.

좋은 웹페이지 즐겨찾기