package com.smartandroid.sa.view;
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.TranslateAnimation;
import android.widget.ScrollView;
public class ReScrollView extends ScrollView {
private static final String TAG = "ElasticScrollView";
// �ƶ�����, ��һ���ٷֱ�, ������ָ�ƶ���100px, ��ôView��ֻ�ƶ�50px
// Ŀ���Ǵﵽһ���ӳٵ�Ч��
private static final float MOVE_FACTOR = 0.5f;
// �ɿ���ָ��, ����ص�����λ����Ҫ�Ķ���ʱ��
private static final int ANIM_TIME = 300;
// ScrollView����View�� Ҳ��ScrollView��Ψһһ����View
private View contentView;
// ��ָ����ʱ��Yֵ, �������ƶ�ʱ�����ƶ�����
// �������ʱ���������������� ������ָ�ƶ�ʱ����Ϊ��ǰ��ָ��Yֵ
private float startY;
// ���ڼ�¼�����IJ���λ��
private Rect originalRect = new Rect();
// ��ָ����ʱ��¼�Ƿ���Լ�������
private boolean canPullDown = false;
// ��ָ����ʱ��¼�Ƿ���Լ�������
private boolean canPullUp = false;
// ����ָ�����Ĺ����м�¼�Ƿ��ƶ��˲���
private boolean isMoved = false;
public ReScrollView(Context context) {
super(context);
}
public ReScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onFinishInflate() {
if (getChildCount() > 0) {
contentView = getChildAt(0);
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
if (contentView == null)
return;
// ScrollView�е�Ψһ�ӿؼ���λ����Ϣ, ���λ����Ϣ�������ؼ������������б��ֲ���
originalRect.set(contentView.getLeft(), contentView.getTop(),
contentView.getRight(), contentView.getBottom());
}
/**
* �ڴ����¼���, ������������������
*/
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (contentView == null) {
return super.dispatchTouchEvent(ev);
}
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
// �ж��Ƿ��������������
canPullDown = isCanPullDown();
canPullUp = isCanPullUp();
// ��¼����ʱ��Yֵ
startY = ev.getY();
break;
case MotionEvent.ACTION_UP:
if (!isMoved)
break; // ���û���ƶ����֣� ������ִ��
// ��������
TranslateAnimation anim = new TranslateAnimation(0, 0,
contentView.getTop(), originalRect.top);
anim.setDuration(ANIM_TIME);
contentView.startAnimation(anim);
// ���ûص������IJ���λ��
contentView.layout(originalRect.left, originalRect.top,
originalRect.right, originalRect.bottom);
// ����־λ���false
canPullDown = false;
canPullUp = false;
isMoved = false;
break;
case MotionEvent.ACTION_MOVE:
// ���ƶ��Ĺ����У� ��û�й��������������ij̶ȣ� Ҳû�й��������������ij̶�
if (!canPullDown && !canPullUp) {
startY = ev.getY();
canPullDown = isCanPullDown();
canPullUp = isCanPullUp();
break;
}
// ������ָ�ƶ��ľ���
float nowY = ev.getY();
int deltaY = (int) (nowY - startY);
// �Ƿ�Ӧ���ƶ�����
boolean shouldMove = (canPullDown && deltaY > 0) // ���������� ������ָ�����ƶ�
|| (canPullUp && deltaY < 0) // ���������� ������ָ�����ƶ�
|| (canPullUp && canPullDown); // �ȿ�������Ҳ�����������������������ScrollView�����Ŀؼ���ScrollView��С��
if (shouldMove) {
// ����ƫ����
int offset = (int) (deltaY * MOVE_FACTOR);
// ������ָ���ƶ����ƶ�����
contentView.layout(originalRect.left,
originalRect.top + offset, originalRect.right,
originalRect.bottom + offset);
isMoved = true; // ��¼�ƶ��˲���
}
break;
default:
break;
}
return super.dispatchTouchEvent(ev);
}
/**
* �ж��Ƿ����������
*/
private boolean isCanPullDown() {
return getScrollY() == 0
|| contentView.getHeight() < getHeight() + getScrollY();
}
/**
* �ж��Ƿ�������ײ�
*/
private boolean isCanPullUp() {
return contentView.getHeight() <= getHeight() + getScrollY();
}
}