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界面上拉下拉的回弹效果实例代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • Android ReboundScrollView仿IOS拖拽回弹效果

    初衷: 其实github上有很多这种ScrollView的项目,但是不得不说功能太多太乱了,我就只是想要一个简单效果的ScrollView,另外监听下滑动距离而已,想想还是自己写了个. 这里先说下思路吧,如果不愿意看的朋友可以直接跳过这一步,看下面的代码: Android 原生的ScrollView是不支持拉出屏幕外,并且也没有回弹效果的,用户友好度却不不太好,不知道为什么不那么设计. 我想做的事情正如上面所述: 1.希望能拉出屏幕外 2.松手后希望控件回弹 我的思路是对ScrollView的子

  • Android编程ViewPager回弹效果实例分析

    本文实例讲述了Android编程ViewPager回弹效果.分享给大家供大家参考,具体如下: 其实在我们很多应用中都看到当ViewPager滑到第一页或者最后一页的时候,如果再滑动的时候,就会有一个缓冲的过程,也就是回弹效果.之前在研究回弹效果的时候,也顺便实现了ViewPager的回弹效果,其实也很简单,一下是实现代码,注释比较少: package com.freesonfish.viewpager_2; import android.content.Context; import andro

  • Android RecyclerView上拉加载更多功能回弹实现代码

    实现原理是使用RecyclerView的OnTouchListener方法监听滑动 在adapter里面增加两项footview 其中date.size为显示的加载条,可以自定义,date.size+1为空白的View,我们设置其高度为0 我们通过LinearLayoutManager的 findLastVisibleItemPosition判断显示的最后一条数据,如果是空白view,表示加载条已经完全展示,松开即可刷新. 回弹效果是通过在滑动时动态改变空白view的高度,达到阻尼效果 ,回弹时

  • 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(Co

  • Android 实现ViewPager边界回弹效果实例代码

    废话不多说了,直接给大家贴代码了,具体代码如下所示: public class BounceBackViewPager extends ViewPager { private int currentPosition = 0; private Rect mRect = new Rect();//用来记录初始位置 private boolean handleDefault = true; private float preX = 0f; private static final float RATI

  • Android 仿今日头条简单的刷新效果实例代码

    点击按钮,先自动进行下拉刷新,也可以手动刷新,刷新完后,最后就多一行数据.有四个选项卡. 前两天导师要求做一个给本科学生预定机房座位的app,出发点来自这里.做着做着遇到很多问题,都解决了.这个效果感觉还不错,整理一下. MainActivity package com.example.fragmentmytest; import android.content.DialogInterface; import android.graphics.Color; import android.os.B

  • Android仿美团下拉菜单(商品选购)实例代码

    美团电商应用平台大家使用非常频繁,下面小编通过本文给大家介绍电商应用平台中常用的选择类别下拉列表的实现.先给大家展示下效果图: 一.下拉列表的实现 其实实现方法有很多,这时实现的也没有什么技术含量,只是总结下自己在项目中的做法,也提供一个思路. 首先是列表的数据,一般数据都是从后台读过来,这里因为没有后台,所以写死在客户端: private void initMenuData() { menuData = new ArrayList<map<string, string=""

  • JavaScript Ajax Json实现上下级下拉框联动效果实例代码

    最近尝试做出一个部门和人员的下拉框联动功能,部门和人员的对应关系是1:N 复制代码 代码如下: <div class="forntName">部门</div> <div class="inpBox"> <select  name="department" id="department"  onchange="change();" style="width:

  • Android自定义ScrollView实现放大回弹效果实例代码

    1,刚刚在别人开源的项目中看到了一个挺不错的用户体验,效果图如下: 2,那下面我们就来实现一下,首先看一下布局,由于一般只是我们包含头像的那部分方法,所以这里我们要把布局分成两部分,对应的布局文件效果图如下: 3,自定义ScrollView 第一步:创建一个类,继承自ScrollView,重写相应的构造函数 public class ZoomInScrollView extends ScrollView { public ZoomInScrollView(Context context) { t

  • Android直播app送礼物连击动画效果(实例代码)

    最近在做公司的直播项目,需要实现一个观看端连击送礼物的控件: 直接上代码: /** * @author yangyinglong on 2017/7/11 16:52. * @Description: todo(这里用一句话描述这个类的作用) * @Copyright Copyright (c) 2017 Tuandai Inc. All Rights Reserved. */ public class CustomGiftView extends LinearLayout { private

  • Android中的Button自定义点击效果实例代码

    方法一1.放在drawable下的selector.xml文件 复制代码 代码如下: <android="http://schemas.android.com/apk/res/Android"> android:drawable="@drawable/temp2" /> 2.布局文件main.xml 复制代码 代码如下: <http://schemas.android.com/apk/res/android"    android:

  • Android如何利用RecyclerView实现列表倒计时效果实例代码

    前言 最近面试时,面试官问了一个列表倒计时效果如何实现,然后脑袋突然懵的了O(∩_∩)O,现在记录一下. 运行效果图 实现思路 实现方法主要有两个: 1.为每个开始倒计时的item启动一个定时器,再做更新item处理: 2.只启动一个定时器,然后遍历数据,再做再做更新item处理. 经过思考,包括性能.实现等方面,决定使用第2种方式实现. 实现过程 数据实体 /** * 总共的倒计时的时间(结束时间-开始时间),单位:毫秒 * 例: 2019-02-23 11:00:30 与 2019-02-2

  • Android仿IOS上拉下拉弹性效果的实例代码

    用过iphone的朋友相信都体验过页面上拉下拉有一个弹性的效果,使用起来用户体验很好:Android并没有给我们封装这样一个效果,我们来看下在Android里如何实现这个效果.先看效果,感觉有些时候还是蛮实用的. 思路:其实原理很简单,实现一个自定义的Scrollview方法(来自网上大神),然后在布局文件中使用自定义方法Scrollview就可以了. 代码: 自定义View,继承自Scrollview.MyReboundScrollView类 package com.wj.myrebounds

随机推荐