Android QQ 목록 슬라이딩 삭제 동작
우선 어 려 운 점 은 ListView 를 통 해 특정한 item 의 View 를 얻 는 것 입 니 다.ViewGroup 에 대해 서 는 getChildAt()방법 으로 대응 하 는 하위 view 를 직접 호출 할 수 있 습 니 다.그러나 ListView 에서 getChildAt()을 직접 사용 하면 ListView 가 미 끄 러 지면 빈 지침 이 이상 하 다 는 것 을 알 수 있 습 니 다.ListView 에 대해 서 는 getChildAt()방법 을 직접 사용 하 는 것 이 통 하지 않 는 것 이 분명 합 니 다.ListView 는 뷰 그룹 이지 만이미 누군가가 이 문제 와 해결 방법 을 설명 했다.아마도 ListView 는 많은 item 이 있 는 것 처럼 보이 지만 이것 은 보기 일 뿐이다.실제로 ListView 는 네가 볼 수 있 는 것 만 구성 했다.바로 화면 에 볼 수 있 는 그렇게 많은 item 의 view 이기 때문에 ListView 의 특정한 위치 position 의 item 의 view 를 가 져 가 야 한다.다음 코드 를 사용 해 야 합 니 다:
int firstVisiblePos = getFirstVisiblePosition() - getHeaderViewsCount();
int factPos = curPos - firstVisiblePos;
mItemView = getChildAt(factPos);
바로 ListView 에서 현재 첫 번 째 로 볼 수 있 는 item 의 firstVisiblePos 를 가 져 오 는 것 입 니 다.물론 header view 의 수 를 빼 고 가 져 오고 싶 은 item 의 curPos 에서 firstVisiblePos 를 빼 면 해당 하 는 item 이 실제 ListView 의 위치 에 있 는 factPos 입 니 다.이제 빈 지침 이상 을 알 리 지 않 을 겁 니 다.특정한 위 치 를 가 져 오 는 item 의 view 를 알 게 되 었 습 니 다.이 제 는 미끄럼 사건 을 감지 하여 현재 ListView 와 어떤 position 의 item 과 상호작용 을 하고 있 는 지 판단 해 야 합 니 다.ListView 에서 다음 과 같은 방법 을 사용 합 니 다.
int curPos = pointToPosition((int)curX, (int)curY);
다음은 ListView 의 touch 사건 을 캡 처 한 것 입 니 다.SlidingDeleteListView 를 사용자 정의 하고 ListView 에서 계승 하여 onTouch Event()방법 을 다시 쓰 는 것 입 니 다.
@Override
public boolean onTouchEvent(MotionEvent event) {
if(!mEnableSliding)
return false;
if(mCancelMotionEvent && event.getAction() == MotionEvent.ACTION_MOVE) {
return true;
} else if(mCancelMotionEvent && event.getAction() == MotionEvent.ACTION_DOWN) {
event.setAction(MotionEvent.ACTION_CANCEL);
}
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN: {
if(mTracker == null)
mTracker = VelocityTracker.obtain();
else
mTracker.clear();
mLastMotionX = event.getX();
mLastMotionY = event.getY();
}break;
case MotionEvent.ACTION_MOVE: {
mTracker.addMovement(event);
mTracker.computeCurrentVelocity(1000);
int curVelocityX = (int) mTracker.getXVelocity();
float curX = event.getX();
float curY = event.getY();
int lastPos = pointToPosition(
(int)mLastMotionX, (int)mLastMotionY);
int curPos = pointToPosition((int)curX, (int)curY);
int distanceX = (int)(mLastMotionX - curX);
if(lastPos == curPos && (distanceX >= MAX_DISTANCE || curVelocityX < -MAX_FLING_VELOCITY)) {
int firstVisiblePos = getFirstVisiblePosition() - getHeaderViewsCount();
int factPos = curPos - firstVisiblePos;
mItemView = getChildAt(factPos);
if(mItemView != null) {
if(mButtonID == -1)
throw new IllegalButtonIDException("Illegal DeleteButton resource id,"
+ "ensure excute the function setButtonID(int id)");
mButton = mItemView.findViewById(mButtonID);
mButton.setVisibility(View.VISIBLE);
mButton.startAnimation(mShowAnim);
mLastButtonShowingPos = curPos;
mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(mDeleteItemListener != null)
mDeleteItemListener.onButtonClick(v, mLastButtonShowingPos);
mButton.setVisibility(View.GONE);
mLastButtonShowingPos = -1;
}
});
mCancelMotionEvent = true;
}
}
}break;
case MotionEvent.ACTION_UP: {
if(mTracker != null) {
mTracker.clear();
mTracker.recycle();
mTracker = null;
}
mCancelMotionEvent = false;
if(mLastButtonShowingPos != -1) {
event.setAction(MotionEvent.ACTION_CANCEL);
}
}break;
case MotionEvent.ACTION_CANCEL: {
hideShowingButtonWithAnim();
}break;
}
return super.onTouchEvent(event);
}
위의 코드 를 설명 하기 전에 안 드 로 이 드 의 touch 사건 의 배포 원 리 를 간단하게 말씀 드 리 겠 습 니 다.주로 MotionEvent.ACTION 입 니 다.DOWN 이 사건 은 가장 중요 합 니 다.사건 의 배 포 는 한 번 에 두 부분 이 있 습 니 다.'자'는 ViewGroup 이 시스템 에 전달 되 는 ACTION 을 가 져 오 는 것 을 말 합 니 다.DOWN 이벤트,ViewGroup 의 onInterceptTouchEvent()방법 을 먼저 호출 합 니 다.이 방법 은 이 사건 ViewGroup 이 캡 처 하고 싶 은 지,true 로 돌아 가면 ACTIONDOWN 이벤트 가 View Group 에 배 포 된 onTouchEvent()방법 으로 처리 되 었 습 니 다.이 사건 은 부모 view 에 의 해 캡 처 되 었 고 하위 view 는 더 이상 이 벤트 를 가 져 오지 않 을 것 임 을 표시 합 니 다.ViewGroup 의 onInterceptTouchEvent()방법 이 false 로 되 돌아 오 면 ViewGroup 이 이 사건 을 캡 처 하지 않 고 다음 사건 이 발생 하 는 위치 에 하위 view 가 존재 한다 면 ViewGroup 은 이 ACTION 을DOWN 사건 은 이 하위 view 에 전달 되 어 처 리 됩 니 다.이 과정 은 사건 의 배포 과정 이 고 그 다음은'회'이다.회'이 과정 은 사건 의 소모 과정 이다.하위 view 의 onTouch Event()방법 은 true 로 돌아 가면 이 ACTION 을 나타 낸다.DOWN 이벤트 가 이 하위 view 에 소모 되면 ViewGroup 은 onTouchEvent()방법 으로 이 사건 을 받 아들 이지 않 습 니 다.이 사건 이 소모 되 었 기 때 문 입 니 다.하위 view 의 onTouchEvent()방법 이 false 로 돌아 오 면 하위 view 가 이 ACTION 을 소모 하지 않 음 을 표시 합 니 다.DOWN 이벤트(물론,하위 view 는 이 사건 을 처리 할 수 있 지만 false 로 돌아 가면 사건 을 View Group 에 던 져 주 고 많은 일 을 할 수 있 습 니 다)이후 사건 은 부모 view 에 게 돌아 갑 니 다.최종 MotionEvent.ACTIONDOWN 이벤트 가 어느 층 의 view 에 소모 되 었 는 지,다음 의 후속 touch 이벤트,예 를 들 어 ACTIONUP、ACTION_MOVE、ACTION_CANCEL 등 사건 은 소모 ACTION 에 게 직접 전 달 됩 니 다.DOWN 이벤트 의 view,다른 층 의 view 는 다음 ACTION 까지 후속 사건 을 받 지 않 습 니 다.DOWN 사건. 이상 의 코드 는 switch 의 코드 블록 에 잠시 관심 을 가 집 니 다.MotionEvent.ACTION 이 검출 되 었 습 니 다.DOWN 이벤트 때 현재 touch 이벤트 의 위 치 를 기록 하 는 동시에 mTracker 를 먼저 가 져 옵 니 다.이것 은 Velocity Tracker 대상 입 니 다.안 드 로 이 드 가 제공 하 는 현재 미끄럼 이벤트 의 속 도 를 계산 하 는 데 사 용 됩 니 다.Motion Event.ACTION 감지MOVE 이벤트,우 리 는 두 가지 상황 에서 처리 해 야 합 니 다.한 가지 상황 은 사용자 가 일정한 거 리 를 미 끄 러 지면 button 을 팝 업 하 는 것 입 니 다.이 거 리 는 현재 미 끄 러 진 위치 와 이번 ACTION 입 니 다.DOWN 이 기록 한 이벤트 위치의 거 리 는 두 번 째 상황 은 사용자 가 미끄럼 속도 가 한 한도 값 을 초과 할 때 button 을 팝 업 하 는 것 입 니 다.이 속도 의 계산 은 앞에서 언급 한 mTracker 를 사용 하 는 것 입 니 다.용법 은 매우 간단 합 니 다.ACTION 검출UP 사건 은 현재 의 이번 상호작용 이 완성 되 었 음 을 나타 내 고 우 리 는 청 소 를 할 수 있 습 니 다.에 대해 ACTIONCANCEL 사건,이 건 잠시 여 기 를 살 게 요.이 건 대 들 보 를 훔 쳐 기둥 을 바 꾸 는 작은 기술 로 시스템 을 괴 롭 히 세 요~
위의 ACTIONMOVE 이벤트 에서 이벤트 가 처리 되 고 button 이 뜨 면 다음 에 ACTION 이 검출 됩 니 다.DOWN 이벤트,이 이벤트 가 발생 한 위치 가 button 의 영역 에 없 으 면 사용자 가 팝 업 button 을 누 르 지 않 았 음 을 표시 합 니 다.이 button 을 제거 해 야 합 니 다.즉,이 button 을 숨 겨 야 합 니 다.여기 에는 앞서 언급 한 View Group 의 onInterceptTouchEvent()방법 을 사용 해 야 합 니 다.이번 ACTIONDOWN 이벤트 가 하위 view 에 전달 되 기 전에 캡 처 되 었 습 니 다.물론 이번 사건 이 button 을 클릭 한 사건 인지 아 닌 지 판단 하 십시오.
private boolean isClickButton(MotionEvent ev) {
mButton.getLocationOnScreen(mShowingButtonLocation);
int left = mShowingButtonLocation[0];
int right = mShowingButtonLocation[0] + mButton.getWidth();
int top = mShowingButtonLocation[1];
int bottom = mShowingButtonLocation[1] + mButton.getHeight();
return (ev.getRawX() >= left
&& ev.getRawX() <= right
&& ev.getRawY() >= top
&& ev.getRawY() <= bottom);
} onInterceptTouchEvent() :
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if(mEnableSliding && mLastButtonShowingPos != -1 &&
ev.getAction() == MotionEvent.ACTION_DOWN && !isClickButton(ev)) {
ev.setAction(MotionEvent.ACTION_CANCEL);
mCancelMotionEvent = true;
return true;
}
return super.onInterceptTouchEvent(ev);
};
ACTION 을 캡 처 할 지 말 지 판단 하기DOWN 이벤트,현재 button 이 팝 업 되 었 는 지 먼저 판단 합 니 다.button 이 팝 업 될 때마다 현재 팝 업 된 item 의 위치 mLastButton ShowingPos 를 기록 하기 때 문 입 니 다.그리고 지금 이 ACTION 인지 아 닌 지...DOWN 이벤트;팝 업 단추 누 를 지 여부 입 니 다.모든 조건 이 부합 되면 우 리 는 이 ACTION 을 압수 할 것 이다.DOWN 이벤트,onInterceptTouchEvent()방법 return true.이렇게 하면 ACTIONDOWN 사건 은 이 SlidingDeleteListView 의 onTouchEvent()방법 으로 전 달 됩 니 다.여기 서 앞의 ACTION 을 설명 하 겠 습 니 다.CANCEL 사건,onTouchEvent()방법 에서 ACTION 으로 판 단 됩 니 다.DOWN,그리고 앞 에 onInterceptTouchEvent()에 표 시 된 mCancel MotionEvent 입 니 다.이 표 시 는 ACTION 을 캡 처 했 음 을 표시 합 니 다.DOWN 이벤트,이 ACTION 을 특수 처리 해 야 합 니 다.DOWN 이벤트,그리고 onTouchEvent()방법 에서 이번 ACTION 을 어떻게 처리 하 는 지 보 세 요.다운 사건 은?
else if(mCancelMotionEvent && event.getAction() == MotionEvent.ACTION_DOWN) {
event.setAction(MotionEvent.ACTION_CANCEL);
}
네,대 들 보 를 훔 쳐 서 기둥 을 바 꾸 고 현재 의 ACTIONDOWN 이벤트 가 ACTION 으로 바 뀌 었 습 니 다.CANCEL 사건,ACTION 에서CANCEL 사건 의 처 리 는 gone 이 현재 팝 업 된 button 을 제거 하 는 것 입 니 다.그러면 두 가지 상황 에서 ACTIONDOWN 이 구분 해서 추가 처 리 를 했 습 니 다.동시에 우 리 는 ACTION 에서UP 이벤트 에서 판단 이 있 습 니 다.현재 mLastButton ShowingPos 가-1 이 아니라면 이번 에는 사용자 가 팝 업 button 을 미 끄 러 뜨리 는 작업 임 을 나타 냅 니 다.이번 touch 사건 은 저희 가 처 리 했 습 니 다.그러면 저 희 는 이번 ACTION 을UP 이 벤트 는 ListView 자체 의 기본 슈퍼.onTouchEvent()논리 로 처리 되 었 습 니 다.앞의 ACTION 때 문 입 니 다.DOWN 및 ACTIONMOVE 우 리 는 모두 기본 절 차 를 밟 고 있 습 니 다.그럼 지금 ListView 의 원래 논 리 는 ACTION 을 기다 리 고 있 습 니 다.UP 이벤트 발송,이렇게 하면 ListView 자체 의 OnItemClick 또는 OnItemLongClick 사건 의 촉발 입 니 다.생각해 보 세 요.만약 에 우리 가 숨겨 진 button 을 팝 업 했 는데 ListView 가 OnItemClick 이나 OnItemLongClick 을 처리 하면 적당 하지 않 을 것 입 니 다.그래서 여기 서 우 리 는 시스템 을 조금 속 이 고 원래 의 ACTION 을UP 를 ACTION 으로 교체CANCEL,이렇게 button 의 팝 업 을 처리 한 후에 ListView 원래 의 OnItemClick 이나 OnItemLongClick 사건 을 처리 하지 않 습 니 다.
if(mLastButtonShowingPos != -1) {
event.setAction(MotionEvent.ACTION_CANCEL);
}
마지막 으로 onTouchEvent()방법 을 다시 쓰 면 이 사용자 정의 ListView 의 onItemClick()과 onItemLongClick()방법 에 영향 을 미 치지 않 을 까요?정 답 은 이 방안 이 아 닙 니 다.onTouchEvent()방법 은 캡 처 되 지 않 은 사건 에 대해 슈퍼.onTouchEvent(ev)로 돌아 가기 때문에 미끄럼 사건 의 검 측 도 처 리 했 습 니 다.시스템 이 이번 사건 에 대한 처리 절 차 를 방 해 했 는 지,캡 처 한 사건 은 사건 의 완전한 생명 주 기 를 주 었 습 니 다.CANCEL 이벤트 로 touch 의 상호작용 을 끝 냅 니 다)여기 서 생명 주 기 를 말씀 드 리 겠 습 니 다.ACTION 으로DOWN 이벤트 시작,ACTIONUP 또는 ACTIONCANCEL 사건 이 끝나 고 중간 에 일련의 ACTION 이 섞 여 있 습 니 다.MOVE 사건.제 최초의 방안 은 ListView.setOnTouch Listener()를 사용 하고 이 Touch Listener 의 onTouch()방법 을 실현 하 는 것 입 니 다.이렇게 사건 을 처리 하 는 것 은 약간 복잡 합 니 다.이 컨트롤 의 처리 논 리 는 ACTION 에 있 기 때 문 입 니 다.MOVE 에서 button 이 나 오 면 모든 후속 ACTIONMOVE 이벤트 무효 화,무효 화 되 지 않 으 면 후속 ACTIONMOVE 이벤트 ListView 는 여전히 받 을 수 있 습 니 다.사용 자 는 ListView 를 위아래 로 끌 수 있 습 니 다.ListView 의 item 이 몇 개의 공 통 된 view 를 다시 사용 하 는 친구 라 는 것 을 알 면 다음 에 무슨 bug 가 나 올 지 생각 할 수 있 습 니 다.바로 button 이 꺼 지지 않 았 던 item 이 화면 에 나타 나 면 button 이 나타 납 니 다.이 item 은 사라 진 item 의 view 를 다시 사용 하기 때 문 입 니 다.그럼 제 가 OnTouch Listener.onTouch()방법 을 사용 할 때 button 이 뜨 자마자 true 로 되 돌아 와 서 이 사건 이 OnTouch Listener 에 의 해 처리 되 었 음 을 나타 내 는데 여기 가 문제 가 생 겼 습 니 다.앞의 ACTION 때 문 입 니 다.DOWN 이 벤트 는 false 로 되 돌아 갑 니 다.touch 의 상호작용 을 나타 내 는 초기 이 벤트 는 ListView 의 기본 onTouchEvent()논리 적 으로 처리 되 었 습 니 다.(false 로 돌아 가 야 합 니 다.그렇지 않 으 면 모든 이벤트 가 OnTouchListener 와 먹 혔 습 니 다)기본 onTouchEvent()에서 이번 ACTION 을 어떻게 처 리 했 는 지 모 르 기 때 문 입 니 다.DOWN,보통 ListView 이지 만 이번 ACTION 소모DOWN,OnItemClick 또는 OnItemLongClick 사건 의 처 리 를 시작 합 니 다.이것 은 아 이 템 의 클릭 사건 이 모두 ListView 의 onTouch Event()에 의 해 처리 되 기 때 문 입 니 다.ACTIONDOWN 은 ListView 자체 의 onTouchEvent()에 소모 되 었 으 나 후속 ACTIONMOVE 심지어 ACTIONUP 이벤트 가 OnTouchListener 에 의 해 소모 되면 기본 적 인 onTouchEvent()에 전달 되 지 않 고 처리 할 수 없습니다.원래 완전한 touch 수명 주기 가 딱딱 하 게 두 부분 으로 자 르 여 두 곳 에서 처리 되 었 습 니 다.그러면 큰 추진 문 제 를 초래 할 수 있 습 니 다.가장 눈 에 띄 는 것 은 ListView 자체 의 OnitemClickListener 등 사건 을 처리 하 는 모니터 가 미끄럼 사건 을 처리 하 는 코드 와 충돌 하 는 것 입 니 다.미 끄 러 진 후에 button 이 튀 어 나 온 것 같 습 니 다.현재 미끄럼 사건 을 처리 하 는 item 은 하 이 라이트 선택 상태(android 에서 pressed 로 표시)입 니 다.손가락 이 화면 을 떠 났 더 라 도.마지막 으로 채택 한 방안 은 사건 처리 의 논 리 를 유지 하 는 것 이다.한 방법 안에 시스템 사건 의 정상 적 인 분배 운행 을 할 수 있 을 뿐만 아니 라 그 자체 도 미끄럼 사건 을 처리 할 수 있다.마지막 코드 는 나의 github 에 제출 되 었 다https://github.com/YoungLeeForeverBoy/SlidingDeleteListView
다음은 이 컨트롤 의 전시 입 니 다:
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
QQ 낯선 사람에게 채팅하는 autoit 스크립트.저장 qq.au3, 실행하기 전에 컴퓨터에 autoit3 프로그램이 있다는 것을 보증해야 합니다. 주소의 문장을 구체적으로 다운로드해야 합니다...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.