Phoenix Pull-to-Refresh 드롭다운 새로 고침 프레임 소스 분석
PullToRefreshView 클래스
하단 리셋의 핵심 클래스입니다.
먼저 초기화를 살펴보십시오.
public PullToRefreshView(Context context, AttributeSet attrs) {
super(context, attrs);
mDecelerateInterpolator = new DecelerateInterpolator(DECELERATE_INTERPOLATION_FACTOR);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
mTotalDragDistance = Utils.convertDpToPixel(context, DRAG_MAX_DISTANCE);
mRefreshView = new ImageView(context);
mRefreshView.setImageResource(R.drawable.buildings);
addView(mRefreshView);
setWillNotDraw(false);
setChildrenDrawingOrderEnabled(true);
}
mDecelerateInterpolator는 애니메이션의 차등기입니다.mTouchSlop은 미끄러질 때 손의 움직임이 이 거리보다 커야 컨트롤을 움직인다는 거리로 미끄러질 수 있는지 판단하는 데 쓰인다.mTotalDragDistance는 드롭다운 가능한 최대 거리입니다.이 세 개는 모두 상량이다.mRefreshView는 드롭다운 탄성 영역의 내용을 채우는 데 사용되며 SunRefreshDrawable에 캐리어를 제공합니다.ViewGroup의 경우 onDraw를 실행하려면 WILL 을 제거해야 합니다.NOT_DRAW의 Flag, 여기에는 사실 onDraw가 없어요. 이 코드는 없앨 수 있어요.setChildrendrawingOrderEnabled 설정은 그림 순서를 재정의할 수 있습니다. 그림 순서를 바꾸려면 getChildDrawingOrder를 다시 써야 합니다. 여기서도 사용하지 마십시오.
onMeasure 및 onLayout 프로세스:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
ensureTarget();
if (mTarget == null)
return;
widthMeasureSpec = MeasureSpec.makeMeasureSpec(getMeasuredWidth() - mTargetPaddingLeft - mTargetPaddingRight, MeasureSpec.EXACTLY);
heightMeasureSpec = MeasureSpec.makeMeasureSpec(getMeasuredHeight() - mTargetPaddingTop - mTargetPaddingBottom, MeasureSpec.EXACTLY);
mTarget.measure(widthMeasureSpec, heightMeasureSpec);
mRefreshView.measure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
ensureTarget();
if (mTarget == null)
return;
int width = getMeasuredWidth();
int height = getMeasuredHeight();
int left = getPaddingLeft();
int top = getPaddingTop();
int right = getPaddingRight();
int bottom = getPaddingBottom();
mTarget.layout(left, top + mCurrentOffsetTop, left + width - right, top + height - bottom + mCurrentOffsetTop);
mRefreshView.layout(left, top, left + width - right, top + height - bottom);
}
mTarget은 드롭다운 컨텐트 객체입니다.onMeasure는 mTarget과 mRefreshView를 같은 높이와 너비로 설정합니다.Layout에서 mRefreshView의 위치를 고정시키고 mCurrent OffsetTop 값을 바꾸어 mTarget를 미끄러뜨리는 효과를 실현한다.
onInterceptTouchEvent 프로세스:
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (!isEnabled() || canChildScrollUp() || mRefreshing)
return false;
final int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
setTargetOffsetTop(0, true);
mActivePointerId = ev.getPointerId(0);
mIsBeingDragged = false;
final float initialMotionY = getMotionEventYByIndex(ev);
if (initialMotionY == -1)
return false;
mInitialMotionY = initialMotionY;
break;
case MotionEvent.ACTION_MOVE:
if (mActivePointerId == INVALID_POINTER)
return false;
final float y = getMotionEventYByIndex(ev);
if (y == -1)
return false;
final float yDiff = y - mInitialMotionY;
if (yDiff > mTouchSlop && !mIsBeingDragged)
mIsBeingDragged = true;
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
mIsBeingDragged = false;
mActivePointerId = INVALID_POINTER;
break;
case MotionEvent.ACTION_POINTER_UP:
onSecondPointerUp(ev);
break;
}
return mIsBeingDragged;
}
이 과정은 주로 제스처가 drag의 표준에 도달했는지 검사하고 도달하면 차단하며 후속 이벤트 서열을 온터치 이벤트에 맡긴다.view가 disabled에 있으면 mTarget의 내용을 위로 미끄러뜨릴 수 있으며, 그 중 하나를 새로 고칠 때 터치 이벤트를 차단하지 않습니다.action이 ACTION이면DOWN:mActivePointerId는down 이벤트를 촉발하는 손가락의 Id를 나타낸다. 이 손가락이 촉발하는 모든 터치 이벤트는 변하지 않는다.다른 코드는view 드롭다운 상태의 초기화입니다.action이 ACTION이면MOVE:getMotionEventYByIndex는 mActivePointerId를 통해 현재 모브의 값을 가져오고 yDiff를 계산하여 mIsBeingDragged를 판단합니다.action이 ACTION이면POINTER_UP: 현재 화면에 있는 손가락이 한 손가락이 아닌 손가락을 만지면 그 손가락이 들어올릴 때 이 사건을 촉발합니다. onSecondPointer Up의 역할은 mActivePointer Id를 화면에 남아 있는 손가락을 가리키는 것입니다.action이 ACTION이면UP 및 ACTIONCANCEL 시 초기 상태를 회복하며 전체 과정 중 drag 기준을 충족하지 못했습니다.
onTouchEvent 프로세스:
@Override
public boolean onTouchEvent(MotionEvent ev) {
...
final int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_MOVE: {
final int pointerIndex = ev.findPointerIndex(mActivePointerId);
if (pointerIndex < 0)
return false;
final float y = getMotionEventYByIndex(ev);
final float yDiff = y - mInitialMotionY;
final float scrollTop = yDiff * DRAG_RATE;
mCurrentDragPercent = scrollTop / mTotalDragDistance;
if (mCurrentDragPercent < 0)
return false;
...
mRefreshDrawable.setPercent(mCurrentDragPercent, true);
setTargetOffsetTop(targetY - mCurrentOffsetTop, true);
break;
}
case MotionEvent.ACTION_POINTER_DOWN:
final int index = ev.getActionIndex();
mActivePointerId = ev.getPointerId(index);
break;
case MotionEvent.ACTION_POINTER_UP:
onSecondPointerUp(ev);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL: {
if (mActivePointerId == INVALID_POINTER)
return false;
final float y = getMotionEventYByIndex(ev);
final float overScrollTop = (y - mInitialMotionY) * DRAG_RATE;
mIsBeingDragged = false;
if (overScrollTop > mTotalDragDistance) {
setRefreshing(true, true);
}else {
mRefreshing = false;
animateOffsetToStartPosition();
}
mActivePointerId = INVALID_POINTER;
return false;
}
}
return true;
}
제스처가drag의 표준에 도달하면view는 이 사건을 차단하고 후속 이벤트 서열을 온터치 이벤트에 맡기며 더 이상 온터치 이벤트를 거치지 않습니다.우리는 이 과정의 코드를 다시 보았다.action이 ACTION이면MOVE를 할 때 이 이벤트에서 mTarget가 드래그할 위치의 값인 targety를 계산해야 합니다. 계산 과정은 여기서 논의하지 않겠습니다.mCurrentOffsetTop은 현재 mTarget의 top 값입니다. 이것은 setTargetOffsetTop 함수에서 알 수 있습니다.양자의 차이는 이 이벤트 mTarget에서 미끄러져야 할 값입니다.action이 ACTION이면POINTER_DOWN 및 ACTIONPOINTER_UP 시, 주요 역할은 이전에 onInterceptTouchEvent의 ACTIONPOINTER_UP는 마찬가지로 mActivePointer Id가 터치스크린에 남아 있는 손가락 중 하나를 가리키는 Id임을 확보하기 위한 것이다.action이 ACTION이면UP 및 MotionEvent.ACTION_CANCEL 시 이 때 mTarget가 미끄러지는 값인 overScrollTop을 가져옵니다. mTotalDragDistance와 비교하면 overScrollTop이 mTotalDragDistance보다 크면 리셋 애니메이션을 터치합니다. mTarget는 먼저 애니메이션 mAnimateTo CorrectPosition을 이용하여 mTotalDragDistance의 위치로 되돌려주고 리셋이 끝난 후에 애니메이션 mAnimateToStartPosition을 이용하여 초기 위치로 되돌려줍니다.overScrollTop이 mTotalDragDistance보다 작을 때 리셋을 터치하지 않고 초기 위치로 되돌려줍니다.
Pull To RefreshView에 대한 원본 코드 분석은 여기까지 하겠습니다. 위에 붙인 코드는 원시 프로젝트의 코드와 약간 다를 수 있습니다. 왜냐하면 저는 Motion Event Compat 같은 종류를 Motion Event로 직접 바꾸었기 때문입니다. 다른 것은 똑같습니다.분석 과정에서 잘못된 점이 있으면 지적해 주십시오.
마지막으로 Phoenix Pull-to-Refresh 항목의 주소:https://github.com/Yalantis/Phoenix
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.