overScrollBy实现下拉视差特效,效果图如下
先来分析overScrollBy方法的使用,它是View的方法,参数有点多:
/**
* 当滑动的超出上,下,左,右最大范围时回调
*
* @param deltaX x方向的瞬时偏移量,左边到头,向右拉为负,右边到头,向左拉为正
* @param deltaY y方向的瞬时偏移量,顶部到头,向下拉为负,底部到头,向上拉为正
* @param scrollX 水平方向的永久偏移量
* @param scrollY 竖直方向的永久偏移量
* @param scrollRangeX 水平方向滑动的范围
* @param scrollRangeY 竖直方向滑动的范围
* @param maxOverScrollX 水平方向最大滑动范围
* @param maxOverScrollY 竖直方向最大滑动范围
* @param isTouchEvent 是否是手指触摸滑动, true为手指, false为惯性
* @return
*/
@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的布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="160dp"
<span style="color:#ff0000;">android:scaleType="centerCrop"</span>
android:src="@drawable/header" />
</LinearLayout>
没什么特别的,就是一个ImageView,通过src设置了一张图片,这里唯一要将的就是scaleType属性,我这边设置了centerCrop,以图片的最小的边开始截取,因为这里选择的图片是高度大于宽度的,所以裁剪的时候会保留完整的宽度,中心裁剪,如下图所示:
自定义ListView代码,整体代码还是比较简短的.
/**
* Created by mChenys on 2015/12/23.
*/
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);
}
/**
* 当滑动的超出上,下,左,右最大范围时回调
*
* @param deltaX x方向的瞬时偏移量,左边到头,向右拉为负,右边到头,向左拉为正
* @param deltaY y方向的瞬时偏移量,顶部到头,向下拉为负,底部到头,向上拉为正
* @param scrollX 水平方向的永久偏移量
* @param scrollY 竖直方向的永久偏移量
* @param scrollRangeX 水平方向滑动的范围
* @param scrollRangeY 竖直方向滑动的范围
* @param maxOverScrollX 水平方向最大滑动范围
* @param maxOverScrollY 竖直方向最大滑动范围
* @param isTouchEvent 是否是手指触摸滑动, true为手指, false为惯性
* @return
*/
@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();
//方式二,通过自定义动画
/*ResetAnimation animation = new ResetAnimation(mHeaderIv, mHeaderIv.getHeight(), mOriginalHeight);
startAnimation(animation);*/
break;
}
return super.onTouchEvent(ev);
}
}
看看自定义动画:
/**
* 自定义动画
* Created by mChenys on 2015/12/24.
*/
public class ResetAnimation extends Animation {
private final ImageView headerIv; //要执行动画的目标ImageView
private final int startHeight;//执行动画的开始时的高度
private final int endHeight;//执行动画结束时的高度
private IntEvaluator mEvaluator; //整型估值器
/**
* 构造方法初始化
*
* @param headerIv 应用动画的目标控件
* @param startHeight 开始的高度
* @param endHeight 结束的高度
*/
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());
}
/**
* 在指定的时间内一直执行该方法,直到动画结束
* interpolatedTime:0-1 标识动画执行的进度或者百分比
*
* @param interpolatedTime
* @param t
*/
@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);
}
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
# Android
# overScrollBy
# 下拉视差
# Android自定义view实现阻尼效果的加载动画
# Android UI设计系列之自定义ListView仿QQ空间阻尼下拉刷新和渐变菜单栏效果(8)
# 自定义
# 偏移量
# 左拉
# 回调
# 后会
# 将其
# 估值
# 拉出
# 是一个
# 好了
# 只需
# 它是
# 时间内
# 有兴趣
# 所示
# 要将
# 这篇文章
# 浅谈
# 拉到
# 先来
相关文章:
巅云智能建站系统:可视化拖拽+多端适配+免费模板一键生成
如何在万网主机上快速搭建网站?
如何通过虚拟主机快速搭建个人网站?
建站之星后台密码遗忘?如何快速找回?
网站制作与设计教程,如何制作一个企业网站,建设网站的基本步骤有哪些?
如何在搬瓦工VPS快速搭建网站?
网站建设设计制作营销公司南阳,如何策划设计和建设网站?
建站之星ASP如何实现CMS高效搭建与安全管理?
建站之星CMS建站配置指南:模板选择与SEO优化技巧
家庭建站与云服务器建站,如何选择更优?
如何选择靠谱的建站公司加盟品牌?
详解一款开源免费的.NET文档操作组件DocX(.NET组件介绍之一)
网站制作的步骤包括,正确网址格式怎么写?
如何高效完成自助建站业务培训?
如何通过VPS建站实现广告与增值服务盈利?
已有域名如何免费搭建网站?
如何基于云服务器快速搭建个人网站?
广州网站建站公司选择指南:建站流程与SEO优化关键词解析
电商平台网站制作流程,电商网站如何制作?
建站VPS能否同时实现高效与安全翻墙?
上海制作企业网站有哪些,上海有哪些网站可以让企业免费发布招聘信息?
网站制作公司广州有几家,广州尚艺美发学校网站是多少?
图册素材网站设计制作软件,图册的导出方式有几种?
制作国外网站的软件,国外有哪些比较优质的网站推荐?
定制建站模板如何实现SEO优化与智能系统配置?18字教程
最好的网站制作公司,网购哪个网站口碑最好,推荐几个?谢谢?
免费制作统计图的网站有哪些,如何看待现如今年轻人买房难的情况?
,巨量百应是干嘛的?
实现点击下箭头变上箭头来回切换的两种方法【推荐】
极客网站有哪些,DoNews、36氪、爱范儿、虎嗅、雷锋网、极客公园这些互联网媒体网站有什么差异?
c# await 一个已经完成的Task会发生什么
学校建站服务器如何选型才能满足性能需求?
javascript中对象的定义、使用以及对象和原型链操作小结
山东网站制作公司有哪些,山东大源集团官网?
如何生成腾讯云建站专用兑换码?
青岛网站建设如何选择本地服务器?
深圳网站制作的公司有哪些,dido官方网站?
如何通过FTP服务器快速搭建网站?
网站app免费制作软件,能免费看各大网站视频的手机app?
如何用wdcp快速搭建高效网站?
建站主机是否等同于虚拟主机?
建站之星后台密码遗忘或太弱?如何重置与强化?
如何在阿里云虚拟服务器快速搭建网站?
如何快速搭建自助建站会员专属系统?
建站之星代理如何获取技术支持?
宿州网站制作公司兴策,安徽省低保查询网站?
如何选择高效可靠的多用户建站源码资源?
jQuery 常见小例汇总
威客平台建站流程解析:高效搭建教程与设计优化方案
如何批量查询域名的建站时间记录?
*请认真填写需求信息,我们会在24小时内与您取得联系。