看着QQ控件的这种效果挺炫的于是就照着教程模仿着写了一个,完成之后整理一下思路,觉着还是比较简单的,实现核心就是根据手指滑动距顶部距离来改变头部ImageView控件的高度。
下面贴出代码:
ListView的头布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/imageview"
android:layout_width="match_parent"
android:layout_height="240dp"
android:scaleType="centerCrop"
android:src="@mipmap/image"
/>
</LinearLayout>
这里的注意点就是图片设置给Src,这样修改ImageView的高度才能看出效果。
activity_main.xml:
<?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.example.studyparallax.MainActivity">
<com.example.studyparallax.com.customUi.ParallaxListView
android:id="@+id/parallaxListView"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</RelativeLayout>
重写的ListView增加了Parallax的功能:
package com.example.studyparallax.com.customUi;
import android.animation.ValueAnimator;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ViewTreeObserver;
import android.view.animation.OvershootInterpolator;
import android.widget.ImageView;
import android.widget.ListView;
/**
* Created by 春水碧于天 on 2017/1/6.
*/
public class ParallaxListView extends ListView {
private int maxHeight; //图片的高度
private int orignalHeight; //ImageView的最初的高度
public ParallaxListView(Context context) {
super(context);
}
public ParallaxListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ParallaxListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public ParallaxListView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
private ImageView imageView;
public void setParallaxImage(final ImageView Imageview){
this.imageView = Imageview;
imageView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
imageView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
orignalHeight = imageView.getHeight(); //获取imageview的最初高度
int drawableHeight = imageView.getDrawable().getIntrinsicHeight();
//如果ImageView的高度比图片的高度大的情况下就设置图片的最大高度为imageview的二倍
maxHeight = orignalHeight >drawableHeight? orignalHeight *2:drawableHeight;
//获取图片的高度,而不是ImageView的高度
maxHeight = Imageview.getDrawable().getIntrinsicHeight();
}
});
}
/**
* 在listView滑动到头的时候,可以获取到继续滑动的距离和方向
* @param deltaY 继续滑动的x方向的距离
* @param scrollY
* @param scrollRangeX
* @param scrollRangeY
* @param maxOverScrollX x方向最大可以滚动的距离
* @param maxOverScrollY y方向最大可以滚动的距离
* @param isTouchEvent true:是手指滑动 false:惯性滑动
* @return
*/
//所有可以滚动的View都有这个方法
@Override
protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {
if(deltaY<0 && isTouchEvent){
Log.i("Tag","deltaY:"+deltaY);
if(imageView!=null){
int newHeight = imageView.getHeight()-deltaY/3;
Log.i("tag","newHeight====>:"+newHeight);
if(newHeight>maxHeight) newHeight =maxHeight;
imageView.getLayoutParams().height = newHeight;
imageView.requestLayout(); //使设置的高度生效
}
}
return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
if(ev.getAction() == MotionEvent.ACTION_UP){
//手指抬起时
//手指抬起将图片从当前高度变换成初始时的高度
final ValueAnimator animator = ValueAnimator.ofInt(imageView.getHeight(),orignalHeight);
//添加一个值的动画监听
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//获取动画的值设置给ImageView
int animatedValue = (int)animator.getAnimatedValue();
imageView.getLayoutParams().height = animatedValue;
imageView.requestLayout();
}
});
animator.setInterpolator(new OvershootInterpolator()); //设置一个弹性插值器
animator.setDuration(350);
animator.start();
}
return super.onTouchEvent(ev);
}
}
MainActivity:
package com.example.studyparallax;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import com.example.studyparallax.com.customUi.ParallaxListView;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
private ParallaxListView parallaxListView;
private ImageView imageView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
parallaxListView = (ParallaxListView) findViewById(R.id.parallaxListView);
ArrayList<String> Arrays = new ArrayList<String>();
for(int i=0;i<=20;i++){
Arrays.add(i+"");
}
View HeaderView = View.inflate(MainActivity.this,R.layout.listview_headre,null);
imageView = (ImageView)HeaderView.findViewById(R.id.imageview);
//取出顶部滑动的蓝色阴影
parallaxListView.setOverScrollMode(ListView.OVER_SCROLL_NEVER);
//将图片设置给ParallaxListView,需要操作头布局设置进去的ImageView的一些参数
parallaxListView.setParallaxImage(imageView);
//给ListView添加一个头布局
parallaxListView.addHeaderView(HeaderView);
parallaxListView.setAdapter(new ArrayAdapter<String>(this,R.layout.support_simple_spinner_dropdown_item,Arrays));
}
}
实现效果:
这里的动画的实现使用的是ValueAnimator,初涉,对它的Api理解的还不够深入,后面要深入的研究一下,对安卓的动画还是挺感兴趣的!(^_^)