最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android 使用 Scroller 實現(xiàn)平滑滾動功能的示例代碼

 更新時間:2020年07月13日 14:12:45   作者:正義啊  
這篇文章主要介紹了Android 使用 Scroller 實現(xiàn)平滑滾動功能,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下

記錄使用Scroller實現(xiàn)平滑滾動,效果圖如下:

在這里插入圖片描述

一、自定義View中實現(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è)置為500ms
  if (mStartX > screenWidth / 2){
   mScroller.extendDuration(500);
  }
  invalidate();
 }

 private int getScreenWidth(){
  return getResources().getDisplayMetrics().widthPixels;
 }
}

Scroller其實是個輔助類,本身并不能完成動畫的執(zhí)行。而是幫我們計算隨著時間的流逝,動畫應(yīng)該執(zhí)行的位置值,我們需要獲得當(dāng)前時間的位置,然后調(diào)用View位置移動方法,將View移動到該位置,完成動畫。

所以,在自定義View中。我們需要調(diào)用invalidate()觸發(fā)View的重繪,并覆寫重繪會執(zhí)行的方法computeScroll()。

computeScroll()方法中調(diào)用ScrollercomputeScrollOffset()計算當(dāng)前時間動畫應(yīng)該移動的位置,返回值是動畫是否在執(zhí)行。

通過mScroller.getCurrX()mScroller.getCurrY()獲得當(dāng)前時間的位置。手動調(diào)用View位置移動的方法將View的位置移動到當(dāng)前時間的位置,實現(xiàn)View的滾動。

然后再次調(diào)用invalidate()觸發(fā)刷新。直到computeScrollOffset()返回false,動畫執(zhí)行完成,滾動完成。

二、直接使用Scroller實現(xiàn)View的平滑滾動

我們知道,Scroller會幫我們計算當(dāng)前時間,插值器返回的值。

而如果直接使用Scroller實現(xiàn)平滑滾動的話,也需要借助帶時間的監(jiān)聽器。

這里借助ValueAnimator來實現(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 實現(xiàn)平滑滾動的文章就介紹到這了,更多相關(guān)android Scroller 平滑滾動內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • flutter Toast實現(xiàn)消息提示框

    flutter Toast實現(xiàn)消息提示框

    這篇文章主要為大家詳細(xì)介紹了flutter Toast實現(xiàn)消息提示框,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-07-07
  • Flutter 完美的驗證碼輸入框?qū)崿F(xiàn)

    Flutter 完美的驗證碼輸入框?qū)崿F(xiàn)

    這篇文章主要介紹了Flutter 完美的驗證碼輸入框?qū)崿F(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-04-04
  • Android如何實現(xiàn)底部菜單固定到底部

    Android如何實現(xiàn)底部菜單固定到底部

    這篇文章主要介紹了Android如何實現(xiàn)底部菜單固定到底部,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-09-09
  • JS實現(xiàn)點(diǎn)擊參數(shù)面板按鈕顯示或隱藏數(shù)據(jù)

    JS實現(xiàn)點(diǎn)擊參數(shù)面板按鈕顯示或隱藏數(shù)據(jù)

    本文主要介紹JS實現(xiàn)點(diǎn)擊參數(shù)面板按鈕顯示或隱藏數(shù)據(jù)的方法,具有很好的參考價值。下面跟著小編一起來看下吧
    2017-03-03
  • Android為textView設(shè)置setText的時候報錯的講解方案

    Android為textView設(shè)置setText的時候報錯的講解方案

    今天小編就為大家分享一篇關(guān)于Android為textView設(shè)置setText的時候報錯的講解方案,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-03-03
  • Android開發(fā)Jetpack組件LiveData使用講解

    Android開發(fā)Jetpack組件LiveData使用講解

    LiveData是Jetpack組件的一部分,更多的時候是搭配ViewModel來使用,相對于Observable,LiveData的最大優(yōu)勢是其具有生命感知的,換句話說,LiveData可以保證只有在組件( Activity、Fragment、Service)處于活動生命周期狀態(tài)的時候才會更新數(shù)據(jù)
    2022-08-08
  • Android自定義PopupWindow簡單小例子

    Android自定義PopupWindow簡單小例子

    這篇文章主要為大家詳細(xì)介紹了Android自定義PopupWindow簡單小例子,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • Android開發(fā)實現(xiàn)多進(jìn)程彈窗效果

    Android開發(fā)實現(xiàn)多進(jìn)程彈窗效果

    這篇文章主要為大家詳細(xì)介紹了Android開發(fā)實現(xiàn)多進(jìn)程彈窗效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • 解析android中隱藏與顯示軟鍵盤及不自動彈出鍵盤的實現(xiàn)方法

    解析android中隱藏與顯示軟鍵盤及不自動彈出鍵盤的實現(xiàn)方法

    本篇文章對android中隱藏與顯示軟鍵盤以及不自動彈出鍵盤的方法進(jìn)行了分析介紹。需要的朋友參考下
    2013-05-05
  • Android通話默認(rèn)打開揚(yáng)聲器的方法

    Android通話默認(rèn)打開揚(yáng)聲器的方法

    這篇文章主要介紹了Android通話默認(rèn)打開揚(yáng)聲器的方法.小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-08-08

最新評論

津市市| 赤水市| 瓮安县| 台中市| 龙门县| 潜山县| 孝义市| 荔浦县| 松原市| 大英县| 连山| 宝丰县| 辽源市| 疏附县| 包头市| 兴文县| 盱眙县| 塘沽区| 沙河市| 石景山区| 岐山县| 东台市| 尚义县| 合阳县| 台北市| 陆川县| 扬州市| 昭通市| 白玉县| 泊头市| 张家川| 甘德县| 凌源市| 瑞安市| 广州市| 惠水县| 景泰县| 沾化县| 新丰县| 申扎县| 绵竹市|