在写着东西之前。从网上找到非常多这方面的源代码,可是基本没有找到惬意的。包含在GitHub上的比較有名的Android-PullToRefresh-master。思来想去还是自己写吧。当然当中借鉴了一些别的开源代码!

废话不多说,直接上代码。凝视非常全乎,应该不难理解,Demo下载地址在最后:

package com.zs.pulltorefreshtest;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
import android.widget.Scroller; /**
 * 下拉刷新控件,主要測试了ScrollView,代码中已实现ListView下拉和上拉刷新,只是没有怎么測
 * 至于GridView、WebView等,代码中没有实现。只是非常好拓展,在isReadyForPullUp() 和 
 * isReadyForPullDown()这两个方法中增加对应的View的上下边界推断就OK了
 * @author zhangshuo 
 * @version 1.0
 */
public class PullToRefreshView extends RelativeLayout { /**手指滑动距离与控件移动距离的比例为2:1*/
static final float FRICTION = 2.0f; /**显示“下拉刷新”的状态*/
static final int PULL_TO_REFRESH = 0x0;
/**显示“释放刷新”的状态*/
static final int RELEASE_TO_REFRESH = 0x1;
/**用户通过下拉进入的刷新状态*/
static final int REFRESHING = 0x2;
/**用户通过代码强制进入的刷新状态*/
static final int MANUAL_REFRESHING = 0x3; /**私有模式,不提供对外调用。
* 仅用来标示“用户下拉刷新成功后,headerView显示在头部,当用户手指向上滑动时。将headerView尾随用户滑动向上滑动”
* 及“用户上拉很多其它成功后,footerView显示在底部,当用户手指向下滑动时。将footerView尾随用户滑动向下滑动”这两个过程的模式*/
private static final int MODE_PULL_TO_SCROLL_HEADER_OR_FOOTER = 0x0;
/**标示当前支持下拉刷新模式*/
public static final int MODE_PULL_DOWN_TO_REFRESH = 0x1;
/**标示当前支持上拉很多其它模式*/
public static final int MODE_PULL_UP_TO_REFRESH = 0x2;
/**标示当前支持下拉刷新和上拉很多其它两种模式*/
public static final int MODE_BOTH = 0x3; private Context context;
/**滚动对象*/
private Scroller scroller;
/**推断用户手指的移动距离是否足以响应为move*/
private int touchSlop; private float initialMotionY;
private float lastMotionX;
private float lastMotionY;
private boolean isBeingDragged = false; /**记录headerView当前的状态*/
private int headerState = PULL_TO_REFRESH;
/**记录footerView当前的状态*/
private int footerState = PULL_TO_REFRESH;
/**当前所支持的模式*/
private int mode = MODE_PULL_DOWN_TO_REFRESH;
/**当前处于的模式*/
private int currentMode; /**依据不同的mode,contentView所在父View的位置不同,下拉刷新时为1,上拉很多其它时为1,上拉下拉都支持时为2*/
private int index = 1; /**标示当处于刷新状态时,是否须要禁用滑动*/
private boolean disableScrollingWhileRefreshing = false; /**标示是否同意滑动刷新*/
private boolean isPullToRefreshEnabled = true; private LoadingLayout headerLayout;
private LoadingLayout footerLayout;
private int headerHeight; /**记录当处于刷新状态时。用户继续下拉的次数*/
private int pullWithRefreshingCount = 0;
/**记录当处于载入很多其它状态时,用户继续上拉的次数*/
private int pullWithLoadingMoreCount = 0; /**刷新回调接口*/
private OnRefreshListener onRefreshListener; /**载入很多其它回调接口*/
private OnLoadMoreListener onLoadMoreListener; public PullToRefreshView(Context context) {
super(context);
init(context, null);
} public PullToRefreshView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
} /**
* @方法描写叙述: 初始化方法
* @作者:zhangshuo
* @param context
* @param attrs
*/
private void init(Context context, AttributeSet attrs) { scroller = new Scroller(context); touchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); this.context = context; this.addLoadingView();
} /**
* @方法描写叙述: 依据当前模式设置,载入头部和底部布局
* @作者:zhangshuo
*/
public void addLoadingView() { String pullDownLabel = context
.getString(R.string.pull_to_refresh_pull_down_label);
String refreshingDownLabel = context
.getString(R.string.pull_to_refresh_refreshing_down_label);
String releaseDownLabel = context
.getString(R.string.pull_to_refresh_release_down_label);
String pullUpLabel = context
.getString(R.string.pull_to_refresh_pull_up_label);
String refreshingUpLabel = context
.getString(R.string.pull_to_refresh_refreshing_up_label);
String releaseUpLabel = context
.getString(R.string.pull_to_refresh_release_up_label); /*载入头部和底部View*/
if (mode == MODE_PULL_DOWN_TO_REFRESH || mode == MODE_BOTH) {
headerLayout = new LoadingLayout(context,
MODE_PULL_DOWN_TO_REFRESH, releaseDownLabel, pullDownLabel,
refreshingDownLabel);
addView(headerLayout, 0, new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
measureView(headerLayout);
headerHeight = headerLayout.getMeasuredHeight();
}
if (mode == MODE_PULL_UP_TO_REFRESH || mode == MODE_BOTH) {
footerLayout = new LoadingLayout(context, MODE_PULL_UP_TO_REFRESH,
releaseUpLabel, pullUpLabel, refreshingUpLabel);
RelativeLayout.LayoutParams lp2 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
lp2.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
addView(footerLayout, lp2);
measureView(footerLayout);
headerHeight = footerLayout.getMeasuredHeight();
} /*隐藏头部和底部View*/
switch (mode) {
case MODE_BOTH:
index = 2;
setPadding(0, -headerHeight, 0, -headerHeight);
break;
case MODE_PULL_UP_TO_REFRESH:
index = 1;
setPadding(0, 0, 0, -headerHeight);
break;
case MODE_PULL_DOWN_TO_REFRESH:
default:
index = 1;
setPadding(0, -headerHeight, 0, 0);
break;
} } /**
* 在头部和底部View增加完毕后。又一次布局。以避免在隐藏headerView和footerView时会把一部分内容(contentView)隐藏
*/
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// TODO Auto-generated method stub
super.onLayout(changed, l, t, r, b);
View contentView = null;
RelativeLayout.LayoutParams lp1 = null;
switch (mode) {
case MODE_BOTH:
contentView = this.getChildAt(index);
lp1 = (LayoutParams) contentView.getLayoutParams();
lp1.setMargins(0, headerHeight, 0, headerHeight);
break;
case MODE_PULL_UP_TO_REFRESH:
contentView = this.getChildAt(index);
lp1 = (LayoutParams) contentView.getLayoutParams();
lp1.setMargins(0, 0, 0, headerHeight);
break;
case MODE_PULL_DOWN_TO_REFRESH:
default:
contentView = this.getChildAt(index);
lp1 = (LayoutParams) contentView.getLayoutParams();
lp1.setMargins(0, headerHeight, 0, 0);
break;
}
} private void measureView(View child) {
ViewGroup.LayoutParams p = child.getLayoutParams();
if (p == null) {
p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
} int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0, p.width);
int lpHeight = p.height;
int childHeightSpec;
if (lpHeight > 0) {
childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight,
MeasureSpec.EXACTLY);
} else {
childHeightSpec = MeasureSpec.makeMeasureSpec(0,
MeasureSpec.UNSPECIFIED);
}
child.measure(childWidthSpec, childHeightSpec);
} @Override
public final boolean onInterceptTouchEvent(MotionEvent event) { Log.e("Intercept", "start"); if (!isPullToRefreshEnabled) {
return false;
} if ((isLoadingMore() || isRefreshing()) && disableScrollingWhileRefreshing) {
return true;
} final int action = event.getAction(); if (action == MotionEvent.ACTION_CANCEL
|| action == MotionEvent.ACTION_UP) {
isBeingDragged = false;
return false;
} if (action != MotionEvent.ACTION_DOWN && isBeingDragged) {
return true;
} switch (action) {
case MotionEvent.ACTION_DOWN: {
Log.e("Intercept", "down");
if (isReadyForPull()) {
lastMotionY = initialMotionY = event.getY();
lastMotionX = event.getX();
isBeingDragged = false;
}
break;
}
case MotionEvent.ACTION_MOVE: {
Log.e("Intercept", "move");
if (isReadyForPull()) {
final float y = event.getY();
final float dy = y - lastMotionY;
final float yDiff = Math.abs(dy);
final float xDiff = Math.abs(event.getX() - lastMotionX); if (yDiff > touchSlop && yDiff > xDiff) {
if ((mode == MODE_PULL_DOWN_TO_REFRESH || mode == MODE_BOTH)
&& dy >= 0.0001f && isReadyForPullDown()) {
/*能够下拉刷新*/
lastMotionY = y;
isBeingDragged = true;
currentMode = MODE_PULL_DOWN_TO_REFRESH;
} else if ((mode == MODE_PULL_UP_TO_REFRESH || mode == MODE_BOTH)
&& dy <= 0.0001f && isReadyForPullUp()) {
/*能够上拉很多其它*/
lastMotionY = y;
isBeingDragged = true;
currentMode = MODE_PULL_UP_TO_REFRESH;
}else if((isRefreshing() && getScrollY() < 0)|| (isLoadingMore() && getScrollY() > 0)){
/*当前headerView或footerView处于显示状态,开启尾随手指滑动模式*/
lastMotionY = y;
isBeingDragged = true;
currentMode = MODE_PULL_TO_SCROLL_HEADER_OR_FOOTER;
}
}
}
break;
}
}
return isBeingDragged;
} @Override
public final boolean onTouchEvent(MotionEvent event) {
Log.e("Touch", "start");
if (!isPullToRefreshEnabled) {
return false;
} if (isRefreshing() && disableScrollingWhileRefreshing) {
return true;
} if (event.getAction() == MotionEvent.ACTION_DOWN
&& event.getEdgeFlags() != 0) {
return false;
} switch (event.getAction()) { case MotionEvent.ACTION_DOWN: {
Log.e("Touch", "down");
if (isReadyForPull()) {
lastMotionY = initialMotionY = event.getY();
return true;
}
break;
}
case MotionEvent.ACTION_MOVE: {
Log.e("Touch", "move");
if (isBeingDragged) {
lastMotionY = event.getY();
this.pullEvent();
return true;
}
break;
}
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP: {
Log.e("Touch", "up");
if (isBeingDragged) {
isBeingDragged = false; if(isRefreshing() && pullWithRefreshingCount == 0){
pullWithRefreshingCount = 1;
}
if(isLoadingMore() && pullWithLoadingMoreCount == 0){
pullWithLoadingMoreCount = 1;
} switch (currentMode) {
case MODE_PULL_TO_SCROLL_HEADER_OR_FOOTER:
/*将headerView和footerView隐藏*/
smoothScrollTo(0);
break;
case MODE_PULL_UP_TO_REFRESH:
/*推断是否激活载入很多其它*/
if (footerState == RELEASE_TO_REFRESH && null != onLoadMoreListener) {
setLoadingMoreInternal(true);
onLoadMoreListener.onLoadMore();
} else {
smoothScrollTo(0);
}
break;
case MODE_PULL_DOWN_TO_REFRESH:
/*推断是否激活刷新*/
if (headerState == RELEASE_TO_REFRESH && null != onRefreshListener) {
setRefreshingInternal(true);
onRefreshListener.onRefresh();
} else {
smoothScrollTo(0);
}
break;
} return true;
}
break;
}
} return false;
} /**
* @方法描写叙述: 处理用户滑动的方法
* @作者:zhangshuo
*
* @return
*/
private boolean pullEvent() { final int newHeight;
final int oldHeight = this.getScrollY(); switch (currentMode) {
case MODE_PULL_TO_SCROLL_HEADER_OR_FOOTER:
newHeight = Math.round((initialMotionY - lastMotionY));
break;
case MODE_PULL_UP_TO_REFRESH:
newHeight = Math.round(Math.max(initialMotionY - lastMotionY, 0)
/ FRICTION);
break;
case MODE_PULL_DOWN_TO_REFRESH:
default:
newHeight = Math.round(Math.min(initialMotionY - lastMotionY, 0)
/ FRICTION);
break;
} if(isRefreshing() && pullWithRefreshingCount == 0){
/*处于刷新状态下,第一次继续下拉。此时headerView已经显示在头部*/
if((-headerHeight + newHeight) < 0){
scrollTo(-headerHeight + newHeight);
}else{
scrollTo(0);
if(((ScrollView)getChildAt(index)).getChildAt(0).getHeight() > getChildAt(index).getHeight()){
getChildAt(index).scrollTo(0, newHeight - headerHeight);
}
}
}else if(isLoadingMore() && pullWithLoadingMoreCount == 0){
/*处于刷新状态下。第一次继续下拉。此时headerView已经显示在头部*/
if((headerHeight + newHeight) > 0){
scrollTo(headerHeight + newHeight);
}else{
scrollTo(0);
if(((ScrollView)getChildAt(index)).getChildAt(0).getHeight() > getChildAt(index).getHeight()){
getChildAt(index).scrollTo(0, newHeight + headerHeight + ((ScrollView)getChildAt(index)).getChildAt(0).getHeight() - getChildAt(index).getHeight());
}
}
}else{
scrollTo(newHeight);
} if (newHeight != 0) { switch (currentMode) {
case MODE_PULL_UP_TO_REFRESH:
if (footerState == PULL_TO_REFRESH && headerHeight < Math.abs(newHeight)) {
footerState = RELEASE_TO_REFRESH;
footerLayout.releaseToRefresh();
return true; } else if (footerState == RELEASE_TO_REFRESH
&& headerHeight >= Math.abs(newHeight)) {
footerState = PULL_TO_REFRESH;
footerLayout.pullToRefresh();
return true;
}
break;
case MODE_PULL_DOWN_TO_REFRESH:
if (headerState == PULL_TO_REFRESH && headerHeight < Math.abs(newHeight)) {
headerState = RELEASE_TO_REFRESH;
headerLayout.releaseToRefresh();
return true; } else if (headerState == RELEASE_TO_REFRESH
&& headerHeight >= Math.abs(newHeight)) {
headerState = PULL_TO_REFRESH;
headerLayout.pullToRefresh();
return true;
}
break;
} } return oldHeight != newHeight;
} /**
* @方法描写叙述: 推断当前状态能否够进行上拉很多其它或下拉刷新的滑动操作
* @作者:zhangshuo
* @return
*/
private boolean isReadyForPull() {
switch (mode) {
case MODE_PULL_DOWN_TO_REFRESH:
return isReadyForPullDown();
case MODE_PULL_UP_TO_REFRESH:
return isReadyForPullUp();
case MODE_BOTH:
return isReadyForPullUp() || isReadyForPullDown();
}
return false;
} /**
* @方法描写叙述: 推断当前状态能否够进行下拉刷新操作
* @作者:zhangshuo
* @return
*/
private boolean isReadyForPullDown() {
// TODO Auto-generated method stub
if (getChildCount() > 1) {
Log.e("Ready--down", String.valueOf(getChildCount()));
View childView = this.getChildAt(index);
if (childView instanceof ListView) {
int top = ((ListView) childView).getChildAt(0).getTop();
int pad = ((ListView) childView).getListPaddingTop();
if ((Math.abs(top - pad)) < 3
&& ((ListView) childView).getFirstVisiblePosition() == 0) {
return true;
} else {
return false;
}
} else if (childView instanceof ScrollView) {
Log.e("Ready--down", "scrollView");
if (((ScrollView) childView).getScrollY() == 0) {
return true;
} else {
return false;
}
} }
return false;
} /**
* @方法描写叙述:推断当前状态能否够上拉很多其它的滑动操作
* @作者:zhangshuo
* @return
*/
private boolean isReadyForPullUp() {
// TODO Auto-generated method stub
if (getChildCount() > 1) {
Log.e("Ready--up", String.valueOf(getChildCount()));
View childView = this.getChildAt(index);
if (childView instanceof ListView) {
int top = ((ListView) childView).getChildAt(
((ListView) childView).getCount()).getBottom();
int pad = ((ListView) childView).getListPaddingBottom();
if ((Math.abs(top - pad)) < 3
&& ((ListView) childView).getFirstVisiblePosition() == ((ListView) childView)
.getCount()) {
return true;
} else {
return false;
}
} else if (childView instanceof ScrollView) {
Log.e("Ready--up", "scrollView");
int off = ((ScrollView) childView).getScrollY()
+ ((ScrollView) childView).getHeight()
- ((ScrollView) childView).getChildAt(0).getHeight();
if (off >= 0) {
return true;
} else {
return false;
}
} }
return false;
} /**
* @方法描写叙述: 是否同意上拉很多其它或下拉刷新的滑动操作
* @作者:zhangshuo
* @return
*/
public final boolean isPullToRefreshEnabled() {
return isPullToRefreshEnabled;
} /**
* @方法描写叙述: 当处于刷新状态时,是否须要禁用滑动
* @作者:zhangshuo
* @return
*/
public final boolean isDisableScrollingWhileRefreshing() {
return disableScrollingWhileRefreshing;
} /**
* @方法描写叙述: 当前正处于刷新中
* @作者:zhangshuo
* @return
*/
public final boolean isRefreshing() {
return headerState == REFRESHING || headerState == MANUAL_REFRESHING;
} /**
* @方法描写叙述: 当前正处于载入很多其它中
* @作者:zhangshuo
* @return
*/
public final boolean isLoadingMore() {
return footerState == REFRESHING || footerState == MANUAL_REFRESHING;
} /**
* @方法描写叙述: 设置当处于刷新状态时。是否须要禁用滑动
* @作者:zhangshuo
* @param disableScrollingWhileRefreshing
*/
public final void setDisableScrollingWhileRefreshing(
boolean disableScrollingWhileRefreshing) {
this.disableScrollingWhileRefreshing = disableScrollingWhileRefreshing;
} /**
* @方法描写叙述: 结束刷新状态
* @作者:zhangshuo
*
*/
public final void onRefreshComplete() {
if (headerState != PULL_TO_REFRESH) {
resetHeader();
}
pullWithRefreshingCount = 0;
} /**
* @方法描写叙述: 结束载入很多其它状态
* @作者:zhangshuo
*
*/
public final void onLoadMoreComplete() {
if (footerState != PULL_TO_REFRESH) {
resetFooter();
}
pullWithLoadingMoreCount = 0;
} /**
* @方法描写叙述: 设置否同意滑动刷新
* @作者:zhangshuo
* @param enable
*/
public final void setPullToRefreshEnabled(boolean enable) {
this.isPullToRefreshEnabled = enable;
} /**
* @方法描写叙述: 强制设置为刷新状态
* @作者:zhangshuo
*/
public final void setRefreshing() {
this.setRefreshing(true);
} /**
* @方法描写叙述: 强制设置为载入很多其它状态
* @作者:zhangshuo
*/
public final void setLoadingMore(){
this.setLoadingMore(true);
} /**
* @方法描写叙述: 强制设置为刷新状态
* @作者:zhangshuo
* @param doScroll
*/
public final void setRefreshing(boolean doScroll) {
if (!isRefreshing()) {
setRefreshingInternal(doScroll);
headerState = MANUAL_REFRESHING;
}
} /**
* @方法描写叙述: 强制设置为载入很多其它状态
* @作者:zhangshuo
* @param doScroll
*/
public final void setLoadingMore(boolean doScroll) {
if (!isLoadingMore()) {
setLoadingMoreInternal(doScroll);
footerState = MANUAL_REFRESHING;
}
} protected final int getCurrentMode() {
return currentMode;
} protected final LoadingLayout getFooterLayout() {
return footerLayout;
} protected final LoadingLayout getHeaderLayout() {
return headerLayout;
} protected final int getHeaderHeight() {
return headerHeight;
} protected final int getMode() {
return mode;
} /**
* @方法描写叙述: 重置headerView
* @作者:zhangshuo
*/
protected void resetHeader() {
headerState = PULL_TO_REFRESH;
isBeingDragged = false; if (null != headerLayout) {
headerLayout.reset();
} smoothScrollTo(0);
} /**
* @方法描写叙述: 重置footerView
* @作者:zhangshuo
*/
protected void resetFooter() {
footerState = PULL_TO_REFRESH;
isBeingDragged = false; if (null != footerLayout) {
footerLayout.reset();
} smoothScrollTo(0);
} /**
* @方法描写叙述: 强制设置为刷新状态,并显示出headerView
* @作者:zhangshuo
* @param doScroll
*/
protected void setRefreshingInternal(boolean doScroll) {
headerState = REFRESHING;
pullWithRefreshingCount = 0; if (null != headerLayout) {
headerLayout.refreshing();
} if (doScroll) {
smoothScrollTo(-headerHeight);
}
} /**
* @方法描写叙述: 强制设置为载入很多其它状态,并显示出footerView
* @作者:zhangshuo
* @param doScroll
*/
protected void setLoadingMoreInternal(boolean doScroll) {
footerState = REFRESHING;
pullWithLoadingMoreCount = 0; if (null != footerLayout) {
footerLayout.refreshing();
} if (doScroll) {
smoothScrollTo(headerHeight);
}
} protected final void scrollTo(int y) {
scrollTo(0, y);
} protected final void smoothScrollTo(int y) { scroller.startScroll(0, getScrollY(), 0, -(getScrollY() - y), 500);
invalidate(); } @Override
public void computeScroll() {
// TODO Auto-generated method stub
if (scroller.computeScrollOffset()) {
scrollTo(0, this.scroller.getCurrY());
postInvalidate();
}
} /**
* @方法描写叙述: 设置刷新回调接口
* @作者:zhangshuo
* @param listener
*/
public final void setOnRefreshListener(OnRefreshListener listener) {
this.onRefreshListener = listener;
} /**
* @方法描写叙述: 设置载入很多其它回调接口
* @作者:zhangshuo
* @param listener
*/
public final void setOnLoadMoreListener(OnLoadMoreListener listener){
this.onLoadMoreListener = listener;
} /**
* @CLASS:OnRefreshListener
* @描写叙述: 刷新回调接口
* @作者:zhangshuo
* @版本号:v1.0
* @日期:2014年7月15日 上午11:59:50
*/
public static interface OnRefreshListener { public void onRefresh(); } /**
* @CLASS:OnLoadMoreListener
* @描写叙述: 载入很多其它回调接口
* @作者:zhangshuo
* @版本号:v1.0
* @日期:2014年7月15日 下午12:00:06
*/
public static interface OnLoadMoreListener { public void onLoadMore(); } }
<span style="font-size:24px;">因为时间关系,我主要測试了ScrollView,代码中已实现ListView下拉和上拉刷新,只是没有怎么測。</span>
<span style="font-size:24px;">至于GridView、WebView等,代码中没有实现。只是非常好拓展,在isReadyForPullUp() 和 
isReadyForPullDown()这两个方法中增加对应的View的上下边界推断就OK了!</span>

源代码下载地址:http://download.csdn.net/detail/super_spy/7642641

Android PullToRefresh 下拉刷新,上拉很多其它,支持ScrollView,ListView,可方便拓展GridView,WebView等的更多相关文章

  1. Android 下拉刷新上拉载入 多种应用场景 超级大放送(上)

    转载请标明原文地址:http://blog.csdn.net/yalinfendou/article/details/47707017 关于Android下拉刷新上拉载入,网上的Demo太多太多了,这 ...

  2. RecyclerView下拉刷新上拉加载(一)

    listview下拉刷新上拉加载扩展(一) http://blog.csdn.net/baiyuliang2013/article/details/50252561 listview下拉刷新上拉加载扩 ...

  3. 带你实现开发者头条APP(五)--RecyclerView下拉刷新上拉加载

    title: 带你实现开发者头条APP(五)--RecyclerView下拉刷新上拉加载 tags: -RecyclerView,下拉刷新,上拉加载更多 grammar_cjkRuby: true - ...

  4. ListView实现Item上下拖动交换位置 并且实现下拉刷新 上拉加载更多

    ListView实现Item上下拖动交换位置  并且实现下拉刷新  上拉加载更多 package com.example.ListViewDragItem; import android.app.Ac ...

  5. JS+CSS实现的下拉刷新/上拉加载插件

    闲来无事,写了一个当下比较常见的下拉刷新/上拉加载的jquery插件,代码记录在这里,有兴趣将代码写成插件与npm包可以留言. 体验地址:http://owenliang.github.io/pull ...

  6. 基于SwiperJs的H5/移动端下拉刷新上拉加载更多的效果

    最早时,公司的H5项目中曾用过点击一个"加载更多"的DOM元素来实现分页的功能,后来又用过网上有人写的一个上拉加载更多的插件,那个插件是页面将要滚动到底部时就自动请求数据并插入到页 ...

  7. ListView下拉刷新上拉加载更多实现

    这篇文章将带大家了解listview下拉刷新和上拉加载更多的实现过程,先看效果(注:图片中listview中的阴影可以加上属性android:fadingEdge="none"去掉 ...

  8. RecyclerView下拉刷新上拉加载(三)—对Adapter的封装

    RecyclerView下拉刷新上拉加载(一) http://blog.csdn.net/baiyuliang2013/article/details/51506036 RecyclerView下拉刷 ...

  9. listview下拉刷新上拉加载扩展(二)-仿美团外卖

    经过前几篇的listview下拉刷新上拉加载讲解,相信你对其实现机制有了一个深刻的认识了吧,那么这篇文章我们来实现一个高级的listview下拉刷新上拉加载-仿新版美团外卖的袋鼠动画: 项目结构: 是 ...

  10. 基于SwiperJs的H5/移动端下拉刷新上拉加载更多

    最早时,公司的H5项目中曾用过点击一个"加载更多"的DOM元素来实现分页的功能,后来又用过网上有人写的一个上拉加载更多的插件,那个插件是页面将要滚动到底部时就自动请求数据并插入到页 ...

随机推荐

  1. Qtopia移植

    Qtopia 是Trolltech 公司为采用嵌入式Linux操作系统的消费电子设备而开发的综合应用平台, Qtopia包含完整的应用层.灵活的用户界面.窗口操作系统.应用程序启动程序以及开发框架.下 ...

  2. Windows Server 2008 R2+SQL Server 2014 R2升级到Windows Server 2016+SQL Server 2016

    环境: 操作系统:Windows Server 2008 R2 数据库:SQL Server 2014 因SQL Server 2016可以无域创建AlwaysOn集群,集群只剩下单节点也不会挂掉,故 ...

  3. UnicodeDecodeError: 'ascii' codec can't decode byte 0xe6 in position 287: ordinal not in range(128)

    python的str默认是ascii编码,和unicode编码冲突,就会报这个错误. import sys reload(sys) sys.setdefaultencoding('utf8')

  4. Python模块目录

    阅读目录 模块 模块语法 常用模块 collections模块 time模块 random模块 os模块 sys模块 序列化模块 shelve模块 pickle模块 json模块 configpars ...

  5. day12-图

  6. cdev_add

    初始化 cdev 后,需要把它添加到系统中去.为此可以调用 cdev_add()函数.传入cdev 结构的指针,起始设备编号,以及设备编号范围. 函数首先将分配的设备号与设备数目保存进cdev结构体中 ...

  7. python 多线程、多进程、协程性能对比(以爬虫为例)

    基本配置:阿里云服务器低配,单核2G内存 首先是看协程的效果: import requests import lxml.html as HTML import sys import time impo ...

  8. 算法复习——序列分治(ssoj光荣的梦想)

    题目: 题目描述 Prince对他在这片大陆上维护的秩序感到满意,于是决定启程离开艾泽拉斯.在他动身之前,Prince决定赋予King_Bette最强大的能量以守护世界.保卫这里的平衡与和谐.在那个时 ...

  9. java面试题之hashcode相等两个类一定相等吗?equals呢?相反呢?

    答:hashcode相等,两个类不一定相等,equals也不一定相等: 反过来,equals相等,hashcode一定相等

  10. FreeMarker数据模板引擎全面教程mark

    http://blog.csdn.net/fhx007/article/details/7902040/#comments 以下内容全部是网上收集: FreeMarker的模板文件并不比HTML页面复 ...