pkpm软件-安卓手机恢复出厂设置

velocitytracker
2023年4月2日发(作者:joy2key)

RecyclerViewfling事件

本⽂旨在分析RecyclerView中的fling事件,并提出⼀些注意事项:

事件拦截处理,只有recyclerViewscrollState是停⽌的时候,事件才会向下分发

@Override

publicbooleanonInterceptTouchEvent(MotionEvente){

switch(action){

_DOWN:

.....

if(mScrollState==SCROLL_STATE_SETTLING){

getParent().requestDisallowInterceptTouchEvent(true);

setScrollState(SCROLL_STATE_DRAGGING);

}

break;

.....

}

//这个地⽅需要注意

//结合上下⽂可以看到,只有recyclerView的state==SCROLL_STATE_IDLE,也就是⾮滑动状态,事件才不被拦截

returnmScrollState==SCROLL_STATE_DRAGGING;

}

fling事件的开始,UP⼿指抬起的时候,开始fling

@Override

publicbooleanonTouchEvent(MotionEvente){

_UP:{

ement(vtev);

eventAddedToVelocityTracker=true;

eCurrentVelocity(1000,mMaxFlingVelocity);

finalfloatxvel=canScrollHorizontally

-locity(mScrollPointerId):0;

finalfloatyvel=canScrollVertically

-locity(mScrollPointerId):0;

//here回调flingapi

if(!((xvel!=0||yvel!=0)&&fling((int)xvel,(int)yvel))){

setScrollState(SCROLL_STATE_IDLE);

}

resetTouch();

}break;

returntrue;

}

fling⼀系列事件,从这个api开始处理

publicbooleanfling(intvelocityX,intvelocityY){

//嵌套滑动事件中,onNestedPreFlingapi被调⽤

if(!dispatchNestedPreFling(velocityX,velocityY)){

finalbooleancanScroll=canScrollHorizontal||canScrollVertical;

//嵌套滑动,onNestedFlingapi被调⽤

dispatchNestedFling(velocityX,velocityY,canScroll);

if(mOnFlingListener!=null&&g(velocityX,velocityY)){

returntrue;

}

if(canScroll){

intnestedScrollAxis=_AXIS_NONE;

if(canScrollHorizontal){

nestedScrollAxis|=_AXIS_HORIZONTAL;

}

if(canScrollVertical){

nestedScrollAxis|=_AXIS_VERTICAL;

}

//嵌套滑动,startNestedScrollapi被调⽤

startNestedScroll(nestedScrollAxis,TYPE_NON_TOUCH);

velocityX=(-mMaxFlingVelocity,(velocityX,mMaxFlingVelocity));

velocityY=(-mMaxFlingVelocity,(velocityY,mMaxFlingVelocity));

//ViewFlinger是RecyclerView中的类,implementsRunnable,⽤来处理fling事件

(velocityX,velocityY);

returntrue;

}

}

returnfalse;

}

ViewFlingerimplementsRunnable

publicvoidfling(intvelocityX,intvelocityY){

//设置当前scroll状态

setScrollState(SCROLL_STATE_SETTLING);

mLastFlingX=mLastFlingY=0;

(0,0,velocityX,velocityY,

_VALUE,_VALUE,_VALUE,_VALUE);

postOnAnimation();

}

voidpostOnAnimation(){

if(mEatRunOnAnimationRequest){

mReSchedulePostAnimationCallback=true;

}else{

removeCallbacks(this);

//回调run()⽅法

Animation(,this);

}

}

这⾥有⼀个问题,RecyclerView滑动到底部是怎么停⽌滑动事件的?

通过以下代码拆解,可以看出,如果⼀次事件中,有滑动距离未被处理,则认为滑动应该停⽌,stopScroll()。

以下代码中,也表现出了,fling事件通过post,实现了分批回调onNestedPrescroll、onNestedScroll,从⽽可以在嵌套滑动事件中,优雅的

处理fling操作。

publicvoidrun(){

//scroll未停⽌滑动

if(eScrollOffset()){

finalint[]scrollConsumed=mScrollConsumed;

finalint[]scrollConsumed=mScrollConsumed;

finalintx=rX();

finalinty=rY();//scroller当前的y值

intdx=x-mLastFlingX;

//dy应该滑动的距离

intdy=y-mLastFlingY;

inthresult=0;

intvresult=0;

mLastFlingX=x;

mLastFlingY=y;

//未被消费的距离

intoverscrollX=0,overscrollY=0;

if(dispatchNestedPreScroll(dx,dy,scrollConsumed,null,TYPE_NON_TOUCH)){

dx-=scrollConsumed[0];

dy-=scrollConsumed[1];

}

if(mAdapter!=null){

eatRequestLayout();

onEnterLayoutOrScroll();

ection(TRACE_SCROLL_TAG);

fillRemainingScrollValues(mState);

if(dx!=0){

//实际滑动了多少x

hresult=HorizontallyBy(dx,mRecycler,mState);

overscrollX=dx-hresult;

}

if(dy!=0){

vresult=VerticallyBy(dy,mRecycler,mState);

//实际滑动了多少y

overscrollY=dy-vresult;

}

.....

//嵌套滑动事件,如果有parent,则不处理代码块中的代码逻辑

//嵌套滑动事件onNestedScrollapi被调⽤,此时child已经滑动完成

//代码块中的逻辑,处理了滑动到底部事件,停⽌滑动的操作

if(!dispatchNestedScroll(hresult,vresult,overscrollX,overscrollY,null,

TYPE_NON_TOUCH)

&&(overscrollX!=0||overscrollY!=0)){

finalintvel=(int)rVelocity();

intvelX=0;

if(overscrollX!=x){

velX=overscrollX<0?-vel:overscrollX>0?vel:0;

}

intvelY=0;

if(overscrollY!=y){

velY=overscrollY<0?-vel:overscrollY>0?vel:0;

}

//如果有剩余未被处理的滑动距离,则abortAnimation

//scroller中的isFinish=true

if((velX!=0||overscrollX==x||alX()==0)

&&(velY!=0||overscrollY==y||alY()==0)){

nimation();

}

}

//scrollListenerapi被调⽤

if(hresult!=0||vresult!=0){

dispatchOnScrolled(hresult,vresult);

}

finalbooleanfullyConsumedVertical=dy!=0&&ollVertically()

&&vresult==dy;

finalbooleanfullyConsumedHorizontal=dx!=0&&ollHorizontally()

&&hresult==dx;

finalbooleanfullyConsumedAny=(dx==0&&dy==0)||fullyConsumedHorizontal

||fullyConsumedVertical;

//如果scroller中isFinish=true,stopScroll,停⽌滑动事件

if(shed()||(!fullyConsumedAny

&&!hasNestedScrollingParent(TYPE_NON_TOUCH))){

//settingstatetoidlewillstopthis.

setScrollState(SCROLL_STATE_IDLE);

setScrollState(SCROLL_STATE_IDLE);

if(ALLOW_THREAD_GAP_WORK){

refetchPositions();

}

stopNestedScroll(TYPE_NON_TOUCH);

}else{

//如果未停⽌,则继续回调run⽅法,fling事件变成了多次回调run的操作,从⽽解决了嵌套滑动中能逐步处理fling事件

postOnAnimation();

}

}

}

更多推荐

velocitytracker