Android开发使用自定义view实现ListView下拉的视差特效功能

本文实例讲述了Android开发使用自定义view实现ListView下拉的视差特效功能。分享给大家供大家参考,具体如下:

一、概述:

现在流型的APP如微信朋友圈,QQ空间,微博个人展示都有视差特效的影子。

如图:下拉图片会产生图片拉升的效果,放手后图片有弹回到原处:

那我们如何实现呢?

1)重写ListView控件:
2)重写里面的overScrollBy方法
3)在松手后执行值动画

二、具体实现:

1.创建ParallaListView 自定义ListView

public class ParallaListView extends ListView {
  private static final String TAG = "tag";
  public ParallaListView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
  }
  public ParallaListView(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
  }
  public ParallaListView(Context context) {
    this(context, null);
  }
}

2)添加到布局里:

<?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" >
  <com.android.imooc.paralla.ParallaListView
    android:id="@+id/lv_paralla"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
  </com.android.imooc.paralla.ParallaListView>
</LinearLayout>

3)生成主页,填充数据:

public class ParallaActivity extends Activity {
  private ParallaListView mListView;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_paralla);
    initViews();
  }
  private void initViews() {
    mListView = (ParallaListView) findViewById(R.id.lv_paralla);
    mListView.setAdapter(new ArrayAdapter<String>(ParallaActivity.this, android.R.layout.simple_list_item_1, Cheeses.NAMES));
  }
}

4)创建头布局:

<?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/iv_header"
    android:scaleType="centerCrop"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/parallax_img" />
</LinearLayout>

图片设成scaleType="centerCrop"模式

其它模式说明:

5)在主页里找到头布局并添加到listview里

View mHeader = LayoutInflater.from(this).inflate(R.layout.view_paralla_header, null);
mListView = (ParallaListView) findViewById(R.id.lv_paralla);
mListView.addHeaderView(mHeader);

三、功能实现:

1.现在基本能看到效果了,但我们必须要拖动图片,这就要实现这个方法overScrollBy

因为拖动是Y轴方向,所以只要打印Y轴方向的各个参数就好了

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

得到数据下拉:deltaY=-3 scrollX=0 scrollRangeY=0 maxOverScrollY=0 isTouchEvent=true

得到数据上拉:deltaY=4 scrollX=0 scrollRangeY=0 maxOverScrollY=0 isTouchEvent=true

2.如果是下拉,我们把值赋给header,但我们如何获得高度呢?

1)在主页里初始化图片,然后设置到parallaListView里

ImageView iv = (ImageView) findViewById(R.id.iv_head);
mListView.setParallaImage(iv);

2)在parallaListView创建方法setParallaImage

public void setParallaImage(ImageView iv) {
    mImageView = iv;
    //在这个方法里获得高度
    int height = iv.getHeight();
    int measureHeight = iv.getMeasuredHeight();
    int instrinsicHeight = iv.getDrawable().getIntrinsicHeight();
    Logger.i(TAG, "height="+height + " measureHeight="+measureHeight+ " instrinsicHeight="+instrinsicHeight );
}

得到结果:height=0 measureHeight=0 instrinsicHeight=732

为什么会如此:因为此时的图片还没有初始化

那我们如何得到高度呢?

记得有个方法叫做iv.getViewTreeObserver(),那我们就在这个方法的监听事件里得到高度

iv.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
  @Override
  public void onGlobalLayout() {
    //当布局填充完成后,此方法会被调用
    mListView.setParallaImage(iv);
    //移除监听
    iv.getViewTreeObserver().removeGlobalOnLayoutListener(this);
  }
});

此时得到的高度height=240 measureHeight=240 instrinsicHeight=732

3)把值赋给图片就能实现拉伸的效果了

if (isTouchEvent && deltaY < 0) {
  mHeight += Math.abs(deltaY);
  if (mHeight <= mBitmapHeight) {
    mImageView.getLayoutParams().height = mHeight;
    mImageView.requestLayout();
  }
}

3.松手后图片回弹,这个功能在onTouchEvent里实现:

@Override
public boolean onTouchEvent(MotionEvent ev) {
    switch (ev.getAction()) {
    case MotionEvent.ACTION_UP:
      final int startHeight = mImageView.getHeight();
      final int endHeight = mBitmapHeight;
      //值动画
      //valueAnim(startHeight, endHeight);
      //竖直移动动画
      ResetAnimation anim = new ResetAnimation(mImageView, startHeight, endHeight);
      anim.setInterpolator(new OvershootInterpolator());
      startAnimation(anim);
      break;
    default:
      break;
    }
    return super.onTouchEvent(ev);
}

4、动画实现:

/**
 * @描述     使用平移动画实现下拉图片后弹射回去
 * @项目名称   App_imooc
 * @包名     com.android.imooc.paralla
 * @类名     ResetAnimation
 * @author   chenlin
 * @date    2016年5月29日 下午12:27:00
 * @version   1.0
 */
public class ResetAnimation extends Animation {
  private ImageView mImageView;
  private int mStartHeight;
  private int mEndHeight;
  public ResetAnimation(ImageView imageView, int startHeight, int endHeight) {
    this.mImageView = imageView;
    this.mStartHeight = startHeight;
    this.mEndHeight = endHeight;
    setDuration(500);
  }
  @Override
  protected void applyTransformation(float interpolatedTime, Transformation t) {
    int newHeight = (int) (ValueUtil.evalute(interpolatedTime, mStartHeight, mEndHeight) + 0.5f);
    mImageView.getLayoutParams().height = newHeight;
    mImageView.requestLayout();
    super.applyTransformation(interpolatedTime, t);
  }
}

四、源码下载:

完整实例代码点击此处本站下载

更多关于Android相关内容感兴趣的读者可查看本站专题:《Android控件用法总结》、《Android开发入门与进阶教程》、《Android视图View技巧总结》、《Android编程之activity操作技巧总结》、《Android数据库操作技巧总结》及《Android资源操作技巧汇总》

希望本文所述对大家Android程序设计有所帮助。

(0)

相关推荐

  • Android自定义View之继承TextView绘制背景

    本文实例为大家分享了TextView绘制背景的方法,供大家参考,具体内容如下 效果: 实现流程: 1.初始化:对画笔进行设置 mPaintIn = new Paint(); mPaintIn.setAntiAlias(true); mPaintIn.setDither(true); mPaintIn.setStyle(Paint.Style.FILL); mPaintIn.setColor(getResources().getColor(R.color.colorPrimary)); mPain

  • 实例讲解Android中的View类以及自定义View控件的方法

    View的简单理解和实例 1.View的基本概念 在Activity显示的控件 都叫做View(View类 是所有的控件类的父类  比如 文本 按钮) 2.在Activity当中获取代表View的对象 Activity读取布局文件生成相对应的 各种View对象 TextView textView=(TextView)findViewBy(R.id.textView) 3.设置view的属性 Activity_mian.xml 这样的xml布局文件中发现了,类似@+id/和@id/到底有什么区别呢

  • Android自定义View实现折线图效果

    下面就是结果图(每种状态用一个表情图片表示): 一.主页面的布局文件如下: <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=&quo

  • Android 自定义View的使用介绍

    在项目开发中,可能系统自带的一些widget不能满足我们的需求,这时就需要自定义View. 通过查看系统中的常用widget如Button,TextView,EditText,他们都继承自View,所以我们在继承自定义View的时候也自然的需要继承View.1.首先新建一个类LView继承自View 复制代码 代码如下: public class LView extends View { private Paint paint; public LView(Context context) {  

  • Android自定义View实现竖直跑马灯效果案例解析

    首先给出跑马灯效果图 中间的色块是因为视频转成GIF造成的失真,自动忽略哈. 大家知道,横向的跑马灯android自带的TextView就可以实现,详情请百度[Android跑马灯效果].但是竖直的跑马灯效果原生Android是不支持的.网上也有很多网友实现了自定义的效果,但是我一贯是不喜欢看别人的代码,所以这篇博客的思路完全是我自己的想法哈. 首先,我们需要给自定义的控件梳理一下格局,如下图所示: 1.首先我们将控件分为三个区块,上面绿色部分为消失不可见的块,中间黑色部分为可见区域,下面红色部

  • Android自定义view制作绚丽的验证码

    废话不多说了,先给大家展示下自定义view效果图,如果大家觉得还不错的话,请继续往下阅读. 怎么样,这种验证码是不是很常见呢,下面我们就自己动手实现这种效果,自己动手,丰衣足食,哈哈~ 一. 自定义view的步骤 自定义view一直被认为android进阶通向高手的必经之路,其实自定义view好简单,自定义view真正难的是如何绘制出高难度的图形,这需要有好的数学功底(后悔没有好好学数学了~),因为绘制图形经常要计算坐标点及类似的几何变换等等.自定义view通常只需要以下几个步骤: 写一个类继承

  • Android自定义View实现带数字的进度条实例代码

    第一步.效果展示 图1.蓝色的进度条 图2.红色的进度条 图3.多条颜色不同的进度条 图4.多条颜色不同的进度条 第二步.自定义ProgressBar实现带数字的进度条 0.项目结构 如上图所示:library项目为自定义的带数字的进度条NumberProgressBar的具体实现,demo项目为示例项目以工程依赖的方式引用library项目,然后使用自定义的带数字的进度条NumberProgressBar来做展示 如上图所示:自定义的带数字的进度条的library项目的结构图 如上图所示:de

  • Android自定义view实现阻尼效果的加载动画

    效果: 需要知识: 1. 二次贝塞尔曲线 2. 动画知识 3. 基础自定义view知识 先来解释下什么叫阻尼运动 阻尼振动是指,由于振动系统受到摩擦和介质阻力或其他能耗而使振幅随时间逐渐衰减的振动,又称减幅振动.衰减振动.[1] 不论是弹簧振子还是单摆由于外界的摩擦和介质阻力总是存在,在振动过程中要不断克服外界阻力做功,消耗能量,振幅就会逐渐减小,经过一段时间,振动就会完全停下来.这种振幅随时间减小的振动称为阻尼振动.因为振幅与振动的能量有关,阻尼振动也就是能量不断减少的振动.阻尼振动是非简谐运

  • Android自定义View实现广告信息上下滚动效果

    先看看效果: 实现代码: public class ScrollBanner extends LinearLayout { private TextView mBannerTV1; private TextView mBannerTV2; private Handler handler; private boolean isShow; private int startY1, endY1, startY2, endY2; private Runnable runnable; private Li

  • Android实现上拉加载更多以及下拉刷新功能(ListView)

    首先为大家介绍Andorid5.0原生下拉刷新简单实现. 先上效果图: 相对于上一个19.1.0版本中的横条效果好看了很多.使用起来也很简单. <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/container" and

  • android开发教程之实现listview下拉刷新和上拉刷新效果

    复制代码 代码如下: public class PullToLoadListView extends ListView implements OnScrollListener { private static final String TAG = PullToLoadListView.class.getSimpleName(); private static final int STATE_NON = 0; private static final int STATE_PULL_TO_REFRE

随机推荐