您的位置:首页 > 移动开发 > Android开发

Android开发笔记之ListView下拉刷新和上拉加载

2016-06-07 19:56 681 查看

实现下拉刷新和上拉加载的效果,采用第三方架包实现

采用第三方架包,我们需要实现的代码及其简洁

采用第三方架包可以缩短开发周期,项目周期

采用第三方架包,可以更好的维护项目和优化项目性能

我们实现一个简单的下拉刷新和上拉加载功能

1.这里我们用到的知识有json解析(有第三方架包提供)

2下拉刷新,上拉加载

3.L;istView基础知识

4.自定义Adapter

5.ListView的优化等等

其它的知识都是我们的基础知识,不懂的,大家可以经常的练习下,当初的我也是这样过来的,不懂常动手,练习才是磨练你的最佳途径,而不是只看不练,嘴上说的比手写的多,程序员必须要写的比说的多,只有常写,才会对知识有更深刻的理解,别的不多说了,接下来就是实现效果

主Activity里面的代码如下

public class MainActivity extends Activity{
private PullToRefreshView refreshView;
private ListView mListView;
private List<TabItem> mList;
private MyAdapter mAdapter;
private TabNews tabNews;

protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initListView();
getNetData(0);
}
/***************************************
*初始化ListView
*/
public void initViewList(){
mListView = (ListView) findViewById(R.id.listview);
refreshView = (PullToRefreshView) findViewById(R.id.main_pull);
mList = new ArrayList<TabItem>();
mAdapter = new MyListAdapter(this, mList);
mListView.setAdapter(mAdapter);
setPullRefreshLisnter();
}


/************************************************
* Set the refresh listeners
*/
public void setPullRefreshLisnter(){
refreshView.setOnHeaderRefreshListener(new OnHeaderRefreshListener() {
@Override
public void onHeaderRefresh(PullToRefreshView view) {
getNetData(1);
}
});
refreshView.setOnFooterLoadListener(new OnFooterLoadListener() {
@Override
public void onFooterLoad(PullToRefreshView view) {
getNetData(2);
}
});
}
/***********************************************
*The method to request data from Internet
*through xutils which is written by others
*/
public void getNetData(final int type){
HttpUtils utils = new HttpUtils();
utils.send(HttpMethod.GET, "http://hi.fuchengquan.cn/wynews/categories.json",
new RequestCallBack<String>() {
@Override
public void onFailure(HttpException arg0, String arg1) {
Log.i("onFailure", "网络数据请求失败");
}
@Override
public void onSuccess(ResponseInfo<String> responseInfo) {
Log.i("onSuccess", "网络数据请求成功");
Gson gson = new Gson();
tabNews = gson.fromJson(responseInfo.result, TabNews.class);
setDataModel(type, tabNews.data.get(0).children);
}
});
}
/*********************************************
* set the model for ruquesting data
* 0: requset data
* 1:pulldown to refresh
* 2:pullup to refresh
*/
public void setDataModel(int type,List<TabItem> mList){
switch (type) {
case 0:
this.mList = mList;
mAdapter.setList(mList);
break;
case 1:
this.mList = mList;
mAdapter.setList(mList);
refreshView.onHeaderRefreshFinish();
break;
case 2:
this.mList.addAll(mList);
mAdapter.setList(this.mList);
refreshView.onFooterLoadFinish();
break;
default:
break;
}
}


自定义Adapter的代码如下

public class MyListAdapter extends BaseAdapter {

Context context;
List<TabItem> list;

public MyListAdapter(Context context, List<TabItem> list) {
super();
this.context = context;
this.list = list;
}

@Override
public int getCount() {
return list.size();
}

@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}

@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(convertView == null){
convertView = View.inflate(context, R.layout.list_item, null);
holder = new ViewHolder();
holder.tv = (TextView) convertView.findViewById(R.id.main_listitem_textview);
convertView.setTag(holder);
}else{
holder = (ViewHolder) convertView.getTag();
}
holder.tv.setText(list.get(position).title);
return convertView;
}
class ViewHolder{
TextView tv;
}
/**
* 更新adapter的方法
* @param list
*/
public void setList(List<TabItem> list){
this.list = list;
notifyDataSetChanged();
}


实体类的代码如下

public class TabNews {

public int retcode;
public List<Integer> extend;
public List<Menu> data;

public class Menu{
public int id;
public String title;
public int type;
public String url;
public String url1;
public String dayurl;
public String excurl;
public String weekurl;
public List<TabItem> children;
}
public class TabItem{
public int id;
public String title;
public int type;
public String url;
}
}


这里需要一个PullToRefreshView.java文件,实现下拉刷新,上拉加载的方法均在里面

/*
* Copyright (C) 2012 www.amsoft.cn
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0 *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.day5musicretry;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.widget.AdapterView;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.ScrollView;
import android.widget.TextView;

/**
* 名称:PullToRefreshView.java 描述:下拉刷新和加载更多的View.
*/
public class PullToRefreshView extends LinearLayout {
/** 时分秒. */
public static final String dateFormatHMS = "HH:mm:ss";
/** 上下文. */
private Context mContext = null;

/** 下拉刷新的开关. */
private boolean mEnablePullRefresh = true;

/** 加载更多的开关. */
private boolean mEnableLoadMore = true;

/** x上一次保存的. */
private int mLastMotionX;

/** y上一次保存的. */
private int mLastMotionY;

/** header view. */
private ListViewHeader mHeaderView;

/** footer view. */
private ListViewFooter mFooterView;

/** list or grid. */
private AdapterView<?> mAdapterView;

/** Scrollview. */
private ScrollView mScrollView;

/** header view 高度. */
private int mHeaderViewHeight;

/** footer view 高度. */
private int mFooterViewHeight;

/** 滑动状态. */
private int mPullState;

/** 上滑动作. */
private static final int PULL_UP_STATE = 0;

/** 下拉动作. */
private static final int PULL_DOWN_STATE = 1;

/** 上一次的数量. */
private int mCount = 0;

/** 正在下拉刷新. */
private boolean mPullRefreshing = false;

/** 正在加载更多. */
private boolean mPullLoading = false;

/** Footer加载更多监听器. */
private OnFooterLoadListener mOnFooterLoadListener;

/** Header下拉刷新监听器. */
private OnHeaderRefreshListener mOnHeaderRefreshListener;

/** UI设计的基准宽度. */
public static int UI_WIDTH = 720;

/** UI设计的基准高度. */
public static int UI_HEIGHT = 1280;

/** UI设计的密度. */
public static int UI_DENSITY = 2;

/**
* 描述:根据屏幕大小缩放.
*
* @param context
*            the context
* @param pxValue
*            the px value
* @return the int
*/
public static int scaleValue(Context context, float value) {
DisplayMetrics mDisplayMetrics = getDisplayMetrics(context);
// 为了兼容尺寸小密度大的情况
if (mDisplayMetrics.scaledDensity > UI_DENSITY) {
// 密度
if (mDisplayMetrics.widthPixels > UI_WIDTH) {
value = value * (1.3f - 1.0f / mDisplayMetrics.scaledDensity);
} else if (mDisplayMetrics.widthPixels < UI_WIDTH) {
value = value * (1.0f - 1.0f / mDisplayMetrics.scaledDensity);
}
}
return scale(mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels,
value);
}

public void setVisible() {
mFooterView.setVisibility(View.VISIBLE);
}

/**
* 获取屏幕尺寸与密度.
*
* @param context
*            the context
* @return mDisplayMetrics
*/
public static DisplayMetrics getDisplayMetrics(Context context) {
Resources mResources;
if (context == null) {
mResources = Resources.getSystem();

} else {
mResources = context.getResources();
}
// DisplayMetrics{density=1.5, width=480, height=854, scaledDensity=1.5,
// xdpi=160.421, ydpi=159.497}
// DisplayMetrics{density=2.0, width=720, height=1280,
// scaledDensity=2.0, xdpi=160.42105, ydpi=160.15764}
DisplayMetrics mDisplayMetrics = mResources.getDisplayMetrics();
return mDisplayMetrics;
}

/**
* 描述:根据屏幕大小缩放.
*
* @param displayWidth
*            the display width
* @param displayHeight
*            the display height
* @param pxValue
*            the px value
* @return the int
*/
public static int scale(int displayWidth, int displayHeight, float pxValue) {
if (pxValue == 0) {
return 0;
}
float scale = 1;
try {
float scaleWidth = (float) displayWidth / UI_WIDTH;
float scaleHeight = (float) displayHeight / UI_HEIGHT;
scale = Math.min(scaleWidth, scaleHeight);
} catch (Exception e) {
}
return Math.round(pxValue * scale + 0.5f);
}

/**
* 设置PX padding.
*
* @param view
*            the view
* @param left
*            the left padding in pixels
* @param top
*            the top padding in pixels
* @param right
*            the right padding in pixels
* @param bottom
*            the bottom padding in pixels
*/
public static void setPadding(View view, int left, int top, int right,
int bottom) {
int scaledLeft = scaleValue(view.getContext(), left);
int scaledTop = scaleValue(view.getContext(), top);
int scaledRight = scaleValue(view.getContext(), right);
int scaledBottom = scaleValue(view.getContext(), bottom);
view.setPadding(scaledLeft, scaledTop, scaledRight, scaledBottom);
}

/**
* 缩放文字大小,这样设置的好处是文字的大小不和密度有关, 能够使文字大小在不同的屏幕上显示比例正确
*
* @param textView
*            button
* @param sizePixels
*            px值
* @return
*/
public static void setTextSize(TextView textView, float sizePixels) {
float scaledSize = scaleTextValue(textView.getContext(), sizePixels);
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, scaledSize);
}

/**
* 描述:根据屏幕大小缩放文本.
*
* @param context
*            the context
* @param pxValue
*            the px value
* @return the int
*/
public static int scaleTextValue(Context context, float value) {
DisplayMetrics mDisplayMetrics = getDisplayMetrics(context);
// 为了兼容尺寸小密度大的情况
if (mDisplayMetrics.scaledDensity > 2) {
// 缩小到密度分之一
// value = value*(1.1f - 1.0f/mDisplayMetrics.scaledDensity);
}
return scale(mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels,
value);
}

/**
* 测量这个view 最后通过getMeasuredWidth()获取宽度和高度.
*
* @param view
*            要测量的view
* @return 测量过的view
*/
public static void measureView(View view) {
ViewGroup.LayoutParams p = view.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);
}
view.measure(childWidthSpec, childHeightSpec);
}

/**
* 描述:获取表示当前日期时间的字符串.
*
* @param format
*            格式化字符串,如:"yyyy-MM-dd HH:mm:ss"
* @return String String类型的当前日期时间
*/
public static String getCurrentDate(String format) {
Log.d("DateUtil.class", "getCurrentDate:" + format);
String curDateTime = null;
try {
SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat(format);
Calendar c = new GregorianCalendar();
curDateTime = mSimpleDateFormat.format(c.getTime());
} catch (Exception e) {
e.printStackTrace();
}
return curDateTime;

}

/**
* 描述:获取src中的图片资源.
*
* @param src
*            图片的src路径,如(“image/arrow.png”)
* @return Bitmap 图片
*/
public static Bitmap getBitmapFromSrc(String src) {
Bitmap bit = null;
try {
bit = BitmapFactory.decodeStream(PullToRefreshView.class
.getResourceAsStream(src));
} catch (Exception e) {
Log.d("FileUtil.class", "获取图片异常:" + e.getMessage());
}
return bit;
}

/**
* 构造.
*
* @param context
*            the context
* @param attrs
*            the attrs
*/
public PullToRefreshView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}

/**
* 构造.
*
* @param context
*            the context
*/
public PullToRefreshView(Context context) {
super(context);
init(context);
}

/**
* 初始化View.
*
* @param context
*            the context
*/
private void init(Context context) {
mContext = context;
this.setOrientation(LinearLayout.VERTICAL);
// 增加HeaderView
addHeaderView();
}

/**
* add HeaderView.
*/
private void addHeaderView() {
mHeaderView = new ListViewHeader(mContext);
mHeaderViewHeight = mHeaderView.getHeaderHeight();
mHeaderView.setGravity(Gravity.BOTTOM);

LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT,
mHeaderViewHeight);
// 设置topMargin的值为负的header View高度,即将其隐藏在最上方
params.topMargin = -(mHeaderViewHeight);
addView(mHeaderView, params);

}

/**
* add FooterView.
*/
private void addFooterView() {

mFooterView = new ListViewFooter(mContext);
mFooterViewHeight = mFooterView.getFooterHeight();

LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT,
mFooterViewHeight);
addView(mFooterView, params);
}

/**
* remove FooterView.
*/
public void removeFooterView() {
// removeView(mFooterView);
mFooterView.setVisibility(View.GONE);
}

/**
* 在此添加footer view保证添加到linearlayout中的最后.
*/
@Override
protected void onFinishInflate() {
super.onFinishInflate();
addFooterView();
initContentAdapterView();
}

/**
* init AdapterView like ListView, GridView and so on; or init ScrollView.
*/
private void initContentAdapterView() {
int count = getChildCount();
if (count < 3) {
throw new IllegalArgumentException(
"this layout must contain 3 child views,and AdapterView or ScrollView must in the second position!");
}
View view = null;
for (int i = 0; i < count - 1; ++i) {
view = getChildAt(i);
if (view instanceof AdapterView<?>) {
mAdapterView = (AdapterView<?>) view;
}
if (view instanceof ScrollView) {
// finish later
mScrollView = (ScrollView) view;
}
}
if (mAdapterView == null && mScrollView == null) {
throw new IllegalArgumentException(
"must contain a AdapterView or ScrollView in this layout!");
}
}

/*
* (non-Javadoc)
*
* @see
* android.view.ViewGroup#onInterceptTouchEvent(android.view.MotionEvent)
*/
@Override
public boolean onInterceptTouchEvent(MotionEvent e) {
int x = (int) e.getX();
int y = (int) e.getY();
switch (e.getAction()) {
case MotionEvent.ACTION_DOWN:
// 首先拦截down事件,记录y坐标
mLastMotionX = x;
mLastMotionY = y;
break;
case MotionEvent.ACTION_MOVE:
// deltaY > 0 是向下运动,< 0是向上运动
int deltaX = x - mLastMotionX;
int deltaY = y - mLastMotionY;
// 解决点击与移动的冲突
if (Math.abs(deltaX) < Math.abs(deltaY) && Math.abs(deltaY) > 10) {
if (isRefreshViewScroll(deltaY)) {
return true;
}
}

break;
}
return false;
}

/*
* 如果在onInterceptTouchEvent()方法中没有拦截(即onInterceptTouchEvent()方法中 return
* false)则由PullToRefreshView 的子View来处理;否则由下面的方法来处理(即由PullToRefreshView自己来处理)
*/
/*
* (non-Javadoc)
*
* @see android.view.View#onTouchEvent(android.view.MotionEvent)
*/
@Override
public boolean onTouchEvent(MotionEvent event) {

int y = (int) event.getY();

switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
int deltaY = y - mLastMotionY;
if (mPullState == PULL_DOWN_STATE) {
// 执行下拉
headerPrepareToRefresh(deltaY);
} else if (mPullState == PULL_UP_STATE) {
// 执行上拉
footerPrepareToRefresh(deltaY);
}
mLastMotionY = y;
break;
// UP和CANCEL执行相同的方法
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 刷新
footerLoading();
} else {
// 还没有执行刷新,重新隐藏
setHeaderTopMargin(-mHeaderViewHeight);
}
}
break;

}
return super.onTouchEvent(event);
}

/**
* 判断滑动方向,和是否响应事件.
*
* @param deltaY
*            deltaY > 0 是向下运动,< 0是向上运动
* @return true, if is refresh view scroll
*/
private boolean isRefreshViewScroll(int deltaY) {

if (mPullRefreshing || mPullLoading) {
return false;
}
// 对于ListView和GridView
if (mAdapterView != null) {
// 子view(ListView or GridView)滑动到最顶端
if (deltaY > 0) {
// 判断是否禁用下拉刷新操作
if (!mEnablePullRefresh) {
return false;
}
View child = mAdapterView.getChildAt(0);
if (child == null) {
// 如果mAdapterView中没有数据,不拦截
// return false;

mPullState = PULL_DOWN_STATE;
return true;
}
if (mAdapterView.getFirstVisiblePosition() == 0
&& child.getTop() == 0) {
mPullState = PULL_DOWN_STATE;
return true;
}
int top = child.getTop();
int padding = mAdapterView.getPaddingTop();
if (mAdapterView.getFirstVisiblePosition() == 0
&& Math.abs(top - padding) <= 11) {
mPullState = PULL_DOWN_STATE;
return true;
}

} else if (deltaY < 0) {
// 判断是否禁用上拉加载更多操作
if (!mEnableLoadMore) {
return false;
}
View lastChild = mAdapterView.getChildAt(mAdapterView
.getChildCount() - 1);
if (lastChild == null) {
// 如果mAdapterView中没有数据,不拦截
// return false;
mPullState = PULL_UP_STATE;
return true;
}
// 最后一个子view的Bottom小于父View的高度说明mAdapterView的数据没有填满父view,
// 等于父View的高度说明mAdapterView已经滑动到最后
if (lastChild.getBottom() <= getHeight()
&& mAdapterView.getLastVisiblePosition() == mAdapterView
.getCount() - 1) {
mPullState = PULL_UP_STATE;
return true;
}
}
}
// 对于ScrollView
if (mScrollView != null) {

// 子scroll view滑动到最顶端
View child = mScrollView.getChildAt(0);
if (deltaY > 0 && mScrollView.getScrollY() == 0) {
// 判断是否禁用下拉刷新操作
if (!mEnablePullRefresh) {
return false;
}
mPullState = PULL_DOWN_STATE;
return true;
} else if (deltaY < 0
&& child.getMeasuredHeight() <= getHeight()
+ mScrollView.getScrollY()) {
// 判断是否禁用上拉加载更多操作
if (!mEnableLoadMore) {
return false;
}
mPullState = PULL_UP_STATE;
return true;
}
}
return false;
}

/**
* header 准备刷新,手指移动过程,还没有释放.
*
* @param deltaY
*            手指滑动的距离
*/
private void headerPrepareToRefresh(int deltaY) {
if (mPullRefreshing || mPullLoading) {
return;
}

int newTopMargin = updateHeaderViewTopMargin(deltaY);
// 当header view的topMargin>=0时,说明header view完全显示出来了 ,修改header view 的提示状态
if (newTopMargin >= 0
&& mHeaderView.getState() != ListViewHeader.STATE_REFRESHING) {
// 提示松开刷新
mHeaderView.setState(ListViewHeader.STATE_READY);

} else if (newTopMargin < 0 && newTopMargin > -mHeaderViewHeight) {
// 提示下拉刷新
mHeaderView.setState(ListViewHeader.STATE_NORMAL);
}
}

/**
* footer 准备刷新,手指移动过程,还没有释放 移动footer view高度同样和移动header view
* 高度是一样,都是通过修改header view的topmargin的值来达到.
*
* @param deltaY
*            手指滑动的距离
*/
private void footerPrepareToRefresh(int deltaY) {
if (mPullRefreshing || mPullLoading) {
return;
}
int newTopMargin = updateHeaderViewTopMargin(deltaY);
// 如果header view topMargin 的绝对值大于或等于header + footer 的高度
// 说明footer view 完全显示出来了,修改footer view 的提示状态
if (Math.abs(newTopMargin) >= (mHeaderViewHeight + mFooterViewHeight)
&& mFooterView.getState() != ListViewFooter.STATE_LOADING) {
mFooterView.setState(ListViewFooter.STATE_READY);
} else if (Math.abs(newTopMargin) < (mHeaderViewHeight + mFooterViewHeight)) {
mFooterView.setState(ListViewFooter.STATE_LOADING);
}
}

/**
* 修改Header view top margin的值.
*
* @param deltaY
*            the delta y
* @return the int
*/
private int updateHeaderViewTopMargin(int deltaY) {
LayoutParams params = (LayoutParams) mHeaderView.getLayoutParams();
float newTopMargin = params.topMargin + deltaY * 0.3f;
// 这里对上拉做一下限制,因为当前上拉后然后不释放手指直接下拉,会把下拉刷新给触发了
// 表示如果是在上拉后一段距离,然后直接下拉
if (deltaY > 0 && mPullState == PULL_UP_STATE
&& Math.abs(params.topMargin) <= mHeaderViewHeight) {
return params.topMargin;
}
// 同样地,对下拉做一下限制,避免出现跟上拉操作时一样的bug
if (deltaY < 0 && mPullState == PULL_DOWN_STATE
&& Math.abs(params.topMargin) >= mHeaderViewHeight) {
return params.topMargin;
}
params.topMargin = (int) newTopMargin;
mHeaderView.setLayoutParams(params);
return params.topMargin;
}

/**
* 下拉刷新.
*/
public void headerRefreshing() {
mPullRefreshing = true;
mHeaderView.setState(ListViewHeader.STATE_REFRESHING);
setHeaderTopMargin(0);
if (mOnHeaderRefreshListener != null) {
mOnHeaderRefreshListener.onHeaderRefresh(this);
}
}

/**
* 加载更多.
*/
private void footerLoading() {
mPullLoading = true;
int top = mHeaderViewHeight + mFooterViewHeight;
setHeaderTopMargin(-top);
if (mOnFooterLoadListener != null) {
mOnFooterLoadListener.onFooterLoad(this);
}
}

/**
* 设置header view 的topMargin的值.
*
* @param topMargin
*            the new header top margin
*/
private void setHeaderTopMargin(int topMargin) {
LayoutParams params = (LayoutParams) mHeaderView.getLayoutParams();
params.topMargin = topMargin;
mHeaderView.setLayoutParams(params);
}

/**
* header view 完成更新后恢复初始状态.
*/
public void onHeaderRefreshFinish() {
setHeaderTopMargin(-mHeaderViewHeight);
mHeaderView.setState(ListViewHeader.STATE_NORMAL);
if (mAdapterView != null) {
mCount = mAdapterView.getCount();
// 判断有没有数据
if (mCount > 0) {
mFooterView.setState(ListViewFooter.STATE_READY);
} else {
mFooterView.setState(ListViewFooter.STATE_EMPTY);
}
} else {
mFooterView.setState(ListViewFooter.STATE_READY);
}

mPullRefreshing = false;
}

/**
* footer view 完成更新后恢复初始状态.
*/
public void onFooterLoadFinish() {
setHeaderTopMargin(-mHeaderViewHeight);
mHeaderView.setState(ListViewHeader.STATE_NORMAL);
if (mAdapterView != null) {
int countNew = mAdapterView.getCount();
// 判断有没有更多数据了
if (countNew > mCount) {
mFooterView.setState(ListViewFooter.STATE_READY);
} else {
mFooterView.setState(ListViewFooter.STATE_NO);
}
} else {
mFooterView.setState(ListViewFooter.STATE_READY);
}

mPullLoading = false;
}

/**
* 获取当前header view 的topMargin.
*
* @return the header top margin
*/
private int getHeaderTopMargin() {
LayoutParams params = (LayoutParams) mHeaderView.getLayoutParams();
return params.topMargin;
}

/**
* 设置下拉刷新的监听器.
*
* @param headerRefreshListener
*            the new on header refresh listener
*/
public void setOnHeaderRefreshListener(
OnHeaderRefreshListener headerRefreshListener) {
mOnHeaderRefreshListener = headerRefreshListener;
}

/**
* 设置加载更多的监听器.
*
* @param footerLoadListener
*            the new on footer load listener
*/
public void setOnFooterLoadListener(OnFooterLoadListener footerLoadListener) {
mOnFooterLoadListener = footerLoadListener;
}

/**
* 打开或者关闭下拉刷新功能.
*
* @param enable
*            开关标记
*/
public void setPullRefreshEnable(boolean enable) {
mEnablePullRefresh = enable;
}

/**
* 打开或者关闭加载更多功能.
*
* @param enable
*            开关标记
*/
public void setLoadMoreEnable(boolean enable) {
mEnableLoadMore = enable;
}

/**
* 下拉刷新是打开的吗.
*
* @return true, if is enable pull refresh
*/
public boolean isEnablePullRefresh() {
return mEnablePullRefresh;
}

/**
* 加载更多是打开的吗.
*
* @return true, if is enable load more
*/
public boolean isEnableLoadMore() {
return mEnableLoadMore;
}

/**
* 描述:获取Header View.
*
* @return the header view
*/
public ListViewHeader getHeaderView() {
return mHeaderView;
}

/**
* 描述:获取Footer View.
*
* @return the footer view
*/
public ListViewFooter getFooterView() {
return mFooterView;
}

/**
* 描述:获取Header ProgressBar,用于设置自定义样式.
*
* @return the header progress bar
*/
public ProgressBar getHeaderProgressBar() {
return mHeaderView.getHeaderProgressBar();
}

/**
* 描述:获取Footer ProgressBar,用于设置自定义样式.
*
* @return the footer progress bar
*/
public ProgressBar getFooterProgressBar() {
return mFooterView.getFooterProgressBar();
}

/**
* Interface definition for a callback to be invoked when list/grid footer
* view should be refreshed.
*
* @see OnFooterLoadEvent
*/
public interface OnFooterLoadListener {

/**
* On footer load.
*
* @param view
*            the view
*/
public void onFooterLoad(PullToRefreshView view);
}

/**
* Interface definition for a callback to be invoked when list/grid header
* view should be refreshed.
*
* @see OnHeaderRefreshEvent
*/
public interface OnHeaderRefreshListener {

/**
* On header refresh.
*
* @param view
*            the view
*/
public void onHeaderRefresh(PullToRefreshView view);
}

}

class ListViewHeader extends LinearLayout {

/** 上下文. */
private Context mContext;

/** 主View. */
private LinearLayout headerView;

/** 箭头图标View. */
private ImageView arrowImageView;

/** 进度图标View. */
private ProgressBar headerProgressBar;

/** 箭头图标. */
private Bitmap arrowImage = null;

/** 文本提示的View. */
private TextView tipsTextview;

/** 时间的View. */
private TextView headerTimeView;

/** 当前状态. */
private int mState = -1;

/** 向上的动画. */
private Animation mRotateUpAnim;

/** 向下的动画. */
private Animation mRotateDownAnim;

/** 动画时间. */
private final int ROTATE_ANIM_DURATION = 180;

/** 显示 下拉刷新. */
public final static int STATE_NORMAL = 0;

/** 显示 松开刷新. */
public final static int STATE_READY = 1;

/** 显示 正在刷新.... */
public final static int STATE_REFRESHING = 2;

/** 保存上一次的刷新时间. */
private String lastRefreshTime = null;

/** Header的高度. */
private int headerHeight;

/**
* 初始化Header.
*
* @param context
*            the context
*/
public ListViewHeader(Context context) {
super(context);
initView(context);
}

/**
* 初始化Header.
*
* @param context
*            the context
* @param attrs
*            the attrs
*/
public ListViewHeader(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context);
}

/**
* 初始化View.
*
* @param context
*            the context
*/
private void initView(Context context) {

mContext = context;

// 顶部刷新栏整体内容
headerView = new LinearLayout(context);
headerView.setOrientation(LinearLayout.HORIZONTAL);
headerView.setGravity(Gravity.CENTER);

PullToRefreshView.setPadding(headerView, 0, 10, 0, 10);

// 显示箭头与进度
FrameLayout headImage = new FrameLayout(context);
arrowImageView = new ImageView(context);
// 从包里获取的箭头图片
arrowImage = PullToRefreshView.getBitmapFromSrc("image/arrow.png");
arrowImageView.setImageBitmap(arrowImage);
// style="?android:attr/progressBarStyleSmall" 默认的样式
headerProgressBar = new ProgressBar(context, null,
android.R.attr.progressBarStyle);
headerProgressBar.setVisibility(View.GONE);

LinearLayout.LayoutParams layoutParamsWW = new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
layoutParamsWW.gravity = Gravity.CENTER;
layoutParamsWW.width = PullToRefreshView.scaleValue(mContext, 50);
layoutParamsWW.height = PullToRefreshView.scaleValue(mContext, 50);
headImage.addView(arrowImageView, layoutParamsWW);
headImage.addView(headerProgressBar, layoutParamsWW);

// 顶部刷新栏文本内容
LinearLayout headTextLayout = new LinearLayout(context);
tipsTextview = new TextView(context);
headerTimeView = new TextView(context);
headTextLayout.setOrientation(LinearLayout.VERTICAL);
headTextLayout.setGravity(Gravity.CENTER_VERTICAL);
PullToRefreshView.setPadding(headTextLayout, 0, 0, 0, 0);
LinearLayout.LayoutParams layoutParamsWW2 = new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
headTextLayout.addView(tipsTextview, layoutParamsWW2);
headTextLayout.addView(headerTimeView, layoutParamsWW2);
tipsTextview.setTextColor(Color.rgb(255, 255, 255));
headerTimeView.setTextColor(Color.rgb(255, 255, 255));
PullToRefreshView.setTextSize(tipsTextview, 30);
PullToRefreshView.setTextSize(headerTimeView, 27);

LinearLayout.LayoutParams layoutParamsWW3 = new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
layoutParamsWW3.gravity = Gravity.CENTER;
layoutParamsWW3.rightMargin = PullToRefreshView
.scaleValue(mContext, 10);

LinearLayout headerLayout = new LinearLayout(context);
headerLayout.setOrientation(LinearLayout.HORIZONTAL);
headerLayout.setGravity(Gravity.CENTER);

headerLayout.addView(headImage, layoutParamsWW3);
headerLayout.addView(headTextLayout, layoutParamsWW3);

LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
lp.gravity = Gravity.BOTTOM;
// 添加大布局
headerView.addView(headerLayout, lp);
this.addView(headerView, lp);
// 获取View的高度
PullToRefreshView.measureView(this);
headerHeight = this.getMeasuredHeight();

mRotateUpAnim = new RotateAnimation(0.0f, -180.0f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
0.5f);
mRotateUpAnim.setDuration(ROTATE_ANIM_DURATION);
mRotateUpAnim.setFillAfter(true);
mRotateDownAnim = new RotateAnimation(-180.0f, 0.0f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
0.5f);
mRotateDownAnim.setDuration(ROTATE_ANIM_DURATION);
mRotateDownAnim.setFillAfter(true);
setState(STATE_NORMAL);
}

/**
* 设置状态.
*
* @param state
*            the new state
*/
public void setState(int state) {
if (state == mState)
return;
if (state == STATE_REFRESHING) {
arrowImageView.clearAnimation();
arrowImageView.setVisibility(View.INVISIBLE);
headerProgressBar.setVisibility(View.VISIBLE);
} else {
arrowImageView.setVisibility(View.VISIBLE);
headerProgressBar.setVisibility(View.INVISIBLE);
}
switch (state) {
case STATE_NORMAL:
if (mState == STATE_READY) {
arrowImageView.startAnimation(mRotateDownAnim);
}
if (mState == STATE_REFRESHING) {
arrowImageView.clearAnimation();
}
tipsTextview.setText("下拉刷新");

if (lastRefreshTime == null) {
lastRefreshTime = PullToRefreshView
.getCurrentDate(PullToRefreshView.dateFormatHMS);
headerTimeView.setText("刷新时间:" + lastRefreshTime);
} else {
headerTimeView.setText("上次刷新时间:" + lastRefreshTime);
}
break;
case STATE_READY:
if (mState != STATE_READY) {
arrowImageView.clearAnimation();
arrowImageView.startAnimation(mRotateUpAnim);
tipsTextview.setText("松开刷新");
headerTimeView.setText("上次刷新时间:" + lastRefreshTime);
lastRefreshTime = PullToRefreshView
.getCurrentDate(PullToRefreshView.dateFormatHMS);
}
break;
case STATE_REFRESHING:
tipsTextview.setText("正在刷新...");
headerTimeView.setText("本次刷新时间:" + lastRefreshTime);
break;
default:
}

mState = state;
}

/**
* 设置header可见的高度.
*
* @param height
*            the new visiable height
*/
public void setVisiableHeight(int height) {
if (height < 0)
height = 0;
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) headerView
.getLayoutParams();
lp.height = height;
headerView.setLayoutParams(lp);
}

/**
* 获取header可见的高度.
*
* @return the visiable height
*/
public int getVisiableHeight() {
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) headerView
.getLayoutParams();
return lp.height;
}

/**
* 描述:获取HeaderView.
*
* @return the header view
*/
public LinearLayout getHeaderView() {
return headerView;
}

/**
* 设置上一次刷新时间.
*
* @param time
*            时间字符串
*/
public void setRefreshTime(String time) {
headerTimeView.setText(time);
}

/**
* 获取header的高度.
*
* @return 高度
*/
public int getHeaderHeight() {
return headerHeight;
}

/**
* 描述:设置字体颜色.
*
* @param color
*            the new text color
*/
public void setTextColor(int color) {
tipsTextview.setTextColor(color);
headerTimeView.setTextColor(color);
}

/**
* 描述:设置背景颜色.
*
* @param color
*            the new background color
*/
public void setBackgroundColor(int color) {
headerView.setBackgroundColor(color);
}

/**
* 描述:获取Header ProgressBar,用于设置自定义样式.
*
* @return the header progress bar
*/
public ProgressBar getHeaderProgressBar() {
return headerProgressBar;
}

/**
* 描述:设置Header ProgressBar样式.
*
* @param indeterminateDrawable
*            the new header progress bar drawable
*/
public void setHeaderProgressBarDrawable(Drawable indeterminateDrawable) {
headerProgressBar.setIndeterminateDrawable(indeterminateDrawable);
}

/**
* 描述:得到当前状态.
*
* @return the state
*/
public int getState() {
return mState;
}

/**
* 设置提示状态文字的大小.
*
* @param size
*            the new state text size
*/
public void setStateTextSize(int size) {
tipsTextview.setTextSize(size);
}

/**
* 设置提示时间文字的大小.
*
* @param size
*            the new time text size
*/
public void setTimeTextSize(int size) {
headerTimeView.setTextSize(size);
}

/**
* Gets the arrow image view.
*
* @return the arrow image view
*/
public ImageView getArrowImageView() {
return arrowImageView;
}

/**
* 描述:设置顶部刷新图标.
*
* @param resId
*            the new arrow image
*/
public void setArrowImage(int resId) {
this.arrowImageView.setImageResource(resId);
}

}

class ListViewFooter extends LinearLayout {

/** The m context. */
private Context mContext;

/** The m state. */
private int mState = -1;

/** The Constant STATE_READY. */
public final static int STATE_READY = 1;

/** The Constant STATE_LOADING. */
public final static int STATE_LOADING = 2;

/** The Constant STATE_NO. */
public final static int STATE_NO = 3;

/** The Constant STATE_EMPTY. */
public final static int STATE_EMPTY = 4;

/** The footer view. */
private LinearLayout footerView;

/** The footer progress bar. */
private ProgressBar footerProgressBar;

/** The footer text view. */
private TextView footerTextView;

/** The footer content height. */
private int footerHeight;

/**
* Instantiates a new ab list view footer.
*
* @param context
*            the context
*/
public ListViewFooter(Context context) {
super(context);
initView(context);
}

/**
* Instantiates a new ab list view footer.
*
* @param context
*            the context
* @param attrs
*            the attrs
*/
public ListViewFooter(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context);
setState(STATE_READY);
}

/**
* Inits the view.
*
* @param context
*            the context
*/
private void initView(Context context) {
mContext = context;

// 底部刷新
footerView = new LinearLayout(context);
// 设置布局 水平方向
footerView.setOrientation(LinearLayout.HORIZONTAL);
footerView.setGravity(Gravity.CENTER);
footerView
.setMinimumHeight(PullToRefreshView.scaleValue(mContext, 100));
footerTextView = new TextView(context);
footerTextView.setGravity(Gravity.CENTER_VERTICAL);
setTextColor(Color.rgb(107, 107, 107));
PullToRefreshView.setTextSize(footerTextView, 30);

PullToRefreshView.setPadding(footerView, 0, 10, 0, 10);

footerProgressBar = new ProgressBar(context, null,
android.R.attr.progressBarStyle);
footerProgressBar.setVisibility(View.GONE);

LinearLayout.LayoutParams layoutParamsWW = new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
layoutParamsWW.gravity = Gravity.CENTER;
layoutParamsWW.width = PullToRefreshView.scaleValue(mContext, 50);
layoutParamsWW.height = PullToRefreshView.scaleValue(mContext, 50);
layoutParamsWW.rightMargin = PullToRefreshView.scaleValue(mContext, 10);
footerView.addView(footerProgressBar, layoutParamsWW);

LinearLayout.LayoutParams layoutParamsWW1 = new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
footerView.addView(footerTextView, layoutParamsWW1);

LinearLayout.LayoutParams layoutParamsFW = new LinearLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
addView(footerView, layoutParamsFW);

// 获取View的高度
PullToRefreshView.measureView(this);
footerHeight = this.getMeasuredHeight();
}

/**
* 设置当前状态.
*
* @param state
*            the new state
*/
public void setState(int state) {

if (state == STATE_READY) {
footerView.setVisibility(View.VISIBLE);
footerTextView.setVisibility(View.VISIBLE);
footerProgressBar.setVisibility(View.GONE);
footerTextView.setText("载入更多");
} else if (state == STATE_LOADING) {
footerView.setVisibility(View.VISIBLE);
footerTextView.setVisibility(View.VISIBLE);
footerProgressBar.setVisibility(View.VISIBLE);
footerTextView.setText("正在加载...");
} else if (state == STATE_NO) {
footerView.setVisibility(View.GONE);
footerTextView.setVisibility(View.VISIBLE);
footerProgressBar.setVisibility(View.GONE);
footerTextView.setText("没有了!");
} else if (state == STATE_EMPTY) {
footerView.setVisibility(View.GONE);
footerTextView.setVisibility(View.GONE);
footerProgressBar.setVisibility(View.GONE);
footerTextView.setText("没有数据");
}
mState = state;
}

/**
* Gets the visiable height.
*
* @return the visiable height
*/
public int getVisiableHeight() {
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) footerView
.getLayoutParams();
return lp.height;
}

/**
* 隐藏footerView.
*/
public void hide() {
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) footerView
.getLayoutParams();
lp.height = 0;
footerView.setLayoutParams(lp);
footerView.setVisibility(View.GONE);
}

/**
* 显示footerView.
*/
public void show() {
footerView.setVisibility(View.VISIBLE);
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) footerView
.getLayoutParams();
lp.height = LayoutParams.WRAP_CONTENT;
footerView.setLayoutParams(lp);
}

/**
* 描述:设置字体颜色.
*
* @param color
*            the new text color
*/
public void setTextColor(int color) {
footerTextView.setTextColor(color);
}

/**
* 描述:设置字体大小.
*
* @param size
*            the new text size
*/
public void setTextSize(int size) {
footerTextView.setTextSize(size);
}

/**
* 描述:设置背景颜色.
*
* @param color
*            the new background color
*/
public void setBackgroundColor(int color) {
footerView.setBackgroundColor(color);
}

/**
* 描述:获取Footer ProgressBar,用于设置自定义样式.
*
* @return the footer progress bar
*/
public ProgressBar getFooterProgressBar() {
return footerProgressBar;
}

/**
* 描述:设置Footer ProgressBar样式.
*
* @param indeterminateDrawable
*            the new footer progress bar drawable
*/
public void setFooterProgressBarDrawable(Drawable indeterminateDrawable) {
footerProgressBar.setIndeterminateDrawable(indeterminateDrawable);
}

/**
* 描述:获取高度.
*
* @return the footer height
*/
public int getFooterHeight() {
return footerHeight;
}

/**
* 设置高度.
*
* @param height
*            新的高度
*/
public void setVisiableHeight(int height) {
if (height < 0)
height = 0;
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) footerView
.getLayoutParams();
lp.height = height;
footerView.setLayoutParams(lp);
}

/**
* Gets the state.
*
* @return the state
*/
public int getState() {
return mState;
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息