我這一次講使用scroll實(shí)現(xiàn)彈性滑動(dòng),我不會(huì)只有一個(gè)例子就說(shuō)完,因?yàn)閷懳恼碌臅r(shí)候我也在學(xué)習(xí),我分幾次講完吧。
創(chuàng)新互聯(lián)是專業(yè)的興文網(wǎng)站建設(shè)公司,興文接單;提供做網(wǎng)站、網(wǎng)站設(shè)計(jì),網(wǎng)頁(yè)設(shè)計(jì),網(wǎng)站設(shè)計(jì),建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行興文網(wǎng)站開發(fā)網(wǎng)頁(yè)制作和功能擴(kuò)展;專業(yè)做搜索引擎喜愛(ài)的網(wǎng)站,專業(yè)的做網(wǎng)站團(tuán)隊(duì),希望更多企業(yè)前來(lái)合作!
首先上一段代碼,
private void smoothScrollByScroller(int dy){ mScroller.startScroll(0,dy,0,dy*-1,1000); invalidate(); } @Override public void computeScroll() { if (mScroller.computeScrollOffset()) { scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); postInvalidate(); } }
這段代碼是實(shí)現(xiàn)彈性滑動(dòng)的核心,第一個(gè)函數(shù)指的是緩慢滑動(dòng)的意思,但是卻沒(méi)有這個(gè)滑動(dòng)的實(shí)際功能。
startScroll這函數(shù)的五個(gè)參數(shù)指的是起點(diǎn)x坐標(biāo),起點(diǎn)y坐標(biāo),x位移量,y位移量,這段滑動(dòng)的時(shí)間。這個(gè)函數(shù)的內(nèi)部是不斷計(jì)算在滑動(dòng)時(shí)間里x和y坐標(biāo)應(yīng)該是什么值,然后因?yàn)閕nvalidate會(huì)調(diào)用computeScroll,這個(gè)computeScrollOffset函數(shù)是判斷當(dāng)前滑動(dòng)是否結(jié)束,如果沒(méi)有結(jié)束通過(guò)getCurrX和getCurry獲得startScroll函數(shù)計(jì)算的值,在使用scrollTo滑動(dòng)相應(yīng)的位置,因?yàn)閟tartScroll會(huì)運(yùn)算很多次,也就是將滑動(dòng)時(shí)間分成很多段,相應(yīng)的坐標(biāo)也都算出來(lái),跟著給scrollTo去實(shí)現(xiàn)滑動(dòng)。
這很像是ValueAmition,將時(shí)間分成很多段,然后計(jì)算相應(yīng)的值,同時(shí)分很多次去實(shí)現(xiàn)。
我貼一個(gè)類似QQ消息列表的常見的彈性滑動(dòng),這里下拉是沒(méi)有刷新的,
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } } public final class PullView extends ViewGroup { private int mLastY; private Context mContext; private Scroller mScroller; //子View的個(gè)數(shù) private int mChildCount; public PullView(Context context){ this(context,null); } public PullView(Context context, AttributeSet attributeSet){ super(context,attributeSet); mContext=context; initView(); } private void initView(){ mScroller=new Scroller(mContext); } @Override public boolean onTouchEvent(MotionEvent event) { int y=(int)event.getY(); switch (event.getAction()){ //手指按下時(shí),初始化按下位置的X,Y位置值 case MotionEvent.ACTION_DOWN: mLastY=y; break; //計(jì)算滑動(dòng)的偏移量,產(chǎn)生滑動(dòng)效果 case MotionEvent.ACTION_MOVE: //手指向下滑動(dòng)delayY>0,向上滑動(dòng)delayY<0 int delayY=y-mLastY; delayY=delayY*-1; scrollBy(0,delayY); break; case MotionEvent.ACTION_UP: /** * scrollY是指:View的上邊緣和View內(nèi)容的上邊緣(其實(shí)就是第一個(gè)ChildView的上邊緣)的距離 * scrollY=上邊緣-View內(nèi)容上邊緣,scrollTo/By方法滑動(dòng)的知識(shí)View的內(nèi)容 * 往下滑動(dòng)scrollY是負(fù)值 */ int scrollY=getScrollY(); smoothScrollByScroller(scrollY); break; } mLastY=y; return true; } /** * 執(zhí)行滑動(dòng)效果 * 使用scroller實(shí)現(xiàn) * @param dy */ private void smoothScrollByScroller(int dy){ mScroller.startScroll(0,dy,0,dy*-1,1000); invalidate(); } @Override public void computeScroll() { if (mScroller.computeScrollOffset()) { scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); postInvalidate(); } } /** * 重新計(jì)算子View的高度和寬度 * @param widthMeasureSpec * @param heightMeasureSpec */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int measuredWidth; int measureHeight; mChildCount = getChildCount(); //測(cè)量子View measureChildren(widthMeasureSpec, heightMeasureSpec); int widthSpaceSize = MeasureSpec.getSize(widthMeasureSpec); int widthSpaceMode = MeasureSpec.getMode(widthMeasureSpec); int heightSpaceSize = MeasureSpec.getSize(heightMeasureSpec); int heightSpaceMode = MeasureSpec.getMode(heightMeasureSpec); //獲取橫向的padding值 int paddingLeft=getPaddingLeft(); int paddingRight=getPaddingRight(); final View childView = getChildAt(0); /** * 如果子View的數(shù)量是0,就讀取LayoutParams中數(shù)據(jù) * 否則就對(duì)子View進(jìn)行測(cè)量 * 此處主要是針對(duì)wrap_content這種模式進(jìn)行處理,因?yàn)槟J(rèn)情況下 * wrap_content等于match_parent */ if (mChildCount == 0) { ViewGroup.LayoutParams layoutParams=getLayoutParams(); if(layoutParams!=null){ setMeasuredDimension(layoutParams.width,layoutParams.height); }else { setMeasuredDimension(0, 0); } } else if (heightSpaceMode == MeasureSpec.AT_MOST && widthSpaceMode == MeasureSpec.AT_MOST) { measuredWidth = childView.getMeasuredWidth() * mChildCount; measureHeight = getChildMaxHeight(); //將兩側(cè)的padding值加上去 measuredWidth=paddingLeft+measuredWidth+paddingRight; setMeasuredDimension(measuredWidth, measureHeight); } else if (heightSpaceMode == MeasureSpec.AT_MOST) { measureHeight = getChildMaxHeight(); setMeasuredDimension(widthSpaceSize, measureHeight); } else if (widthSpaceMode == MeasureSpec.AT_MOST) { measuredWidth = childView.getMeasuredWidth() * mChildCount; measuredWidth=paddingLeft+measuredWidth+paddingRight; setMeasuredDimension(measuredWidth, heightSpaceSize); } } /** * 獲取子View中最大高度 * @return */ private int getChildMaxHeight(){ int maxHeight=0; for (int i = 0; i < mChildCount; i++) { View childView = getChildAt(i); if (childView.getVisibility() != View.GONE) { int height = childView.getMeasuredHeight(); if(height>maxHeight){ maxHeight=height; } } } return maxHeight; } /** * 設(shè)置子View的布局 * @param changed * @param l * @param t * @param r * @param b */ @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { int childLeft = 0; for (int i = 0; i < mChildCount; i++) { View childView = getChildAt(i); if (childView.getVisibility() != View.GONE) { int childWidth = childView.getMeasuredWidth(); childView.layout(childLeft, 0, childLeft + childWidth, childView.getMeasuredHeight()); childLeft += childWidth; } } } }
這里的ViewGroup的繪畫和測(cè)量我就不多說(shuō),我就說(shuō)一下它獲取函數(shù),計(jì)算坐標(biāo)的一些事。
它在手指按下時(shí)記錄y坐標(biāo),在手指移動(dòng)時(shí),跟著移動(dòng)子View,在手指抬起時(shí),使用彈性滑動(dòng)的函數(shù)smoothScrollByScroller。
大家會(huì)發(fā)現(xiàn)為什么一些計(jì)算出的坐標(biāo)要加負(fù)號(hào),因?yàn)樵谖覀內(nèi)搜劾?,我們下拉y坐標(biāo)的位移量是正的,但是在系統(tǒng)認(rèn)為這個(gè)值是負(fù)的,原因我太菜不知道,知道的求大神評(píng)論留言告訴。
下一次寫一個(gè)隨手指彈性滑動(dòng)的例子。
以上這篇Android Scroll實(shí)現(xiàn)彈性滑動(dòng)_列表下拉彈性滑動(dòng)的示例代碼就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持創(chuàng)新互聯(lián)。