实现需求效果图:
其实这样的效果实现起来很简单,但是从来没做过的我们,看到这样的需求,一脸闷逼。
我们常规的办法是直接百度,去github,掘金,简书,看有没有类似的demo,当你找到类似这样的demo,当你看到代码时你忽然明白了一件事,好简单!!! 其实有些效果实现起来不难,只是你不愿意去想,去做。接下来,我们就实现上述效果图:
分析:
1.我们肯定需要ListView /RecyclerView去展示数据。
2.头部显示的图片。
3.拉伸,缩放Animation。
思考:
1.列表如何展示数据这个大家都会。
2.列表如何添加头部。
3.列表向下滚动头部图片随着放大,手指松开图片收起到原始的图片高度 这个如何实现呢???
实现
有了想法 我们接下来就去实现。
1.自定义ListView 初始化数 : ImitateQQHeaderSrollView
public class ImitateQQHeaderSrollView extends ListView {
private static final String TAG = "---------------->";
private ImageView mImageView;
/**
* 初始高度
*/
private int mImageViewHeight;
/**
* 获取头部imagview控件
* @param iv
*/
public void setZoomImageView(ImageView iv) {
mImageView = iv;
}
public ImitateQQHeaderSrollView(Context context) {
super(context);
}
public ImitateQQHeaderSrollView(Context context, AttributeSet attrs) {
super(context, attrs);
this.mImageViewHeight=context.getResources().getDimensionPixelSize(R.dimen.size_default_height);
}
public ImitateQQHeaderSrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
2. 向下滚动头部图片放大
@Override
protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {
Log.i(TAG, "overScrollBy: "+deltaY);
if (deltaY < 0) {
// int heig = mImageView.getHeight();
mImageView.getLayoutParams().height = mImageView.getHeight() - deltaY;
mImageView.requestLayout();
}else {
// 上拉
mImageView.getLayoutParams().height = mImageView.getHeight() - deltaY;
mImageView.requestLayout();
}
return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);
}
3.头部收缩
列表滚动松开手指向上弹起收缩,我们需要重写onTouchEvent方法做处理。
@Override
public boolean onTouchEvent(MotionEvent ev) {
int action = ev.getAction();
if(action==MotionEvent.ACTION_UP){
//添加动画向上收缩处理..............
resetAnimation.setInterpolator(new OvershootInterpolator());
resetAnimation.setDuration(600);
mImageView.startAnimation(。。。。。。。。。。。。。。。。);
}
return super.onTouchEvent(ev);
}
4.动画处理
public class ResetAnimation extends Animation {
private int extraHeight;
private int currentHeight;
public ResetAnimation(int targetHeight) {
currentHeight = mImageView.getHeight();
extraHeight = mImageView.getHeight() - targetHeight;
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
mImageView.getLayoutParams().height = (int) (currentHeight - extraHeight * interpolatedTime);
mImageView.requestLayout();
super.applyTransformation(interpolatedTime, t);
}
}
5.activity调用处理
//
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imitateQQHeaderSrollView = findViewById(R.id.lv);
for (int i = 0; i < 30; i++) {
listData.add("data" + i);
}
ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1,
listData
);
View header = View.inflate(this, R.layout.listview_header, null);
iv = (ImageView) header.findViewById(R.id.layout_header_image);
imitateQQHeaderSrollView.setZoomImageView(iv);
imitateQQHeaderSrollView.addHeaderView(header);
imitateQQHeaderSrollView.setAdapter(adapter);
}
interpolator介绍
- OvershootInterpolator:表示向前甩一定值后再回到原来位置。
- AnticipateOvershootInterpolator:表示开始的时候向后然后向前甩一定值后返回最后的值。
- AnticipateInterpolator:表示开始的时候向后然后向前甩。
- BounceInterpolator:表示动画结束的时候弹起。
- OvershootInterpolator:表示向前甩一定值后再回到原来位置。
- CycleInterpolator:表示动画循环播放特定的次数,速率改变沿着正弦曲线。
- DecelerateInterpolator:表示在动画开始的地方快然后慢。
- LinearInterpolator:表示以常量速率改变。
完!!!
代码:https://github.com/yangxiansheng123/QQHeader
Android Animation推荐文章
1.https://www.jianshu.com/p/fcd9c7e9937e
2.http://cogitolearning.co.uk/2013/10/android-animations-tutorial-5-more-on-interpolators/
3.https://www.cnblogs.com/kross/p/4087780.html