栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 移动开发 > Android

Android通过overScrollBy实现下拉视差特效

Android 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Android通过overScrollBy实现下拉视差特效

overScrollBy实现下拉视差特效,效果图如下

先来分析overScrollBy方法的使用,它是View的方法,参数有点多:

 
  @Override 
  protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, 
   int scrollRangeX, int scrollRangeY, int maxOverScrollX, 
   int maxOverScrollY, boolean isTouchEvent) { 
    return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, 
 scrollRangeX, scrollRangeY, maxOverScrollX, maxOverScrollY, 
 isTouchEvent); 
  } 

大致步骤如下:

1.这整体是一个ListView,所以需要自定义一个ListView.
2.处理头部布局文件,将其以HeaderView的方式添加到自定义的ListView中
3.需要获取HeaderView的ImageView的初始高度和ImageView中图片的高度.因为这2个高度将决定下来的时候图片拉出的范围,以及松手后图片回弹的动画效果.对应控件宽高的获取,有兴趣的可以看这篇文章浅谈自定义View的宽高获取
4.在overScrollBy方法内通过修改ImageView的LayoutParams的height值来显示更多的图片内容.
5.在onTouchEvent方法内处理ACTION_UP事件,使ImageView有回弹的动画效果,这里介绍2种方式,分别是属性动画和自定义动画.

好了,先来看HeaderView的布局文件:

 
 
   
 

没什么特别的,就是一个ImageView,通过src设置了一张图片,这里唯一要将的就是scaleType属性,我这边设置了centerCrop,以图片的最小的边开始截取,因为这里选择的图片是高度大于宽度的,所以裁剪的时候会保留完整的宽度,中心裁剪,如下图所示:

自定义ListView代码,整体代码还是比较简短的.

 
public class MyListView extends ListView { 
  private ImageView mHeaderIv; //HeaderView 的ImageView 
  private int mOriginalHeight; //最初ImageView的高度 
  private int mDrawableHeight;//ImageView中图片的高度 
 
  public MyListView(Context context) { 
    this(context, null); 
  } 
 
  public MyListView(Context context, AttributeSet attrs) { 
    this(context, attrs, 0); 
  } 
 
  public MyListView(Context context, AttributeSet attrs, int defStyleAttr) { 
    super(context, attrs, defStyleAttr); 
    init(); 
  } 
 
   
  private void init() { 
    //初始化头部文件 
    View headerView = View.inflate(getContext(), R.layout.view_header, null); 
    mHeaderIv = (ImageView) headerView.findViewById(R.id.imageView); 
    //将其添加到ListView的头部 
    addHeaderView(headerView); 
    //通过设置监听来获取控件的高度 
    mHeaderIv.getViewTreeObserver().addonGlobalLayoutListener(new ViewTreeObserver.onGlobalLayoutListener() { 
      @TargetApi(Build.VERSION_CODES.JELLY_BEAN) 
      @Override 
      public void onGlobalLayout() { 
 //只需监听一次,否则之后的onLayout方法回调的时候还是会回调这里 
 mHeaderIv.getViewTreeObserver().removeonGlobalLayoutListener(this); 
 mOriginalHeight = mHeaderIv.getMeasuredHeight();//获取ImageView的初始高度 
 mDrawableHeight = mHeaderIv.getDrawable().getIntrinsicHeight();//获取ImageView中图片的高度 
      } 
    }); 
    //去掉下拉到头部后的蓝色线 
    setOverScrollMode(OVER_SCROLL_NEVER); 
  } 
 
   
  @Override 
  protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, 
    int scrollRangeX, int scrollRangeY, int maxOverScrollX, 
    int maxOverScrollY, boolean isTouchEvent) { 
    // 手指拉动并且是下拉 
    if (isTouchEvent && deltaY < 0) { 
      // 把拉动的瞬时变化量的绝对值交给Header, 就可以实现放大效果 
      if (mHeaderIv.getHeight() <= mDrawableHeight) { 
 // 高度不超出图片最大高度时,才让其生效 
 int newHeight = (int) (mHeaderIv.getHeight() + Math.abs(deltaY / 3.0f));//这里除以3是为了达到视差的效果 
 mHeaderIv.getLayoutParams().height = newHeight; 
 //此方法必须调用,调用后会重新调用onMeasure和onLayout方法进行测量和定位 
 mHeaderIv.requestLayout(); 
      } 
    } 
    return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent); 
  } 
 
  @Override 
  public boolean onTouchEvent(MotionEvent ev) { 
    switch (ev.getAction()) { 
      case MotionEvent.ACTION_UP: 
 // 执行回弹动画, 方式一: 属性动画值动画 
 //获取ImageView在松手时的高度 
 int currHeight = mHeaderIv.getHeight(); 
 // 从当前高度mHeaderIv.getHeight(), 执行动画到原始高度mOriginalHeight 
 ValueAnimator animator = ValueAnimator.ofInt(currHeight, mOriginalHeight); 
 animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 
   @Override 
   public void onAnimationUpdate(ValueAnimator animation) { 
     int value = (int) animation.getAnimatedValue(); 
     mHeaderIv.getLayoutParams().height = value; 
     //此方法必须调用,调用后会重新调用onMeasure和onLayout方法进行测量和定位 
     mHeaderIv.requestLayout(); 
   } 
 }); 
 animator.setDuration(500); 
 animator.setInterpolator(new OvershootInterpolator()); 
 animator.start(); 
 
 //方式二,通过自定义动画 
  
 break; 
    } 
    return super.onTouchEvent(ev); 
  } 
} 

看看自定义动画:

 
public class ResetAnimation extends Animation { 
  private final ImageView headerIv; //要执行动画的目标ImageView 
  private final int startHeight;//执行动画的开始时的高度 
  private final int endHeight;//执行动画结束时的高度 
  private Intevaluator mevaluator; //整型估值器 
 
   
  public ResetAnimation(ImageView headerIv, int startHeight, int endHeight) { 
    this.headerIv = headerIv; 
    this.startHeight = startHeight; 
    this.endHeight = endHeight; 
    //定义一个int类型的类型估值器,用于获取实时变化的高度值 
    mevaluator = new Intevaluator(); 
    //设置动画持续时间 
    setDuration(500); 
    //设置插值器 
    setInterpolator(new OvershootInterpolator()); 
  } 
 
   
  @Override 
  protected void applyTransformation(float interpolatedTime, Transformation t) { 
    int currHeight = mevaluator.evaluate(interpolatedTime, startHeight, endHeight); 
    //通过LayoutParams不断的改变其高度 
    headerIv.getLayoutParams().height = currHeight; 
    //此方法必须调用,调用后会重新调用onMeasure和onLayout方法进行测量和定位 
    headerIv.requestLayout(); 
  } 
} 

MainActivity测试类:

public class MainActivity extends AppCompatActivity { 
 
  @Override 
  protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    MyListView listView = new MyListView(this); 
    listView.setDividerHeight(1); 
    listView.setSelector(new ColorDrawable()); 
    listView.setCacheColorHint(Color.TRANSPARENT); 
    listView.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, Cheeses.NAMES)); 
    setContentView(listView); 
  } 
} 

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

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/158232.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号