Android Scroll实现弹性滑动_列表下拉弹性滑动的示例代码

我这一次讲使用scroll实现弹性滑动,我不会只有一个例子就说完,因为写文章的时候我也在学习,我分几次讲完吧。

首先上一段代码,

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();
 }
}

这段代码是实现弹性滑动的核心,第一个函数指的是缓慢滑动的意思,但是却没有这个滑动的实际功能。

startScroll这函数的五个参数指的是起点x坐标,起点y坐标,x位移量,y位移量,这段滑动的时间。这个函数的内部是不断计算在滑动时间里x和y坐标应该是什么值,然后因为invalidate会调用computeScroll,这个computeScrollOffset函数是判断当前滑动是否结束,如果没有结束通过getCurrX和getCurry获得startScroll函数计算的值,在使用scrollTo滑动相应的位置,因为startScroll会运算很多次,也就是将滑动时间分成很多段,相应的坐标也都算出来,跟着给scrollTo去实现滑动。

这很像是ValueAmition,将时间分成很多段,然后计算相应的值,同时分很多次去实现。

我贴一个类似QQ消息列表的常见的弹性滑动,这里下拉是没有刷新的,

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的个数
 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()){
   //手指按下时,初始化按下位置的X,Y位置值
   case MotionEvent.ACTION_DOWN:
    mLastY=y;
    break;
   //计算滑动的偏移量,产生滑动效果
   case MotionEvent.ACTION_MOVE:
    //手指向下滑动delayY>0,向上滑动delayY<0
    int delayY=y-mLastY;
    delayY=delayY*-1;
    scrollBy(0,delayY);
    break;
   case MotionEvent.ACTION_UP:
    /**
     * scrollY是指:View的上边缘和View内容的上边缘(其实就是第一个ChildView的上边缘)的距离
     * scrollY=上边缘-View内容上边缘,scrollTo/By方法滑动的知识View的内容
     * 往下滑动scrollY是负值
     */
    int scrollY=getScrollY();
    smoothScrollByScroller(scrollY);
    break;
  }
  mLastY=y;
  return true;
 }
 /**
  * 执行滑动效果
  * 使用scroller实现
  * @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();
  }
 }

 /**
  * 重新计算子View的高度和宽度
  * @param widthMeasureSpec
  * @param heightMeasureSpec
  */
 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  int measuredWidth;
  int measureHeight;
  mChildCount = getChildCount();
  //测量子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的数量是0,就读取LayoutParams中数据
   * 否则就对子View进行测量
   * 此处主要是针对wrap_content这种模式进行处理,因为默认情况下
   * 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();
   //将两侧的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;
 }

 /**
  * 设置子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;
   }
  }
 }
}

<android.com.listfragment.PullView xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:orientation="horizontal" >

 <LinearLayout
  android:layout_width="match_parent"
  android:layout_height="1500dp"
  android:background="#806363"></LinearLayout>
</android.com.listfragment.PullView>

这里的ViewGroup的绘画和测量我就不多说,我就说一下它获取函数,计算坐标的一些事。

它在手指按下时记录y坐标,在手指移动时,跟着移动子View,在手指抬起时,使用弹性滑动的函数smoothScrollByScroller。

大家会发现为什么一些计算出的坐标要加负号,因为在我们人眼里,我们下拉y坐标的位移量是正的,但是在系统认为这个值是负的,原因我太菜不知道,知道的求大神评论留言告诉。

下一次写一个随手指弹性滑动的例子。

以上这篇Android Scroll实现弹性滑动_列表下拉弹性滑动的示例代码就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

您可能感兴趣的文章:

  • Android继承ViewGroup实现Scroll滑动效果的方法示例
  • Android自定义View弹性滑动Scroller详解
  • Android自定义ViewGroup实现弹性滑动效果
  • Android使用Scroller实现弹性滑动效果
(0)

相关推荐

  • Android自定义ViewGroup实现弹性滑动效果

    自定义View实现一个弹性滑动的效果,供大家参考,具体内容如下 实现原理 onMeasure()中测量所有子View @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // 测量所有子View int count = getChildCount(); for (int i = 0; i < count; i++) { View childView = getChildAt(i); m

  • Android继承ViewGroup实现Scroll滑动效果的方法示例

    本文实例讲述了Android继承ViewGroup实现Scroll滑动效果的方法.分享给大家供大家参考,具体如下: extends ViewGroup需要重写onMeasure和onLayout方法 onMeasure方法是去测量ViewGroup需要的大小以及包含的子View需要的大小. 执行完上面的方法后,再执行onLayout方法去设置子View的摆放位置. 实现Scroll滑动效果需要去检测滑动速率,即要知道每个单位时间滑动了多少像素值,根据这个像素值去判断Scroll滑动到下一页还是上

  • Android自定义View弹性滑动Scroller详解

    本文实例为大家分享了Android弹性滑动类Scroller的具体代码,供大家参考,具体内容如下 Scroller是什么 Scroller就是一个滑动帮助类.它并不可以使View真正的滑动,而是配合scrollTo/ScrollBy让view产生缓慢的滑动,产生动画的效果,其实和属性动画是同一个原理.在我看来,Scroller跟属性动画的平移的效果是一样的. 如何使用 //①实例一个Scroller,它有三个构造方法如下 //public Scroller (Context context) /

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

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

  • Android Scroll实现弹性滑动_列表下拉弹性滑动的示例代码

    我这一次讲使用scroll实现弹性滑动,我不会只有一个例子就说完,因为写文章的时候我也在学习,我分几次讲完吧. 首先上一段代码, private void smoothScrollByScroller(int dy){ mScroller.startScroll(0,dy,0,dy*-1,1000); invalidate(); } @Override public void computeScroll() { if (mScroller.computeScrollOffset()) { scr

  • flutter实现一个列表下拉抽屉的示例代码

    目录 使用 源码 使用 通过监听滚动事件实现DragOpenDrawer 组件,可以给滚动组件添加一个下拉抽屉.其使用方式如下: DragOpenDrawer(   openDuration: Duration(microseconds: 900),   closeDuration: Duration(milliseconds: 300),   onOpen: (){     print("onOpen");   },  child: Column(       children: [

  • Android实现简单的下拉阻尼效应示例代码

    OS的下拉上拉都会出现一个很玄的动态效果.在Android中,虽然可以实现类似的效果,但有点不同的是,如果调用overScrollBy来实现类似的阻尼效应的话,最顶部会出现一片亮的区域,让人感觉不是很爽.所以决定不采用该方法来实现而是改用自定义的方式来实现. 下面是自定义控件的代码部分: public class MyView extends ScrollView { //记录下最开始点击的位置 int initY; //移动的位置 int deltaY; int touchY; //记录第一个

  • 微信小程序实现触底加载与下拉刷新的示例代码

    目录 触底加载 loader函数思考 loader函数实现 触底加载动画 触底加载的优点 下拉刷新 最后 在最近做小程序的时候有这么一个很常见的需求,加载一个信息列表,要求需要触底加载和下拉刷新,我突然想起来掘金小册界面和这个需求很相似,接下来我给大家介绍一下我的实现方案. 触底加载 步骤如下: 封装一个loader函数 在监听页面加载的时候触发这个loader函数 在监听到触底的时候再次触发这个函数 onLoad: function (options) { this.loadBooks(thi

  • iview实现select tree树形下拉框的示例代码

    本文介绍了iview实现select tree树形下拉框的示例代码,分享给大家,具体如下: html部分 <Tree :data="treeData" ref="tree" :render="renderContent"></Tree> 数据部分 export const treeData= [ { title: 'parent 1', expand: true, selected: true, value: '1', c

  • 在Angular中实现一个级联效果的下拉框的示例代码

    实现一个具有级联效果的下拉搜索框,实现的结果如下图所示 我们主要通过这个组件,来学习一些细微的逻辑,比如: 如何计算input框内文字的长度: 如何获取光标的位置:如何实现滚动条随着上下键盘的按动进行移动...... 具体需求如下 级联搜索最多不超过三级,以"."作为级联搜索的连接符 搜索框跟着文本框中的"."进行向后移动,向右移动的最大距离不能超过文本框的宽度 当用户修改之前的级联内容,则不进行搜索,并隐藏搜索框:若用户在之前输入的是".",

  • Vue+ElementUI实现从后台动态填充下拉框的示例代码

    1.首先编写前端代码,将elementUI中的标签写到.vue界面中.  <el-select       v-model="xxxQuery.xxxid"       placeholder="请在下拉框中选择名称"       maxlength="255"       :disabled="false"       clearable>             <el-option          

  • Java实现级联下拉结构的示例代码

    目录 前言 构建统一返回下拉结构 构建集合<对象>转下拉树工具类 构建List<Map>转下拉或下拉树的工具类 前言 在开发过程中,会遇到很多的实体需要将查出的数据处理为下拉或者级联下拉的结构,提供给前端进行展示. 在数据库查出的结构中,可能是集合<实体类>的结构,也有可能是List<Map>的结构. 在下拉或者级联下拉的节点数据中,有时候还需要动态的携带其他的参数,已便于前端对某些数据的显示 如区域的级联下拉树中,需要携带经纬度的区域–在选择的时候在地图展

  • JS下拉缓冲菜单示例代码

    复制代码 代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <style> body,html

  • react实现移动端下拉菜单的示例代码

    前言 项目中要实现类似与vant的DropdownMenu:下拉菜单.看了vans 的效果 其实也没什么难度,于是动手鲁了一个这样的组件. 项目的技术栈为react全家桶+material UI + ant Design mobile. vans的效果 我自己实现的效果 思路 常规做法获取dom元素,动态修改选中dom的innerHtml. 当然这种方式不是react推荐的 我的做法既然react不推荐直接操作dom元素,那可以采用动态动态修改class的方式达到效果,例如: let cls =

随机推荐