您的位置:首页 > 其它

扩展HorizontalScrollView实现整个屏幕滚动

2013-07-17 14:39 435 查看
import java.lang.reflect.Field;
import android.content.Context;
import android.util.AttributeSet;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.view.animation.OvershootInterpolator;
import android.widget.HorizontalScrollView;
import android.widget.OverScroller;
import android.widget.Scroller;

public class HorizontalScrollViewEx extends HorizontalScrollView {

static final int ANIMATED_SCROLL_GAP = 250;
private long mLastScroll;
private Field mScrollerField;
ScrollerEx scrollerEx = null;

public HorizontalScrollViewEx(Context context) {

this(context, null);
}

public HorizontalScrollViewEx(Context context, AttributeSet attrs) {

super(context, attrs);
this.setSmoothScrollingEnabled(false);
initScroller();
}

public HorizontalScrollViewEx(Context context, AttributeSet attrs, int defStyle) {

super(context, attrs, defStyle);
this.setSmoothScrollingEnabled(false);
initScroller();

}

private void initScroller() {

try {

mScrollerField = HorizontalScrollView.class.getDeclaredField("mScroller");
mScrollerField.setAccessible(true);
String type = mScrollerField.getType().getSimpleName();

if ("OverScroller".equals(type)) {

scrollerEx = new ScrollerEx() {
private OverScroller mScroller = null;

public void startScroll(int startX, int startY, int dx, int dy, int duration) {
mScroller.startScroll(startX, startY, dx, dy, duration);
}

public boolean isFinished() {
return mScroller.isFinished();
}

public Object getScroller() {
return mScroller;
}

public void create(Context context, Interpolator interpolator) {
mScroller = new OverScroller(context, interpolator);
}

public void abortAnimation() {
if (mScroller != null) {
mScroller.abortAnimation();
}
}
};

} else {

scrollerEx = new ScrollerEx() {
private Scroller mScroller = null;

public void startScroll(int startX, int startY, int dx, int dy, int duration) {
mScroller.startScroll(startX, startY, dx, dy, duration);
}

public boolean isFinished() {
return mScroller.isFinished();
}

public Object getScroller() {
return mScroller;
}

public void create(Context context, Interpolator interpolator) {
mScroller = new Scroller(context, interpolator);
}

public void abortAnimation() {
if (mScroller != null) {

mScroller.abortAnimation();
}
}
};
}
} catch (Exception ex) {
}

}public final void smoothScrollBy(int dx, int dy, int addDuration) {

float tension = 0f;
scrollerEx.abortAnimation();
Interpolator ip = new OvershootInterpolator(tension);
scrollerEx.create(getContext(), ip);

try {
mScrollerField.set(this, scrollerEx.getScroller());
} catch (Exception e) {
}

long duration = AnimationUtils.currentAnimationTimeMillis() - mLastScroll;
if (duration > ANIMATED_SCROLL_GAP) {

scrollerEx.startScroll(getScrollX(), getScrollY(), dx, dy, addDuration);
awakenScrollBars();

// awakenScrollBars(mScroller.getDuration());
invalidate();
} else {

if (!scrollerEx.isFinished()) {
scrollerEx.abortAnimation();
}

scrollBy(dx, dy);
}

mLastScroll = AnimationUtils.currentAnimationTimeMillis();
}

public final void smoothScrollTo(int x, int y, int duration) {
smoothScrollBy(x - getScrollX(), y - getScrollY(), duration);

}

private interface ScrollerEx {

void create(Context context, Interpolator interpolator);
Object getScroller();
void abortAnimation();
void startScroll(int startX, int startY, int dx, int dy, int duration);
boolean isFinished();
}
}


核心部分是利用反射的方法取得父类的 mScroller对象,然后再使用 mScroller控制滚动。
然后在Activity里重写dispatchTouchEvent方法,使用GestureDetector控制滚动距离。 下面是部分代码

private HorizontalScrollViewEx hsvMain;

@Override
public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

hsvMain = (HorizontalScrollViewEx) findViewById(R.id.hsvMain);

}

// 监听屏幕动作事件
GestureDetector =    gestureDetector = new GestureDetector(new OnGestureListener() {

private int LEFT_DISTANCE = -150;
private int RIGHT_DISTANCE = 150;

// 用户轻触触摸屏,由1个MotionEvent ACTION_DOWN触发

public boolean onDown(MotionEvent e) {
return true;
}

// 用户按下触摸屏、快速移动后松开,由1个MotionEvent ACTION_DOWN,
// 多个ACTION_MOVE, 1个ACTION_UP触发
// e1:第1个ACTION_DOWN MotionEvent
// e2:最后一个ACTION_MOVE MotionEvent
// velocity X:X 轴上的移动速度,像素/秒
// velocity Y:Y 轴上的移动速度,像素/秒

public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {

float distanceX = e2.getX() - e1.getX();
if (distanceX < LEFT_DISTANCE) {

// left
setXPosition(true);

} else if (distanceX > RIGHT_DISTANCE) {

// right
setXPosition(false);

}

hsvMain.smoothScrollTo(xPosition, 0, speed);
return true;

}
// 用户长按触摸屏,由多个MotionEvent ACTION_DOWN触发
public void onLongPress(MotionEvent e) {

}
// 用户按下触摸屏,并拖动,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE触发
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {

hsvMain.scrollBy((int) distanceX, 0);
return true;

}
// 用户轻触触摸屏,尚未松开或拖动,由一个1个MotionEvent ACTION_DOWN触发
// 注意和onDown()的区别,强调的是没有松开或者拖动的状态

public void onShowPress(MotionEvent e) {

}
// 用户(轻触触摸屏后)松开,由一个1个MotionEvent ACTION_UP触发

public boolean onSingleTapUp(MotionEvent e) {

if (e.getY() < offsetOfBottom) {
return true;
}

if (e.getX() > halfOfWidth) {
setXPosition(true);
} else {

setXPosition(false);

}
hsvMain.scrollTo(xPosition, 0);
return true;

}
});

@Override

public boolean dispatchTouchEvent(MotionEvent ev) {
boolean result = gestureDetector.onTouchEvent(ev);

if (result == false) {
final int action = ev.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_UP:

hsvMain.smoothScrollTo(xPosition, 0, speed);
result = true;
}

}
return true;

}


效果:
第一页



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: