GestureDetector封装手势检测上下滑动

mx64 10年前

项目中需要检测ListView的上滑下滑隐藏顶部View控件,之前在网上也有很多实现案例。在git上发现个封装很不错的例子,记录下来。


GestureDetector是一个手势检测类,内部有个SimpleOnGestureListener手势监听类。

定义一个抽象类SimpleDetector,继承 GestureDetector.SimpleOnGestureListener抽象类,实现View.OnTouchListener接口。这样做有什么好处呢?首先ListView只要setOnTouchListener,把定义的这个抽象类SimpleDetector设置进就好。然后这个类SimpleDetector只需要负责检测上滑还是下滑事件,逻辑得到了分离。

为了要实现ListView顶部View控件的动画效果,需要定义另外一个类继承上面抽象的SimpleDetector类,在这个类里单独处理上滑下滑时候需要执行的动画或者其它逻辑事件。上面的SimpleDetector抽象类提供两个抽象方法供子类去实现。这样整个封装就显得非常完美了。

    public abstract class SimpleDetector extends GestureDetector.SimpleOnGestureListener implements View.OnTouchListener{                    private final GestureDetector mDetector;            private final int mSlop;//slop晃荡的意思            private boolean mIgnore;//是否忽略监听上下滚动            private float mDownY;                        public abstract void onScrollDown();            public abstract void onScrollUp();                        public SimpleDetector(Context context){                mDetector = new GestureDetector(context,this);                mSlop = getSlop(context);            }                        public boolean isIgnore() {                return mIgnore;            }            public void setIgnore(boolean mIgnore) {                this.mIgnore = mIgnore;            }            protected int getSlop(Context context){                if(Build.VERSION.SDK_INT < Build.VERSION_CODES.FROYO){                    return ViewConfiguration.getTouchSlop() * 2;                }else{                    return ViewConfiguration.get(context).getScaledPagingTouchSlop();                }            }                        @Override            public boolean onDown(MotionEvent e) {                // TODO Auto-generated method stub                mDownY = e.getY();                return false;            }                        @Override            public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,                    float distanceY) {                // TODO Auto-generated method stub                if(mIgnore)                    return false;                if(distanceY==0){                    mDownY = e2.getY();                }                                float distance = mDownY - e2.getY();                                if(distance < -mSlop){                    onScrollDown();                }else if(distance > mSlop){                    onScrollUp();                }                return false;            }                        @Override            public boolean onTouch(View v, MotionEvent event) {                // TODO Auto-generated method stub                mDetector.onTouchEvent(event);                return false;            }                }  

处理动画显示隐藏事件逻辑处理类
    public class ShowHideOnScroll extends SimpleDetector implements AnimatorListener{                    private final View mView;            private int mShowAnimation;            private int mHideAnimation;            private int mTranslationY;            private int curShowHide = 0;                        public ShowHideOnScroll(View view,int translationY){                super(view.getContext());                mView = view;                mTranslationY = translationY;            }                        public ShowHideOnScroll(View view,int show,int hide,int translationY) {                super(view.getContext());                mView = view;                mShowAnimation = show;                mHideAnimation = hide;                mTranslationY = translationY;            }                    @Override            public void onScrollDown() {                mView.setVisibility(View.VISIBLE);                animateShow();                curShowHide = 0;            }                    @Override            public void onScrollUp() {                mView.setVisibility(View.VISIBLE);                animateHide();                curShowHide = 1;            }            private void animateShow(){                mView.setTranslationY(mTranslationY);                mView.animate().translationY(0).setInterpolator(new AccelerateDecelerateInterpolator())                .setStartDelay(0).setDuration(400).setListener(ShowHideOnScroll.this).start();                setIgnore(true);            }            private void animateHide(){                mView.setTranslationY(0);                mView.animate().translationY(mTranslationY).setInterpolator(new AccelerateDecelerateInterpolator())                .setStartDelay(0).setDuration(400).setListener(ShowHideOnScroll.this).start();                setIgnore(true);            }                    @Override            public void onAnimationStart(Animator animation) {                // TODO Auto-generated method stub                            }                    @Override            public void onAnimationEnd(Animator animation) {                // TODO Auto-generated method stub                if(curShowHide==0){                    mView.setVisibility(View.VISIBLE);                    mView.setTranslationY(0);                }else if(curShowHide == 1){                    mView.setVisibility(View.INVISIBLE);                    mView.setTranslationY(mTranslationY);                }                setIgnore(false);            }                    @Override            public void onAnimationCancel(Animator animation) {                // TODO Auto-generated method stub                            }                    @Override            public void onAnimationRepeat(Animator animation) {                // TODO Auto-generated method stub                            }                                    }  

好了,上面两个类的封装很简单,但却很完美,每个事件的逻辑处理分离了,ListView之类的控件只需要把自己的touchlistener事件传递进去就可以了。这个可以举一反三运用到其它地方去,以后写代码框架很重要,事物逻辑要做到分离,这样代码写的很完美无可挑剔.

来自:http://blog.csdn.net/fancylovejava/article/details/46602669