Android 제스처 슬라이딩 멀 티 터치 확대 축소 이미지 효과 구현
14965 단어 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 요 소 는 여러분 이 직접 수정 하여 추가 할 수 있 습 니 다.여기 서 저 는 이런 형식의 실현 을 여러분 에 게 바 칠 뿐 입 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Bitrise에서 배포 어플리케이션 설정 테스트하기이 글은 Bitrise 광고 달력의 23일째 글입니다. 자체 또는 당사 등에서 Bitrise 구축 서비스를 사용합니다. 그나저나 며칠 전 Bitrise User Group Meetup #3에서 아래 슬라이드를 발표했...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.