0
回答

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
; }
效果:
第一页
原文链接:http://www.cnblogs.com/vus520/archive/2011/11/29/2561951.html