前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android 使用 Scroller 实现平滑滚动功能的示例代码

Android 使用 Scroller 实现平滑滚动功能的示例代码

作者头像
砸漏
发布2020-10-16 10:17:52
9550
发布2020-10-16 10:17:52
举报
文章被收录于专栏:恩蓝脚本

记录使用Scroller实现平滑滚动,效果图如下:

在这里插入图片描述
在这里插入图片描述

一、自定义View中实现View的平滑滚动

代码语言:javascript
复制
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默认大小
*/
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动画默认250ms,超过屏幕一半时设置为500ms
if (mStartX   screenWidth / 2){
mScroller.extendDuration(500);
}
invalidate();
}
private int getScreenWidth(){
return getResources().getDisplayMetrics().widthPixels;
}
}

Scroller其实是个辅助类,本身并不能完成动画的执行。而是帮我们计算随着时间的流逝,动画应该执行的位置值,我们需要获得当前时间的位置,然后调用View位置移动方法,将View移动到该位置,完成动画。

所以,在自定义View中。我们需要调用invalidate()触发View的重绘,并覆写重绘会执行的方法computeScroll()

computeScroll()方法中调用ScrollercomputeScrollOffset()计算当前时间动画应该移动的位置,返回值是动画是否在执行。

通过mScroller.getCurrX()mScroller.getCurrY()获得当前时间的位置。手动调用View位置移动的方法将View的位置移动到当前时间的位置,实现View的滚动。

然后再次调用invalidate()触发刷新。直到computeScrollOffset()返回false,动画执行完成,滚动完成。

二、直接使用Scroller实现View的平滑滚动

我们知道,Scroller会帮我们计算当前时间,插值器返回的值。

而如果直接使用Scroller实现平滑滚动的话,也需要借助带时间的监听器。

这里借助ValueAnimator来实现Scroller平滑滚动

代码语言:javascript
复制
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当前值。并移动位置。效果如下:

在这里插入图片描述
在这里插入图片描述

到此这篇关于Android 使用 Scroller 实现平滑滚动的文章就介绍到这了,更多相关android Scroller 平滑滚动内容请搜索ZaLou.Cn以前的文章或继续浏览下面的相关文章希望大家以后多多支持ZaLou.Cn!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-09-11 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档