1. 程式人生 > >Android:上下拖動切換介面

Android:上下拖動切換介面

import android.content.Context;
import android.support.v4.view.MotionEventCompat;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.ViewDragHelper;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;

/**
* 用於上下拖動切換介面的控制元件, 只允許兩個子view */ public class VerticalSlideLayout extends ViewGroup { private static final int THRESHOLD_VEL = 100; private static final int THRESHOLD_DISTANCE = 100; private ViewDragHelper mDragHelper; private PageChangeListener mListener; private View mViewOne, mViewTwo
; private int mViewHeight; private int mPageNum; private float mOldX, mOldY; public VerticalSlideLayout(Context context) { this(context, null); } public VerticalSlideLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); } public VerticalSlideLayout(Context context, AttributeSet attrs, int
defStyle) { super(context, attrs, defStyle); mDragHelper = ViewDragHelper.create(this, 10f, new DragHelperCallback()); mDragHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_BOTTOM); } @Override protected void onFinishInflate() { mViewOne = getChildAt(0); mViewTwo = getChildAt(1); } @Override public void computeScroll() { if (mDragHelper.continueSettling(true)) { ViewCompat.postInvalidateOnAnimation(this); } } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { if (mViewOne.getBottom() > 0 && mViewOne.getTop() < 0) { return false; } final int action = MotionEventCompat.getActionMasked(ev); switch (action) { case MotionEvent.ACTION_DOWN: mOldX = ev.getX(); mOldY = ev.getY(); break; case MotionEvent.ACTION_MOVE: float adx = Math.abs(ev.getX() - mOldX); float ady = Math.abs(ev.getY() - mOldY); if (ady < adx) { mDragHelper.cancel(); return false; } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: mDragHelper.cancel(); return false; } return mDragHelper.shouldInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent e) { mDragHelper.processTouchEvent(e); return true; } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { if (mViewOne.getTop() == 0) { mViewOne.layout(l, 0, r, b - t); mViewTwo.layout(l, 0, r, b - t); mViewHeight = mViewOne.getMeasuredHeight(); mViewTwo.offsetTopAndBottom(mViewHeight); } else { mViewOne.layout(l, mViewOne.getTop(), r, mViewOne.getBottom()); mViewTwo.layout(l, mViewTwo.getTop(), r, mViewTwo.getBottom()); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { measureChildren(widthMeasureSpec, heightMeasureSpec); int maxWidth = MeasureSpec.getSize(widthMeasureSpec); int maxHeight = MeasureSpec.getSize(heightMeasureSpec); setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, 0), resolveSizeAndState(maxHeight, heightMeasureSpec, 0)); } public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) { int result = size; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); switch (specMode) { case MeasureSpec.UNSPECIFIED: result = size; break; case MeasureSpec.AT_MOST: if (specSize < size) { result = specSize | MEASURED_STATE_TOO_SMALL; } else { result = size; } break; case MeasureSpec.EXACTLY: result = specSize; break; } return result | (childMeasuredState & MEASURED_STATE_MASK); } private class DragHelperCallback extends ViewDragHelper.Callback { @Override public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) { if (changedView == mViewOne) { mViewTwo.offsetTopAndBottom(dy); } else { mViewOne.offsetTopAndBottom(dy); } invalidate(); } @Override public boolean tryCaptureView(View child, int pointerId) { return true; } @Override public int getViewVerticalDragRange(View child) { return 1; } @Override public void onViewReleased(View releasedChild, float xvel, float yvel) { int finalTop = 0; if (releasedChild == mViewOne) { if (yvel < -THRESHOLD_VEL || mViewOne.getTop() < -THRESHOLD_DISTANCE) { finalTop = -mViewHeight; mPageNum = 1; if (null != mListener) { mListener.onNextPage(); } } } else { if (yvel > THRESHOLD_VEL || releasedChild.getTop() > THRESHOLD_DISTANCE) { finalTop = mViewHeight; mPageNum = 0; if (null != mListener) { mListener.onPrevPage(); } } } if (mDragHelper.smoothSlideViewTo(releasedChild, 0, finalTop)) { ViewCompat.postInvalidateOnAnimation(VerticalSlideLayout.this); } } @Override public int clampViewPositionVertical(View child, int top, int dy) { if (child == mViewOne) { if (top > 0) { dy = 0; } } else { if (top < 0) { dy = 0; } } return child.getTop() + dy / 3; } } /** * 由外部ActivityonBackPressed實現, 從第二頁面返回第一頁面 * * @return false時可呼叫finish關閉當前Activity */ public boolean back() { if (mPageNum == 1) { if (null != mListener) { mListener.onPrevPage(); } if (mDragHelper.smoothSlideViewTo(mViewTwo, 0, mViewHeight)) { ViewCompat.postInvalidateOnAnimation(VerticalSlideLayout.this); } mPageNum = 0; return true; } return false; } /** * 外部實現, 用於處理切換頁面後的邏輯 */ public void setPageChangeListener(PageChangeListener listener) { this.mListener = listener; } public interface PageChangeListener { /** * 切換到第一頁時觸發 */ void onPrevPage(); /** * 切換到第二頁時觸發 */ void onNextPage(); } }
<com...ui.widget.VerticalSlideLayout
android:id="@+id/slideLl"
android:layout_width="match_parent"
android:layout_height="match_parent">

    <FrameLayout
android:id="@+id/one"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

    <FrameLayout
android:id="@+id/two"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</com...ui.widget.VerticalSlideLayout>

/**
 * 框架
*/
public class TabActivity extends BaseActivity implements VerticalSlideLayout.PageChangeListener {
    private VerticalSlideLayout mSlideLayout;
    private OneFragment mOneFrament;
    private TwoFragment mTwoFrament;

    @Override
public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.match_detail);
        initView();
    }

    private void initView() {
        mSlideLayout = (VerticalSlideLayout) findViewById(R.id.slideLl);
        mSlideLayout.setPageChangeListener(this);
        mOneFrament = new OneFragment();
        mTwoFrament = new TwoFragment();
        getSupportFragmentManager().beginTransaction().add(R.id.one, mOneFrament).add(R.id.two, mTwoFrament).commit();
    }

    @Override
public void onPrevPage() {
        setTouchMove(true);
        mOneFrament.onRefresh();
    }

    @Override
public void onNextPage() {
        setTouchMove(false);
        int[] pagePosition = new int[1];
        long[] cubeId = new long[1];
        mOneFrament.getNextPageParams(pagePosition, cubeId);
        mTwoFrament.setParams(pagePosition[0], mMatchId, cubeId[0]);
        mTwoFrament.onRefresh();
    }

    @Override
public void onBackPressed() {
        if (!mSlideLayout.back()) {
            finish();
        }
    }
}