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

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
发布评论