针对自定义组件上拉刷新下拉加载更多PullToRefreshView的分析(二)
2013-08-09 14:40
579 查看
第二篇要从触摸事件讲起,前面已经可以看到各个子view已经加载进来,并且做了一些初始化,于是接下来,就是对用户输入做一些判断操作,让view可以跟着用户手势进行相应的改变。
转载请注明出处:/article/9484999.html
当你看见手指拖着列表往下拉的时候,头部的view会慢慢往下滑而不是一下子就跳出来,这个也是根据子view距离父view的距离来做相应的判断然后让view一点点的出来的,可以说这里面的操作大部分都跟距离位置相关,这也是值得学习的地方,因为细节的一些不同才能更加做出体验自然的应用。
这里需要对触摸手势做出反应,需要重写两个方法,分别是onInterceptTouchEvent(MotionEvent e)和onTouchEvent(MotionEvent event),onInterceptTouchEvent()用于处理事件并改变事件的传递方向,系统会根据它的返回值决定是把接下来的触摸事件让给自己的onTouchEvent()还是子view的onTouchEvent()来处理,而onTouchEvent()
用于处理事件,返回值决定当前控件是否消费(consume)了这个事件。对这一块有疑问的,可以参考这个链接所进行的解释:/article/5556616.html
搞懂了上面的内容,接下来的事情就好办了,我们只需要对MotionEvent是上下还是移动还是取消进行相应的判断并进行一些view的改动就能达到我们的目的。
首先我们来看下onInterceptTouchEvent()这个方法:
也返回真,那就该由父view的onTouchEvent() 处理接下来触摸手势事件。
看下isRefreshViewScroll()的部分关键代码
来看下onTouchEvent() 中的这部分代码
来看下headerPrepareToRefresh()做了些什么,可以看到其实是对header 的refreshView进行一些变动,改隐藏的隐藏该显示的显示,比如从“下拉刷新”的文字变成“松开手刷新”之类的,以及对那个箭头的动画启动。
当我们的newTopMargin大于等于0也就是表示那个refreshView已经完全显示出来了,就可以放开手进行刷新操作了,于是下面的事件就是判断是上拉刷新还是下拉刷新,或者是refreshView还没有完全显示出来就进行了释放操作是不会进行刷新的,而是隐藏refreshView,然后用invalidate();告知UI线程进行界面刷新。
这里就直接设置了这个refreshView的各种组件的状态,并用mOnHeaderRefreshListener.onHeaderRefresh(this);(在TestListView中进行了重写的回调方法),去调用onHeaderRefreshComplete()进行相应的刷新完成之后的恢复操作。
至此,整个PullToRefreshView的自定义组件的概念就出来了,相信以后遇到此种类似组件的时候,也能够达到举一反三的效果。
转载请注明出处:/article/9484999.html
当你看见手指拖着列表往下拉的时候,头部的view会慢慢往下滑而不是一下子就跳出来,这个也是根据子view距离父view的距离来做相应的判断然后让view一点点的出来的,可以说这里面的操作大部分都跟距离位置相关,这也是值得学习的地方,因为细节的一些不同才能更加做出体验自然的应用。
这里需要对触摸手势做出反应,需要重写两个方法,分别是onInterceptTouchEvent(MotionEvent e)和onTouchEvent(MotionEvent event),onInterceptTouchEvent()用于处理事件并改变事件的传递方向,系统会根据它的返回值决定是把接下来的触摸事件让给自己的onTouchEvent()还是子view的onTouchEvent()来处理,而onTouchEvent()
用于处理事件,返回值决定当前控件是否消费(consume)了这个事件。对这一块有疑问的,可以参考这个链接所进行的解释:/article/5556616.html
搞懂了上面的内容,接下来的事情就好办了,我们只需要对MotionEvent是上下还是移动还是取消进行相应的判断并进行一些view的改动就能达到我们的目的。
首先我们来看下onInterceptTouchEvent()这个方法:
@Override public boolean onInterceptTouchEvent(MotionEvent e) { int y = (int) e.getRawY(); switch (e.getAction()) { case MotionEvent.ACTION_DOWN: // 首先拦截down事件,记录y坐标 mLastMotionY = y; break; case MotionEvent.ACTION_MOVE: // deltaY > 0 是向下运动,< 0是向上运动 int deltaY = y - mLastMotionY; if (isRefreshViewScroll(deltaY)) { return true; } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: break; } return false; }可以看到,第一句用int y = (int) e.getRawY();得到了触摸事件触发时第一个点的Y坐标值,并且用e.getAction()得到了MotionEvent事件的值,很显然,第一个事件必然就是MotionEvent.ACTION_DOWN,记录了起始Y坐标之后,返回false,到第二次事件为MotionEvent.ACTION_MOVE的时候,调用了isRefreshViewScroll()来判断列表是滑到了顶部还是底部,这样就可以根据它的返回值来确定接下来是不是该让父view也就是PullToRefreshView中的两个refreshView进行滑动了。如果是isRefreshViewScroll()返回真,则onInterceptTouchEvent()
也返回真,那就该由父view的onTouchEvent() 处理接下来触摸手势事件。
看下isRefreshViewScroll()的部分关键代码
//返回屏幕上可见的第一个view在adapter中的位置&&返回adapterview中第一个view的上边界与父view之间的像素距离 if (mAdapterView.getFirstVisiblePosition() == 0 && child.getTop() == 0) { mPullState = PULL_DOWN_STATE;//设置下拉状态为正在下拉 return true;//返回true,这个时候父view的onTouchEvent开始接受触摸事件 }注释里面已经讲得比较清楚了,接下来它如果返回true的话就到了父view的onTouchEvent() 来处理下拉或者上拉事件了。
来看下onTouchEvent() 中的这部分代码
case MotionEvent.ACTION_MOVE: int deltaY = y - mLastMotionY; if (mPullState == PULL_DOWN_STATE) { // PullToRefreshView执行下拉 Log.i(TAG, " pull down!parent view move!"); headerPrepareToRefresh(deltaY); // setHeaderPadding(-mHeaderViewHeight); } else if (mPullState == PULL_UP_STATE) { // PullToRefreshView执行上拉 Log.i(TAG, "pull up!parent view move!"); footerPrepareToRefresh(deltaY); } mLastMotionY = y; break;这里的mPullState是之前在isRefreshViewScroll()中已经被赋值了,这里进行判断是上拉还是下拉,从而进行相应的刷新操作。
来看下headerPrepareToRefresh()做了些什么,可以看到其实是对header 的refreshView进行一些变动,改隐藏的隐藏该显示的显示,比如从“下拉刷新”的文字变成“松开手刷新”之类的,以及对那个箭头的动画启动。
private void headerPrepareToRefresh(int deltaY) { int newTopMargin = changingHeaderViewTopMargin(deltaY); // 当header view的topMargin>=0时,说明已经完全显示出来了,修改header view 的提示状态 if (newTopMargin >= 0 && mHeaderState != RELEASE_TO_REFRESH) { mHeaderTextView.setText(R.string.pull_to_refresh_release_label); mHeaderUpdateTextView.setVisibility(View.VISIBLE); mHeaderImageView.clearAnimation(); mHeaderImageView.startAnimation(mFlipAnimation); mHeaderState = RELEASE_TO_REFRESH; } else if (newTopMargin < 0 && newTopMargin > -mHeaderViewHeight) {// 拖动时没有释放 mHeaderImageView.clearAnimation(); mHeaderImageView.startAnimation(mFlipAnimation); // mHeaderImageView. mHeaderTextView.setText(R.string.pull_to_refresh_pull_label); mHeaderState = PULL_TO_REFRESH; } }上面代买中changingHeaderViewTopMargin(int deltaY) 起到了下拉的弹簧效果,实际上市根据你下拉的距离来乘以小于1的正数来让你感觉拉着有感觉,这里面还做了限制上拉下拉同时触发的情况,这里可以自己注释掉那个判断去实验一下。
当我们的newTopMargin大于等于0也就是表示那个refreshView已经完全显示出来了,就可以放开手进行刷新操作了,于是下面的事件就是判断是上拉刷新还是下拉刷新,或者是refreshView还没有完全显示出来就进行了释放操作是不会进行刷新的,而是隐藏refreshView,然后用invalidate();告知UI线程进行界面刷新。
case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: int topMargin = getHeaderTopMargin(); if (mPullState == PULL_DOWN_STATE) { if (topMargin >= 0) { // 开始刷新 headerRefreshing(); } else { // 还没有执行刷新,重新隐藏 setHeaderTopMargin(-mHeaderViewHeight); } } else if (mPullState == PULL_UP_STATE) { if (Math.abs(topMargin) >= mHeaderViewHeight + mFooterViewHeight) { // 开始执行footer 刷新 footerRefreshing(); } else { // 还没有执行刷新,重新隐藏 setHeaderTopMargin(-mHeaderViewHeight); } } break;我们来看下刷新操作
private void headerRefreshing() { mHeaderState = REFRESHING; setHeaderTopMargin(0); mHeaderImageView.setVisibility(View.GONE); mHeaderImageView.clearAnimation(); mHeaderImageView.setImageDrawable(null); mHeaderProgressBar.setVisibility(View.VISIBLE); mHeaderTextView.setText(R.string.pull_to_refresh_refreshing_label); if (mOnHeaderRefreshListener != null) { mOnHeaderRefreshListener.onHeaderRefresh(this); } }
这里就直接设置了这个refreshView的各种组件的状态,并用mOnHeaderRefreshListener.onHeaderRefresh(this);(在TestListView中进行了重写的回调方法),去调用onHeaderRefreshComplete()进行相应的刷新完成之后的恢复操作。
至此,整个PullToRefreshView的自定义组件的概念就出来了,相信以后遇到此种类似组件的时候,也能够达到举一反三的效果。
相关文章推荐
- 针对自定义组件上拉刷新下拉加载更多PullToRefreshView的分析(一)
- 针对自定义组件上拉刷新下拉加载更多PullToRefreshView的分析(一)
- 将上拉加载更多下拉刷新PullToRefreshView用到项目中去
- 使用自定义的item、Adapter和AsyncTask、第三方开源框架PullToRefresh联合使用实现自定义的下拉列表(从网络加载图片显示在item中的ImageView)
- pulltoRefreshSwipeMenuListview-带侧滑的可下拉刷新、上拉加载更多的控件
- 超简单的 listview的第三方控件PullToRefreshListView 上拉刷新,下拉加载更多,分页加载
- PullToRefreshRecyclerView——带上拉刷新下拉加载功能的RecyclerView
- 使用自定义的item、Adapter和AsyncTask、第三方开源框架PullToRefresh联合使用实现自定义的下拉列表(从网络加载图片显示在item中的ImageView)
- Android - 框架】之刷新加载框架Ultra-Pull-To-Refresh的使用,及其自定义头部刷新和底部加载更多
- PullToRefresh上拉刷新下拉加载更多的使用
- PullToRefreshRecyclerView——带上拉刷新下拉加载功能的RecyclerView
- pulltorefreshscrollview的简单实现(上拉刷新,下拉加载)
- PullToReFresh 实现 RecycleView 横向滑动的刷新和加载更多
- Android自定义上拉加载下拉刷新PullToRefreshListView
- 上拉刷新 下拉加载更多-PullToRefreshListView的简介
- PullToRefresh的实现上拉刷新下拉加载
- pulltorefresh上拉刷新,下拉加载
- 使用pullToRefresh进行下拉刷新和上拉加载
- 使用pullToRefresh进行下拉刷新和上拉加载
- PullToRefresh实现ListView的刷新,加载更多的展示