GridView基于pulltorefresh实现下拉刷新 上拉加载更多功能(推荐)

原理和listview一样 ,都是重写Android原生控件

Activity

package com.example.refreshgridview;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.os.Bundle;
import android.widget.GridView;
import android.widget.Toast;
import com.example.refreshgridview.PullToRefreshBase.OnRefreshListener;
public class MainActivity extends Activity {
private PullToRefreshGridView mPullRefreshGridView;
private GridView mGridView;
private GridViewAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPullRefreshGridView = (PullToRefreshGridView) findViewById(R.id.video_gridView);
mPullRefreshGridView.init(PullToRefreshGridView.MODE_BOTH);
mGridView = mPullRefreshGridView.getRefreshableView();
mPullRefreshGridView.setOnRefreshListener(refreshListener);
List<String> list = new ArrayList<String>();
for (int i = 0; i < 40; i++) {
list.add(i+"");
}
adapter = new GridViewAdapter(MainActivity.this,list);
mGridView.setAdapter(adapter);
}
private OnRefreshListener refreshListener = new OnRefreshListener() {
@Override
public void onRefresh(int mode) {
if (PullToRefreshGridView.MODE_PULL_DOWN_TO_REFRESH == mPullRefreshGridView.getCurrentMode()) {
Toast.makeText(MainActivity.this, "下拉刷新", Toast.LENGTH_SHORT).show();
mPullRefreshGridView.onRefreshComplete();
} else if (mode == PullToRefreshGridView.MODE_PULL_UP_TO_REFRESH) {
// 加载更多
Toast.makeText(MainActivity.this, "上拉加载更多", Toast.LENGTH_SHORT).show();
mPullRefreshGridView.onRefreshComplete();
}
}
};
}

adapter

package com.example.refreshgridview;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.content.Intent;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
public class GridViewAdapter extends BaseAdapter {
private List<String> mList = new ArrayList<String>();
private Context mContext;
public GridViewAdapter(Context context,List<String> list) {
super();
this.mContext = context;
this.mList = list;
}
@Override
public int getCount() {
return mList.size();
}
@Override
public String getItem(int position) {
return mList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ChildHolderOne holder;
if (convertView == null) {
convertView = LayoutInflater.from(mContext).inflate(R.layout.item_grid_live_show, parent, false);
holder = new ChildHolderOne();
holder.tvTitle = (TextView)convertView.findViewById(R.id.title_tv);
convertView.setTag(holder);
} else {
holder = (ChildHolderOne) convertView.getTag();
}
return convertView;
}
class ChildHolderOne {
TextView tvTitle;
}
}

PullToRefreshGridView

package com.example.refreshgridview;
import android.content.Context;
import android.util.AttributeSet;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View;
import android.widget.GridView;
public class PullToRefreshGridView extends PullToRefreshAdapterViewBase<GridView> {
class InternalGridView extends GridView implements EmptyViewMethodAccessor {
public InternalGridView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public void setEmptyView(View emptyView) {
PullToRefreshGridView.this.setEmptyView(emptyView);
}
@Override
public void setEmptyViewInternal(View emptyView) {
super.setEmptyView(emptyView);
}
@Override
public ContextMenuInfo getContextMenuInfo() {
return super.getContextMenuInfo();
}
}
public PullToRefreshGridView(Context context) {
super(context);
}
public PullToRefreshGridView(Context context, int mode) {
super(context, mode);
}
public PullToRefreshGridView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected final GridView createRefreshableView(Context context, AttributeSet attrs) {
GridView gv = new InternalGridView(context, attrs);
// Use Generated ID (from res/values/ids.xml)
gv.setId(R.id.gridview);
return gv;
}
@Override
public ContextMenuInfo getContextMenuInfo() {
return ((InternalGridView) getRefreshableView()).getContextMenuInfo();
}
}

PullToRefreshBase

package com.example.refreshgridview;
import android.content.Context;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Interpolator;
import android.widget.LinearLayout;
import android.widget.TextView;
/**
*
* @author zlw
*/
public abstract class PullToRefreshBase<T extends View> extends LinearLayout {
final class SmoothScrollRunnable implements Runnable {
static final int ANIMATION_DURATION_MS = 190;
static final int ANIMATION_FPS = 1000 / 60;
private final Interpolator interpolator;
private final int scrollToY;
private final int scrollFromY;
private final Handler handler;
private boolean continueRunning = true;
private long startTime = -1;
private int currentY = -1;
public SmoothScrollRunnable(Handler handler, int fromY, int toY) {
this.handler = handler;
this.scrollFromY = fromY;
this.scrollToY = toY;
this.interpolator = new AccelerateDecelerateInterpolator();
}
@Override
public void run() {
/**
* Only set startTime if this is the first time we're starting, else
* actually calculate the Y delta
*/
if (startTime == -1) {
startTime = System.currentTimeMillis();
} else {
/**
* We do do all calculations in long to reduce software float
* calculations. We use 1000 as it gives us good accuracy and
* small rounding errors
*/
long normalizedTime = (1000 * (System.currentTimeMillis() - startTime))
/ ANIMATION_DURATION_MS;
normalizedTime = Math.max(Math.min(normalizedTime, 1000), 0);
final int deltaY = Math
.round((scrollFromY - scrollToY)
* interpolator
.getInterpolation(normalizedTime / 1000f));
this.currentY = scrollFromY - deltaY;
setHeaderScroll(currentY);
}
// If we're not at the target Y, keep going...
if (continueRunning && scrollToY != currentY) {
handler.postDelayed(this, ANIMATION_FPS);
}
}
public void stop() {
this.continueRunning = false;
this.handler.removeCallbacks(this);
}
};
// ===========================================================
// Constants
// ===========================================================
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;
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;
// ===========================================================
// Fields
// ===========================================================
private int touchSlop;
private float initialMotionY;
private float lastMotionX;
private float lastMotionY;
private boolean isBeingDragged = false;
private int state = PULL_TO_REFRESH;
private int mode = MODE_PULL_UP_TO_REFRESH;
private int currentMode;
private boolean disableScrollingWhileRefreshing = true;
T refreshableView;
private boolean isPullToRefreshEnabled = true;
private LoadingLayout headerLayout;
private LoadingLayout footerLayout;
private int headerHeight;
private final Handler handler = new Handler();
private OnRefreshListener onRefreshListener;
private SmoothScrollRunnable currentSmoothScrollRunnable;
// ===========================================================
// Constructors
// ===========================================================
public PullToRefreshBase(Context context) {
super(context);
init(context, null);
}
public PullToRefreshBase(Context context, int mode) {
super(context);
this.mode = mode;
init(context, null);
}
public PullToRefreshBase(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
// ===========================================================
// Getter & Setter
// ===========================================================
/**
* Deprecated. Use {@link #getRefreshableView()} from now on.
*
* @deprecated
* @return The Refreshable View which is currently wrapped
*/
public final T getAdapterView() {
return refreshableView;
}
/**
* Get the Wrapped Refreshable View. Anything returned here has already been
* added to the content view.
*
* @return The View which is currently wrapped
*/
public final T getRefreshableView() {
return refreshableView;
}
/**
* Whether Pull-to-Refresh is enabled
*
* @return enabled
*/
public final boolean isPullToRefreshEnabled() {
return isPullToRefreshEnabled;
}
/**
* Returns whether the widget has disabled scrolling on the Refreshable View
* while refreshing.
*
* @return true if the widget has disabled scrolling while refreshing
*/
public final boolean isDisableScrollingWhileRefreshing() {
return disableScrollingWhileRefreshing;
}
/**
* Returns whether the Widget is currently in the Refreshing state
*
* @return true if the Widget is currently refreshing
*/
public final boolean isRefreshing() {
return state == REFRESHING || state == MANUAL_REFRESHING;
}
/**
* By default the Widget disabled scrolling on the Refreshable View while
* refreshing. This method can change this behaviour.
*
* @param disableScrollingWhileRefreshing
* - true if you want to disable scrolling while refreshing
*/
public final void setDisableScrollingWhileRefreshing(
boolean disableScrollingWhileRefreshing) {
this.disableScrollingWhileRefreshing = disableScrollingWhileRefreshing;
}
/**
* Mark the current Refresh as complete. Will Reset the UI and hide the
* Refreshing View
*/
public final void onRefreshComplete() {
if (state != PULL_TO_REFRESH) {
resetHeader();
if (onShowLayoutListener != null) {
onShowLayoutListener.onDismiss();
}
}
}
/**
* Set OnRefreshListener for the Widget
*
* @param listener
* - Listener to be used when the Widget is set to Refresh
*/
public final void setOnRefreshListener(OnRefreshListener listener) {
onRefreshListener = listener;
}
/**
* auto load headerLayout to refresh
*
* @param listener
*/
public final void setFirstAutoPullUpToRefresh(OnRefreshListener listener) {
setRefreshingInternal(true, MODE_PULL_DOWN_TO_REFRESH);
listener.onRefresh(MODE_PULL_DOWN_TO_REFRESH);
}
/**
* set refreshLable , default use null
*
* @param pullLabel
* @param releaseLabel
* @param refreshingLabel
*/
public void setRefreshLabel(String pullLabel, String releaseLabel,
String refreshingLabel) {
if (pullLabel != null) {
setPullLabel(pullLabel);
}
if (releaseLabel != null) {
setReleaseLabel(releaseLabel);
}
if (refreshingLabel != null) {
setRefreshingLabel(refreshingLabel);
}
}
/**
* A mutator to enable/disable Pull-to-Refresh for the current View
*
* @param enable
* Whether Pull-To-Refresh should be used
*/
public final void setPullToRefreshEnabled(boolean enable) {
this.isPullToRefreshEnabled = enable;
}
/**
* Set Text to show when the Widget is being pulled, and will refresh when
* released
*
* @param releaseLabel
* - String to display
*/
private void setReleaseLabel(String releaseLabel) {
if (null != headerLayout) {
headerLayout.setReleaseLabel(releaseLabel);
}
if (null != footerLayout) {
footerLayout.setReleaseLabel(releaseLabel);
}
}
/**
* Set Text to show when the Widget is being Pulled
*
* @param pullLabel
* - String to display
*/
private void setPullLabel(String pullLabel) {
if (null != headerLayout) {
headerLayout.setPullLabel(pullLabel);
}
if (null != footerLayout) {
footerLayout.setPullLabel(pullLabel);
}
}
/**
* Set Text to show when the Widget is refreshing
*
* @param refreshingLabel
* - String to display
*/
private void setRefreshingLabel(String refreshingLabel) {
if (null != headerLayout) {
headerLayout.setRefreshingLabel(refreshingLabel);
}
if (null != footerLayout) {
footerLayout.setRefreshingLabel(refreshingLabel);
}
}
public final void setRefreshing() {
this.setRefreshing(true);
}
/**
* Sets the Widget to be in the refresh state. The UI will be updated to
* show the 'Refreshing' view.
*
* @param doScroll
* - true if you want to force a scroll to the Refreshing view.
*/
public final void setRefreshing(boolean doScroll) {
if (!isRefreshing()) {
setRefreshingInternal(doScroll);
state = MANUAL_REFRESHING;
}
}
public final boolean hasPullFromTop() {
return currentMode != MODE_PULL_UP_TO_REFRESH;
}
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
@Override
public final boolean onTouchEvent(MotionEvent event) {
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_MOVE: {
if (isBeingDragged) {
if (Math.abs(event.getY() - downLocation) > 5
&& onShowLayoutListener != null) {
onShowLayoutListener.onShow();
}
lastMotionY = event.getY();
this.pullEvent();
return true;
}
break;
}
case MotionEvent.ACTION_DOWN: {
if (isReadyForPull()) {
downLocation = event.getY();
lastMotionY = initialMotionY = event.getY();
return true;
}
break;
}
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP: {
if (isBeingDragged) {
isBeingDragged = false;
if (state == RELEASE_TO_REFRESH && null != onRefreshListener) {
setRefreshingInternal(true);
onRefreshListener.onRefresh(currentMode);
} else {
smoothScrollTo(0);
if (onShowLayoutListener != null) {
onShowLayoutListener.onDismiss();
}
}
return true;
}
break;
}
}
return false;
}
// remeber to down location
private float downLocation = 0;
@Override
public final boolean onInterceptTouchEvent(MotionEvent event) {
if (!isPullToRefreshEnabled) {
return false;
}
if (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_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;
if (mode == MODE_BOTH) {
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;
if (mode == MODE_BOTH) {
currentMode = MODE_PULL_UP_TO_REFRESH;
}
}
}
}
break;
}
case MotionEvent.ACTION_DOWN: {
if (isReadyForPull()) {
lastMotionY = initialMotionY = event.getY();
lastMotionX = event.getX();
isBeingDragged = false;
}
break;
}
case MotionEvent.ACTION_UP:
break;
}
setRefreshLabel(currentMode);
return isBeingDragged;
}
protected void addRefreshableView(Context context, T refreshableView) {
addView(refreshableView, new LinearLayout.LayoutParams(
LayoutParams.FILL_PARENT, 0, 1.0f));
}
/**
* This is implemented by derived classes to return the created View. If you
* need to use a custom View (such as a custom ListView), override this
* method and return an instance of your custom class.
*
* Be sure to set the ID of the view in this method, especially if you're
* using a ListActivity or ListFragment.
*
* @param context
* @param attrs
* AttributeSet from wrapped class. Means that anything you
* include in the XML layout declaration will be routed to the
* created View
* @return New instance of the Refreshable View
*/
protected abstract T createRefreshableView(Context context,
AttributeSet attrs);
public 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;
}
/**
* Implemented by derived class to return whether the View is in a state
* where the user can Pull to Refresh by scrolling down.
*
* @return true if the View is currently the correct state (for example, top
* of a ListView)
*/
protected abstract boolean isReadyForPullDown();
/**
* Implemented by derived class to return whether the View is in a state
* where the user can Pull to Refresh by scrolling up.
*
* @return true if the View is currently in the correct state (for example,
* bottom of a ListView)
*/
protected abstract boolean isReadyForPullUp();
// ===========================================================
// Methods
// ===========================================================
protected void resetHeader() {
state = PULL_TO_REFRESH;
isBeingDragged = false;
if (null != headerLayout) {
headerLayout.reset();
}
if (null != footerLayout) {
footerLayout.reset();
}
smoothScrollTo(0);
}
/**
* unless special requirements to call the method ,default call the method
* {@link #setRefreshingInternal(boolean doScroll)}
*
* @param doScroll
* @param mode
*/
protected void setRefreshingInternal(boolean doScroll, int mode) {
state = REFRESHING;
setRefreshLabel(mode);
if (null != headerLayout) {
headerLayout.refreshing();
}
if (doScroll) {
smoothScrollTo(mode == MODE_PULL_DOWN_TO_REFRESH ? -headerHeight
: headerHeight);
}
}
/**
* set last refresh time
*
* @param time
*/
public void setRefreshTime(String time) {
TextView mHeaderTimeView = (TextView) headerLayout
.findViewById(R.id.xlistview_header_time);
mHeaderTimeView.setText(time);
}
public void setRefreshTime(long time){
TextView mHeaderTimeView = (TextView) headerLayout
.findViewById(R.id.xlistview_header_time);
mHeaderTimeView.setText(TimeUtil.getChatTime(time));
}
protected void setRefreshingInternal(boolean doScroll) {
state = REFRESHING;
setRefreshLabel(currentMode);
if (null != footerLayout) {
footerLayout.refreshing();
}
if (null != headerLayout) {
headerLayout.refreshing();
}
if (doScroll) {
smoothScrollTo(currentMode == MODE_PULL_DOWN_TO_REFRESH ? -headerHeight
: headerHeight);
}
}
private void setRefreshLabel(int mode) {
if (mode == MODE_PULL_DOWN_TO_REFRESH) {
setRefreshLabel("涓嬫媺鍒锋柊", "閲婃斁绔嬪嵆鍒锋柊", "姝e湪鍒锋柊");
}
if (mode == MODE_PULL_UP_TO_REFRESH) {
setRefreshLabel("涓婃媺鑾峰彇鏇村", "鏉惧紑鏄剧ず鏇村", "姝e湪鍔犺浇");
}
}
protected final void setHeaderScroll(int y) {
scrollTo(0, y);
}
protected final void smoothScrollTo(int y) {
if (null != currentSmoothScrollRunnable) {
currentSmoothScrollRunnable.stop();
}
if (this.getScrollY() != y) {
this.currentSmoothScrollRunnable = new SmoothScrollRunnable(
handler, getScrollY(), y);
handler.post(currentSmoothScrollRunnable);
}
}
public void init(int mode) {
// Loading View Strings
String pullLabel = context
.getString(R.string.pull_to_refresh_pull_label);
String refreshingLabel = context
.getString(R.string.pull_to_refresh_refreshing_label);
String releaseLabel = context
.getString(R.string.pull_to_refresh_release_label);
// Add Loading Views
if (mode == MODE_PULL_DOWN_TO_REFRESH || mode == MODE_BOTH) {
headerLayout = new LoadingLayout(context,MODE_PULL_DOWN_TO_REFRESH, releaseLabel, pullLabel,refreshingLabel);
addView(headerLayout, 0, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_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,releaseLabel, pullLabel, refreshingLabel);
addView(footerLayout, new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
measureView(footerLayout);
headerHeight = footerLayout.getMeasuredHeight();
}
// Styleables from XML
if (null != headerLayout) {
// headerLayout.setTextColor(Color.BLACK);
}
if (null != footerLayout) {
// footerLayout.setTextColor(Color.BLACK);
}
// Hide Loading Views
switch (mode) {
case MODE_BOTH:
setPadding(0, -headerHeight, 0, -headerHeight);
break;
case MODE_PULL_UP_TO_REFRESH:
setPadding(0, 0, 0, -headerHeight);
break;
case MODE_PULL_DOWN_TO_REFRESH:
default:
setPadding(0, -headerHeight, 0, 0);
break;
}
// If we're not using MODE_BOTH, then just set currentMode to current
// mode
if (mode != MODE_BOTH) {
currentMode = mode;
}
this.mode = mode;
}
private void init(Context context, AttributeSet attrs) {
this.context = context;
setOrientation(LinearLayout.VERTICAL);
touchSlop = ViewConfiguration.getTouchSlop();
// Refreshable View
// By passing the attrs, we can add ListView/GridView params via XML
refreshableView = this.createRefreshableView(context, attrs);
this.addRefreshableView(context, refreshableView);
}
private Context context;
private void measureView(View child) {
ViewGroup.LayoutParams p = child.getLayoutParams();
if (p == null) {
p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_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);
}
/**
* Actions a Pull Event
*
* @return true if the Event has been handled, false if there has been no
* change
*/
private boolean pullEvent() {
final int newHeight;
final int oldHeight = this.getScrollY();
switch (currentMode) {
case MODE_PULL_UP_TO_REFRESH:
newHeight = Math.round(Math.max(initialMotionY - lastMotionY, 0)
/ FRICTION);
// newHeight = Math.round((initialMotionY - lastMotionY) /
// FRICTION);
break;
case MODE_PULL_DOWN_TO_REFRESH:
default:
newHeight = Math.round(Math.min(initialMotionY - lastMotionY, 0)
/ FRICTION);
// newHeight = Math.round((initialMotionY - lastMotionY) /
// FRICTION);
break;
}
setHeaderScroll(newHeight);
if (newHeight != 0) {
if (state == PULL_TO_REFRESH && headerHeight < Math.abs(newHeight)) {
state = RELEASE_TO_REFRESH;
switch (currentMode) {
case MODE_PULL_UP_TO_REFRESH:
footerLayout.releaseToRefresh();
break;
case MODE_PULL_DOWN_TO_REFRESH:
headerLayout.releaseToRefresh();
break;
}
return true;
} else if (state == RELEASE_TO_REFRESH
&& headerHeight >= Math.abs(newHeight)) {
state = PULL_TO_REFRESH;
switch (currentMode) {
case MODE_PULL_UP_TO_REFRESH:
footerLayout.pullToRefresh();
break;
case MODE_PULL_DOWN_TO_REFRESH:
headerLayout.pullToRefresh();
break;
}
return true;
}
}
return oldHeight != newHeight;
}
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;
}
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
public static interface OnRefreshListener {
public void onRefresh(int mode);
}
private OnShowLayoutListener onShowLayoutListener;
public void setOnShowLayoutListener(OnShowLayoutListener listener) {
this.onShowLayoutListener = listener;
}
public static interface OnShowLayoutListener {
/**
* 鏄惁姝e湪鏄剧ず搴曢儴甯冨眬
*/
public void onShow();
/**
* 鏄惁娑堝け
*/
public void onDismiss();
}
public static interface OnLastItemVisibleListener {
public void onLastItemVisible();
}
@Override
public void setLongClickable(boolean longClickable) {
getRefreshableView().setLongClickable(longClickable);
}
}

主要代码都在上面贴出来了,当然还是一定要有demo

DEMO源码下载

这个源码里面 我把 PullToRefreshExpandableListView 和 PullToRefreshListView 也都放进来了,一样的逻辑。希望对大家有用。如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • Swift版使用ThPullRefresh实现下拉上拉刷新数据

    最近自己写了一个下拉加载最新,上拉加载更多的刷新控件.借鉴了其他优秀开源代码的实现效果比如MJRefresh和DGElasticPullRefresh.主要是为了学习别人的优秀思想. 如何使用: Cocoapods 导入:pod 'ThPullRefresh', 在项目中 import 'ThPullRefresh' 手动导入:将'ThPullRefresh' 文件夹中的所有文件拽入项目中 head与foot基本效果的添加 具体代码如下: override func viewDidLoad()

  • 实例讲解动态加载gridview中的行及其样式

    知识点及实例 复制代码 代码如下: protected void gvSuperAdminSeeInfo_RowDataBound(object sender, GridViewRowEventArgs e) { if (e.Row.RowType != DataControlRowType.DataRow)//判断是否是数据行 { return; } e.Row.Attributes.Add("onmouseover", "this.style.backgroundColo

  • 用JavaScript页面不刷新时全选择,全删除(GridView)

    /* 全选择*/ function SB002SelectAll() { var table = document.getElementById("ctl00_MainContent_grvDevelopKit"); for(var i=1;i<table.rows.length;i++) { var input = table.rows[i].cells[0].getElementsByTagName("input")[0]; input.checked =

  • jquery+ashx无刷新GridView数据显示插件(实现分页、排序、过滤功能)

    理由:jquery简单,兼容性好且容易封装.废话不多说,马上开始我们的Jquery插件编写吧.应该有很多人写过类似的插件,我也是有些模仿flexGrid的形式. 需求:GridView显示数据,无刷新分页,无刷新排序,无刷新过滤(搜索数据),基于ASP.NET(我们这里有ashx一般处理文件来实现). 使用到技术:asp.net2.0, jquery,css 首先写的是jquery插件方面,使用的核心函数还是jquery的ajax函数,方便快捷. 复制代码 代码如下: $.ajax({ type

  • 使用ajax局部刷新gridview进行数据绑定示例

    具体代码如下: 复制代码 代码如下: <% @ Page Language = " C# " %> <! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" > < script runat ="server" &

  • Flutter 给列表增加下拉刷新和上滑加载更多功能

    有状态组件 当 Flutter 的页面需要动态更新数据的时候,就会涉及到 UI 组件需要根据数据变化更新,此时也就意味着组件有了"状态".这就类似 React 的类组件和函数组件(只是后续 React 使用了勾子函数实现了函数组件也可以有状态).在 Flutter 中,组件也分为无状态组件(StatelessWidget)和有状态组件(StatefulWidget),一般尽量使用无状态组件.但是如果组件本身需要维护自身状态的时候,就需要使用有状态组件了.有状态组件的定义形式如下: //

  • Android仿XListView支持下拉刷新和上划加载更多的自定义RecyclerView

    首先给大家展示下效果图,感觉还不错,请继续往下阅读: 下拉刷新:        上划加载        在项目更新的过程中,遇到了一个将XListView换成recyclerView的需求,而且更换完之后大体效果不能变,但是对于下拉刷新这样的效果,谷歌给出的解决方案是把RecyclerView放在一个SwipeRefreshLayout中,但是这样其实是拉下一个小圆形控件实现的,和XListView的header效果不同.在网上找了很多的别人代码,都没有实现我想要的效果,于是自己动手写了一个.

  • GridView基于pulltorefresh实现下拉刷新 上拉加载更多功能(推荐)

    原理和listview一样 ,都是重写Android原生控件 Activity package com.example.refreshgridview; import java.util.ArrayList; import java.util.List; import android.app.Activity; import android.os.Bundle; import android.widget.GridView; import android.widget.Toast; import

  • android使用PullToRefresh框架实现ListView下拉刷新上拉加载更多

    本文实例为大家分享了Android实现ListView下拉刷新上拉加载更多的具体代码,供大家参考,具体内容如下 其实谷歌官方目前已经推出ListView下拉刷新框架SwipeRefreshLayout,想了解的朋友可以点击 android使用SwipeRefreshLayout实现ListView下拉刷新上拉加载了解一下: 大家不难发现当你使用SwipeRefreshLayout下拉的时候布局文件不会跟着手势往下滑,而且想要更改这个缺陷好像非常不容易. 虽然SwipeRefreshLayout非

  • android RecyclerView侧滑菜单,滑动删除,长按拖拽,下拉刷新上拉加载

    本文介绍的库中的侧滑效果借鉴自SwipeMenu,并对SipwMenu的源码做了修改与Bug修复,然后才开发出的SwipeRecyclerView. 需要说明的是,本库没有对RecyclerView做大的修改,只是ItemView的封装.看起来是对RecyclerView的修改,其实仅仅是为RecyclerView添加了使用的方法API而已. 本库已经更新了三个版本了,会一直维护下去,根据小伙伴的要求,以后也会添加一些其它功能. SwipeRecyclerView将完美解决这些问题: 以下功能全

  • 基于iScroll实现下拉刷新和上滑加载效果

    本文实例为大家分享了iScroll下拉刷新上滑加载展示的具体代码,供大家参考,具体内容如下 html代码: <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta name="viewport" content="width=devi

  • 基于vue封装下拉刷新上拉加载组件

    基于vue和原生javascript封装的下拉刷新上拉加载组件,供大家参考,具体内容如下 upTilte插槽是下拉刷新的自定义内容放的地方 downTilte插槽是上拉加载的自定义内容放的地方 默认插槽为列表内容区域 组件代码如下 <template> <div class="refresh" id="refresh"> <slot name="upTilte"></slot> <slot&g

  • Android下拉刷新上拉加载控件(适用于所有View)

    前面写过一篇关于下拉刷新控件的文章下拉刷新控件终结者:PullToRefreshLayout,后来看到好多人还有上拉加载更多的需求,于是就在前面下拉刷新控件的基础上进行了改进,加了上拉加载的功能.不仅如此,我已经把它改成了对所有View都通用!可以随心所欲使用这两个功能~~ 我做了一个大集合的demo,实现了ListView.GridView.ExpandableListView.ScrollView.WebView.ImageView.TextView的下拉刷新和上拉加载.后面会提供demo的

  • JS+CSS实现下拉刷新/上拉加载插件

    闲来无事,写了一个当下比较常见的下拉刷新/上拉加载的jquery插件,代码记录在这里,有兴趣将代码写成插件与npm包可以留言. 体验地址:http://owenliang.github.io/pullToRefresh/ 项目地址:https://github.com/owenliang/pullToRefresh 实现注意: 利用transition做动画时,优先使用transform:translate取代top,后者动画流畅度存在问题. 各移动浏览器对手势触摸的处理不同(简单罗列如下),但

  • RecyclerView下拉刷新上拉加载

    一 .前言 最近实在太忙,一个多礼拜没有更新文章了,于是今晚加班加点把demo写出来,现在都12点了才开始写文章. 1.我们的目标 把RecyclerView下拉刷新上拉加载更多加入到我们的开发者头条APP中. 2.效果图 3.实现步骤 找一个带上拉刷新下载加载更多的RecyclerView开源库,我们要站在巨人的肩膀上 下载下来自己先运行下demo,然后看看是不是我们需要的功能,觉得不错就把module依赖进来,整合主项目. 整合进来了之后,我们肯定需要进行修改,例如我这边就有滑动冲突,有多个

随机推荐