Android PullToRefresh 下拉刷新,上拉很多其它,支持ScrollView,ListView,可方便拓展GridView,WebView等
在写着东西之前。从网上找到非常多这方面的源代码,可是基本没有找到惬意的。包含在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等的更多相关文章
- Android 下拉刷新上拉载入 多种应用场景 超级大放送(上)
转载请标明原文地址:http://blog.csdn.net/yalinfendou/article/details/47707017 关于Android下拉刷新上拉载入,网上的Demo太多太多了,这 ...
- RecyclerView下拉刷新上拉加载(一)
listview下拉刷新上拉加载扩展(一) http://blog.csdn.net/baiyuliang2013/article/details/50252561 listview下拉刷新上拉加载扩 ...
- 带你实现开发者头条APP(五)--RecyclerView下拉刷新上拉加载
title: 带你实现开发者头条APP(五)--RecyclerView下拉刷新上拉加载 tags: -RecyclerView,下拉刷新,上拉加载更多 grammar_cjkRuby: true - ...
- ListView实现Item上下拖动交换位置 并且实现下拉刷新 上拉加载更多
ListView实现Item上下拖动交换位置 并且实现下拉刷新 上拉加载更多 package com.example.ListViewDragItem; import android.app.Ac ...
- JS+CSS实现的下拉刷新/上拉加载插件
闲来无事,写了一个当下比较常见的下拉刷新/上拉加载的jquery插件,代码记录在这里,有兴趣将代码写成插件与npm包可以留言. 体验地址:http://owenliang.github.io/pull ...
- 基于SwiperJs的H5/移动端下拉刷新上拉加载更多的效果
最早时,公司的H5项目中曾用过点击一个"加载更多"的DOM元素来实现分页的功能,后来又用过网上有人写的一个上拉加载更多的插件,那个插件是页面将要滚动到底部时就自动请求数据并插入到页 ...
- ListView下拉刷新上拉加载更多实现
这篇文章将带大家了解listview下拉刷新和上拉加载更多的实现过程,先看效果(注:图片中listview中的阴影可以加上属性android:fadingEdge="none"去掉 ...
- RecyclerView下拉刷新上拉加载(三)—对Adapter的封装
RecyclerView下拉刷新上拉加载(一) http://blog.csdn.net/baiyuliang2013/article/details/51506036 RecyclerView下拉刷 ...
- listview下拉刷新上拉加载扩展(二)-仿美团外卖
经过前几篇的listview下拉刷新上拉加载讲解,相信你对其实现机制有了一个深刻的认识了吧,那么这篇文章我们来实现一个高级的listview下拉刷新上拉加载-仿新版美团外卖的袋鼠动画: 项目结构: 是 ...
- 基于SwiperJs的H5/移动端下拉刷新上拉加载更多
最早时,公司的H5项目中曾用过点击一个"加载更多"的DOM元素来实现分页的功能,后来又用过网上有人写的一个上拉加载更多的插件,那个插件是页面将要滚动到底部时就自动请求数据并插入到页 ...
随机推荐
- NFS基础优化
一.环境 环境接上篇 https://www.cnblogs.com/suffergtf/p/9486250.html 二.参数详解 1.nfsserver端配置参数详解 [root@nfsserve ...
- RN踩坑
使用夜神 使用夜神作为模拟器,这个模拟器启动就会监听62001端口. 开发工具与模拟器的通信都是通过adb.夜神模拟器的安装目录/bin下有一个adb.exe,android sdk tools下也有 ...
- luogu1963 [NOI2009]变换序列
#include <iostream> #include <cstring> #include <cstdio> using namespace std; int ...
- swift写一个简单的列表unable to dequeue a cell with identifier reuseIdentifier - must register a nib or a cla
报错:unable to dequeue a cell with identifier reuseIdentifier - must register a nib or a class for the ...
- Python+unittest发送测试报告
案例:将E:\Python_script\unittest\Test_Baidu生成的最新测试报告发送到指定邮箱. 我们将之前的unittest的报告生成和Python自动发送邮件结合在一起,就可以完 ...
- Leetcode 357.计算各个位数不同的数字个数
计算各个位数不同的数字个数 给定一个非负整数 n,计算各位数字都不同的数字 x 的个数,其中 0 ≤ x < 10n . 示例: 输入: 2 输出: 91 解释: 答案应为除去 11,22,33 ...
- Leetcode 354.俄罗斯套娃信封问题
俄罗斯套娃信封问题 给定一些标记了宽度和高度的信封,宽度和高度以整数对形式 (w, h) 出现.当另一个信封的宽度和高度都比这个信封大的时候,这个信封就可以放进另一个信封里,如同俄罗斯套娃一样. 请计 ...
- 鼠标移动或者鼠标点击div消失不见排查
点击事件,导致某div或者容器样式隐藏,如果不能直接发现click事件绑定,那么首先排查哪些方法在控制div的样式, 然后看一看哪些方法在调用修改样式的方法. 然后再排查什么在调用修改样式的方法的方法 ...
- C# 方法冒号this的用法
public Class1(string host, int port, string password = null):this() { this.Host=host; this.Port=port ...
- 九度oj 题目1026:又一版 A+B
题目描述: 输入两个不超过整型定义的非负10进制整数A和B(<=231-1),输出A+B的m (1 < m <10)进制数. 输入: 输入格式:测试输入包含若干测试用例.每个测试用例 ...