扩展HorizontalScrollView实现整个屏幕滚动
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;
}
效果:
第一页