Android简易实战教程--第五十四话《视差特效》
2017-10-26 11:19
274 查看
查看更多进阶知识,可以关注我的公众号,微信搜索:Android小菜
这个简易实战教程系列专栏发现已经大半年没更新了啊,赶紧添点东西。
本文实现一个视差特效效果,动态效果如下:
代码十分简单,自定义View代码添加在下面:
// deltaY : 竖直方向的瞬时偏移量, 顶部下拉- , 底部上拉+, 速度越快绝对值越大.
// scrollY : 竖直方向ListView滚动的距离, 顶部- , 底部+
// scrollRangeY : 竖直方向滚动距离
// maxOverScrollY : 最大的超出滚动范围
// isTouchEvent : 是否是手指触摸到顶部/底部. true触摸, false惯性
因为是在头部下拉,所以判断deltaY<0 且是触摸状态(非惯性滑动状态),才去处理事件。得到最新的ImageView的高度【因为手指下滑有一个滑动了多少的绝对值,类加后就是当前ImagView的当前高度】,并把最新的高度设置给ImageView。这样就实现了ImagView的放大效果了。
那么松开手要做的逻辑,肯定是放在onTouchEvent的UP事件里面了,主要做的工作就是,记录松开手时候ImagView的高度,使用属性动画把ImagView控件不断地缩小,这里还使用了插值器,让ImagView恢复原来高度值后有一个弹性效果。这样整个简易的自定义View就完成了。
然后看看客户端如何使用这个控件:
MainActivity的布局文件:
最后可能会存在一点点的bug:
代码下载链接地址:源码下载
这个简易实战教程系列专栏发现已经大半年没更新了啊,赶紧添点东西。
本文实现一个视差特效效果,动态效果如下:
代码十分简单,自定义View代码添加在下面:
public class ParallaxListView extends ListView { private static final String TAG = "ParallaxListView"; private ImageView ParallaxHeaderImageView;//头部视视差效果的图片 private int mOldHeight;//此时ImageView的高度 private int mRealHeight;//图片的真正高度 public ParallaxListView(Context context) { this(context,null); } public ParallaxListView(Context context, AttributeSet attrs) { super(context, attrs); } public void setHeadImageView(ImageView ivHeadImageView) { this.ParallaxHeaderImageView = ivHeadImageView; mOldHeight = ParallaxHeaderImageView.getMeasuredHeight(); // int height = ParallaxHeaderImageView.getHeight(); // Log.e(TAG,mOldHeight+"----"+height);//两个值一样 mRealHeight = ParallaxHeaderImageView.getDrawable().getIntrinsicHeight(); } @Override protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) { System.out.println("deltaY: "+ deltaY + " scrollY: " + scrollY + " scrollRangeY: " + scrollRangeY + " maxOverScrollY: " + maxOverScrollY + " isTouchEvent: " + isTouchEvent); // deltaY : 竖直方向的瞬时偏移量, 顶部下拉- , 底部上拉+, 速度越快绝对值越大. // scrollY : 竖直方向ListView滚动的距离, 顶部- , 底部+ // scrollRangeY : 竖直方向滚动距离 // maxOverScrollY : 最大的超出滚动范围 // isTouchEvent : 是否是手指触摸到顶部/底部. true触摸, false惯性 if(deltaY <0 && isTouchEvent){ int newHeight = ParallaxHeaderImageView.getHeight() + Math.abs(deltaY)/2;//减少拖动的距离 setCurrentImageViewHeight(newHeight); } return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent); } private void setCurrentImageViewHeight(int newHeight) { ParallaxHeaderImageView.getLayoutParams().height = newHeight; ParallaxHeaderImageView.requestLayout(); } @Override public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_UP: int startHeight = ParallaxHeaderImageView.getHeight(); ValueAnimator animator = ValueAnimator.ofInt(startHeight, mOldHeight); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { // 500 毫秒内多次调用 // 0.0 -> 1.0 System.out.println("animation: " + animation.getAnimatedFraction()); // 模拟出来的中间值 Object animatedValue = animation.getAnimatedValue(); System.out.println("animation: " + animatedValue); // 让新的高度生效 setCurrentImageViewHeight((Integer)animatedValue); } }); animator.setInterpolator(new OvershootInterpolator(4)); animator.setDuration(500); animator.start(); break; default: break; } return super.onTouchEvent(ev); } }代码解析:通过setHeadImageView方法传入一头布局,然后拿到当前ImageView的高度和图片的真实高度(注意:真实高度和控件的高度是不一样的)。然后重写overScrollBy方法,这个方法会对ListView滑动到边缘时候做一些判断,具体的参数含义如下:
// deltaY : 竖直方向的瞬时偏移量, 顶部下拉- , 底部上拉+, 速度越快绝对值越大.
// scrollY : 竖直方向ListView滚动的距离, 顶部- , 底部+
// scrollRangeY : 竖直方向滚动距离
// maxOverScrollY : 最大的超出滚动范围
// isTouchEvent : 是否是手指触摸到顶部/底部. true触摸, false惯性
因为是在头部下拉,所以判断deltaY<0 且是触摸状态(非惯性滑动状态),才去处理事件。得到最新的ImageView的高度【因为手指下滑有一个滑动了多少的绝对值,类加后就是当前ImagView的当前高度】,并把最新的高度设置给ImageView。这样就实现了ImagView的放大效果了。
那么松开手要做的逻辑,肯定是放在onTouchEvent的UP事件里面了,主要做的工作就是,记录松开手时候ImagView的高度,使用属性动画把ImagView控件不断地缩小,这里还使用了插值器,让ImagView恢复原来高度值后有一个弹性效果。这样整个简易的自定义View就完成了。
然后看看客户端如何使用这个控件:
MainActivity的布局文件:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.itydl.a04.MainActivity"> <com.itydl.a04.view.ParallaxListView android:id="@+id/lv" android:layout_width="match_parent" android:layout_height="match_parent" /> </RelativeLayout>然后在onCreat方法中:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mListView = (ParallaxListView) findViewById(R.id.lv); mHeadView = View.inflate(this, R.layout.layout_head,null); mIvHead = (ImageView) mHeadView.findViewById(R.id.iv); mListView.addHeaderView(mHeadView); mIvHead.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { mListView.setHeadImageView(mIvHead); mIvHead.getViewTreeObserver().removeGlobalOnLayoutListener(this); } }); mListView.setAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,Strings.NAMES)); }拿到ListView的实例,给其设置数据进去。在试图绘制完毕的时候,把拿到的一张图片设置到刚才的自定义View中去了。然后运行后,就是开头的效果了。
最后可能会存在一点点的bug:
if(deltaY <0 && isTouchEvent){ int newHeight = ParallaxHeaderImageView.getHeight() + Math.abs(deltaY)/2;//减少拖动的距离 if(newHeight <= mRealHeight){ //只有在滑动的距离小于图片的真正高度的时候才去重新设置,超过了图片的高度就不去设置了。 setCurrentImageViewHeight(newHeight); } }超过图片的实际高度不应该再往下下拉设置高度给ImagView了吧。如果觉得有点作用记得加个关注哈,要想看更高级的文章,欢迎关注微信公众号“Android小菜”
代码下载链接地址:源码下载
相关文章推荐
- Android实战简易教程-第五十四枪(通过实现OnScrollListener接口实现下拉刷新功能)
- Android实战简易教程<十二>(ViewFlipper实现幻灯效果)
- Android简易实战教程--第五十二话《满屏拖动的控件2》
- Android实战简易教程<五十八>(AlarmManager类用法研究小实例)
- Android实战简易教程<四十五>(SlideSwitch-好看又实用的开关按钮)
- Android实战简易教程-第十七枪(LayoutAnimation布局动画)
- Android简易实战教程--第二十话《通过广播接收者,对拨打电话外加ip号》
- Android简易实战教程--第二十九话《创建图片副本》
- Android实战简易教程-第二十五枪(基于Baas的数据表查询下拉刷新和上拉载入实现!)
- Android简易实战教程--第四十五话《几种对话框》
- Android实战简易教程-第二十三枪(基于Baas的用户注册和登录模块实现!)
- Android实战简易教程<七>(Activity的启动模式)
- Android实战简易教程<十四>(介绍SwipeMenuListView-简单实现类似QQ的滑动删除效果)
- Android实战简易教程<五十七>(分享小米手电筒源码)
- Android实战简易教程-第十三枪(五大布局研究)
- Android实战简易教程<三十八>(模仿腾讯QQ的网络状态提示和设置功能实现)