当前位置: 首页 > 编程笔记 >

Android界面上拉下拉的回弹效果实例代码

狄旻
2023-03-14
本文向大家介绍Android界面上拉下拉的回弹效果实例代码,包括了Android界面上拉下拉的回弹效果实例代码的使用技巧和注意事项,需要的朋友参考一下

废话不多说,具体代码如下所示:

public class MyScrollView extends ScrollView {
  private View childView;
  public MyScrollView(Context context) {
    super(context);
  }
  public MyScrollView(Context context, AttributeSet attrs) {
    super(context, attrs);
  }
  public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
  }
//  @Override
//  protected void onLayout(boolean changed, int l, int t, int r, int b) {
//    super.onLayout(changed, l, t, r, b);
//  }
  //获取子视图
  @Override
  protected void onFinishInflate() {
    super.onFinishInflate();
    if (getChildCount() > 0) {
      childView = getChildAt(0);
    }
  }
  private int lastY;//上一次y轴方向操作的坐标位置
  private Rect normal = new Rect();//用于记录临界状态的左、上、右、下
  private boolean isFinishAnimation = true;//是否动画结束
  private int lastX, downX, downY;
  //拦截:实现父视图对子视图的拦截
  //是否拦截成功,取决于方法的返回值。返回值true:拦截成功。反之,拦截失败
  @Override
  public boolean onInterceptTouchEvent(MotionEvent ev) {
    boolean isIntercept = false;
    int eventX = (int) ev.getX();
    int eventY = (int) ev.getY();
    switch (ev.getAction()) {
      case MotionEvent.ACTION_DOWN:
        lastX = downX = eventX;
        lastY = downY = eventY;
        break;
      case MotionEvent.ACTION_MOVE:
        //获取水平和垂直方向的移动距离
        int absX = Math.abs(eventX - downX);
        int absY = Math.abs(eventY - downY);
        if(absY > absX && absY >= UIUtils.dp2px(10)){
          isIntercept = true;//执行拦截
        }
        lastX = eventX;
        lastY = eventY;
        break;
    }
    return isIntercept;
  }
  @Override
  public boolean onTouchEvent(MotionEvent ev) {
    if (childView == null || !isFinishAnimation) {
      return super.onTouchEvent(ev);
    }
    int eventY = (int) ev.getY();//获取当前的y轴坐标
    switch (ev.getAction()) {
      case MotionEvent.ACTION_DOWN:
        lastY = eventY;
        break;
      case MotionEvent.ACTION_MOVE:
        int dy = eventY - lastY;//微小的移动量
        if (isNeedMove()) {
          if (normal.isEmpty()) {
            //记录了childView的临界状态的左、上、右、下
            normal.set(childView.getLeft(), childView.getTop(), childView.getRight(), childView.getBottom());
          }
          //重新布局
          childView.layout(childView.getLeft(), childView.getTop() + dy / 2, childView.getRight(), childView.getBottom() + dy / 2);
        }
        lastY = eventY;//重新赋值
        break;
      case MotionEvent.ACTION_UP:
        if (isNeedAnimation()) {
          //使用平移动画
          int translateY = childView.getBottom() - normal.bottom;
          TranslateAnimation translateAnimation = new TranslateAnimation(0, 0, 0, -translateY);
          translateAnimation.setDuration(200);
//        translateAnimation.setFillAfter(true);//停留在最终位置上
          translateAnimation.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
              isFinishAnimation = false;
            }
            @Override
            public void onAnimationEnd(Animation animation) {
              isFinishAnimation = true;
              childView.clearAnimation();//清除动画
              //重新布局
              childView.layout(normal.left, normal.top, normal.right, normal.bottom);
              //清除normal的数据
              normal.setEmpty();
            }
            @Override
            public void onAnimationRepeat(Animation animation) {
            }
          });
          //启动动画
          childView.startAnimation(translateAnimation);
        }
        break;
    }
    return super.onTouchEvent(ev);
  }
  //判断是否需要执行平移动画
  private boolean isNeedAnimation() {
    return !normal.isEmpty();
  }
  private boolean isNeedMove() {
    int childMeasuredHeight = childView.getMeasuredHeight();//获取子视图的高度
    int scrollViewMeasuredHeight = this.getMeasuredHeight();//获取布局的高度
    Log.e("TAG", "childMeasuredHeight = " + childMeasuredHeight);
    Log.e("TAG", "scrollViewMeasuredHeight = " + scrollViewMeasuredHeight);
    int dy = childMeasuredHeight - scrollViewMeasuredHeight;//dy >= 0
    int scrollY = this.getScrollY();//获取用户在y轴方向上的偏移量 (上 + 下 -)
    if (scrollY <= 0 || scrollY >= dy) {
      return true;//按照我们自定义的MyScrollView的方式处理
    }
    //其他处在临界范围内的,返回false。即表示,仍按照ScrollView的方式处理
    return false;
  }
}

以上所述是小编给大家介绍的Android界面上拉下拉的回弹效果实例代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对小牛知识库网站的支持!

 类似资料:
  • 本文向大家介绍Android仿IOS上拉下拉弹性效果的实例代码,包括了Android仿IOS上拉下拉弹性效果的实例代码的使用技巧和注意事项,需要的朋友参考一下 用过iphone的朋友相信都体验过页面上拉下拉有一个弹性的效果,使用起来用户体验很好;Android并没有给我们封装这样一个效果,我们来看下在Android里如何实现这个效果。先看效果,感觉有些时候还是蛮实用的。 思路:其实原理很简单,实现

  • 本文向大家介绍Android使用PullToRefresh实现上拉加载和下拉刷新效果的代码,包括了Android使用PullToRefresh实现上拉加载和下拉刷新效果的代码的使用技巧和注意事项,需要的朋友参考一下 在没给大家介绍正文之前,先给大家介绍展示下运行图,如果大家感觉还不错,请继续往下阅读: 相关阅读:分享Android中pullToRefresh的使用心得 项目已同步至:https:/

  • 本文向大家介绍Bootstrap下拉菜单效果实例代码分享,包括了Bootstrap下拉菜单效果实例代码分享的使用技巧和注意事项,需要的朋友参考一下 下拉菜单Dropdown不是表单中<select><option value=''></option></select>那种啊,而是导航条中常见的那种。  Bootstrap官方网站对下拉菜单Dropdown的解释很少,即使是他们的英文官方网站。  对

  • 本文向大家介绍Android实现RecyclerView下拉刷新效果,包括了Android实现RecyclerView下拉刷新效果的使用技巧和注意事项,需要的朋友参考一下 本文为大家分享了Android实现RecyclerView下拉刷新效果的具体代码,供大家参考,具体内容如下 思路 RealPullRefreshView继承了一个LinearLayout 里面放置了一个刷新头布局,将其margi

  • 本文向大家介绍Android下拉列表spinner的实例代码,包括了Android下拉列表spinner的实例代码的使用技巧和注意事项,需要的朋友参考一下 spinner组件有点类型于HTML中的下拉框<Select></select>的样子,让用户每次从下拉框中选取一个,本文为大家分享了Android下拉列表spinner的具体实现代码,供大家参考,具体内容如下 mian.xml Main.ja

  • 本文向大家介绍微信小程序下拉菜单效果的实例代码,包括了微信小程序下拉菜单效果的实例代码的使用技巧和注意事项,需要的朋友参考一下 总结 以上所述是小编给大家介绍的微信小程序下拉菜单效果的实例代码,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!