AutoScrollTopBottomView
来源:互联网 发布:软件开发常用模型 编辑:程序博客网 时间:2024/06/05 10:52
这个自定义控件是用来展示底层view的,当顶层的view滑动到底层view的中间时,顶层view会自动滚动到底层view的顶部或者底部,顶层view可以是scrollview,listview等. 希望对大家有帮助.
github地址:https://github.com/X-FAN/AutoScrollTopBottomView 欢迎star
下面附上源码,代码思路很简单利用Scroller进行滚动处理.
public class AutoScrollTopBottomView extends RelativeLayout { private final int ANI_TIME = 800; private float mLastActionDownY; private View mBottomView; private ViewGroup mTopView; private Scroller mScroller; private MotionEvent mLastMoveEvent; public AutoScrollTopBottomView(Context context) { super(context); mScroller = new Scroller(context); } public AutoScrollTopBottomView(Context context, AttributeSet attrs) { super(context, attrs); mScroller = new Scroller(context); } public AutoScrollTopBottomView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mScroller = new Scroller(context); } @Override protected void onFinishInflate() { super.onFinishInflate(); if (getChildCount() != 2) { throw new IllegalStateException("only and should contain two child view"); } mBottomView = getChildAt(0); if (!(getChildAt(1) instanceof ViewGroup)) { throw new IllegalStateException("top view should be contained by a viewgroup"); } mTopView = (ViewGroup) getChildAt(1); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { View view = null; if (mTopView.getChildCount() > 0) { view = mTopView.getChildAt(0); } if (view != null) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: mLastActionDownY = ev.getRawY(); break; case MotionEvent.ACTION_MOVE: float distance = ev.getRawY() - mLastActionDownY; mLastActionDownY = ev.getRawY(); mLastMoveEvent = ev; if (!mScroller.computeScrollOffset()) { if (distance > 0 && isViewAtTop(view)) {//pull down if (Math.abs(mTopView.getScrollY() - distance) > mBottomView.getMeasuredHeight()) {//avoid out of bottom boundary mTopView.scrollBy(0, -mTopView.getScrollY() - mBottomView.getMeasuredHeight()); } else { mTopView.scrollBy(0, (int) -distance); } sendCancelEvent(); return true; } else if (distance < 0 && !isViewAtTop(mTopView)) {//pull up if ((distance - mTopView.getScrollY()) < 0) {//avoid out of top boundary mTopView.scrollBy(0, -mTopView.getScrollY()); } else { mTopView.scrollBy(0, (int) -distance); } sendCancelEvent(); return true; } } else { sendCancelEvent(); return true; } break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: if (isInUp()) {//prepare scroll to top mScroller.startScroll(mTopView.getScrollX(), mTopView.getScrollY(), 0, -mTopView.getScrollY(), ANI_TIME); } else if (isInDown()) {//prepare scroll to bottom mScroller.startScroll(mTopView.getScrollX(), mTopView.getScrollY(), 0, -mTopView.getScrollY() - mBottomView.getMeasuredHeight(), ANI_TIME); } invalidate(); break; default: break; } } return super.dispatchTouchEvent(ev); } @Override public void computeScroll() { if (mScroller.computeScrollOffset()) { mTopView.scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); invalidate(); } } /** * detect top view in top half of bottom view * * @return */ private boolean isInUp() {//在上半部分内 int y = -mTopView.getScrollY(); if (y > 0 && y < mBottomView.getMeasuredHeight() / 2) { return true; } return false; } /** * detect top view in bottom half of bottom view * * @return */ private boolean isInDown() {//在下半部分内 int y = -mTopView.getScrollY(); if (y >= mBottomView.getMeasuredHeight() / 2 && y < mBottomView.getMeasuredHeight()) { return true; } return false; } private boolean isViewAtTop(View view) { if (view instanceof AbsListView) {//这里可以自己更改代码,判断listview等在什么情况下为拉到顶部,默认为第一个item可见的时候 final AbsListView absListView = (AbsListView) view; return absListView.getChildCount() > 0 && (absListView.getFirstVisiblePosition() == 0 && absListView.getChildAt(0).getTop() >= absListView.getPaddingTop()); } else { return view.getScrollY() == 0; } } /** * 滑动过程调用,解决滑动与其他事件冲突 * solve conflict move event between other event */ private void sendCancelEvent() { if (mLastMoveEvent == null) { return; } MotionEvent last = mLastMoveEvent; MotionEvent e = MotionEvent.obtain(last.getDownTime(), last.getEventTime() + ViewConfiguration.getLongPressTimeout(), MotionEvent.ACTION_CANCEL, last.getX(), last.getY(), last.getMetaState()); super.dispatchTouchEvent(e); }}
效果图
0 0
- AutoScrollTopBottomView
- 使用python测试你的电脑开启最大线程数
- Flash as3播放器功能实现(mp4,flv)
- Python爬虫实战(3):安居客房产经纪人信息采集
- 关于多线程
- android4.4上全屏界面实现禁止状态栏下拉
- AutoScrollTopBottomView
- Hadoop DataNode 增加磁盘
- 坚持使用官方仿真器,也不贵才1000多,
- Java RMI 框架(远程方法调用)
- 微软公司等数据结构+算法面试100题
- git配置过程中出现错误的解决办法
- li里面嵌套a标签html和css小例子
- 不用看透风景 也要细水长流
- Javascript 仿Flash图片轮翻