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

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

一、自定义View中实现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默认大小
  */
 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平滑滚动

 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 平滑滚动内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • android开发教程之使用线程实现视图平滑滚动示例

    最近一直想做下拉刷新的效果,琢磨了好久,才走到通过onTouch方法把整个视图往下拉的步骤,接下来就是能拉下来,松开手要能滑回去啊.网上看了好久,没有找到详细的下拉刷新的例子,只有自己慢慢琢磨了.昨天和今天,研究了两天,下拉之后回滚回去的效果终于今天做出来了!开心.现在来分享下我的实现方法和一些心得体会吧.我看了网上一个大神的例子,发现是在onTouch里面使用View的scrollTo(int, int)方法,来使整个视图往下滚动的,我尝试了使用setTranslationY()来对视图进行回

  • 详解Android应用开发中Scroller类的屏幕滑动功能运用

    今天给大家介绍下Android中滑屏功能的一个基本实现过程以及原理初探,最后给大家重点讲解View视图中scrollTo 与scrollBy这两个函数的区别 .   首先 ,我们必须明白在Android View视图是没有边界的,Canvas是没有边界的,只不过我们通过绘制特定的View时对Canvas对象进行了一定的操作,例如 : translate(平移).clipRect(剪切)等,以便达到我们的对该Canvas对象绘制的要求 ,我们可以将这种无边界的视图称为"视图坐标"----

  • Android用Scroller实现一个可向上滑动的底部导航栏

    静静等了5分钟竟不知道如何写我这第一篇文章.每次都想好好的学习学习,有时间多敲敲代码,写几篇自己的文章.今天终于开始实行了,还是有点小激动的.哈哈! 好了废话就不多收了.我今天想实现的一个功能就是一个可以上滑底部菜单栏.为什么我会想搞这么个东西呢, 还是源于一年前,我们app 有这么个需求,当时百度也好谷歌也好,都没有找到想要的效果,其实很简单的一个效果.但是当时我也是真的太菜了,所有有关自定义的控件真的是不会,看别人的代码还好,真要是自己写,一点头绪都没有.因为我试着写了,真的不行啊.当时觉得

  • Android游戏开发实践之人物移动地图的平滑滚动处理

    如图所示为程序效果动画图 地图滚动的原理 在本人之前博客的文章中介绍过人物在屏幕中的移动方式,因为之前拼的游戏地图是完全填充整个手机屏幕的,所以无需处理地图的平滑滚动.这篇文章我着重的向 大家介绍一下控制人物移动后地图滚动的处理方式.举个例子 如上图所示 比如人物向右移动,如果地图贴在屏幕左边边界 将先移动人物在地图的坐标,当人物在屏幕中超过三分之二后 则将地图向人物行走的反方向移动给玩家一种人物还在向右移动的假象,其实这时候人物只是播放向右行走的动画 在屏幕中的坐标不变 ,当地图向人物行走反方

  • android使用 ScrollerView 实现 可上下滚动的分类栏实例

    如果不考虑更深层的性能问题,我个人认为ScrollerView还是很好用的.而且单用ScrollerView就可以实现分类型的RecyclerView或ListView所能实现的效果. 下面我单单从效果展示方面考虑,使用ScrollerView实现如下图所示的可滚动的多条目分类,只是为了跟大家一起分享一下新思路.(平时:若从复用性等方面考虑,这显然是存在瑕疵的~) 特点描述: 1.可上下滚动 2.有类似于网格布局的样式 3.子条目具有点击事件 刚看到这个效果时,首先想到的是使用分类型的Recyc

  • Android使用Scroller实现弹性滑动效果

    本文实例为大家分享了Android使用Scroller实现弹性滑动展示的具体代码,供大家参考,具体内容如下 scrollTo.scrollBy View内部为了实现滑动提供了这两个方法,但是使用这两个方法滑动的效果是瞬间的不够平滑,如何实现View的弹性滑动呢?这正是本博文讨论的主题.另外这两个函数滑动的是View的内容不是View本身.比如对于普通View好比TextView其内容就是文本,ImageView的内容则是drawable对象,采用这两种方法滑动的时候其实分别滑动的是文本及draw

  • 详解Android Scroller与computeScroll的调用机制关系

    Android ViewGroup中的Scroller与computeScroll的有什么关系? 答:没有直接的关系 知道了答案,是不是意味着下文就没必要看了,如果说对ViewGroup自定义控件不感兴趣,可以不用看了. 1.Scroller到底是什么? 答:Scroller只是个计算器,提供插值计算,让滚动过程具有动画属性,但它并不是UI,也不是滑动辅助UI运动,反而是单纯地为滑动提供计算. 无论从构造方法还是其他方法,以及Scroller的属性可知,其并不会持有View,辅助ViewGrou

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

    记录使用Scroller实现平滑滚动,效果图如下: 一.自定义View中实现View的平滑滚动 public class ScrollerView extends View { private Scroller mScroller; private Paint mPaint; /** * 屏幕拖动最小像素 */ private int mTouchSlop; /** * View宽度 */ private int width; /** * View高度 */ private int height

  • Android实现显示和隐藏密码功能的示例代码

    在前端中我们知道用javascript就可以可以很容易实现,那么在Android中怎么实现这个功能呢? Java代码 package com.example.test2; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.text.method.HideReturnsTransformationMethod; import android.text.method.Pa

  • Android仿淘宝搜索联想功能的示例代码

    现在不少应用都提供了搜索功能,有些还提供了搜索联想.对于一个搜索联想功能,最基本的实现流程为:客户端通过监听输入框内容的变化,当输入框发生变化之后就会回调afterTextChanged方法,客户端利用当前输入框内的文字向服务器发起请求,服务器返回与该搜索文字关联的结果给客户端进行展示.服务器那边,一般要做内存缓存池,就是把有可能的结果都放在内存中. 效果图 APP这边也有几个重要的问题需要我们思考 当搜索词为空时,不应该发起网络请求. 在用户连续输入的情况下,可能会发起某些不必要的请求.例如用

  • Android仿微信发送语音消息的功能及示例代码

    微信的发送语音是有一个向上取消的,我们使用onTouchListener来监听手势,然后做出相应的操作就行了. 直接上代码: //语音操作对象 private MediaPlayer mPlayer = null; private MediaRecorder mRecorder = null; //语音文件保存路径 private String FileName = null; FileName = Environment.getExternalStorageDirectory().getAbs

  • Android仿微信右滑返回功能的实例代码

    先上效果图,如下: 先分析一下功能的主要技术点,右滑即手势判断,当滑到一直距离时才执行返回,并且手指按下的位置是在屏幕的最左边(这个也是有一定范围的),  这些可以实现onTouchEvent来实现. 接着就是返回时,有滑动效果,很显然这个是Acitivty切换动画实现的.好啦,分析完了就开干.下面上代码: @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()){ case Mot

  • Android中使用ShareSDK集成分享功能的实例代码

    引言 现在APP开发集成分享功能已经是非常普遍的需求了.其他集成分享技术我没有使用过,今天我就来介绍下使用ShareSDK来进行分享功能开发的一些基本步骤和注意点,帮助朋友们避免一些坑.好了,下面切入正题正式开始介绍. 1.ShareSDK开发包及配置 这个不用多说,去他们官网看找SDK开发包和集成文档即可. Android版本地址:http://www.mob.com/downloadDetail/ShareSDK/android. 注意:记得要注册ShareSDK账号获取AppKey哦.这些

  • Android加载loading对话框的功能及实例代码(不退出沉浸式效果)

    一.自定义Dialog 在沉浸式效果下,当界面弹出对话框时,对话框将获取到焦点,这将导致界面退出沉浸式效果,那么是不是能通过屏蔽对话框获取焦点来达到不退出沉浸式的目的呢.说干就干,我们先来看一下改善后的效果图. 普通对话框弹出效果 LoadingDialog弹出效果 自定义LoadingDialog public class LoadingDialog extends Dialog { public LoadingDialog(Context context) { super(context);

  • Android 选择相册照片并返回功能的实现代码

    首先由于进行读写操作,要在 AndroidManifest.xml中声明权限: <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> 调用系统相册: private static final in

  • Android 中TeaPickerView数据级联选择器功能的实例代码

    Github地址 YangsBryant/TeaPickerView (Github排版比较好,建议进入这里查看详情,如果觉得好,点个star吧!) 引入module allprojects { repositories { google() jcenter() maven { url 'https://www.jitpack.io' } } } implementation 'com.github.YangsBryant:TeaPickerView:1.0.2' 主要代码 public cla

  • Android简单的短信验证功能的实现代码

    相信有很多朋友在做三方登陆的时候会加入短信验证的功能,最近刚好被分配安排实现这一需求,本人新手一枚,特地去网上搜了资料,目前用的比较多的大汉.云通讯还有MOB的smssdk,对比之下,最终选择了完全免费的MOB产品试试手,下面就是我在使用sdk过程中一些心得,希望看到的大神给点建议,喜欢的给个小心心就好. 首先我上网百度了下Mob的官网(http://www.mob.com/)作为第一次使用习惯性的先打开文档介绍,关于使用方法这里介绍的算是比较详细的,我这里也不做赘述了,整个文档浏览了一遍,介绍

随机推荐