參考: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