欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2023-12-06 17:11:46
1,刚刚在别人开源的项目中看到了一个挺不错的用户体验,效果图如下: 2,那下面我们就来实现一下,首先看一下布局,由于一般只是我们包含头像的那部分方法,所以这里我们要把...

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

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

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

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

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

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

  } 

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

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

demo下载:zoominscrollview_jb51.rar

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