Android 使用 Scroller 實(shí)現(xiàn)平滑滾動功能的示例代碼
記錄使用Scroller實(shí)現(xiàn)平滑滾動,效果圖如下:
一、自定義View中實(shí)現(xiàn)View的平滑滾動
public class ScrollerView extends View { private Scroller mScroller; private Paint mPaint; /** * 屏幕拖動最小像素 */ private int mTouchSlop; /** * View寬度 */ private int width; /** * View高度 */ private int height; /** * MotionEvent.getX() */ private int mEventX; /** * MotionEvent.getY() */ private int mEventY; private Bitmap mBitmap; /** * View到屏幕左邊距離 */ private int mStartX; /** * View到屏幕頂部距離 */ private int mStartY; /** * View默認(rèn)大小 */ private static int DEFAULT_SIZE = 200; public ScrollerView(Context context) { this(context, null); } public ScrollerView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); mPaint = new Paint(); mScroller = new Scroller(context); ViewConfiguration configuration = ViewConfiguration.get(context); mTouchSlop = ViewConfigurationCompat.getScaledHoverSlop(configuration); mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); if (widthMode == MeasureSpec.EXACTLY) { width = MeasureSpec.getSize(widthMeasureSpec); } else { if (heightMode == MeasureSpec.EXACTLY) { width = MeasureSpec.getSize(heightMeasureSpec); } else { width = DEFAULT_SIZE; } } if (heightMode == MeasureSpec.EXACTLY) { height = MeasureSpec.getSize(heightMeasureSpec); } else { height = width; } setMeasuredDimension(width, height); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (null != mBitmap) { Rect src = new Rect(0, 0, mBitmap.getWidth(), mBitmap.getHeight()); Rect dst = new Rect(0, 0, width, height); canvas.drawBitmap(mBitmap, src, dst, mPaint); } else { Log.e("zzy", "Bitmap is null"); } } @Override public boolean onTouchEvent(MotionEvent event) { int action = event.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: mEventX = (int) event.getX(); mEventY = (int) event.getY(); break; case MotionEvent.ACTION_MOVE: mStartX = (int) event.getRawX() - mEventX; mStartY = (int) event.getRawY() - mEventY; layout(mStartX,mStartY,mStartX+width,mStartY+height); break; case MotionEvent.ACTION_UP: startScroller(); break; } return true; } @Override public void computeScroll() { if (mScroller.computeScrollOffset()){ int l = mScroller.getCurrX(); layout(l,mStartY,l+width,mStartY+height); invalidate(); } } /** * 開始Scroller動畫 */ private void startScroller(){ mScroller.forceFinished(true); mScroller.startScroll(mStartX, mStartY,-mStartX,0); int screenWidth = getScreenWidth(); // Scroller動畫默認(rèn)250ms,超過屏幕一半時(shí)設(shè)置為500ms if (mStartX > screenWidth / 2){ mScroller.extendDuration(500); } invalidate(); } private int getScreenWidth(){ return getResources().getDisplayMetrics().widthPixels; } }
Scroller其實(shí)是個輔助類,本身并不能完成動畫的執(zhí)行。而是幫我們計(jì)算隨著時(shí)間的流逝,動畫應(yīng)該執(zhí)行的位置值,我們需要獲得當(dāng)前時(shí)間的位置,然后調(diào)用View位置移動方法,將View移動到該位置,完成動畫。
所以,在自定義View中。我們需要調(diào)用invalidate()
觸發(fā)View的重繪,并覆寫重繪會執(zhí)行的方法computeScroll()
。
在computeScroll()
方法中調(diào)用Scroller
的computeScrollOffset()
計(jì)算當(dāng)前時(shí)間動畫應(yīng)該移動的位置,返回值是動畫是否在執(zhí)行。
通過mScroller.getCurrX()
和mScroller.getCurrY()
獲得當(dāng)前時(shí)間的位置。手動調(diào)用View位置移動的方法將View的位置移動到當(dāng)前時(shí)間的位置,實(shí)現(xiàn)View的滾動。
然后再次調(diào)用invalidate()
觸發(fā)刷新。直到computeScrollOffset()
返回false,動畫執(zhí)行完成,滾動完成。
二、直接使用Scroller實(shí)現(xiàn)View的平滑滾動
我們知道,Scroller會幫我們計(jì)算當(dāng)前時(shí)間,插值器返回的值。
而如果直接使用Scroller實(shí)現(xiàn)平滑滾動的話,也需要借助帶時(shí)間的監(jiān)聽器。
這里借助ValueAnimator
來實(shí)現(xiàn)Scroller平滑滾動
private Scroller mScroller; private ImageView mImage; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mImage = findViewById(R.id.image); mScroller =new Scroller(this); } public void btnStart(View view){ start(); } private void start(){ mScroller.forceFinished(false); mScroller.extendDuration(500); mScroller.startScroll(0,0,400,400); ValueAnimator valueAnimator = ValueAnimator.ofFloat(0,1); valueAnimator.setDuration(500); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { if (mScroller.computeScrollOffset()){ ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) mImage.getLayoutParams(); params.leftMargin = mScroller.getCurrX(); params.topMargin = mScroller.getCurrY(); mImage.setLayoutParams(params); } } }); valueAnimator.start(); }
在ValueAnimator的addUpdateListener
中刷新Scroller當(dāng)前值。并移動位置。效果如下:
到此這篇關(guān)于Android 使用 Scroller 實(shí)現(xiàn)平滑滾動的文章就介紹到這了,更多相關(guān)android Scroller 平滑滾動內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Android使用Scroller實(shí)現(xiàn)彈性滑動效果
- Android用Scroller實(shí)現(xiàn)一個可向上滑動的底部導(dǎo)航欄
- android使用 ScrollerView 實(shí)現(xiàn) 可上下滾動的分類欄實(shí)例
- 詳解Android應(yīng)用開發(fā)中Scroller類的屏幕滑動功能運(yùn)用
- 詳解Android Scroller與computeScroll的調(diào)用機(jī)制關(guān)系
- Android游戲開發(fā)實(shí)踐之人物移動地圖的平滑滾動處理
- android開發(fā)教程之使用線程實(shí)現(xiàn)視圖平滑滾動示例
相關(guān)文章
Android模擬用戶點(diǎn)擊的實(shí)現(xiàn)方法
這篇文章主要給大家介紹了關(guān)于Android模擬用戶點(diǎn)擊的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)學(xué)習(xí)學(xué)習(xí)吧。2018-02-02Kotlin開發(fā)實(shí)戰(zhàn)之hello world
這篇文章主要為大家詳細(xì)介紹了Kotlin開發(fā)實(shí)戰(zhàn)之hello world的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05Android長按imageview把圖片保存到本地的實(shí)例代碼
本文通過代碼給大家介紹了Android長按imageview把圖片保存到本地的實(shí)現(xiàn)方法,代碼簡單易懂,非常不錯,具有參考借鑒價(jià)值,需要的朋友參考下吧2017-12-12Android ImageView 不顯示JPEG圖片的問題解決
本篇文章主要介紹了Android ImageView 不顯示JPEG圖片及Android Studio中如何引用圖片資源的相關(guān)知識,具有很好的參考價(jià)值。下面跟著小編一起來看下吧2017-05-05java,Android:在eclipse中的快捷鍵(經(jīng)典收藏)
下面的快捷鍵是常用的,本人就本身喜好且常用的收拾一下,現(xiàn)在曬出來與大家分享,感興趣的朋友可以了解小哦2013-01-01Android使用SurfaceView實(shí)現(xiàn)飄贊動畫
這篇文章主要為大家詳細(xì)介紹了Android如何使用SurfaceView實(shí)現(xiàn)飄贊動畫,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-03-03自定義視圖view使用Canvas實(shí)現(xiàn)手寫板和涂鴉功能
這篇文章主要介紹了自定義視圖view使用Canvas實(shí)現(xiàn)手寫板和涂鴉功能,這里直接上代碼,里面有詳細(xì)講解和注釋,需要的朋友可以參考下2023-04-04