Android Scroller 및 드 롭 다운 리 셋 구성 요소 원리 분석

Android 이벤트 차단 메커니즘
Android 에서 이벤트 의 전달 과 차단 은 View 트 리 구조 와 관련 이 있 습 니 다.View 트 리 에서 잎 노드 와 일반 노드 로 나 뉘 는데 일반 노드 에 하위 노드 가 있 으 면 ViewGroup 만 있 고 잎 노드 는 View 또는 ViewGroup 일 수 있 습 니 다.Android 와 이벤트 배포 차단 방법 은
dispatchTouchEvent(MotionEvent ev)
이벤트 배포 와 관련 된 방법 은 View 트 리 를 따라 사용자 의 터치 이 벤트 를 아래로 나 누 어 줍 니 다.
onInterceptTouchEvent(MotionEvent ev)
dispatchTouchEvent 에서 호출 되 었 습 니 다.특정한 단계 에서 이 벤트 를 차단 하 는 지 여 부 를 판단 하 는 데 사 용 됩 니 다.true 로 돌아 가면 차단 합 니 다.이 벤트 는 더 이상 아래로 나 누 어 주지 않 습 니 다.View 트 리 의 잎 노드(View 와 View Group)가 이 벤트 를 직접 차단 하 는 것 을 주의 하 십시오.
onTouchEvent(MotionEvent ev)
한 단계 씩 이 벤트 를 차단 하면 모든 이벤트 시퀀스 는 이 벤트 를 처리 합 니 다.그 다음 에 onInterceptTouchEvent 는 다시 호출 되 지 않 고 onTouchEvent 는 호출 됩 니 다.OnTouchEvent 가 true 로 돌아 가면 이 이벤트 시퀀스 를 소모 합 니 다.ACTION 이 소모 되 지 않 으 면DOWN 사건 은 이벤트 시퀀스 가 View 트 리 를 따라 위로 전 달 됩 니 다.이 사건 을 처리 할 수 있 는 부모 View 를 찾 습 니 다.ACTION 을 소모 하면DOWN 이 다른 사건 을 소모 하지 않 으 면 이 사건 의 순 서 는 사라 집 니 다.
전체 프로 세 스 설명:이벤트 가 특정한 ViewGroup 에 전 달 될 때 먼저 onInterceptTouchEvent 가 호출 됩 니 다.현재 ViewGroup 에서 이 이 벤트 를 차단 하면 true 로 돌아 갑 니 다.따라서 onTouchEvent 가 호출 됩 니 다.그렇지 않 으 면 하위 View 의 dispatchTouchEvent 진행 방법 에 대한 차단 판단 과 해당 하 는 처 리 를 계속 호출 할 것 입 니 다.
View 가 이 벤트 를 처리 할 때 먼저 OnTouchListener 를 호출 합 니 다.OnTouchListener 가 false 로 돌아 가면 onTouchEvent 를 계속 호출 합 니 다.onTouchEvent 에서 onClickListener 를 검사 합 니 다.이 를 통 해 세 가지 처리 방법의 우선 순 위 는 OnTouchListener>onTouchEvent>onClickListener 입 니 다.
ScrollTo,ScrollBy,Scroller
미끄럼 효 과 를 실현 할 때 가장 많이 사용 하 는 세 가지 방법 은 ScrollTo,ScrollBy,Scroller 입 니 다.
먼저 ScrollTo 와 ScrollBy 를 소개 합 니 다.두 가지 방법 중 하 나 는 어느 위치 로 미 끄 러 지 는 것 입 니 다.하 나 는 얼마나 미 끄 러 지 는 것 입 니까?관건 은 ScrollTo 와 ScrollBy 가 일반적인 View 구성 요소,예 를 들 어 TextView,ImageView 의 효 과 는 모 바 일 View 의 내용,즉 해당 하 는 글꼴,사진 으로 ViewGroup 만 모든 하위 View 를 이동 하 는 것 이다.스크롤 투 와 스크롤 바 이 는 보통 사용자 정의 뷰 그룹 이 슬라이딩 효 과 를 낼 때 사용 된다 는 것 이다.
그 다음 에 ViewGroup 이 미 끄 러 지 는 좌 표를 이해 해 야 합 니 다.예 를 들 어 아래 그림 왼쪽 은 미 끄 러 지기 전의 레이아웃 입 니 다.하나의 ViewGroup 아래 에 두 개의 키 View 가 있 습 니 다.ViewGroup 에서 Scrollto(0,300)를 호출 하면 ViewGroup 을 아래로 미 끄 러 뜨리 는 것 입 니 다.ViewGroup 을 투명 한 창 으로 보고 미 끄 러 진 후에 첫 번 째 키 View 가 사라 지고 두 번 째 키 View 의 상대 적 인 효 과 는 위로 미 끄 러 지 는 것 입 니 다.따라서 여 기 는 ScrollTo 와 ScrollBy 의 양음 값 을 주의해 야 하 며,동시에 미 끄 러 지 는 것 은 View Group 이 고,하위 View 는 간접 적 으로 미 끄 러 지 는 것 임 을 기억 해 야 한다.
마지막 으로 Scroller 는 간단 합 니 다.Scroller 는 애니메이션 의 플러그 인 과 유사 합 니 다.계산 과 좌표 값 을 처리 하고 저장 하 며 아무것도 하지 않 았 습 니 다.우리 가 호출 할 때
mScroller.startScroll(getScrollX(),getScrollY(),0,mHeaderHeight+getPaddingTop(),3000);
그 다음 에 실제 적 으로 시간 과 이동 할 픽 셀 에 따라 매 순간 있어 야 할 픽 셀 위 치 를 계산 한 다음 에 scrollBy 를 이 위치 로 이동 시 켜 다시 그립 니 다.또한 View 가 다시 그 릴 때 compute Scroll 방법 을 사용 하기 때문에 우 리 는 그 중에서 판단 하고 scroll 을 계속 하여 조건 부 재 귀 를 형성 하여 애니메이션 을 형성 해 야 합 니 다.

드 롭 다운 리 셋 구성 요소 의 간단 한 원리
기본 소개

전형 적 인 드 롭 다운 리 셋 인터페이스 가 위 와 같 고 드 롭 다운 리 셋 기능 에 있어 화면 은 주로 두 부분 을 포함한다.하 나 는 Refresh 인터페이스 를 보 여 주 는 부분 이 고 하 나 는 ListView 와 같은 목록 을 보 여 주 는 부분 이다.드 롭 다운 리 셋 기능 을 실현 하기 위해 서 는 뷰 그룹 을 사용자 정의 하 는 것 이 필요 합 니 다.우리 의 Refresh Layout 에는 두 개의 키 View,header,content 가 포함 되 어 있 습 니 다.헤더 인 터 페 이 스 는 다음 과 같 습 니 다:

content 는 ListView 일 수도 있 고 View Group 일 수도 있 습 니 다.화면 이 초기 에 header 와 content 를 모두 볼 수 있 기 때문에 RefreshLayout 의 onLayout 방법 이 끝나 기 전에 scrollTo(0,header Height)를 호출 하면 header 를 화면 에서 미 끄 러 뜨 릴 수 있 습 니 다.그 다음 에 전체적인 사고방식 은 RefreshLayout 와 ListView 가 터치 사건 에 대해 누가 차단 하고 누가 처리 하 는 문 제 를 분석 하 는 것 이다.
RefreshLayout 구현:
새로 고침 레이아웃 그리 기 과정:
먼저 Layout Inflater.from(context).inflate 및 addView 방법 을 통 해 Refresh Layout 구조 함수 에 header 와 content 를 레이아웃 에 추가 합 니 다.뷰 그룹 에 있어 서 그 리 는 과정 에서 가장 중요 한 것 은 onMeasure 와 onLayout 방법 입 니 다.
onMeasure

@Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  int width = MeasureSpec.getSize(widthMeasureSpec);
  int height = 0;
  for(int i=0;i<getChildCount();i++) {
   measureChild(getChildAt(i),widthMeasureSpec,heightMeasureSpec);
   height += getChildAt(i).getMeasuredHeight();
  }
  height = heightMeasureSpec;
  setMeasuredDimension(width,height);
 }
onMeasure 방법 에 서 는 모든 하위 View 를 measure 해 야 합 니 다.여기 서 measure Child 방법 을 사용 합 니 다.measure Child 내 부 는 하위 View 의 LayoutParams 에 따라 MeasureSpec 를 추가 로 밀봉 하여 측정 하기 때 문 입 니 다.

@Override
 protected void onLayout(boolean changed, int l, int t, int r, int b) {
  int count = getChildCount();
  int left =getPaddingLeft();
  Log.d("TAG", l + " " + t + " " + r + " " + b);
  int top = getPaddingTop();
  for(int i=0;i<count;i++) {
   View child = getChildAt(i);
   child.layout(left,top,child.getMeasuredWidth(),child.getMeasuredHeight() + top);
   Log.d("TAG", "child: " + child.getMeasuredWidth() + " " + child.getMeasuredHeight());
   top += child.getMeasuredHeight();
  }
  if(!init){
   // ViewGroup y      ,      View y      
   scrollTo(0,mHeaderHeight+getPaddingTop());
   invalidate();
   init = true;
  }

 }

onLayout 방법 에서 우리 가 원 하 는 레이아웃 을 진행 합 니 다.다시 그 릴 때 onMeasure 와 onLayout 가 여러 번 호출 되 기 때문에 초기 화 방법의 실행 에 주의해 야 합 니 다.
RefreshLayout 이벤트 차단 및 처리

@Override
 public boolean onInterceptTouchEvent(MotionEvent ev) {
  switch (ev.getAction()) {
   case MotionEvent.ACTION_DOWN:
    prevY = (int) ev.getRawY();
    break;
   case MotionEvent.ACTION_MOVE:
    int delY = (int) (ev.getRawY() - prevY);
    Log.d("TAG", "delY " + delY);
    if(delY>0) {
     return true;
    }
    break;
  }
  return false;
 }
차단 사건 에서 간단 한 판단 만 했 습 니 다.미 끄 러 지 는 수직 거리 가 0 보다 크 면 손가락 이 위 에서 아래로 떨 어 지 는 것 을 나타 내 는 동시에 ListView 에 표 시 된 첫 번 째 가 모든 데이터 중의 첫 번 째 인지 판단 해 야 합 니 다.그리고 사건 을 차단 한 후 onTouch Event 에 맡 깁 니 다.

@Override
 public boolean onTouchEvent(MotionEvent event) {
  switch (event.getAction()) {
   case MotionEvent.ACTION_MOVE:
    int dy = (int) (event.getRawY() - prevY);
    int sy = mHeaderHeight-dy;
    scrollTo(0,sy>0?sy:0);
    Log.d("TAG", "dy " + dy);
    break;
   case MotionEvent.ACTION_UP:
    refresh();
    break;
  }
  return true;
 }
그 전에 ViewGroup 을 header Height 의 거 리 를 아래로 미 끄 러 뜨 렸 습 니 다.header 가 나타 나 기 위해 서 는 ViewGroup 을 위로 미 끄 러 뜨 려 야 합 니 다.즉,Y 축 이 작 아 지 는 동시에 지나치게 미 끄 러 지지 않도록 판단 해 야 합 니 다.손가락 을 들 어 올 릴 때 이동 하 는 Y 축 증 가 량 에 따라 효과 적 인 미끄럼 여 부 를 판단 한 다음 에 응답 하 는 업무 논 리 를 처리 해 야 한다.주의해 야 할 것 은 현재 메 인 스 레 드 이기 때문에 사용 해 야 한 다 는 것 이다.

  new Thread(new Runnable() {
   @Override
   public void run() {
    mission();
    post(new Runnable() {
     @Override
     public void run() {
      mScroller.startScroll(getScrollX(),getScrollY(),0,mHeaderHeight+getPaddingTop(),3000);
      mArrowView.setVisibility(VISIBLE);
      mProgress.setVisibility(GONE);
     }
    });
   }
  }).start();
새 스 레 드 를 시작 하여 mission 을 완성 하 는 동시에 현재 ViewGroup 의 메시지 큐 를 통 해 작업 이 끝 난 후에 UI 를 수정 합 니 다.
관련 된 원 리 는 대체적으로 이런 것 이다.완전한 코드 는 하 홍 양 선생님 의 블 로 그 를 볼 수 있다.
https://github.com/hehonghui/android_my_pull_refresh_view
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기