[置顶] PullToRefreshListView总结
2016-03-02 20:16
337 查看
PullToRefreshListView工作原理:
整体是个LinearLayout,包含一个Header,一个Footer,中间夹着一个ListView,其中Header和Footer的位置居于不可见范围内。
以竖向下拉为例,当接收到下拉手势时,如果ListView内容居于置顶位置,则LinearLayout向下滚动,显示出Header的内容,当Header内容展示完全后,如果用户松开,则进行刷新操作,当刷新完成后,LinearLayout向上滚动,回到初始位置。如果Header内容未展示完全,用户即松开,则LinearLayout直接回到初始位置。如果收到下拉手势时,ListView内容居于未置顶位置,LinearLayout会将手势交给ListView消费,ListView进行内容滑动。
问题一.LinearLayout如何加入header和footer,
1.首先,PullToRefreshBase的init()方法中(构造函数中调用)
2. 看下updateUIForMode()方法
其中addViewInternal() 是LinearLayout将headerLayout和footerLayout添加的位置。
问题二.如何实现初始位置中不展示header和footer的?
看到问题一中,refreshLoadingViewSize()方法
问题三.PullToRefreshListView为何添加两个Header 两个Footer
PullToRefreshBase添加
PullToRefreshListView的ListView也添加了
但默认展示中只展示1个 两者互相切换
问题四.LinearLayout如何拦截手势操作
onInterceptTouchEvent和onTouchEvent配合
以竖向下拉为例
1.首先,onInterceptTouchEvent接收到ActionDown事件
如果此时ListView内容居于置顶位置,则记录初始点击位置
2.其次是接收到ActionMove事件,如果滑动距离大于最小滑动距离,且竖向滑动距离大于横向滑动距离,则认为处于滑动状态,将mIsBeingDragged设置true,onInterceptTouchEvent返回true。
3.这样交给LinearLayout的onTouchEvent处理,在ActionMove事件的处理中,调用pullEvent()方法,获取滑动距离、将LinearLayout滑动相应距离(显示header),同时header和footer根据滑动距离进行处理(动画)。如果滑动距离超过header高度,更改状态为松手刷新,同时传递给LoadingLayout进行处理。如果滑动距离不超过header高度,更改状态为下拉刷新,同时传递给LoadingLayout进行处理。
问题五.PullToRefreshListView控件是如何封装给用户直接使用的?如果不是封装的控件,自己如何实现PullToRefresh功能?
问题六.PullToRefreshListView如何实现xml属性设置和读取
问题七.PullToRefreshListView如何实现滚动、刷新等动画
问题八.PullToRefreshListView用到的设计模式
整体是个LinearLayout,包含一个Header,一个Footer,中间夹着一个ListView,其中Header和Footer的位置居于不可见范围内。
以竖向下拉为例,当接收到下拉手势时,如果ListView内容居于置顶位置,则LinearLayout向下滚动,显示出Header的内容,当Header内容展示完全后,如果用户松开,则进行刷新操作,当刷新完成后,LinearLayout向上滚动,回到初始位置。如果Header内容未展示完全,用户即松开,则LinearLayout直接回到初始位置。如果收到下拉手势时,ListView内容居于未置顶位置,LinearLayout会将手势交给ListView消费,ListView进行内容滑动。
问题一.LinearLayout如何加入header和footer,
1.首先,PullToRefreshBase的init()方法中(构造函数中调用)
// Finally update the UI for the modes updateUIForMode();
2. 看下updateUIForMode()方法
/** * Updates the View State when the mode has been set. This does not do any * checking that the mode is different to current state so always updates. */ protected void updateUIForMode() { // We need to use the correct LayoutParam values, based on scroll // direction final LinearLayout.LayoutParams lp = getLoadingLayoutLayoutParams(); // Remove Header, and then add Header Loading View again if needed if (this == mHeaderLayout.getParent()) { removeView(mHeaderLayout); } if (mMode.showHeaderLoadingLayout()) { addViewInternal(mHeaderLayout, 0, lp); } // Remove Footer, and then add Footer Loading View again if needed if (this == mFooterLayout.getParent()) { removeView(mFooterLayout); } if (mMode.showFooterLoadingLayout()) { addViewInternal(mFooterLayout, lp); } // Hide Loading Views refreshLoadingViewsSize(); // If we're not using Mode.BOTH, set mCurrentMode to mMode, otherwise // set it to pull down mCurrentMode = (mMode != Mode.BOTH) ? mMode : Mode.PULL_FROM_START; }
其中addViewInternal() 是LinearLayout将headerLayout和footerLayout添加的位置。
问题二.如何实现初始位置中不展示header和footer的?
看到问题一中,refreshLoadingViewSize()方法
/** * Re-measure the Loading Views height, and adjust internal padding as * necessary */ protected final void refreshLoadingViewsSize() { final int maximumPullScroll = (int) (getMaximumPullScroll() * 1.2f); int pLeft = getPaddingLeft(); int pTop = getPaddingTop(); int pRight = getPaddingRight(); int pBottom = getPaddingBottom(); switch (getPullToRefreshScrollDirection()) { case HORIZONTAL: if (mMode.showHeaderLoadingLayout()) { mHeaderLayout.setWidth(maximumPullScroll); pLeft = -maximumPullScroll; } else { pLeft = 0; } if (mMode.showFooterLoadingLayout()) { mFooterLayout.setWidth(maximumPullScroll); pRight = -maximumPullScroll; } else { pRight = 0; } break; case VERTICAL: if (mMode.showHeaderLoadingLayout()) { mHeaderLayout.setHeight(maximumPullScroll); pTop = -maximumPullScroll; } else { pTop = 0; } if (mMode.showFooterLoadingLayout()) { mFooterLayout.setHeight(maximumPullScroll); pBottom = -maximumPullScroll; } else { pBottom = 0; } break; } if (DEBUG) { Log.d(LOG_TAG, String.format( "Setting Padding. L: %d, T: %d, R: %d, B: %d", pLeft, pTop, pRight, pBottom)); } setPadding(pLeft, pTop, pRight, pBottom); }
问题三.PullToRefreshListView为何添加两个Header 两个Footer
PullToRefreshBase添加
PullToRefreshListView的ListView也添加了
但默认展示中只展示1个 两者互相切换
问题四.LinearLayout如何拦截手势操作
onInterceptTouchEvent和onTouchEvent配合
以竖向下拉为例
1.首先,onInterceptTouchEvent接收到ActionDown事件
如果此时ListView内容居于置顶位置,则记录初始点击位置
//判断ListView内容是否居于置顶位置
private boolean isFirstItemVisible() { final Adapter adapter = mRefreshableView.getAdapter(); if (null == adapter || adapter.isEmpty()) { //listView中无内容 if (DEBUG) { Log.d(LOG_TAG, "isFirstItemVisible. Empty View."); } return true; } else { /** * This check should really just be: * mRefreshableView.getFirstVisiblePosition() == 0, but PtRListView * internally use a HeaderView which messes the positions up. For * now we'll just add one to account for it and rely on the inner * condition which checks getTop(). */ if (mRefreshableView.getFirstVisiblePosition() <= 1) { // 显示ListView第一个元素 final View firstVisibleChild = mRefreshableView.getChildAt(0); if (firstVisibleChild != null) { return firstVisibleChild.getTop() >= mRefreshableView.getTop(); //ListView第一个元素的顶部与ListView的顶部相符或者在ListView顶部的下面 } } } return false; }
2.其次是接收到ActionMove事件,如果滑动距离大于最小滑动距离,且竖向滑动距离大于横向滑动距离,则认为处于滑动状态,将mIsBeingDragged设置true,onInterceptTouchEvent返回true。
3.这样交给LinearLayout的onTouchEvent处理,在ActionMove事件的处理中,调用pullEvent()方法,获取滑动距离、将LinearLayout滑动相应距离(显示header),同时header和footer根据滑动距离进行处理(动画)。如果滑动距离超过header高度,更改状态为松手刷新,同时传递给LoadingLayout进行处理。如果滑动距离不超过header高度,更改状态为下拉刷新,同时传递给LoadingLayout进行处理。
问题五.PullToRefreshListView控件是如何封装给用户直接使用的?如果不是封装的控件,自己如何实现PullToRefresh功能?
问题六.PullToRefreshListView如何实现xml属性设置和读取
问题七.PullToRefreshListView如何实现滚动、刷新等动画
问题八.PullToRefreshListView用到的设计模式
相关文章推荐
- elasticsearch-dsl 2.0.0 介绍
- 【慕课笔记】2-1 进制转换
- oracle trunc函数
- bzoj1096: [ZJOI2007]仓库建设 2011-12-26
- 关于某些时候notifyDataSetChanged不运行的问题
- 公有继承 保护继承 私有继承
- linux线程
- 数组的循环移位
- hdoj 5505 GT and numbers
- 简单插入排序
- 内核裁剪,将自己写的驱动加入内核及按键驱动的代码(arm TQ2440)
- android四大组件之一Serveric
- ZooKeeper学习笔记(一)
- 06-联系人管理(xib应用)
- bzoj 1911: [Apio2010]特别行动队 2011-12-26
- Windows编程基础
- 是否素数
- MySql “Row size too large (> 8126)”
- Elecator
- Qt之QHeaderView自定义排序(终极版)