以前的项目下拉刷新用的都是XListView,用久了之后就有些审美疲劳了。谷歌推出的SwipeRefreshLayout很好用,样式也蛮好看的,用起来也比较方便。但是强迫症表示,还是希望能有下拉弹出和弹回去的效果,就尝试下SwipeRefreshLayout增加下拉弹出效果。
效果图:

大致思路:获取SwipeRefreshLayout子控件的位置,在SwipeRefreshLayout的dispatchTouchEvent方法里处理滑动监听事件,计算滑动的距离,移动子控件的位置,达到弹出的效果。
直接上代码:
package com.example.zet.uncaughtexception;
import android.content.Context;
import android.graphics.Rect;
import android.support.v4.widget.SwipeRefreshLayout;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.TranslateAnimation;
/**
* Created by 仓颉 on 2015/11/16.
*/
public class MySwiperefreshlayout extends SwipeRefreshLayout {
private static final String TAG = "MySwiperefreshlayout ";
private static final float MOVE_MODE = 0.5f;
private static final int ANIM_TIME = 300;
private View view;
private View child;
private float startY;
private Rect rect = new Rect();
private boolean isMoved = false;
private boolean isTop = false;
public static int time;
public static int getTime() {
return time;
}
public static void setTime(int time) {
MySwiperefreshlayout.time = time;
}
public MySwiperefreshlayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
if (getChildCount() > 0) {
child = getChildAt(0);
view = getChildAt(getChildCount() - 1);
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
if (view == null) return;
rect.set(view.getLeft(), view.getTop(), view
.getRight(), view.getBottom());
}
/**
* 滑动监听,处理下拉事件
*/
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (view == null) {
return super.dispatchTouchEvent(ev);
}
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
canDropDown();
startY = ev.getY();
break;
case MotionEvent.ACTION_UP:
if (!isMoved) break;
int distance = (int) ((int) (ev.getY() - startY) * MOVE_MODE);
if (distance > child.getTop()) {
distance = child.getTop() + 30;
}
view.layout(rect.left, rect.top + distance,
rect.right, rect.bottom + distance);
TranslateAnimation anim = new TranslateAnimation(0, 0, view.getTop(),
rect.top);
anim.setDuration(ANIM_TIME);
if (time > 0) {
if (distance > 92) {
anim.setStartOffset(time);
}
}
view.startAnimation(anim);
view.layout(rect.left, rect.top,
rect.right, rect.bottom);
isTop = false;
isMoved = false;
startY = 0;
break;
case MotionEvent.ACTION_MOVE:
if (!canDropDown()) {
break;
}
int distanceMove = (int) (ev.getY() - startY);
if (isTop && distanceMove > 0) {
int offset = (int) (distanceMove * MOVE_MODE);
view.layout(rect.left, rect.top + offset,
rect.right, rect.bottom + offset);
isMoved = true;
}
break;
default:
break;
}
return super.dispatchTouchEvent(ev);
}
/**
* 判断是否滚动到顶部
*/
private boolean canDropDown() {
if (child.getVisibility() == View.VISIBLE)
isTop = true;
else
isTop = false;
return isTop;
}
}

