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

发布时间 - 2026-01-11 00:10:20    点击率:

1,刚刚在别人开源的项目中看到了一个挺不错的用户体验,效果图如下:

2,那下面我们就来实现一下,首先看一下布局,由于一般只是我们包含头像的那部分方法,所以这里我们要把布局分成两部分,对应的布局文件效果图如下:

3,自定义ScrollView

第一步:创建一个类,继承自ScrollView,重写相应的构造函数

public class ZoomInScrollView extends ScrollView {

 public ZoomInScrollView(Context context) {

    this(context, null);

  } 

  public ZoomInScrollView(Context context, AttributeSet attrs) {

    this(context, attrs, 0);

  }

  public ZoomInScrollView(Context context, AttributeSet attrs, int defStyleAttr) {

    super(context, attrs, defStyleAttr);

  }

} 

第二步:重写OnFinishInflate()方法,并记录第一个子view,即我们的head_fragment

@Override

  protected void onFinishInflate() {

    super.onFinishInflate();

    //设置不可过度滚动,否则上移后下拉会出现部分空白的情况

    setOverScrollMode(OVER_SCROLL_NEVER);

    View child = getChildAt(0);

    if (child != null && child instanceof ViewGroup) {

      //获取默认第一个子View

      mHeaderView = ((ViewGroup) child).getChildAt(0);

    }

  } 

第三步:重写OnTouchEvent()方法,在Action_Move方法中拿到下滑的距离,通过设置head_view的属性参数来改变它的大小,在UP的时候还原head_view

@Override

  public boolean onTouchEvent(MotionEvent ev) {

    if (mHeaderView == null)

      return super.onTouchEvent(ev);

    switch (ev.getAction()) {

      case MotionEvent.ACTION_MOVE:

        if (!mIsPulling) {

          //第一次下拉

          if (getScrollY() == 0) {

            //在顶部的时候,记录顶部位置

            mLastY = (int) ev.getY();

          } else {

            break;

          }

        }

        if (ev.getY() - mLastY < 0)

          return super.onTouchEvent(ev);

        int distance = (int) ((ev.getY() - mLastY) * mScaleRatio);

        mIsPulling = true;

        setZoom(distance);

        return true;

      case MotionEvent.ACTION_UP:

        mIsPulling = false;

        replyView();

        break;

    }

    return super.onTouchEvent(ev);

  } 

在回弹view的时候通过属性动画动态的改变head_view的值,并重写onSizeChange()方法,实时的记录head_view的宽高

/**

 ** 放大view

 */

  private void setZoom(float s) {

    float scaleTimes = (float) ((mHeaderWidth + s) / (mHeaderWidth * 1.0));

//    如超过最大放大倍数,直接返回

    if (scaleTimes > mScaleTimes) return;

 

    ViewGroup.LayoutParams layoutParams = mHeaderView.getLayoutParams();

    layoutParams.width = (int) (mHeaderWidth + s);

    layoutParams.height = (int) (mHeaderHeight * ((mHeaderWidth + s) / mHeaderWidth));

//    设置控件水平居中

    ((MarginLayoutParams) layoutParams).setMargins(-(layoutParams.width - mHeaderWidth) / 2, 0, 0, 0);

    mHeaderView.setLayoutParams(layoutParams);

  }

 

  /**

   * 回弹

   */

  private void replyView() {

    final float distance = mHeaderView.getMeasuredWidth() - mHeaderWidth;

    // 设置动画

    ValueAnimator anim = ObjectAnimator.ofFloat(distance, 0.0F).setDuration((long) (distance * mReplyRatio));

    anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

      @Override

      public void onAnimationUpdate(ValueAnimator animation) {

        setZoom((Float) animation.getAnimatedValue());

      }

    });

    anim.start();

  }

 

@Override

  protected void onSizeChanged(int w, int h, int oldw, int oldh) {

    super.onSizeChanged(w, h, oldw, oldh);

    mHeaderWidth = mHeaderView.getMeasuredWidth();

    mHeaderHeight = mHeaderView.getMeasuredHeight();

  } 

这样就实现了我们的效果了,看一下我们自己实现的效果:

demo下载:ZoomInScrollView_jb51.rar

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


# scrollview回弹效果  # scrollview回弹  # scrollview下拉回弹  # android ScrollView实现水平滑动回弹  # android实现可上下回弹的scrollview  # Android实现回弹ScrollView的原理  # Android自定义ScrollView实现阻尼回弹  # Android自定义scrollview实现回弹效果  # Android ScrollView实现横向和竖向拖动回弹效果  # Android ScrollView的顶部下拉和底部上拉回弹效果  # Android自定义ScrollView实现放大回弹效果  # Android ReboundScrollView仿IOS拖拽回弹效果  # Android ScrollView实现滚动超过边界松手回弹  # 重写  # 看一下  # 要把  # 自定义  # 就来  # 第二步  # 两部分  # 创建一个  # 第三步  # 开源  # 大家多多  # 实现了  # OVER_SCROLL_NEVER  # setOverScrollMode  # View  # amp  # getChildAt  # child  # Override  # head_fragment 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 如何选择可靠的免备案建站服务器?  大连 网站制作,大连天途有线官网?  Python文件异常处理策略_健壮性说明【指导】  INTERNET浏览器怎样恢复关闭标签页_INTERNET浏览器标签恢复快捷键与方法【指南】  Win11关机界面怎么改_Win11自定义关机画面设置【工具】  敲碗10年!Mac系列传将迎来「触控与联网」双革新  详解vue.js组件化开发实践  深圳网站制作公司好吗,在深圳找工作哪个网站最好啊?  Laravel如何实现数据库事务?(DB Facade示例)  个人网站制作流程图片大全,个人网站如何注销?  Laravel中的Facade(门面)到底是什么原理  香港服务器网站卡顿?如何解决网络延迟与负载问题?  标准网站视频模板制作软件,现在有哪个网站的视频编辑素材最齐全的,背景音乐、音效等?  Win11怎么开启自动HDR画质_Windows11显示设置HDR选项  高防网站服务器:DDoS防御与BGP线路的AI智能防护方案  移动端脚本框架Hammer.js  为什么要用作用域操作符_php中访问类常量与静态属性的优势【解答】  Laravel如何使用软删除(Soft Deletes)功能_Eloquent软删除与数据恢复方法  如何快速配置高效服务器建站软件?  Laravel怎么使用Intervention Image库处理图片上传和缩放  Laravel怎么实现前端Toast弹窗提示_Laravel Session闪存数据Flash传递给前端【方法】  Laravel如何实现文件上传和存储?(本地与S3配置)  ai格式如何转html_将AI设计稿转换为HTML页面流程【页面】  公司门户网站制作公司有哪些,怎样使用wordpress制作一个企业网站?  详解jQuery中基本的动画方法  如何在IIS管理器中快速创建并配置网站?  C++用Dijkstra(迪杰斯特拉)算法求最短路径  laravel怎么配置Redis作为缓存驱动_laravel Redis缓存配置教程  如何实现javascript表单验证_正则表达式有哪些实用技巧  Laravel storage目录权限问题_Laravel文件写入权限设置  Laravel如何为API生成Swagger或OpenAPI文档  Bootstrap CSS布局之列表  如何快速启动建站代理加盟业务?  Laravel如何生成URL和重定向?(路由助手函数)  Laravel路由Route怎么设置_Laravel基础路由定义与参数传递规则【详解】  深圳网站制作设计招聘,关于服装设计的流行趋势,哪里的资料比较全面?  Laravel与Inertia.js怎么结合_使用Laravel和Inertia构建现代单页应用  Laravel的HTTP客户端怎么用_Laravel HTTP Client发起API请求教程  如何在 React 中条件性地遍历数组并渲染元素  PHP怎么接收前端传的文件路径_处理文件路径参数接收方法【汇总】  如何在万网ECS上快速搭建专属网站?  LinuxCD持续部署教程_自动发布与回滚机制  EditPlus中的正则表达式实战(6)  Laravel如何使用Telescope进行调试?(安装和使用教程)  如何在建站主机中优化服务器配置?  IOS倒计时设置UIButton标题title的抖动问题  Laravel如何创建和注册中间件_Laravel中间件编写与应用流程  如何在腾讯云服务器上快速搭建个人网站?  PHP的CURL方法curl_setopt()函数案例介绍(抓取网页,POST数据)  如何在阿里云购买域名并搭建网站?