查看更多进阶知识,可以关注我的公众号,微信搜索:Android小菜

这个简易实战教程系列专栏发现已经大半年没更新了啊,赶紧添点东西。

本文实现一个视差特效效果,动态效果如下:

代码十分简单,自定义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();}@Overrideprotected 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();}@Overridepublic 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() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {// 500 毫秒内多次调用// 0.0 -> 1.0System.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"?>
<RelativeLayoutxmlns: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.ParallaxListViewandroid: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() {@Overridepublic 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简易实战教程--第五十四话《视差特效》相关推荐

  1. Android简易实战教程--第三十二话《使用Lrucache和NetworkImageView加载图片》

    转载本专栏每一篇博客请注明转载出处地址,尊重原创.此博客转载链接地址:小杨的博客    http://blog.csdn.net/qq_32059827/article/details/5279131 ...

  2. Android简易实战教程--第五话《开发一键锁屏应用》

    转载请注明出处:http://blog.csdn.net/qq_32059827/article/details/51860900 点击打开链接 Device Administration 对于这个应 ...

  3. Android简易实战教程--第四十四话《ScrollView和HorizontalScrollView简单使用》

    一.ScrollView 由于手机屏幕的高度有限,当普通布局放不下现实和的内容时,ScrollView视图(滚动视图)就会派上用场,因为数据可以往下滚动显示. 二.HorizontalScrollVi ...

  4. Android简易实战教程--第二十四话《画画板》

    今天完成一个画画板. 首先来个布局: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android ...

  5. Android简易实战教程--第四十七话《使用OKhttp回调方式获取网络信息》

    在之前的小案例中写过一篇使用HttpUrlConnection获取网络数据的例子.在OKhttp盛行的时代,当然要学会怎么使用它,本篇就对其基本使用做一个介绍,然后再使用它的接口回调的方式获取相同的数 ...

  6. Android开发笔记(一百五十四)OpenGL的画笔工具GL10

    上一篇文章介绍了OpenGL绘制三维图形的流程,其实没有传说中的那么玄乎,只要放平常心把它当作一个普通控件就好了,接下来继续介绍OpenGL具体的绘图操作,这项工作得靠三维图形的画笔GL10来完成了. ...

  7. Android简易实战教程--第九话《短信备份~二》

    这一篇,承接地八话.使用高效的方式备份短信--xml序列化器. 存储短信,要以对象的方式存储.首先创建javabean: package com.itydl.createxml.domain;publ ...

  8. MATLAB应用实战系列(五十四)-MATLAB多维度绘图实战应用案例

    前言 强大的绘图功能是Matlab的特点之一,Matlab提供了一系列的绘图函数,用户不需要过多的考虑绘图的细节,只需要给出一些基本参数就能得到所需图形,这类函数称为高层绘图函数.此外,Matlab还 ...

  9. 基于eclipse的android项目实战—博学谷(十四)课程界面

    本项目是用eclipse软件编写,经过我的亲自实践,其真实有效,希望能给您有所帮助

最新文章

  1. SAP Spartacus SpartacusB2cConfigurationModule 的使用场景
  2. 使用 CNF 测试套件测试云原生最佳实践
  3. POJ2115 C Looooops(线性同余方程)
  4. 第八节:实战前必须掌握的10个指令(下)
  5. java多态 重写(override)的调用优先级
  6. Leetcode-9-回文数(简单)
  7. mysql group by聚合字段合并_mysql groupby 字段合并问题(group_concat)
  8. CCNP交换实验(5) -- 网关热备冗余
  9. Javascript Python 翻译 excel trend 函数
  10. RISC-V MCU 应用教程之RTC自动唤醒
  11. python3_实现BP神经网络 + BP神经网络应用实例
  12. 建造者模式之Java实战个人理解和图解
  13. 机械指令 对应 汇编指令
  14. c语言采用文件存储数据,C语言读写文件大全 之 基础篇
  15. Android:MTK的Dialer模块联系人搜索
  16. 车万翔:ChatGPT只是“搬运工”而不是“创造者”,但NLP学术界确实非常危急!...
  17. 【Datawhale】【机器学习】糖尿病遗传风险检测挑战赛
  18. kkilfeview预览源文件来自不受信任的站点
  19. 巴比特 | 元宇宙每日必读:微信或首次以“涉数字藏品二级交易”为由封禁一公众号,平台新规也对此提出警告...
  20. excel自动排班表_巧用常见工具:怎样将图片格式数据转换成EXCEL表格

热门文章

  1. 假如爱过的人,可以遗忘
  2. 博途位置型PID/PI控制器算法 (附SCL源代码)
  3. 论文SlimYOLOv3: Narrower, Faster and Better for Real-Time UAV Applications
  4. python Scapy 随心所欲撩tcp协议栈
  5. 【视觉基础篇】12 # 如何使用滤镜函数实现美颜效果?
  6. monodepth2 理解
  7. 从JavaScript属性描述器剖析Vue.js响应式视图
  8. 2022电大国家开放大学网上形考任务-老年用药基本知识非免费(非答案)
  9. 计算机的主要性能指标总结
  10. 独立思考Justic:How to Measure Pleasure