Listview下拉头部View放大效果

This commit is contained in:
zengfantian 2015-04-16 00:33:41 +08:00
parent adb7b5e09d
commit 0599b7a223
1 changed files with 227 additions and 0 deletions

View File

@ -0,0 +1,227 @@
package com.zftlive.android.view;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.PointF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.NinePatchDrawable;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.RelativeLayout;
/**
* Listview下拉放大效果 ,初始化时需调用方法setHeadView
* @author 曾繁添
* @version 1.0
*
*/
public class PullZoomListView extends ListView {
private final static int BACK_SCALE = 0;
private float scaleY = 0;
private boolean isBacking = false;// 是否处在回弹状态
/** 用于记录拖拉图片移动的坐标位置 */
private Matrix matrix = new Matrix();
/** 用于记录图片要进行拖拉时候的坐标位置 */
private Matrix currentMatrix = new Matrix();
private Matrix defaultMatrix = new Matrix();
/** 图片宽高 **/
private float imgHeight, imgWidth;
/** 记录是拖拉照片模式还是放大缩小照片模式 0:拖拉模式1放大 */
private int MODE_NORMAL = 0;
/** 拖拉照片模式 */
private final int MODE_DRAG = 1;
/** 用于记录开始时候的坐标位置 */
private PointF startPoint = new PointF();
private ImageView mHeadImage;
private Bitmap mHeadImageBmp;
public PullZoomListView(Context context) {
this(context, null);
}
public PullZoomListView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public PullZoomListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
/**
* 设置头部View并指定缩放目标Imageview
* @param mHeadView Listview头部view
* @param zoomImageView 需要缩放的Imageview
*/
public void setHeadView(View mHeadView,ImageView zoomImageView){
super.addHeaderView(mHeadView);
//头部背景图片
this.mHeadImage = zoomImageView;
mHeadImageBmp = drawableToBitmap(mHeadImage.getDrawable());
float scale = (float) getScreenWidth() / (float) mHeadImageBmp.getWidth();
matrix.postScale(scale, scale, 0, 0);
mHeadImage.setImageMatrix(matrix);
defaultMatrix.set(matrix);
imgHeight = scale * mHeadImageBmp.getHeight();
imgWidth = scale * mHeadImageBmp.getWidth();
RelativeLayout.LayoutParams relativeLayout = new RelativeLayout.LayoutParams((int) imgWidth, (int) imgHeight);
mHeadImage.setLayoutParams(relativeLayout);
}
/**
* Drawable转成Bitmap
* @param drawable
* @return
*/
public Bitmap drawableToBitmap(Drawable drawable) {
if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
} else if (drawable instanceof NinePatchDrawable) {
Bitmap bitmap = Bitmap
.createBitmap(
drawable.getIntrinsicWidth(),
drawable.getIntrinsicHeight(),
drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
: Bitmap.Config.RGB_565);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(),
drawable.getIntrinsicHeight());
drawable.draw(canvas);
return bitmap;
} else {
return null;
}
}
/**
* 获取屏幕宽度
*
* @return
*/
private int getScreenWidth() {
DisplayMetrics displayMetrics = getContext().getResources()
.getDisplayMetrics();
return displayMetrics.widthPixels;
}
/**
* 慢慢回弹初始状态
*/
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case BACK_SCALE:
float scale = (scaleY / 2 + imgHeight) / (imgHeight);
if (scaleY > 0) {
isBacking = true;
matrix.set(currentMatrix);
RelativeLayout.LayoutParams relativeLayout = new RelativeLayout.LayoutParams(
(int) (scale * imgWidth), (int) (scale * imgHeight));
mHeadImage.setLayoutParams(relativeLayout);
matrix.postScale(scale, scale, imgWidth / 2, 0);
mHeadImage.setImageMatrix(matrix);
scaleY = (float) (scaleY / 2 - 1);
mHandler.sendEmptyMessageDelayed(BACK_SCALE, 20);
} else {
scaleY = 0;
RelativeLayout.LayoutParams relativeLayout = new RelativeLayout.LayoutParams(
(int) imgWidth, (int) imgHeight);
mHeadImage.setLayoutParams(relativeLayout);
matrix.set(defaultMatrix);
mHeadImage.setImageMatrix(matrix);
isBacking = false;
}
break;
default:
break;
}
super.handleMessage(msg);
}
};
/**
* 向下滑动让图片变大
*
* @param event
* @return
*/
@SuppressLint("ClickableViewAccessibility")
public boolean onTouchEvent(MotionEvent event) {
// 无Header
if (getHeaderViewsCount() == 0) {
return super.onTouchEvent(event);
}
/**
* 使用switch (event.getAction())可以处理ACTION_DOWN和ACTION_UP事件
* 使用switch (event.getAction() & MotionEvent.ACTION_MASK)就可以处理处理多点触摸的ACTION_POINTER_DOWN和ACTION_POINTER_UP事件
*/
switch (event.getAction() & MotionEvent.ACTION_MASK) {
// 手指压下屏幕
case MotionEvent.ACTION_DOWN:
if (isBacking) {
return super.onTouchEvent(event);
}
int[] location = new int[2];
mHeadImage.getLocationInWindow(location);
if (location[1] >= 0) {
MODE_NORMAL = MODE_DRAG;
// 记录ImageView当前的移动位置
currentMatrix.set(mHeadImage.getImageMatrix());
startPoint.set(event.getX(), event.getY());
}
break;
// 手指在屏幕上移动改事件会被不断触发
case MotionEvent.ACTION_MOVE:
// 拖拉图片
if (MODE_NORMAL == MODE_DRAG) {
float dy = event.getY() - startPoint.y; // 得到y轴的移动距离
// 在没有移动之前的位置上进行移动
if (dy / 2 + imgHeight <= 1.5 * imgHeight) {
matrix.set(currentMatrix);
float scale = (dy / 2 + imgHeight) / (imgHeight);// 得到缩放倍数
if (dy > 0) {
scaleY = dy;
RelativeLayout.LayoutParams relativeLayout = new RelativeLayout.LayoutParams(
(int) (scale * imgWidth),
(int) (scale * imgHeight));
mHeadImage.setLayoutParams(relativeLayout);
matrix.postScale(scale, scale, imgWidth / 2, 0);
mHeadImage.setImageMatrix(matrix);
}
}
}
break;
// 手指离开屏幕
case MotionEvent.ACTION_UP:
// 当触点离开屏幕图片还原
mHandler.sendEmptyMessage(BACK_SCALE);
//一个非主要的手指抬起
case MotionEvent.ACTION_POINTER_UP:
MODE_NORMAL = 0;
break;
}
return super.onTouchEvent(event);
}
}