Android 터치 이벤트 전달 메커니즘 초기 인식

12382 단어 Android터치
머리말
오늘 정리 한 지식 포 인 트 는 Andorid 에서 View 사건 전달 체제 이자 핵심 지식 점 입 니 다.많은 개발 자 들 이 이 문제 에 직면 할 때 곤 혹 스 러 울 것 이 라 고 믿 습 니 다.또한 View 의 또 다른 어 려 운 문제 인 미끄럼 충돌,예 를 들 어 ScrollView 에 ListView 를 포함 하 는 것 은 모두 상하 미끄럼 입 니 다.이것 은 어떻게 해결 해 야 합 니까?이것 이 해결 하 는 근 거 는 바로 View 사건 의 전달 체제 입 니 다.그래서 개발 자 는 View 의 사건 전달 체제 에 대해 깊이 이해 해 야 합 니 다.
목차
활동,뷰,뷰 그룹 3 자 관계터치 이벤트 유형
사건 전달 3 단계
사건 전달 메커니즘 보기ViewGroup 이벤트 전달 메커니즘소결
액 티 비 티,뷰,뷰 그룹 3 자 관계
우 리 는 모두 Android 에서 보 이 는 페이지 가 Activity 구성 요소 라 는 것 을 알 고 있 습 니 다.그 다음 에 Activity 에 컨트롤 을 포함 합 니 다.예 를 들 어 TextView,RelativeLayout 레이아웃 등 이 있 습 니 다.사실은 이런 컨트롤 의 기본 클래스 는 모두 View 라 는 추상 적 인 유형 이 고 ViewGroup 도 View 의 하위 클래스 입 니 다.차이 점 은 ViewGroup 은 다른 하위 클래스 로 사용 할 수 있 는 용기 이 고 관계 도 는 다음 과 같 습 니 다.

한 마디 로 하면 이 View 컨트롤 의 캐리어 는 Activity 이 고 Activity 는 DecorView 부터 그립 니 다.
터치 이벤트 종류
ACTION_DOWN:사용자 의 손가락 을 눌 러 조작 하 는 것 은 종종 터치 사건 의 시작 을 대표 합 니 다.
ACTION_MOVE:사용자 의 손가락 이 화면 에서 이동 하면 일반적인 상황 에서 가 벼 운 이동 은 일련의 이동 사건 을 촉발 합 니 다.
ACTION_POINTER_DOWN:추가 손가락 누 르 기 동작.
ACTION_POINTER_UP:추가 손가락 떼 기 동작
ACTION_UP:사용자 손가락 이 화면 을 떠 나 는 동작 입 니 다.한 번 들 어 올 리 는 동작 은 터치 이벤트 의 끝 을 표시 합 니 다.
화면 터치 동작 중,ACTIONDOWN 과 ACTIONUP 는 필수,ACTIONMOVE 는 상황 을 보고 정 하고 클릭 만 하면 누 르 고 들 어 올 리 는 동작 만 감지 된다.
이벤트 전달 3 단계
배포(Dispatch):사건 의 배 포 는 dispatchTouchEvent 방법 에 대응 하고 Andorid 시스템 에서 모든 터치 사건 은 이 방법 을 통 해 배 포 됩 니 다.
java boolean dispatchTouchEvent (MotionEvent ev)
이 방법 에 서 는 이 사건 을 직접 소비 하거나 하위 보기 에 사건 을 계속 나 누 어 처리 하기 로 결정 할 수 있다.
차단(Intercept):이벤트 차단 은 onIntercept TouchEvent 방법 에 대응 합 니 다.이 방법 은 ViewGroup 과 그 하위 클래스 에 만 존재 합 니 다.View 와 Activity 에 서 는 존재 하지 않 습 니 다.
java boolean onInterceptTouchEvent (MotionEvent ev)
이 방법 은 어떤 사건 을 차단 하 는 지 여 부 를 판단 하 는 데 쓰 인 다.만약 어떤 사건 을 차단 했다 면 같은 서열 의 사건 에서 이 방법 은 다시 호출 되 지 않 을 것 이다.
소비(Consume):이벤트 소 비 는 onTouch Event 방법 에 대응 합 니 다.
java boolean onTouchEvent (MotionEvent event)
클릭 이 벤트 를 처리 하 는 데 사 용 됩 니 다.결 과 를 되 돌려 주 는 것 은 현재 이 벤트 를 소모 하 는 지 여 부 를 표시 합 니 다.소모 하지 않 으 면 같은 이벤트 시퀀스 에서 현재 View 는 이 벤트 를 다시 받 을 수 없습니다.
Android 시스템 에서 이벤트 전달 처리 능력 을 가 진 것 은 세 가지 가 있 습 니 다.
Activity:dispatchTouchEvent,onTouchEvent 두 가지 방법 이 있 습 니 다.
ViewGroup:dispatchTouchEvent,onInterceptTouchEvent,onTouchEvent 세 가지 방법 이 있 습 니 다.
View:dispatchTouchEvent,onTouchEvent 두 가지 방법 이 있 습 니 다.
이벤트 전달 메커니즘 보기
여기 서 말 하 는 View 는 View Group 을 제외 한 View 컨트롤 을 말 합 니 다.예 를 들 어 TextView,Button,CheckBox 등 은 View 컨트롤 자체 가 가장 작은 단위 이 고 다른 View 의 용기 로 사용 할 수 없습니다.View 는 dispatchTouchEvent,onTouchEvent 두 가지 방법 을 가지 고 있 기 때문에 TextView 를 계승 하 는 클래스 MyTextView 를 정 의 했 습 니 다.코드 를 통 해 로 그 를 보고 절차 가 어떻게 가 는 지 볼 수 있 습 니 다.

public class MyTextView extends TextView {

 private static final String TAG = "MyTextView";

 public MyTextView(Context context) {
  super(context);
 }

 public MyTextView(Context context, AttributeSet attrs) {
  super(context, attrs);
 }

 @Override
 public boolean dispatchTouchEvent(MotionEvent ev) {
  switch (ev.getAction()) {
   case MotionEvent.ACTION_DOWN:
    Log.e(TAG, "dispatchTouchEvent ACTION_DOWN");
    break;
   case MotionEvent.ACTION_MOVE:
    Log.e(TAG, "dispatchTouchEvent ACTION_MOVE");
    break;
   case MotionEvent.ACTION_UP:
    Log.e(TAG, "dispatchTouchEvent ACTION_UP");
    break;
   case MotionEvent.ACTION_CANCEL:
    Log.e(TAG, "dispatchTouchEvent ACTION_CANCEL");
    break;
   default:
    break;
  }
  return super.dispatchTouchEvent(ev);
 }

 @Override
 public boolean onTouchEvent(MotionEvent event) {
  switch (event.getAction()) {
   case MotionEvent.ACTION_DOWN:
    Log.e(TAG, "onTouchEvent ACTION_DOWN");
    break;
   case MotionEvent.ACTION_MOVE:
    Log.e(TAG, "onTouchEvent ACTION_MOVE");
    break;
   case MotionEvent.ACTION_UP:
    Log.e(TAG, "onTouchEvent ACTION_UP");
    break;
   case MotionEvent.ACTION_CANCEL:
    Log.e(TAG, "onTouchEvent ACTION_CANCEL");
    break;
   default:
    break;
  }
  return super.onTouchEvent(event);
 }

}

동시에 MainActivity 클래스 를 정의 하여 MyTextView 를 보 여 줍 니 다.이 Activity 에서 저 희 는 MyTextView 에 onClick 과 onTouch 감청 을 클릭 하여 사건 전달 절 차 를 추적 하고 이해 할 수 있 도록 설정 합 니 다.

public class MainActivity extends AppCompatActivity implements View.OnClickListener, View.OnTouchListener {

 private static final String TAG = "MainActivity";

 private MyTextView mTextView;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  mTextView = (MyTextView) findViewById(R.id.my_text_view);
  mTextView.setOnClickListener(this); //   MyTextView     
  mTextView.setOnTouchListener(this); //   MyTextView     
 }

 @Override
 public boolean dispatchTouchEvent(MotionEvent ev) {
  switch (ev.getAction()) {
   case MotionEvent.ACTION_DOWN:
    Log.e(TAG, "dispatchTouchEvent ACTION_DOWN");
    break;
   case MotionEvent.ACTION_MOVE:
    Log.e(TAG, "dispatchTouchEvent ACTION_MOVE");
    break;
   case MotionEvent.ACTION_UP:
    Log.e(TAG, "dispatchTouchEvent ACTION_UP");
    break;
   case MotionEvent.ACTION_CANCEL:
    Log.e(TAG, "dispatchTouchEvent ACTION_CANCEL");
    break;
   default:
    break;
  }
  return super.dispatchTouchEvent(ev);
 }

 @Override
 public boolean onTouchEvent(MotionEvent event) {
  switch (event.getAction()) {
   case MotionEvent.ACTION_DOWN:
    Log.e(TAG, "onTouchEvent ACTION_DOWN");
    break;
   case MotionEvent.ACTION_MOVE:
    Log.e(TAG, "onTouchEvent ACTION_MOVE");
    break;
   case MotionEvent.ACTION_UP:
    Log.e(TAG, "onTouchEvent ACTION_UP");
    break;
   case MotionEvent.ACTION_CANCEL:
    Log.e(TAG, "onTouchEvent ACTION_CANCEL");
    break;
   default:
    break;
  }
  return super.onTouchEvent(event);
 }

 @Override
 public void onClick(View view) {
  switch (view.getId()) {
   case R.id.my_text_view:
    Log.e(TAG, "MyTextView onClick");
    break;
   default:
    break;
  }
 }

 @Override
 public boolean onTouch(View view, MotionEvent motionEvent) {
  switch(view.getId()) {
   case R.id.my_text_view:
    switch (motionEvent.getAction()) {
     case MotionEvent.ACTION_DOWN:
      Log.e(TAG, "MyTextView onTouch ACTION_DOWN");
      break;
     case MotionEvent.ACTION_MOVE:
      Log.e(TAG, "MyTextView onTouch ACTION_MOVE");
      break;
     case MotionEvent.ACTION_UP:
      Log.e(TAG, "MyTextView onTouch ACTION_UP");
      break;
     default:
      break;
    }
    break;
   default:
    break;
  }
  return false;
 }
}

결과 보기:

이 를 통 해 알 수 있 듯 이 사건 은 down-move-up 순서 로 실 행 됩 니 다.onTouch 방법 은 onClick 방법 보다 우선 합 니 다.모두 슈퍼 방법 으로 전달 된다 면 마지막 결 과 는 MyTextView 의 onTouch Event 방법 에서 소비 되 고 소비 하지 않 으 면 이 벤트 를 부모 급 으로 되 돌려 소비 합 니 다.부모 급 도 소비 하지 않 으 면그러면 결국 액 티 비 티 로 돌아 가서 처리 하 겠 습 니 다.
ViewGroup 이벤트 전달 메커니즘
ViewGroup 은 View 컨트롤 의 용기 로 존재 합 니 다.ViewGroup 은 dispatchTouchEvent,onInterceptTouchEvent,onTouchEvent 세 가지 방법 을 가지 고 있 습 니 다.마찬가지 로 저 희 는 ViewGroup 을 사용자 정의 하여 RelativeLayout 에서 계승 하여 MyRelativeLayout 를 실현 합 니 다.

public class MyRelativeLayout extends RelativeLayout {

 private static final String TAG = "MyRelativeLayout";

 public MyRelativeLayout(Context context) {
  super(context);
 }

 public MyRelativeLayout(Context context, AttributeSet attrs) {
  super(context, attrs);
 }

 @Override
 public boolean dispatchTouchEvent(MotionEvent ev) {
  switch (ev.getAction()) {
   case MotionEvent.ACTION_DOWN:
    Log.e(TAG, "dispatchTouchEvent ACTION_DOWN");
    break;
   case MotionEvent.ACTION_MOVE:
    Log.e(TAG, "dispatchTouchEvent ACTION_MOVE");
    break;
   case MotionEvent.ACTION_UP:
    Log.e(TAG, "dispatchTouchEvent ACTION_UP");
    break;
   case MotionEvent.ACTION_CANCEL:
    Log.e(TAG, "dispatchTouchEvent ACTION_CANCEL");
    break;
   default:
    break;
  }
  return super.dispatchTouchEvent(ev);
 }

 @Override
 public boolean onInterceptTouchEvent(MotionEvent ev) {
  switch (ev.getAction()) {
   case MotionEvent.ACTION_DOWN:
    Log.e(TAG, "onInterceptTouchEvent ACTION_DOWN");
    break;
   case MotionEvent.ACTION_MOVE:
    Log.e(TAG, "onInterceptTouchEvent ACTION_MOVE");
    break;
   case MotionEvent.ACTION_UP:
    Log.e(TAG, "onInterceptTouchEvent ACTION_UP");
    break;
   default:
    break;
  }
  return true;
 }

 @Override
 public boolean onTouchEvent(MotionEvent event) {
  switch (event.getAction()) {
   case MotionEvent.ACTION_DOWN:
    Log.e(TAG, "onTouchEvent ACTION_DOWN");
    break;
   case MotionEvent.ACTION_MOVE:
    Log.e(TAG, "onTouchEvent ACTION_MOVE");
    break;
   case MotionEvent.ACTION_UP:
    Log.e(TAG, "onTouchEvent ACTION_UP");
    break;
   case MotionEvent.ACTION_CANCEL:
    Log.e(TAG, "onTouchEvent ACTION_CANCEL");
    break;
   default:
    break;
  }
  return super.onTouchEvent(event);
 }
}

결과 보기:

터치 이벤트 의 전달 순 서 를 볼 수 있 는 것 도 Activity 에서 ViewGroup 까지 다시 ViewGroup 에서 전달 하 는 하위 View 입 니 다.ViewGroup 은 onInterceptTouchEvent 방법 을 통 해 이 벤트 를 차단 합 니 다.이 방법 이 true 로 돌아 가면 이 벤트 는 하위 View 에 계속 전달 되 지 않 습 니 다.false 나 슈퍼.onInterceptTouchEvent 로 돌아 가면 이 벤트 는 하위 View 에 계속 전 달 됩 니 다.하위 뷰 에서 이 벤트 를 소비 하면 뷰 그룹 은 이 벤트 를 받 지 않 습 니 다.
작은 매듭
Android 시스템 이벤트 에서 View 와 View Group 의 위조 코드 는 다음 과 같 습 니 다.

public boolean dispatchTouchEvent(MotionEvent ev){
 boolean consume = false;
 if(onInterceptTouchEvent(ev)){
 consume = onTouchEvent(ev);
 }
 else{
 consume = child.dispatchTouchEvent(ev);
 }
 return consume;
}
안 드 로 이 드 의 터치 메커니즘 의 절 차 를 세 장의 그림 으로 표시 합 니 다.
1.View 내 터치 이 벤트 는 소비 하지 않 음

2.뷰 내 터치 이벤트 소비

3.ViewGroup 터치 차단 이벤트

일부 총화:
4.567917.같은 사건 서열 은 손가락 이 화면 에 닿 는 순간 부터 손가락 이 화면 을 떠 나 는 순간 까지 끝 나 는 것 을 말한다.일반적으로 다운 이벤트 로 시작 합 니 다.중간 에 수량 이 정 해 지지 않 은 move 이벤트 가 포함 되 어 있 고 최종 적 으로 up 이벤트 로 끝 납 니 다4.567917.정상 적 인 상황 에서 하나의 사건 서열 은 하나의 View 에 의 해 차단 되 고 소 모 될 수 밖 에 없다4.567917.특정한 View 가 차단 을 결정 하면 이 사건 의 순 서 는 그것 으로 만 처리 할 수 있 습 니 다.그러면 같은 사건 서열 중의 다른 사건 은 더 이상 그것 에 게 맡 기지 않 고 사건 은 그의 부모 요소 에 다시 맡 길 것 입 니 다.즉,부모 요소 의 onTouchEvent 가 호출 될 것 입 니 다
  • View 가 ACTION 을 소모 하지 않 으 면DOWN 이외 의 다른 이벤트,그러면 이 클릭 이 벤트 는 사라 집 니 다.이때 부모 요소 의 onTouchEvent 는 호출 되 지 않 고 Activity 에 의 해 처 리 됩 니 다
  • ViewGroup 은 어떤 사건 도 차단 하지 않 습 니 다
  • View 에는 onIntercept TouchEvent 방법 이 없습니다
  • View 의 onTouch Event 는 클릭 할 수 없 는 것 이 아니라면 기본 값 이 소 모 됩 니 다
  • 4.567917.사건 전달 과정 은 외 향 적 인 것 이다.즉,사건 은 먼저 아버지 요소 에 전달 한 다음 에 아버지 요소 에 의 해 서브 View 에 나 누 어 준다이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

    좋은 웹페이지 즐겨찾기