Android:上下拖动切换界面
来源:互联网 发布:java空指针异常处理 编辑:程序博客网 时间:2024/05/22 00:19
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; } } /** * 由外部Activity的onBackPressed实现, 从第二页面返回第一页面 * * @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(); } }}
0 0
- Android:上下拖动切换界面
- Android:拖动退出界面
- android ScrollView--Linearlayout可以上下拖动
- Android ListView头部随着上下拖动缩放
- Android中自定上下拖动Viewpager
- 实现多楼层,每个楼层多房间,上下拖动切换楼层,左右拖动查看其他房间
- 可左右上下滑动切换图片的界面
- Android界面切换
- Android界面切换
- android界面切换
- Android界面切换
- android 界面切换
- Android实现 界面切换
- android界面切换动画
- Android Activity上下滑动切换背景
- Android ActionBar随ScorllView上下拖动而透明度渐变效果
- 一个简单的界面拖动切换效果类ScrollViewGroup
- jquery 上下拖动div
- Netty框架(一)————BIO编程
- 求数组第二(n)大值及下标
- iOS开发之Xcode常用调试技巧总结
- RecyclerView加载间距
- Javaweb微专业第三弹-----从数据类型说起
- Android:上下拖动切换界面
- Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'user
- 纹理坐标
- 《多线程编程》学习之十:定时器Timer的使用,线程安全的单例模式
- Java程序员必备知识-多线程框架Executor详解
- IBATIS学习中需要注意的问题
- Linux常用命令(三)文件搜索命令
- 关于Nginx+tomcat集群配置
- RS232标准中的RTS与CTS