android实现刷新有多种方式,不过上个项目用的dragdown类,发现总是有bug,看到就心赛!突然回忆起以前用过的xlistview多不错的,于是就在github,找了下!花了几分钟就找到了,用了一下确实好用!不过用的时候发现了一个bug,就是item 很少的时候(就是头部和底部在同一视线时),下拉刷新也会加载更多,然后使用起来总是怪怪的!,太影响用户体验了!于是就花了点时间改了一下,加了一句判断就ok了!
好了是时候贴代码了!
先来一个头部:
package com.zhiyisoft.associations.widget;
import android.content.Context;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.zhiyisoft.associations.R;
/**
*
* 下拉刷新的头部
*
* @author markmjw
* @date 2013-10-08
*/
public class XHeaderView extends LinearLayout {
public final static int STATE_NORMAL = 0; // 普通状态
public final static int STATE_READY = 1; // 松开可以刷新的时候那个状态
public final static int STATE_REFRESHING = 2; // 正在刷新的状态
private final int ROTATE_ANIM_DURATION = 180;
private LinearLayout mContainer;
private ImageView mArrowImageView;
private ProgressBar mProgressBar;
private TextView mHintTextView;
private int mState = STATE_NORMAL;
private Animation mRotateUpAnim;
private Animation mRotateDownAnim;
private boolean mIsFirst;
public XHeaderView(Context context) {
super(context);
initView(context);
}
public XHeaderView(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context);
}
private void initView(Context context) {
// 初始化时候,把头部高度设置问0
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LayoutParams.MATCH_PARENT, 0);
mContainer = (LinearLayout) LayoutInflater.from(context).inflate(
R.layout.vw_header, null);
addView(mContainer, lp); // 布局文件生成的view放到线性布局文件里面,并放到底部
setGravity(Gravity.BOTTOM);
mArrowImageView = (ImageView) findViewById(R.id.header_arrow);
mHintTextView = (TextView) findViewById(R.id.header_hint_text);
mProgressBar = (ProgressBar) findViewById(R.id.header_progressbar);
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);
}
/**
* 设置状态
*
* @param state
*/
public void setState(int state) {
if (state == mState && mIsFirst) {
mIsFirst = true;
return;
}
if (state == STATE_REFRESHING) {
// show progress
mArrowImageView.clearAnimation();
mArrowImageView.setVisibility(View.INVISIBLE);
mProgressBar.setVisibility(View.VISIBLE);
} else {
// show arrow image
mArrowImageView.setVisibility(View.VISIBLE);
mProgressBar.setVisibility(View.INVISIBLE);
}
// 这里是典型的状态模式,所以可以用状态模式实现它
switch (state) {
case STATE_NORMAL:
if (mState == STATE_READY) {
mArrowImageView.startAnimation(mRotateDownAnim);
}
if (mState == STATE_REFRESHING) {
mArrowImageView.clearAnimation();
}
mHintTextView.setText(R.string.header_hint_refresh_normal);
break;
case STATE_READY:
if (mState != STATE_READY) {
mArrowImageView.clearAnimation();
mArrowImageView.startAnimation(mRotateUpAnim);
mHintTextView.setText(R.string.header_hint_refresh_ready);
}
break;
case STATE_REFRESHING:
mHintTextView.setText(R.string.header_hint_refresh_loading);
break;
default:
break;
}
mState = state;
}
/**
* 设置头部可见的高度
*
* @param height
*/
public void setVisibleHeight(int height) {
if (height < 0)
height = 0;
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mContainer
.getLayoutParams();
lp.height = height;
mContainer.setLayoutParams(lp);
}
/**
* 获取头部可见的高度
*
* @return
*/
public int getVisibleHeight() {
return mContainer.getHeight();
}
}
再来一个尾部嘛!
package com.zhiyisoft.associations.widget;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.zhiyisoft.associations.R;
/**
* 下拉刷新的尾部
*
* @author markmjw
* @date 2013-10-08
*/
public class XFooterView extends LinearLayout {
public final static int STATE_NORMAL = 0;
public final static int STATE_READY = 1;
public final static int STATE_LOADING = 2;
private final int ROTATE_ANIM_DURATION = 180;
private View mLayout;
private View mProgressBar;
private TextView mHintView;
// private ImageView mHintImage;
private Animation mRotateUpAnim;
private Animation mRotateDownAnim;
private int mState = STATE_NORMAL;
public XFooterView(Context context) {
super(context);
initView(context);
}
public XFooterView(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context);
}
private void initView(Context context) {
mLayout = LayoutInflater.from(context)
.inflate(R.layout.vw_footer, null);
mLayout.setLayoutParams(new LinearLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
addView(mLayout);
mProgressBar = mLayout.findViewById(R.id.footer_progressbar);
mHintView = (TextView) mLayout.findViewById(R.id.footer_hint_text);
// mHintImage = (ImageView) mLayout.findViewById(R.id.footer_arrow);
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);
}
/**
* Set footer view state
*
* @see #STATE_LOADING
* @see #STATE_NORMAL
* @see #STATE_READY
*
* @param state
*/
public void setState(int state) {
// 当前后状态相同的时候就return;
if (state == mState)
return;
if (state == STATE_LOADING) {
// mHintImage.clearAnimation();
// mHintImage.setVisibility(View.INVISIBLE);
mProgressBar.setVisibility(View.VISIBLE);
mHintView.setVisibility(View.INVISIBLE);
} else {
mHintView.setVisibility(View.VISIBLE);
// mHintImage.setVisibility(View.VISIBLE);
mProgressBar.setVisibility(View.INVISIBLE);
}
switch (state) {
case STATE_NORMAL:
mHintView.setText(R.string.footer_hint_load_normal);
break;
case STATE_READY:
if (mState != STATE_READY) {
mHintView.setText(R.string.footer_hint_load_ready);
}
break;
case STATE_LOADING:
break;
}
mState = state;
}
/**
* Set footer view bottom margin.
*
* @param margin
*/
public void setBottomMargin(int margin) {
if (margin < 0)
return;
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mLayout
.getLayoutParams();
lp.bottomMargin = margin;
mLayout.setLayoutParams(lp);
}
/**
* Get footer view bottom margin.
*
* @return
*/
public int getBottomMargin() {
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mLayout
.getLayoutParams();
return lp.bottomMargin;
}
/**
* normal status
*/
public void normal() {
mHintView.setVisibility(View.VISIBLE);
mProgressBar.setVisibility(View.GONE);
}
/**
* loading status
*/
public void loading() {
mHintView.setVisibility(View.GONE);
mProgressBar.setVisibility(View.VISIBLE);
}
/**
* hide footer when disable pull load more
*/
public void hide() {
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mLayout
.getLayoutParams();
lp.height = 0;
mLayout.setLayoutParams(lp);
}
/**
* show footer
*/
public void show() {
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mLayout
.getLayoutParams();
lp.height = LayoutParams.WRAP_CONTENT;
mLayout.setLayoutParams(lp);
}
}
呵呵,别急!现在推出了关键的的代码
package com.zhiyisoft.associations.widget;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.animation.DecelerateInterpolator;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.Scroller;
import android.widget.TextView;
import com.zhiyisoft.associations.R;
/**
*
*
* @author markmjw
* @date 2013-10-08
*/
public class XListView extends ListView implements OnScrollListener {
// private static final String TAG = "XListView";
private final static int SCROLL_BACK_HEADER = 0;
private final static int SCROLL_BACK_FOOTER = 1;
private final static int SCROLL_DURATION = 400;
// when pull up >= 50px
private final static int PULL_LOAD_MORE_DELTA = 50;
// support iOS like pull
private final static float OFFSET_RADIO = 1.8f;
private float mLastY = -1;
// used for scroll back
private Scroller mScroller;
// user's scroll listener
private OnScrollListener mScrollListener;
// for mScroller, scroll back from header or footer.
private int mScrollBack;
// the interface to trigger refresh and load more.
private IXListViewListener mListener;
private XHeaderView mHeader;
// header view content, use it to calculate the Header's height. And hide it
// when disable pull refresh.
private RelativeLayout mHeaderContent;
private TextView mHeaderTime;
private int mHeaderHeight;
private LinearLayout mFooterLayout;
private XFooterView mFooterView;
private boolean mIsFooterReady = false; // 底部是否准备好
private boolean mEnablePullRefresh = true;// 能否下拉刷新
private boolean mPullRefreshing = false;// 是否在刷新
private boolean mEnablePullLoad = true; // 能否加载更多
private boolean mEnableAutoLoad = false;// 能否自动加载
private boolean mPullLoading = false; // 是否在加载更多
// listview的总的item数量,这个主要是用于程序检测能否上拉加载更多(起了一个判断作用)
private int mTotalItemCount;
public XListView(Context context) {
super(context);
initWithContext(context);
}
public XListView(Context context, AttributeSet attrs) {
super(context, attrs);
initWithContext(context);
}
public XListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initWithContext(context);
}
private void initWithContext(Context context) {
mScroller = new Scroller(context, new DecelerateInterpolator());
super.setOnScrollListener(this);
// 初始化 header view
mHeader = new XHeaderView(context);
mHeaderContent = (RelativeLayout) mHeader
.findViewById(R.id.header_content);
mHeaderTime = (TextView) mHeader.findViewById(R.id.header_hint_time);
addHeaderView(mHeader);
// 初始化 footer view
mFooterView = new XFooterView(context);
mFooterLayout = new LinearLayout(context);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT);
params.gravity = Gravity.CENTER;
mFooterLayout.addView(mFooterView, params);
// init header height
ViewTreeObserver observer = mHeader.getViewTreeObserver();
if (null != observer) {
observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@SuppressWarnings("deprecation")
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@Override
public void onGlobalLayout() {
mHeaderHeight = mHeaderContent.getHeight();
ViewTreeObserver observer = getViewTreeObserver();
if (null != observer) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
observer.removeGlobalOnLayoutListener(this);
} else {
observer.removeOnGlobalLayoutListener(this);
}
}
}
});
}
}
@Override
public void setAdapter(ListAdapter adapter) {
// 保证listview的尾部只能有一个尾部
if (!mIsFooterReady) {
mIsFooterReady = true;
addFooterView(mFooterLayout);
}
super.setAdapter(adapter);
}
/**
* 设置是否能可以下拉刷新,共外部调用选择
*
* @param enable
*/
public void setPullRefreshEnable(boolean enable) {
mEnablePullRefresh = enable;
// 如果设置不可以的话,就隐藏头部
mHeaderContent.setVisibility(enable ? View.VISIBLE : View.INVISIBLE);
}
/**
* 设置是否能可以底部加载更多,共外部调用选择
*
* @param enable
*/
public void setPullLoadEnable(boolean enable) {
mEnablePullLoad = enable;
if (!mEnablePullLoad) {
mFooterView.setBottomMargin(0);
mFooterView.hide();
mFooterView.setPadding(0, 0, 0, 0);
mFooterView.setOnClickListener(null);
} else {
mPullLoading = false;
mFooterView.setPadding(0, 0, 0, 0);
mFooterView.show();
mFooterView.setState(XFooterView.STATE_NORMAL);
// 设置监听器,让不仅上拉加载更多,点击也会加载更多
mFooterView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
startLoadMore();
}
});
}
}
/**
* 设置当移动到listview底部的时候是否可以自动加载更多
*
* @param enable
*/
public void setAutoLoadEnable(boolean enable) {
mEnableAutoLoad = enable;
}
/**
* 停止刷新, 重置header view.
*/
public void stopRefresh() {
if (mPullRefreshing) {
mPullRefreshing = false;
resetHeaderHeight();
}
}
/**
* 停止加载更多, 重置 footer view.
*/
public void stopLoadMore() {
if (mPullLoading) {
mPullLoading = false;
mFooterView.setState(XFooterView.STATE_NORMAL);
}
}
/**
* 设置最后的 refresh time
*
* @param time
*/
public void setRefreshTime(String time) {
mHeaderTime.setText(time);
}
/**
* 设置监听器 listener.
*
* @param listener
*/
public void setXListViewListener(IXListViewListener listener) {
mListener = listener;
}
/**
* 自动刷新.
*/
public void autoRefresh() {
mHeader.setVisibleHeight(mHeaderHeight);
if (mEnablePullRefresh && !mPullRefreshing) {
// update the arrow image not refreshing
if (mHeader.getVisibleHeight() > mHeaderHeight) {
mHeader.setState(XHeaderView.STATE_READY);
} else {
mHeader.setState(XHeaderView.STATE_NORMAL);
}
}
mPullRefreshing = true;
mHeader.setState(XHeaderView.STATE_REFRESHING);
refresh();
}
private void invokeOnScrolling() {
if (mScrollListener instanceof OnXScrollListener) {
OnXScrollListener listener = (OnXScrollListener) mScrollListener;
listener.onXScrolling(this);
}
}
private void updateHeaderHeight(float delta) {
mHeader.setVisibleHeight((int) delta + mHeader.getVisibleHeight());
if (mEnablePullRefresh && !mPullRefreshing) {
// update the arrow image unrefreshing
if (mHeader.getVisibleHeight() > mHeaderHeight) {
mHeader.setState(XHeaderView.STATE_READY);
} else {
mHeader.setState(XHeaderView.STATE_NORMAL);
}
}
// scroll to top each time
setSelection(0);
}
private void resetHeaderHeight() {
int height = mHeader.getVisibleHeight();
if (height == 0)
return;
// 刷新中,但是头部没有完全显示出来,这个时候不需要干什么事情,(这种情况发现在,正在刷新的时候,然后又故意向上滑动)
if (mPullRefreshing && height <= mHeaderHeight)
return;
int finalHeight = 0;
// is refreshing, just scroll back to show all the header.
// 当触发到刷新的临界点,然后继续下拉的时候,松开手就弹到头部的高端
if (mPullRefreshing && height > mHeaderHeight) {
finalHeight = mHeaderHeight;
}
mScrollBack = SCROLL_BACK_HEADER;
// 这就是我们看到的弹到原位置的感觉(在这里其实可以实现一弹一弹的感觉)
mScroller.startScroll(0, height, 0, finalHeight - height,
SCROLL_DURATION);
// 调用这个方法请求重绘界面 这个方法又会触发 computeScroll
invalidate();
}
private void updateFooterHeight(float delta) {
int height = mFooterView.getBottomMargin() + (int) delta;
if (mEnablePullLoad && !mPullLoading) {
if (height > PULL_LOAD_MORE_DELTA) {
// height enough to invoke load more.
mFooterView.setState(XFooterView.STATE_READY);
} else {
mFooterView.setState(XFooterView.STATE_NORMAL);
}
}
mFooterView.setBottomMargin(height);
}
private void resetFooterHeight() {
int bottomMargin = mFooterView.getBottomMargin();
if (bottomMargin > 0) {
mScrollBack = SCROLL_BACK_FOOTER;
mScroller.startScroll(0, bottomMargin, 0, -bottomMargin,
SCROLL_DURATION);
invalidate();
}
}
/**
* <span style="color:#ff0000;">修复了listview里面item很少的时候,下拉刷新会同时加载更多的bug</span>
*/
private void startLoadMore() {
if (!mPullRefreshing) {
mPullLoading = true;
mFooterView.setState(XFooterView.STATE_LOADING);
loadMore();
}
}
// 核心方法
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (mLastY == -1) {
mLastY = ev.getRawY();
}
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
mLastY = ev.getRawY();
break;
case MotionEvent.ACTION_MOVE:
final float deltaY = ev.getRawY() - mLastY;
mLastY = ev.getRawY();
if (getFirstVisiblePosition() == 0
&& (mHeader.getVisibleHeight() > 0 || deltaY > 0)) {
// the first item is showing, header has shown or pull down.
updateHeaderHeight(deltaY / OFFSET_RADIO);
invokeOnScrolling();
} else if (getLastVisiblePosition() == mTotalItemCount - 1
&& (mFooterView.getBottomMargin() > 0 || deltaY < 0)) {
// last item, already pulled up or want to pull up.
updateFooterHeight(-deltaY / OFFSET_RADIO);
}
break;
default:
// reset 其实本质上就是松开手后执行的操作
mLastY = -1;
if (getFirstVisiblePosition() == 0) {
// invoke refresh
if (mEnablePullRefresh
&& mHeader.getVisibleHeight() > mHeaderHeight) {
mPullRefreshing = true;
mHeader.setState(XHeaderView.STATE_REFRESHING);
refresh();
}
resetHeaderHeight();
} else if (getLastVisiblePosition() == mTotalItemCount - 1) {
// invoke load more.
if (mEnablePullLoad
&& mFooterView.getBottomMargin() > PULL_LOAD_MORE_DELTA) {
startLoadMore();
}
resetFooterHeight();
}
break;
}
return super.onTouchEvent(ev);
}
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
if (mScrollBack == SCROLL_BACK_HEADER) {
mHeader.setVisibleHeight(mScroller.getCurrY());
} else {
mFooterView.setBottomMargin(mScroller.getCurrY());
}
postInvalidate();
invokeOnScrolling();
}
super.computeScroll();
}
@Override
public void setOnScrollListener(OnScrollListener l) {
mScrollListener = l;
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (mScrollListener != null) {
mScrollListener.onScrollStateChanged(view, scrollState);
}
if (scrollState == OnScrollListener.SCROLL_STATE_IDLE) {
if (mEnableAutoLoad && getLastVisiblePosition() == getCount() - 1) {
startLoadMore();
}
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// send to user's listener
mTotalItemCount = totalItemCount;
if (mScrollListener != null) {
mScrollListener.onScroll(view, firstVisibleItem, visibleItemCount,
totalItemCount);
}
}
private void refresh() {
if (mEnablePullRefresh && null != mListener) {
mListener.onRefresh();
}
}
private void loadMore() {
if (mEnablePullLoad && null != mListener) {
mListener.onLoadMore();
}
}
/**
* You can listen ListView.OnScrollListener or this one. it will invoke
* onXScrolling when header/footer scroll back.
*
* 自定义OnScrollListener,暂时用不到
*/
public interface OnXScrollListener extends OnScrollListener {
public void onXScrolling(View view);
}
/**
* 实现这个接口就可以刷新或者加载更多
*
*
*/
public interface IXListViewListener {
public void onRefresh();
public void onLoadMore();
}
}
下面就是一些相关的配置文件
<string name="header_hint_refresh_normal"></string>
<string name="header_hint_refresh_ready">下拉刷新</string>
<string name="header_hint_refresh_loading">刷新中</string>
<string name="header_hint_refresh_time">上次刷新时间:</string>
<string name="footer_hint_load_normal">加载更多</string>
<string name="footer_hint_load_ready">加载中</string>
布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="@dimen/footer_height"
android:alpha="0.5"
android:padding="@dimen/footer_padding" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<ProgressBar
android:id="@+id/footer_progressbar"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_centerInParent="true"
android:visibility="invisible" />
<TextView
android:id="@+id/footer_hint_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="@string/footer_hint_load_normal"
android:textColor="#333333" />
<ImageView
android:id="@+id/footer_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="30dp"
android:layout_toLeftOf="@id/footer_hint_text"
android:contentDescription="@null"
android:src="@drawable/arrow_up"
android:visibility="gone" />
</RelativeLayout>
</LinearLayout>
---------------------------------------------------------------------------- 我是邪恶的分界线------------------------------------------------------------------------------------------------------
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="bottom">
<RelativeLayout
android:id="@+id/header_content"
android:layout_width="match_parent"
android:layout_height="@dimen/header_height">
<LinearLayout
android:id="@+id/header_text_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center"
android:orientation="vertical">
<TextView
android:id="@+id/header_hint_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/header_hint_refresh_normal" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="3dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/header_hint_refresh_time"
android:textSize="12sp" />
<TextView
android:id="@+id/header_hint_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="12sp" />
</LinearLayout>
</LinearLayout>
<ProgressBar
android:id="@+id/header_progressbar"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_toLeftOf="@id/header_text_layout"
android:layout_marginRight="30dp"
android:layout_centerVertical="true"
android:visibility="gone" />
<ImageView
android:id="@+id/header_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="@id/header_text_layout"
android:layout_marginRight="30dp"
android:layout_centerVertical="true"
android:contentDescription="@null"
android:src="@drawable/arrow_down" />
</RelativeLayout>
</LinearLayout>
差不多了哈,下拉刷新的图片就不贴了哈,自己去找一张就ok!
核心代码都贴出来了,如果要在有下拉刷新的地方都使用他的话,不可能总是引用他赛,并设置是否需要下拉刷新或者加载更多,所以还是写一个类来继承它,这样以后的下拉刷新就可以直接说了,就相当于把xlistview封装一下,不过这样就更加方便使用了哦!
下面贴一下我的封装类baselistview
package com.zhiyisoft.associations.listview.base;
/***********************************************************************
* Module: BaseListView.java
* Author: qcj qq:260964739
* Purpose: Defines the Class BaseListView
***********************************************************************/
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.ListAdapter;
import android.widget.Toast;
import com.zhiyisoft.associations.R;
import com.zhiyisoft.associations.adapter.base.BAdapter;
import com.zhiyisoft.associations.application.Association;
import com.zhiyisoft.associations.model.base.Model;
import com.zhiyisoft.associations.widget.XListView;
/** listview的基类 ,任何listview都可以继承它,减少代码的冗余 */
public abstract class BaseListView extends XListView implements
XListView.IXListViewListener {
public BaseListView(Context context) {
super(context, null);
initSet(context);
initXListView();
}
public BaseListView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
initSet(context);
initXListView();
}
private Context mContext;
// /** mlist數據 */
private List<Model> mList;
/** activity */
private BAdapter mAdapter;
/**
* 最后可见的位置
*/
private int mLastVisiablPos;
public Association mApp;
/** 初始化设置 */
public void initSet(Context context) {
this.setScrollbarFadingEnabled(true);
this.setCacheColorHint(0);
this.setDividerHeight(2);
mApp = (Association) context.getApplicationContext();
}
private void initXListView() {
this.setPullRefreshEnable(true);
this.setPullLoadEnable(true);
this.setAutoLoadEnable(true);
this.setRefreshTime(getTime());
this.setXListViewListener(this);
}
@Override
public void setAdapter(ListAdapter adapter) {
this.mAdapter = (BAdapter) adapter;
mAdapter.setListView(this);
super.setAdapter(adapter);
this.mList = ((BAdapter) adapter).getList();
Log.i("hhh", "---------------走到这里没有?");
this.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// 点击加载更多
if (view.getId() == R.id.footer_content) {
Toast.makeText(mContext, "点击了加載更多", Toast.LENGTH_LONG)
.show();
return;
}
// 子类去实现他
onClick(parent, view, position, id);
}
});
}
/** 重新每一個item的點擊事件 */
public abstract void onClick(AdapterView<?> parent, View view,
int position, long id);
@Override
public void onRefresh() {
if (mAdapter != null) {
mAdapter.doRefreshHeader();
}
}
@Override
public void onLoadMore() {
if (mAdapter != null) {
mAdapter.doRefreshFooter();
}
}
private String getTime() {
return new SimpleDateFormat("MM-dd HH:mm", Locale.CHINA)
.format(new Date());
}
/**
* 取消下拉刷新 或者加载更多
*/
public void onLoad() {
this.stopRefresh();
this.stopLoadMore();
this.setRefreshTime(getTime());
}
}