视差特效 
* 应用场景: 微信朋友圈, QQ空间, 微博个人展示,向下拉出,松开回弹
* 功能实现:
> 1. 重写overScrollBy

> 2. 松手之后执行动画, 类型估值器

activity_main
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >
    <com.itheima.parallaxdemo.ui.MyListView
    android:id="@+id/lv"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
    </RelativeLayout>
view_header
  1. <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/iv"
    android:layout_width="match_parent"
    android:layout_height="160dp"
    android:scaleType="centerCrop"
    android:src="@drawable/parallax_img" />
    </LinearLayout>
MyListView
  1. /**
    * 视差特效ListView
    * overScrollBy
    * @author poplar
    *
    */
    public class MyListView extends ListView {
    private static final String TAG = "TAG";
    private int mOriginalHeight;
    private int drawableHeight;
    private ImageView mImage;
    public MyListView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    }
    public MyListView(Context context, AttributeSet attrs) {
    super(context, attrs);
    }
    public MyListView(Context context) {
    super(context);
    } /**
    * 设置ImageView图片, 拿到引用
    * @param mImage
    */
    public void setParallaxImage(ImageView mImage) {
    this.mImage = mImage;
    mOriginalHeight = mImage.getHeight(); // 160
    drawableHeight = mImage.getDrawable().getIntrinsicHeight(); // 488,图片的高,而不是显示的高 Log.d(TAG, "height: " + mOriginalHeight + " drawableHeight: " + drawableHeight);
    } @Override
    protected boolean overScrollBy(int deltaX, int deltaY,
    int scrollX, int scrollY, int scrollRangeX, int scrollRangeY,
    int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {
    // deltaY : 竖直方向的瞬时偏移量 / 变化量 dx 顶部到头下拉为-, 底部到头上拉为+
    // scrollY : 竖直方向的偏移量 / 变化量
    // scrollRangeY : 竖直方向滑动的范围
    // maxOverScrollY : 竖直方向最大滑动范围
    // isTouchEvent : 是否是手指触摸滑动, true为手指, false为惯性 Log.d(TAG, "deltaY: " +deltaY + " scrollY: " + scrollY + " scrollRangeY: " + scrollRangeY
    + " maxOverScrollY: " + maxOverScrollY + " isTouchEvent: " + isTouchEvent); // 手指拉动 并且 是下拉
    if(isTouchEvent && deltaY < 0){
    // 把拉动的瞬时变化量的绝对值交给Header, 就可以实现放大效果
    if(mImage.getHeight() <= drawableHeight){
    int newHeight = (int) (mImage.getHeight() + Math.abs(deltaY / 3.0f)); // 高度不超出图片最大高度时,才让其生效
    mImage.getLayoutParams().height = newHeight;
    mImage.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:
    // 执行回弹动画, 方式一: 属性动画\值动画
    // 从当前高度mImage.getHeight(), 执行动画到原始高度mOriginalHeight
    final int startHeight = mImage.getHeight();
    final int endHeight = mOriginalHeight; // valueAnimator(startHeight, endHeight);
    // 执行回弹动画, 方式二: 自定义Animation
    ResetAnimation animation = new ResetAnimation(mImage, startHeight, endHeight);
    startAnimation(animation); break;
    }
    return super.onTouchEvent(ev);
    }
    private void valueAnimator(final int startHeight, final int endHeight) {
    ValueAnimator mValueAnim = ValueAnimator.ofInt(1);//不起作用,写几都行
    mValueAnim.addUpdateListener(new AnimatorUpdateListener() { @Override
    public void onAnimationUpdate(ValueAnimator mAnim) {
    float fraction = mAnim.getAnimatedFraction();
    // percent 0.0 -> 1.0
    Log.d(TAG, "fraction: " +fraction);
    Integer newHeight = evaluate(fraction, startHeight, endHeight);//固值器
    mImage.getLayoutParams().height = newHeight;//设置imageview高度
    mImage.requestLayout();
    }
    }); mValueAnim.setInterpolator(new OvershootInterpolator());
    mValueAnim.setDuration(500);
    mValueAnim.start();
    } public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
    int startInt = startValue;
    return (int)(startInt + fraction * (endValue - startInt));
    } }
ResetAnimation
  1. public class ResetAnimation extends Animation {
    private final ImageView mImage;
    private final int startHeight;
    private final int endHeight;
    public ResetAnimation(ImageView mImage, int startHeight, int endHeight) {
    this.mImage = mImage;
    this.startHeight = startHeight;
    this.endHeight = endHeight; setInterpolator(new OvershootInterpolator());
    //设置动画执行时长
    setDuration(500);
    }
    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
    // interpolatedTime 0.0f -> 1.0f Integer newHeight = evaluate(interpolatedTime, startHeight, endHeight);
    mImage.getLayoutParams().height = newHeight;//设置imageview高
    mImage.requestLayout(); super.applyTransformation(interpolatedTime, t);
    } /**
    * 类型估值器
    * @param fraction
    * @param startValue
    * @param endValue
    * @return
    */
    public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
    int startInt = startValue;
    return (int)(startInt + fraction * (endValue - startInt));
    } }
  2.   MainActivity

  3. public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main); final MyListView mListView = (MyListView) findViewById(R.id.lv);
    mListView.setOverScrollMode(View.OVER_SCROLL_NEVER);
    // 加Header
    final View mHeaderView = View.inflate(MainActivity.this, R.layout.view_header, null);
    final ImageView mImage = (ImageView) mHeaderView.findViewById(R.id.iv);
    mListView.addHeaderView(mHeaderView); mHeaderView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() { @Override
    public void onGlobalLayout() {
    // 当布局填充结束之后, 此方法会被调用
    mListView.setParallaxImage(mImage); mHeaderView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
    }
    }); // 填充数据
    mListView.setAdapter(new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, Cheeses.NAMES)); }
    }

9.视差特效、回弹动画、overScrollBy的更多相关文章

  1. QQ视差特效和ListView侧滑删除

    如图所示是效果图,当向下拉时,图片会被拉出来,松手后恢复.和ListView的侧滑删除   1.视差特效 首先图片是通过addHeaderView加上去的,所以在设置Adapter前先设置一个View ...

  2. WPF特效-粒子动画

    原文:WPF特效-粒子动画 WPF实现泡泡龙小游戏效果.     /// -Ball to Ball Collision - Detection and Handling    /// http:// ...

  3. iOS Swift 实现图片点击缩放回弹动画

    效果就是下面这个样子: 思路借鉴的是MZTimerLabel,有想过做一个自定义的ImageView,但那样的话之前view用必须要改代码,索性就按照MZTimerLabel这个方式实现,简单易用,从 ...

  4. 测开之路一百零一:jquery文字特效、动画、方法链

    文字特效 html内容 1.卷起/展开 2.隐藏/显示 3.淡入淡出 <!DOCTYPE html><html lang="en"><head> ...

  5. 利用tween,使用原生js实现模块回弹动画效果

    最近有一个需求,就是当屏幕往下一定像素时,下方会有一个隐藏的模块马上显现出来,向上运动后带有回弹效果.然后屏幕滚回去时这个模块能够原路返回 其实这个效果css3就可以很轻松实现,但是公司要求最低兼容i ...

  6. 第五篇 jQuery特效与动画

    5.1 show()与hide()方法 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" &quo ...

  7. [一位菜鸟的COCOS-2D编程之路]COCOS2D中得动作,特效和动画

    一,CCActionManager 管理所有节点动作的对象 来看看打飞机里面的一个onEnter 方法 - (void)onEnter { [super onEnter]; //一定要注意添加此方法, ...

  8. css3实现的4种动画特效按钮

    今天要给大家介绍的是css3按钮,里面包含四种特效的动画,如下图: 在线预览    下载源码 实现html代码: <div align="center" class=&quo ...

  9. python 制作影视动画、电影特效工具

    一直觉得电影特效,动画制作这些都很什么,在google上搜索了下python开发电影特效的内容,发现了几个不错的软件,都支持python脚本开发. Houdini  Houdini (电影特效魔术师) ...

随机推荐

  1. Win7远程桌面:发生身份验证错误

    下载并安装KB4103718补丁,安装完成后重启计算机 http://www.catalog.update.microsoft.com/Search.aspx?q=KB4103718 根据操作系统选择 ...

  2. CentOS查询端口占用和清除端口占用的程序

    1.查询端口号占用,根据端口查看进程信息 [root@server2 ~]# lsof -i: COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME httpd ...

  3. eclipse Filter web.xml 问题解决 异步请求@WebServlet

    <filter> <filter-name>AsynServlete</filter-name> <filter-class>com.kad.app.a ...

  4. Linux-01初级学习

    刚刚接触 Linux学习中的一点笔记`02 ps:自己学习过程中的记录,略菜,给没学过的纯小白 配置网络 1.虚拟网卡 2.虚拟机服务  我的电脑-->管理-->服务 3.修改网络配置文件 ...

  5. centos中病毒

    嗯 很开中了病毒,,,而且这是第二次了.... 然后大佬说让我  crontab -l  一下 然后试了下 然后出来这个东东 执行下  crontab -r  这个  然后就crontab -l  就 ...

  6. Visual Studio Code 如何将新项目发布到GIT服务器

    1.在VSCode中新建或打开未添加源码管理的文件夹 2.按Ctrl+Shift+G切换到"源控件"视图,点击右上方的[初始化储存库]按钮 3.输入消息内容,然后点击右上方的[提交 ...

  7. 单点登录的三种实现方式 转自: https://blog.csdn.net/python_tty/article/details/53113612

    单点登录SSO(Single Sign On)说得简单点就是在一个多系统共存的环境下,用户在一处登录后,就不用在其他系统中登录,也就是用户的一次登录能得到其他所有系统的信任.单点登录在大型网站里使用得 ...

  8. MVC Razor视图下ViewData传递html内容被转义

    页面输出: html源码: <div style="width: 90%; height: auto;"> <p>付凯航 阿豆 ADOU</p> ...

  9. Tomcat 500error: Could not initialize class

    Web 项目报错Could not initialize class ,出现500,说明服务器是起来了,可能是这个类的驱动有问题,缺少初始化需要的文件 查到有相关情况: 考虑是jar 包的问题,检查了 ...

  10. 字典 Dictionary

    字典 Dictionary {Key-Value} 1.字典是无序的,没有下标(因为有key,取值直接用key值) Key尽量不要用中文编写,以防止编码不同导致取不出来 2.字典常用方法: 查找: ① ...