上代码,下边是核心代码
public class ImitateQQListView extends ListView {
public View mHeaderView;
private int mHeaderHeight;
public View mHeaderTitleView;
public float mMaxScrollY;
public ImitateQQListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@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) {
//表示下拉,需要改变高度
if (mHeaderView != null) {
mHeaderView.getLayoutParams().height = mHeaderView.getHeight() - deltaY;
mHeaderView.requestLayout();
}
}
return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
if (t < 0) {
mHeaderView.getLayoutParams().height = mHeaderHeight;
mHeaderView.requestLayout();
}
//获取到listview滚动的y轴距离
if (mHeaderView != null) {
calculationAlpha(mHeaderView.getTop());
}
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_UP:
//判断头部的高度是否与初始化时候的高度一致,如果不一致则需要执行动画缓慢撤回到原来状态
if (mHeaderHeight != mHeaderView.getHeight()) {
//执行动画缓慢回到原来位置
resetHeadViewHeight();
}
break;
}
return super.onTouchEvent(ev);
}
/***
* 执行动画缓慢回到原来状态
* 计算思路:总共多出(mHeaderView.getHeight() - mHeaderHeight)
*/
private void resetHeadViewHeight() {
ValueAnimator mValueAnimator = ValueAnimator.ofFloat(1.0f);
mValueAnimator.setDuration(600);
mValueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (float) animation.getAnimatedValue();
//计算高度
mHeaderView.getLayoutParams().height = (int) (mHeaderView.getHeight() - value * (mHeaderView.getHeight() - mHeaderHeight));
mHeaderView.requestLayout();
}
});
mValueAnimator.start();
}
/****
* 根据滚动距离计算alpha值
*
* @param top
*/
private void calculationAlpha(int top) {
mHeaderTitleView.setAlpha(Math.abs(1.0f / mMaxScrollY * top));
}
@Override
public void addHeaderView(View v, Object data, boolean isSelectable) {
super.addHeaderView(v, data, isSelectable);
if (mHeaderView == null) {
mHeaderView = v;
mHeaderHeight = v.getMeasuredHeight();
mMaxScrollY = mHeaderHeight - DensityUtil.dip2px(getContext(), 50);
}
}
}
然后是mainActivity中的代码
public class QQMainActivity extends Activity {
private Context mContext;
private ImitateQQListView listview;
private List<String> mList;
private FrameLayout id_fl_title;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_qq);
listview = (ImitateQQListView) findViewById(R.id.listview);
id_fl_title = (FrameLayout) findViewById(R.id.id_fl_title);
listview.mHeaderTitleView = id_fl_title;
mContext = getApplicationContext();
mList = new ArrayList<>();
for (int i = 0; i < 20; i++) {
mList.add("哈哈哈,条目" + i);
}
//添加头部布局
LayoutInflater inflater = LayoutInflater.from(this);
View view = inflater.inflate(R.layout.layout_listview_head_imageview, null);
//测量view的高度
measureHeadViewHeight(view);
listview.addHeaderView(view, null, false);
listview.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mList));
}
/***
* 测量view的高度
*
* @param view
*/
private void measureHeadViewHeight(View view) {
AbsListView.LayoutParams params = (AbsListView.LayoutParams) view.getLayoutParams();
if (params == null) {
params = new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, AbsListView.LayoutParams.WRAP_CONTENT);
}
int width = params.width;
int widthSpec = 0;
if (width <= 0) {
widthSpec = View.MeasureSpec.makeMeasureSpec(DevicesUtils.getScreenWidth(mContext), View.MeasureSpec.EXACTLY);
}
//获取高度
int height = params.height;
int heightMeasureSpec = 0;
if (height <= 0) {
heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(DensityUtil.dip2px(mContext, 220), View.MeasureSpec.EXACTLY);
}
view.measure(widthSpec, heightMeasureSpec);
height = view.getMeasuredHeight();
params.height = height;
view.setLayoutParams(params);
}
}
布局也贴上
<?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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".qq.QQMainActivity">
<com.wxj.customview.qq.ImitateQQListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<FrameLayout
android:id="@+id/id_fl_title"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_alignParentTop="true"
android:alpha="0"
android:background="@android:color/holo_red_dark">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="title"
android:textColor="@android:color/white"
android:textSize="20dp" />
</FrameLayout>
</RelativeLayout>
头部布局
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="220dp"
android:src="@drawable/img2"
android:scaleType="centerCrop"
>
</ImageView>
全部代码都在上边,资源文件可以自己替换.
另外附上写的很好的一篇博客
http://blog.csdn.net/llew2011/article/details/51559694