扩展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;

 

    }

 

效果:
第一页

扩展HorizontalScrollView实现整个屏幕滚动

扩展HorizontalScrollView实现整个屏幕滚动

你可能感兴趣的:(扩展HorizontalScrollView实现整个屏幕滚动)