package com.tiger.quicknews.wedget.gesture; import android.content.Context; import android.os.Handler; import android.os.Message; import android.util.AttributeSet; import android.view.GestureDetector; import android.view.GestureDetector.OnGestureListener; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.Scroller; import java.lang.ref.WeakReference; /** * 自定义的 ViewGroup,具有监听手势滑动功能; 用于封装 DecorView 中的LinearLayout;可�?Activity * 具有滑动关闭效果�? * * @author caizenghui */ public class GestureViewGroup extends ViewGroup { private final Context context; private Scroller scroller; /** * 标记�?ViewGroup 是否处于 fling 状�?�? */ private boolean isFling = false; private final Handler mHandler = new MyHandler(this); private static class MyHandler extends Handler { private final WeakReference<GestureViewGroup> myGestureViewGroup; public MyHandler(GestureViewGroup gestureViewGroup) { myGestureViewGroup = new WeakReference<GestureViewGroup>( gestureViewGroup); } @Override public void handleMessage(Message msg) { if (myGestureViewGroup.get() != null) myGestureViewGroup.get().getGestureViewGroupGoneListener() .onFinish(); } } public GestureViewGroup(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); this.context = context; initview(); } public GestureViewGroup(Context context, AttributeSet attrs) { super(context, attrs); this.context = context; initview(); } public GestureViewGroup(Context context) { super(context); this.context = context; initview(); } private GestureDetector detector; private void initview() { scroller = new Scroller(context); detector = new GestureDetector(context, new GestureDetectorListener()); } class GestureDetectorListener implements OnGestureListener { @Override public boolean onSingleTapUp(MotionEvent e) { return false; } @Override public void onShowPress(MotionEvent e) { } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { int scrollX = -getScrollX(); float finger_originX = e2.getX() - e1.getX(); if (finger_originX < 0 && scrollX < Math.abs(finger_originX) + 120) { scrollTo(0, 0); return false; } int scroll_distanceX = (int) (scrollX - distanceX < 0 ? scrollX : -distanceX); scrollBy(-scroll_distanceX, 0); return false; } @Override public void onLongPress(MotionEvent e) { } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { if (velocityX > 100 && e2.getX() - e1.getX() > 80 && Math.abs(velocityX) > Math.abs(velocityY) && Math.abs(e2.getX() - e1.getX()) > Math.abs(e2.getY() - e1.getY())) {// 向右滑动; isFling = true; int distance = -getScrollX(); scroller.startScroll(getScrollX(), 0, -(getWidth() - distance), 0, 400); invalidate(); Message mes = Message.obtain(); mHandler.sendMessageDelayed(mes, 400); } return false; } @Override public boolean onDown(MotionEvent e) { return false; } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); MeasureSpec.getSize(widthMeasureSpec); MeasureSpec.getMode(widthMeasureSpec); for (int i = 0; i < getChildCount(); i++) { View view = getChildAt(i); view.measure(widthMeasureSpec, heightMeasureSpec); } } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { for (int i = 0; i < getChildCount(); i++) { View view = getChildAt(i); if (view != null) { view.layout(0, 0, getWidth(), getHeight()); } } } private float lastX; private float lastY; @Override public boolean onInterceptTouchEvent(MotionEvent ev) { boolean result = false; switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: lastX = (int) ev.getX(); lastY = (int) ev.getY(); detector.onTouchEvent(ev); break; case MotionEvent.ACTION_MOVE: int distanceX = (int) Math.abs(ev.getX() - lastX); int distanceY = (int) Math.abs(ev.getY() - lastY); if (distanceX > distanceY && distanceX > 10) { result = true; } break; default: break; } return result; } @Override public boolean onTouchEvent(MotionEvent event) { detector.onTouchEvent(event); switch (event.getAction()) { case MotionEvent.ACTION_UP: if (!isFling) { moveToDest(); } isFling = false; break; } return true; } /** * 处理 up 事件发生时,界面进行还原或�?消失�? */ public void moveToDest() { int distance = -getScrollX(); // distance<0; if (distance < getWidth() * 6 / 10) { scroller.startScroll(getScrollX(), 0, distance, 0, Math.abs(distance)); invalidate(); } else { scroller.startScroll(getScrollX(), 0, -(getWidth() - distance), 0, 400); invalidate(); Message mes = Message.obtain(); mHandler.sendMessageDelayed(mes, 400); } } @Override public void computeScroll() { if (scroller.computeScrollOffset()) { int x = scroller.getCurrX(); scrollTo(x, 0); postInvalidate(); } } private GestureViewGroupGoneListener GestureViewGroupGoneListener; public GestureViewGroupGoneListener getGestureViewGroupGoneListener() { return GestureViewGroupGoneListener; } public void setGestureViewGroupGoneListener( GestureViewGroupGoneListener gestureViewGroupGoneListener) { GestureViewGroupGoneListener = gestureViewGroupGoneListener; } /** * 用于定义界面滑动消失后要进行的操作的接口�? */ public interface GestureViewGroupGoneListener { /** * 用于定义界面滑动消失后要进行的操作; */ void onFinish(); } }