今天要写的这个效果属于刷新类,比较实用,像很多流行的 app 都是用了这种效果,大家熟知的QQ空间、微博个人主页等,这个效果在 github 上也有别人实现好的源码,点击查看。这里也参考了上面的源码;还是那句话,看 blog主要是学习其中的原理和思路。
动态效果图
图片放大的原理是什么呢?
通过改变图片显示控件 ImageView 的父控件的高度,比如这里的头部 View 是一个 FrameLayout,FrameLayout 中再 通过 add 方法把图片 View 添加进去,addView(ImageView),ImageView有几个属性是要特别注意的,ImageView 的放缩类型为从中间截取
setScaleType(ImageView.ScaleType.CENTER_CROP);
并且宽高设为匹配父控件;所以想要图片有放大效果,只需设置 FrameLayout 的 LayoutParams 中的 height值,通过改变 height 的值从而改变 ImageView 的显示高度。讲的有点混乱,可以结合下面的代码来理解。
如果你是对手势事件处理很了解的朋友,对这个效果的实现应该没有什么难度,唯一的一点就是判断何时该放大图片,何时该滚动ListView。
这里就直接贴代码:
/**
* Created by gyzhong on 15/3/22.
*/
public class PullZoomListView extends ListView {
/*头部View 的容器*/
private FrameLayout mHeaderContainer;
/*头部View 的图片*/
private ImageView mHeaderImg;
/*屏幕的高度*/
private int mScreenHeight;
/*屏幕的宽度*/
private int mScreenWidth;
private int mHeaderHeight;
/*无效的点*/
private static final int INVALID_POINTER = -1;
/*滑动动画执行的时间*/
private static final int MIN_SETTLE_DURATION = 200; // ms
/*定义了一个时间插值器,根据ViewPage控件来定义的*/
private static final Interpolator sInterpolator = new Interpolator() {
public float getInterpolation(float t) {
t -= 1.0f;
return t * t * t * t * t + 1.0f;
}
};
/*记录上一次手指触摸的点*/
private float mLastMotionX;
private float mLastMotionY;
/*当前活动的点Id,有效的点的Id*/
protected int mActivePointerId = INVALID_POINTER;
/*开始滑动的标志距离*/
private int mTouchSlop;
/*放大的倍数*/
private float mScale;
/*上一次放大的倍数*/
private float mLastScale;
/*最大放大的倍数*/
private final float mMaxScale = 2.0f;
/*是否需要禁止ListView 的事件响应*/
private boolean isNeedCancelParent;
/*这个不解释*/
private OnScrollListener mScrollListener ;
/*下拉刷新的阈值*/
private final float REFRESH_SCALE = 1.20F;
/*下拉刷新监听*/
private OnRefreshListener mRefreshListener ;
public PullZoomListView(Context context) {
super(context);
init(context);
}
public PullZoomListView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public PullZoomListView(Context context, AttributeSet attrs, int defStyleAttr) {