android computescroll_Android Scroller与computeScroll方法的调用关系
Android ViewGroup中的Scroller與computeScroll的有什么關(guān)系?
答:沒有直接的關(guān)系
知道了答案,是不是意味著下文就沒必要看了,如果說對ViewGroup自定義控件不感興趣,可以不用看了。
1.Scroller到底是什么?
答:Scroller只是個(gè)計(jì)算器,提供插值計(jì)算,讓滾動(dòng)過程具有動(dòng)畫屬性,但它并不是UI,也不是輔助UI滑動(dòng),反而是單純地為滑動(dòng)提供計(jì)算。
無論從構(gòu)造方法還是其他方法,以及Scroller的屬性可知,其并不會(huì)持有View,輔助ViewGroup滑動(dòng)
2.Scroller只是提供計(jì)算,那誰來調(diào)用computeScroll使得ViewGroup滑動(dòng)
答:computeScroll也不是來讓ViewGroup滑動(dòng)的,真正讓ViewGroup滑動(dòng)的是scrollTo,scrollBy。computeScroll的作用是計(jì)算ViewGroup如何滑動(dòng)。而computeScroll是通過draw來調(diào)用的。
3.computeScroll和Scroller都是計(jì)算,兩者有啥關(guān)系?
答:文章開始已作答,沒有直接的關(guān)系。computeScroll和Scroller要是飛得拉關(guān)系的話,那就是computeScroll可以參考Scroller計(jì)算結(jié)果來影響scrollTo,scrollBy,從而使得滑動(dòng)發(fā)生改變。也就是Scroller不會(huì)調(diào)用computeScroll,反而是computeScroll調(diào)用Scroller。
4.滑動(dòng)時(shí)連續(xù)的,如何讓Scroller的計(jì)算也是連續(xù)的?
這個(gè)就問到了什么時(shí)候調(diào)用computeScroll了,如上所說computeScroll調(diào)用Scroller,只要computeScroll調(diào)用連續(xù),Scroller也會(huì)連續(xù),實(shí)質(zhì)上computeScroll的連續(xù)性又invalidate方法控制,scrollTo,scrollBy都會(huì)調(diào)用invalidate,而invalidate回去觸發(fā)draw,從而computeScroll被連續(xù)調(diào)用,綜上,Scroller也會(huì)被連續(xù)調(diào)用,除非invalidate停止調(diào)用。
5.computeScroll如何和Scroller的調(diào)用過程保持一致。
computeScroll參考Scroller影響scrollTo,scrollBy,實(shí)質(zhì)上,為了不重復(fù)影響scrollTo,scrollBy,那么Scroller必須終止計(jì)算currX,currY。要知道計(jì)算有沒有終止,需要通過mScroller.computeScrollOffset()
6.如上問題應(yīng)該說的很清楚了吧,如果不明白,請留言。
7.通過一個(gè)SlidePanel的例子,我們來深刻的了解一下
注意:在移動(dòng)平臺(tái)中,要明確知道“滑動(dòng)”與“滾動(dòng)”的不同,具體來說,滑動(dòng)和滾動(dòng)的方向總是相反的。
public?class?SlidingPanel?extends?RelativeLayout?{
private?Context?context;
private?FrameLayout?leftMenu;
private?FrameLayout?middleMenu;
private?FrameLayout?rightMenu;
private?FrameLayout?middleMask;
private?Scroller?mScroller;
public??final?int?LEFT_ID?=?0xaabbcc;
public??final?int?MIDEELE_ID?=?0xaaccbb;
public??final?int?RIGHT_ID?=?0xccbbaa;
private?boolean?isSlideCompete;
private?boolean?isHorizontalScroll;
private?Point?point?=?new?Point();
private?static?final?int?SLIDE_SLOP?=?20;
public?SlidingPanel(Context?context)?{
super(context);
initView(context);
}
public?SlidingPanel(Context?context,?AttributeSet?attrs)?{
super(context,?attrs);
initView(context);
}
private?void?initView(Context?context)?{
this.context?=?context;
mScroller?=?new?Scroller(context,?new?DecelerateInterpolator());
leftMenu?=?new?FrameLayout(context);
middleMenu?=?new?FrameLayout(context);
rightMenu?=?new?FrameLayout(context);
middleMask?=?new?FrameLayout(context);
leftMenu.setBackgroundColor(Color.RED);
middleMenu.setBackgroundColor(Color.GREEN);
rightMenu.setBackgroundColor(Color.RED);
middleMask.setBackgroundColor(0x88000000);
addView(leftMenu);
addView(middleMenu);
addView(rightMenu);
addView(middleMask);
middleMask.setAlpha(0);
}
public?float?onMiddleMask(){
return?middleMask.getAlpha();
}
@Override
public?void?scrollTo(int?x,?int?y)?{
super.scrollTo(x,?y);
onMiddleMask();
//?Log.e("getScrollX","getScrollX="+getScrollX());//可以是負(fù)值
int?curX?=?Math.abs(getScrollX());
float?scale?=?curX/(float)leftMenu.getMeasuredWidth();
middleMask.setAlpha(scale);
}
@Override
protected?void?onMeasure(int?widthMeasureSpec,?int?heightMeasureSpec)?{
super.onMeasure(widthMeasureSpec,?heightMeasureSpec);
middleMenu.measure(widthMeasureSpec,?heightMeasureSpec);
middleMask.measure(widthMeasureSpec,?heightMeasureSpec);
int?realWidth?=?MeasureSpec.getSize(widthMeasureSpec);
int?tempWidthMeasure?=?MeasureSpec.makeMeasureSpec(
(int)?(realWidth?*?0.8f),?MeasureSpec.EXACTLY);
leftMenu.measure(tempWidthMeasure,?heightMeasureSpec);
rightMenu.measure(tempWidthMeasure,?heightMeasureSpec);
}
@Override
protected?void?onLayout(boolean?changed,?int?l,?int?t,?int?r,?int?b)?{
super.onLayout(changed,?l,?t,?r,?b);
middleMenu.layout(l,?t,?r,?b);
middleMask.layout(l,?t,?r,?b);
leftMenu.layout(l?-?leftMenu.getMeasuredWidth(),?t,?r,?b);
rightMenu.layout(
l?+?middleMenu.getMeasuredWidth(),
t,
l?+?middleMenu.getMeasuredWidth()
+?rightMenu.getMeasuredWidth(),?b);
}
@Override
public?boolean?dispatchTouchEvent(MotionEvent?ev)?{
if?(!isSlideCompete)?{
handleSlideEvent(ev);
return?true;
}
if?(isHorizontalScroll)?{
switch?(ev.getActionMasked())?{
case?MotionEvent.ACTION_MOVE:
int?curScrollX?=?getScrollX();
int?dis_x?=?(int)?(ev.getX()?-?point.x);
//滑動(dòng)方向和滾動(dòng)滾動(dòng)條方向相反,因此dis_x必須取負(fù)值
int?expectX?=?-dis_x?+?curScrollX;
if(dis_x>0)
{
Log.d("I","Right-Slide,Left-Scroll");//向右滑動(dòng),向左滾動(dòng)
}else{
Log.d("I","Left-Slide,Right-Scroll");
}
Log.e("I","ScrollX="+curScrollX+"?,?X="+ev.getX()+"?,?dis_x="+dis_x);
//規(guī)定expectX的變化范圍
int????finalX?=?Math.max(-leftMenu.getMeasuredWidth(),Math.min(expectX,?rightMenu.getMeasuredWidth()));
scrollTo(finalX,?0);
point.x?=?(int)?ev.getX();//更新,保證滑動(dòng)平滑
break;
case?MotionEvent.ACTION_UP:
case?MotionEvent.ACTION_CANCEL:
curScrollX?=?getScrollX();
if?(Math.abs(curScrollX)?>?leftMenu.getMeasuredWidth()?>>?1)?{
if?(curScrollX?
mScroller.startScroll(curScrollX,?0,
-leftMenu.getMeasuredWidth()?-?curScrollX,?0,
200);
}?else?{
mScroller.startScroll(curScrollX,?0,
leftMenu.getMeasuredWidth()?-?curScrollX,?0,
200);
}
}?else?{
mScroller.startScroll(curScrollX,?0,?-curScrollX,?0,?200);
}
invalidate();
isHorizontalScroll?=?false;
isSlideCompete?=?false;
break;
}
}?else?{
switch?(ev.getActionMasked())?{
case?MotionEvent.ACTION_UP:
isHorizontalScroll?=?false;
isSlideCompete?=?false;
break;
default:
break;
}
}
return?super.dispatchTouchEvent(ev);
}
/**
*?通過invalidate操縱,此方法通過draw方法調(diào)用
*/
@Override
public?void?computeScroll()?{
super.computeScroll();
if?(!mScroller.computeScrollOffset())?{
//計(jì)算currX,currY,并檢測是否已完成“滾動(dòng)”
return;
}
int?tempX?=?mScroller.getCurrX();
scrollTo(tempX,?0);?//會(huì)重復(fù)調(diào)用invalidate
}
private?void?handleSlideEvent(MotionEvent?ev)?{
switch?(ev.getAction()&MotionEvent.ACTION_MASK)?{
case?MotionEvent.ACTION_DOWN:
point.x?=?(int)?ev.getX();
point.y?=?(int)?ev.getY();
super.dispatchTouchEvent(ev);
break;
case?MotionEvent.ACTION_MOVE:
int?dX?=?Math.abs((int)?ev.getX()?-?point.x);
int?dY?=?Math.abs((int)?ev.getY()?-?point.y);
if?(dX?>=?SLIDE_SLOP?&&?dX?>?dY)?{?//?左右滑動(dòng)
isHorizontalScroll?=?true;
isSlideCompete?=?true;
point.x?=?(int)?ev.getX();
point.y?=?(int)?ev.getY();
}?else?if?(dY?>=?SLIDE_SLOP?&&?dY?>?dX)?{?//?上下滑動(dòng)
isHorizontalScroll?=?false;
isSlideCompete?=?true;
point.x?=?(int)?ev.getX();
point.y?=?(int)?ev.getY();
}
break;
case?MotionEvent.ACTION_UP:
case?MotionEvent.ACTION_OUTSIDE:
case?MotionEvent.ACTION_CANCEL:
super.dispatchTouchEvent(ev);
isHorizontalScroll?=?false;
isSlideCompete?=?false;
break;
}
}
}
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的android computescroll_Android Scroller与computeScroll方法的调用关系的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 计算机网络实验报告哈工大_哈工大计算机网
- 下一篇: html验证座机号码_html5表单pa