参考:https://www.jb51.net/article/120240.htm
要实现的效果如下所示:
大致步骤如下:
- 这整体是一个ListView,所以需要自定义一个ListView.
- 处理头部布局文件,将其以HeaderView的方式添加到自定义的ListView中
- 在overScrollBy方法内通过修改ImageView的LayoutParams的height值来显示更多的图片内容.
- 在onTouchEvent方法内处理ACTION_UP事件,使ImageView有回弹的动画效果。
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);
}
头部布局
完整的头部图片:
header的布局如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/layout_header_image"
android:layout_width="match_parent"
android:layout_height="160dp"
android:scaleType="centerCrop"
android:src="@drawable/img_header4" />
<ImageView
android:id="@+id/iv_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentBottom="true"
android:layout_marginLeft="40dp"
android:layout_marginBottom="40dp"
android:src="@drawable/head" />
</RelativeLayout>
通过src设置了一张图片,这里唯一要将的就是scaleType属性,我这边设置了centerCrop,以图片的最小的边开始截取,因为这里选择的图片是高度大于宽度的,所以裁剪的时候会保留完整的宽度,中心裁剪,如下图所示:
自定义ListView
overScrollBy方法中,当下拉ListView的时候deltaY<0,此时让头部的ImageView实现放大效果。
public class QQHeaderSrollView extends ListView {
private ImageView mImageView;
public QQHeaderSrollView(Context context) {
super(context);
}
public QQHeaderSrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public QQHeaderSrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
/**
* 设置要改变大小的图片
*/
public void setZoomImageView(ImageView iv) {
this.mImageView = iv;
}
/**
* 越界下拉的方法 就是数据到头了 依然能下拉的方法
*
* @param deltaY Y轴的增量
*/
@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) {
mImageView.getLayoutParams().height = mImageView.getHeight() - deltaY / 3;
mImageView.requestLayout();
}
return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);
}
}
添加头部到ListView中:
public class MainActivity extends AppCompatActivity {
private QQHeaderSrollView qqHeaderSrollView;
private ImageView iv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
qqHeaderSrollView = findViewById(R.id.lv);
ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1,
new String[]{
"星期一 和马云洽谈",
"星期二 约见李彦宏",
"星期三 约见乔布斯",
"星期四 和Lance钓鱼",
"星期五 和Jett洽谈",
"星期六 和Jason洽谈",
"星期日 和MZ洽谈",
"星期一 和马云洽谈",
"星期二 约见李彦宏",
"星期三 约见乔布斯",
"星期四 和Ricky钓鱼",
"星期五 和David洽谈",
"星期六 和Jason洽谈",
"星期日 和MZ洽谈",
"……"
}
);
//获取到头部的View
View header = View.inflate(this, R.layout.listview_header, null);
//获取到头部的View的图片控件
iv = header.findViewById(R.id.layout_header_image);
//将imageView传入到ListView中
qqHeaderSrollView.setZoomImageView(iv);
//将头部的View设置给ListView的HeaderView
qqHeaderSrollView.addHeaderView(header);
//设置适配器
qqHeaderSrollView.setAdapter(adapter);
}
}
效果如下:
实现了下拉,头部图片放大的效果。接下来需要实现松手图片高度回复,并实现回弹动画的效果。
回弹动画效果
@Override
public boolean onTouchEvent(MotionEvent ev) {
int action = ev.getAction();
if(action == MotionEvent.ACTION_UP){
ResetAnimation resetAnimation = new ResetAnimation(mImageViewHeight);
//设置动画的迭代器 有波动的迭代器
resetAnimation.setInterpolator(new OvershootInterpolator());
//设置间隔时间
resetAnimation.setDuration(700);
mImageView.startAnimation(resetAnimation);
}
return super.onTouchEvent(ev);
}
public class ResetAnimation extends Animation {
//ImageView增加了的高度
private int extraHeight;
//ImageView当前的高度
private int currentHeight;
public ResetAnimation(int targetHeight) {
currentHeight = mImageView.getHeight();
extraHeight = mImageView.getHeight() - targetHeight;
}
/**
*
* @param interpolatedTime 标准化的时间的值 0-1
* @param t
*/
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
//让mImageView的高度回到它原来的高度
mImageView.getLayoutParams().height = (int)(currentHeight - extraHeight*interpolatedTime);
mImageView.requestLayout();
super.applyTransformation(interpolatedTime, t);
}
}
最后效果如下:
Github:https://github.com/345166018/AndroidUI/tree/master/HxQQZone