欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android程序開發(fā)之Listview下拉刷新上拉(滑動(dòng)分頁)加載更多

 更新時(shí)間:2016年07月08日 11:26:56   作者:還是你最好  
這篇文章主要介紹了Android程序開發(fā)之Listview下拉刷新上拉(滑動(dòng)分頁)加載更多的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下

最近做的類似于微博的項(xiàng)目中,有個(gè)Android功能要使用到listview的向下拉刷新來刷新最新消息,向上拉刷新(滑動(dòng)分頁)來加載更多。

新浪微博就是使用這種方式的典型。

當(dāng)用戶從網(wǎng)絡(luò)上讀取微博的時(shí)候,如果一下子全部加載用戶未讀的微博這將耗費(fèi)比較長的時(shí)間,造成不好的用戶體驗(yàn),同時(shí)一屏的內(nèi)容也不足以顯示如此多的內(nèi)容。這時(shí)候,我們就需要用到另一個(gè)功能,那就是listview的分頁了,其實(shí)這個(gè)分頁可以做成客戶端的分頁,也可以做成服務(wù)器端的分頁(點(diǎn)擊加載時(shí),從服務(wù)器對應(yīng)的加載第N頁就好了?。。。Mㄟ^分頁分次加載數(shù)據(jù),用戶看多少就去加載多少。

通常這也分為兩種方式,一種是設(shè)置一個(gè)按鈕,用戶點(diǎn)擊即加載。另一種是當(dāng)用戶滑動(dòng)到底部時(shí)自動(dòng)加載。今天我就和大家分享一下滑動(dòng)到底端時(shí)自動(dòng)加載這個(gè)功能的實(shí)現(xiàn)。

效果圖如下所示:

下拉刷新最主要的流程是:

(1). 下拉,顯示提示頭部界面(HeaderView),這個(gè)過程提示用戶”下拉刷新”

(2). 下拉到一定程度,超出了刷新最基本的下拉界限,我們認(rèn)為達(dá)到了刷新的條件,提示用戶可以”松手刷新”了,效果上允許用戶繼續(xù)下拉

(3). 用戶松手,可能用戶下拉遠(yuǎn)遠(yuǎn)不止提示頭部界面,所以這一步,先反彈回僅顯示提示頭部界面,然后提示用戶”正在加載”。

(4). 加載完成后,隱藏提示頭部界面。

那么讓我們看看怎么才能實(shí)現(xiàn)呢???

第一步:既然是要顯示listview ,那么就應(yīng)該有個(gè)listview 的容器pulldown.xml

<?xml version="1.0" encoding="utf-8"?>
<com.solo.pulldown.PullDownView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pull_down_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@android:color/white">
</com.solo.pulldown.PullDownView> 

第二步:自定義一個(gè)listview中顯示的item對象pulldown_item.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/text1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:gravity="center_vertical"
android:paddingLeft="6dip"
android:minHeight="?android:attr/listPreferredItemHeight"
android:textColor="@android:color/black"
/> 

第三步:定義一個(gè)header的xml布局文件pulldown_header.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingBottom="10dp"
android:paddingTop="10dp" >
<ImageView
android:id="@+id/pulldown_header_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_marginLeft="20dp"
android:scaleType="centerCrop"
android:src="@drawable/z_arrow_down"
android:visibility="invisible" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/pulldown_header_arrow"
android:layout_alignTop="@+id/pulldown_header_arrow"
android:layout_centerHorizontal="true"
android:gravity="center_vertical"
android:orientation="vertical" >
<TextView
android:id="@+id/pulldown_header_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="加載中..." />
<TextView
android:id="@+id/pulldown_header_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="更新于:"
android:visibility="gone" />
</LinearLayout>
<ProgressBar
android:id="@+id/pulldown_header_loading"
style="@android:style/Widget.ProgressBar.Small.Inverse"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp" />
</RelativeLayout> 

第四步:如果需要向上拉更新更多的話,那就定義一個(gè)底部的footer的布局文件,在此為方便起見,只定義一個(gè)progressbar跟textview,更加復(fù)雜的顯示,就交給你們了~~~~~pulldown_footer.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingBottom="10dp"
android:paddingTop="10dp" >
<TextView
android:id="@+id/pulldown_footer_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="更多"
android:textSize="15dp" />
<ProgressBar
android:id="@+id/pulldown_footer_loading"
style="@android:style/Widget.ProgressBar.Small.Inverse"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:visibility="gone" />
</RelativeLayout> 

第五步:那么主要的文件這才登場:::::::重寫listview這個(gè)文件主要任務(wù)是提供觸摸的事件的處理方法。

/**
* <p>一個(gè)可以監(jiān)聽ListView是否滾動(dòng)到最頂部或最底部的自定義控件</p>
* 只能監(jiān)聽由觸摸產(chǎn)生的,如果是ListView本身Flying導(dǎo)致的,則不能監(jiān)聽</br>
* 如果加以改進(jìn),可以實(shí)現(xiàn)監(jiān)聽scroll滾動(dòng)的具體位置等
*/
public class ScrollOverListView extends ListView {
private int mLastY;
private int mTopPosition;
private int mBottomPosition;
public ScrollOverListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public ScrollOverListView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public ScrollOverListView(Context context) {
super(context);
init();
}
private void init(){
mTopPosition = 0;
mBottomPosition = 0;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
final int action = ev.getAction();
final int y = (int) ev.getRawY();
switch(action){
case MotionEvent.ACTION_DOWN:{
mLastY = y;
final boolean isHandled = mOnScrollOverListener.onMotionDown(ev);
if (isHandled) {
mLastY = y;
return isHandled;
}
break;
}
case MotionEvent.ACTION_MOVE:{
final int childCount = getChildCount();
if(childCount == 0) return super.onTouchEvent(ev);
final int itemCount = getAdapter().getCount() - mBottomPosition;
final int deltaY = y - mLastY;
//DLog.d("lastY=%d y=%d", mLastY, y);
final int firstTop = getChildAt(0).getTop();
final int listPadding = getListPaddingTop();
final int lastBottom = getChildAt(childCount - 1).getBottom();
final int end = getHeight() - getPaddingBottom();
final int firstVisiblePosition = getFirstVisiblePosition();
final boolean isHandleMotionMove = mOnScrollOverListener.onMotionMove(ev, deltaY);
if(isHandleMotionMove){
mLastY = y;
return true;
}
//DLog.d("firstVisiblePosition=%d firstTop=%d listPaddingTop=%d deltaY=%d", firstVisiblePosition, firstTop, listPadding, deltaY);
if (firstVisiblePosition <= mTopPosition && firstTop >= listPadding && deltaY > 0) {
final boolean isHandleOnListViewTopAndPullDown;
isHandleOnListViewTopAndPullDown = mOnScrollOverListener.onListViewTopAndPullDown(deltaY);
if(isHandleOnListViewTopAndPullDown){
mLastY = y;
return true;
}
}
// DLog.d("lastBottom=%d end=%d deltaY=%d", lastBottom, end, deltaY);
if (firstVisiblePosition + childCount >= itemCount && lastBottom <= end && deltaY < 0) {
final boolean isHandleOnListViewBottomAndPullDown;
isHandleOnListViewBottomAndPullDown = mOnScrollOverListener.onListViewBottomAndPullUp(deltaY);
if(isHandleOnListViewBottomAndPullDown){
mLastY = y;
return true;
}
}
break;
}
case MotionEvent.ACTION_UP:{
final boolean isHandlerMotionUp = mOnScrollOverListener.onMotionUp(ev);
if (isHandlerMotionUp) {
mLastY = y;
return true;
}
break;
}
}
mLastY = y;
return super.onTouchEvent(ev);
}
/**空的*/
private OnScrollOverListener mOnScrollOverListener = new OnScrollOverListener(){
@Override
public boolean onListViewTopAndPullDown(int delta) {
return false;
}
@Override
public boolean onListViewBottomAndPullUp(int delta) {
return false;
}
@Override
public boolean onMotionDown(MotionEvent ev) {
return false;
}
@Override
public boolean onMotionMove(MotionEvent ev, int delta) {
return false;
}
@Override
public boolean onMotionUp(MotionEvent ev) {
return false;
}
};
// =============================== public method ===============================
/**
* 可以自定義其中一個(gè)條目為頭部,頭部觸發(fā)的事件將以這個(gè)為準(zhǔn),默認(rèn)為第一個(gè)
*
* @param index 正數(shù)第幾個(gè),必須在條目數(shù)范圍之內(nèi)
*/
public void setTopPosition(int index){
if(getAdapter() == null)
throw new NullPointerException("You must set adapter before setTopPosition!");
if(index < 0)
throw new IllegalArgumentException("Top position must > 0");
mTopPosition = index;
}
/**
* 可以自定義其中一個(gè)條目為尾部,尾部觸發(fā)的事件將以這個(gè)為準(zhǔn),默認(rèn)為最后一個(gè)
*
* @param index 倒數(shù)第幾個(gè),必須在條目數(shù)范圍之內(nèi)
*/
public void setBottomPosition(int index){
if(getAdapter() == null)
throw new NullPointerException("You must set adapter before setBottonPosition!");
if(index < 0)
throw new IllegalArgumentException("Bottom position must > 0");
mBottomPosition = index;
}
/**
* 設(shè)置這個(gè)Listener可以監(jiān)聽是否到達(dá)頂端,或者是否到達(dá)低端等事件</br>
*
* @see OnScrollOverListener
*/
public void setOnScrollOverListener(OnScrollOverListener onScrollOverListener){
mOnScrollOverListener = onScrollOverListener;
}
/**
* 滾動(dòng)監(jiān)聽接口</br>
* @see ScrollOverListView#setOnScrollOverListener(OnScrollOverListener)
*
*/
public interface OnScrollOverListener {
/**
* 到達(dá)最頂部觸發(fā)
*
* @param delta 手指點(diǎn)擊移動(dòng)產(chǎn)生的偏移量
* @return
*/
boolean onListViewTopAndPullDown(int delta);
/**
* 到達(dá)最底部觸發(fā)
*
* @param delta 手指點(diǎn)擊移動(dòng)產(chǎn)生的偏移量
* @return
*/
boolean onListViewBottomAndPullUp(int delta);
/**
* 手指觸摸按下觸發(fā),相當(dāng)于{@link MotionEvent#ACTION_DOWN}
*
* @return 返回true表示自己處理
* @see View#onTouchEvent(MotionEvent)
*/
boolean onMotionDown(MotionEvent ev);
/**
* 手指觸摸移動(dòng)觸發(fā),相當(dāng)于{@link MotionEvent#ACTION_MOVE}
*
* @return 返回true表示自己處理
* @see View#onTouchEvent(MotionEvent)
*/
boolean onMotionMove(MotionEvent ev, int delta);
/**
* 手指觸摸后提起觸發(fā),相當(dāng)于{@link MotionEvent#ACTION_UP}
*
* @return 返回true表示自己處理
* @see View#onTouchEvent(MotionEvent)
*/
boolean onMotionUp(MotionEvent ev);
}
} 

第六步:下拉刷新控件,真正實(shí)現(xiàn)下拉刷新的是這個(gè)控件,而上面的那個(gè)ScrollOverListView只是提供觸摸的事件等

/**
* 下拉刷新控件</br>
* 真正實(shí)現(xiàn)下拉刷新的是這個(gè)控件,
* ScrollOverListView只是提供觸摸的事件等
*/
public class PullDownView extends LinearLayout implements OnScrollOverListener{
private static final String TAG = "PullDownView";
private static final int START_PULL_DEVIATION = 50; // 移動(dòng)誤差
private static final int AUTO_INCREMENTAL = 10; // 自增量,用于回彈
private static final int WHAT_DID_LOAD_DATA = 1; // Handler what 數(shù)據(jù)加載完畢
private static final int WHAT_ON_REFRESH = 2; // Handler what 刷新中
private static final int WHAT_DID_REFRESH = 3; // Handler what 已經(jīng)刷新完
private static final int WHAT_SET_HEADER_HEIGHT = 4;// Handler what 設(shè)置高度
private static final int WHAT_DID_MORE = 5; // Handler what 已經(jīng)獲取完更多
private static final int DEFAULT_HEADER_VIEW_HEIGHT = 105; // 頭部文件原本的高度
private static SimpleDateFormat dateFormat = new SimpleDateFormat("MM-dd HH:mm");
private View mHeaderView;
private LayoutParams mHeaderViewParams;
private TextView mHeaderViewDateView;
private TextView mHeaderTextView;
private ImageView mHeaderArrowView;
private View mHeaderLoadingView;
private View mFooterView;
private TextView mFooterTextView;
private View mFooterLoadingView;
private ScrollOverListView mListView;
private OnPullDownListener mOnPullDownListener;
private RotateAnimation mRotateOTo180Animation;
private RotateAnimation mRotate180To0Animation;
private int mHeaderIncremental; // 增量
private float mMotionDownLastY; // 按下時(shí)候的Y軸坐標(biāo)
private boolean mIsDown; // 是否按下
private boolean mIsRefreshing; // 是否下拉刷新中
private boolean mIsFetchMoreing; // 是否獲取更多中
private boolean mIsPullUpDone; // 是否回推完成
private boolean mEnableAutoFetchMore; // 是否允許自動(dòng)獲取更多
// 頭部文件的狀態(tài)
private static final int HEADER_VIEW_STATE_IDLE = 0; // 空閑
private static final int HEADER_VIEW_STATE_NOT_OVER_HEIGHT = 1; // 沒有超過默認(rèn)高度
private static final int HEADER_VIEW_STATE_OVER_HEIGHT = 2; // 超過默認(rèn)高度
private int mHeaderViewState = HEADER_VIEW_STATE_IDLE;
public PullDownView(Context context, AttributeSet attrs) {
super(context, attrs);
initHeaderViewAndFooterViewAndListView(context);
}
public PullDownView(Context context) {
super(context);
initHeaderViewAndFooterViewAndListView(context);
}
/*
* ==================================
* Public method
* 外部使用,具體就是用這幾個(gè)就可以了
*
* ==================================
*/
/**
* 刷新事件接口
*/
public interface OnPullDownListener {
void onRefresh();
void onMore();
}
/**
* 通知加載完了數(shù)據(jù),要放在Adapter.notifyDataSetChanged后面
* 當(dāng)你加載完數(shù)據(jù)的時(shí)候,調(diào)用這個(gè)notifyDidLoad()
* 才會(huì)隱藏頭部,并初始化數(shù)據(jù)等
*/
public void notifyDidLoad() {
mUIHandler.sendEmptyMessage(WHAT_DID_LOAD_DATA);
}
/**
* 通知已經(jīng)刷新完了,要放在Adapter.notifyDataSetChanged后面
* 當(dāng)你執(zhí)行完刷新任務(wù)之后,調(diào)用這個(gè)notifyDidRefresh()
* 才會(huì)隱藏掉頭部文件等操作
*/
public void notifyDidRefresh() {
mUIHandler.sendEmptyMessage(WHAT_DID_REFRESH);
}
/**
* 通知已經(jīng)獲取完更多了,要放在Adapter.notifyDataSetChanged后面
* 當(dāng)你執(zhí)行完更多任務(wù)之后,調(diào)用這個(gè)notyfyDidMore()
* 才會(huì)隱藏加載圈等操作
*/
public void notifyDidMore() {
mUIHandler.sendEmptyMessage(WHAT_DID_MORE);
}
/**
* 設(shè)置監(jiān)聽器
* @param listener
*/
public void setOnPullDownListener(OnPullDownListener listener){
mOnPullDownListener = listener;
}
/**
* 獲取內(nèi)嵌的listview
* @return ScrollOverListView
*/
public ListView getListView(){
return mListView;
}
/**
* 是否開啟自動(dòng)獲取更多
* 自動(dòng)獲取更多,將會(huì)隱藏footer,并在到達(dá)底部的時(shí)候自動(dòng)刷新
* @param index 倒數(shù)第幾個(gè)觸發(fā)
*/
public void enableAutoFetchMore(boolean enable, int index){
if(enable){
mListView.setBottomPosition(index);
mFooterLoadingView.setVisibility(View.VISIBLE);
}else{
mFooterTextView.setText("更多");
mFooterLoadingView.setVisibility(View.GONE);
}
mEnableAutoFetchMore = enable;
}
/*
* ==================================
* Private method
* 具體實(shí)現(xiàn)下拉刷新等操作
*
* ==================================
*/
/**
* 初始化界面
*/
private void initHeaderViewAndFooterViewAndListView(Context context){
setOrientation(LinearLayout.VERTICAL);
//setDrawingCacheEnabled(false);
/*
* 自定義頭部文件
* 放在這里是因?yàn)榭紤]到很多界面都需要使用
* 如果要修改,和它相關(guān)的設(shè)置都要更改
*/
mHeaderView = LayoutInflater.from(context).inflate(R.layout.pulldown_header, null);
mHeaderViewParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
addView(mHeaderView, 0, mHeaderViewParams);
mHeaderTextView = (TextView) mHeaderView.findViewById(R.id.pulldown_header_text);
mHeaderArrowView = (ImageView) mHeaderView.findViewById(R.id.pulldown_header_arrow);
mHeaderLoadingView = mHeaderView.findViewById(R.id.pulldown_header_loading);
// 注意,圖片旋轉(zhuǎn)之后,再執(zhí)行旋轉(zhuǎn),坐標(biāo)會(huì)重新開始計(jì)算
mRotateOTo180Animation = new RotateAnimation(0, 180,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
mRotateOTo180Animation.setDuration(250);
mRotateOTo180Animation.setFillAfter(true);
mRotate180To0Animation = new RotateAnimation(180, 0,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
mRotate180To0Animation.setDuration(250);
mRotate180To0Animation.setFillAfter(true);
/**
* 自定義腳部文件
*/
mFooterView = LayoutInflater.from(context).inflate(R.layout.pulldown_footer, null);
mFooterTextView = (TextView) mFooterView.findViewById(R.id.pulldown_footer_text);
mFooterLoadingView = mFooterView.findViewById(R.id.pulldown_footer_loading);
mFooterView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if(!mIsFetchMoreing){
mIsFetchMoreing = true;
mFooterLoadingView.setVisibility(View.VISIBLE);
mOnPullDownListener.onMore();
}
}
});
/*
* ScrollOverListView 同樣是考慮到都是使用,所以放在這里
* 同時(shí)因?yàn)?,需要它的監(jiān)聽事件
*/
mListView = new ScrollOverListView(context);
mListView.setOnScrollOverListener(this);
mListView.setCacheColorHint(0);
addView(mListView, LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
// 空的listener
mOnPullDownListener = new OnPullDownListener() {
@Override
public void onRefresh() {}
@Override
public void onMore() {}
};
}
/**
* 在下拉和回推的時(shí)候檢查頭部文件的狀態(tài)</br>
* 如果超過了默認(rèn)高度,就顯示松開可以刷新,
* 否則顯示下拉可以刷新
*/
private void checkHeaderViewState(){
if(mHeaderViewParams.height >= DEFAULT_HEADER_VIEW_HEIGHT){
if(mHeaderViewState == HEADER_VIEW_STATE_OVER_HEIGHT) return;
mHeaderViewState = HEADER_VIEW_STATE_OVER_HEIGHT;
mHeaderTextView.setText("松開可以刷新");
mHeaderArrowView.startAnimation(mRotateOTo180Animation);
}else{
if(mHeaderViewState == HEADER_VIEW_STATE_NOT_OVER_HEIGHT
|| mHeaderViewState == HEADER_VIEW_STATE_IDLE) return;
mHeaderViewState = HEADER_VIEW_STATE_NOT_OVER_HEIGHT;
mHeaderTextView.setText("下拉可以刷新");
mHeaderArrowView.startAnimation(mRotate180To0Animation);
}
}
private void setHeaderHeight(final int height){
mHeaderIncremental = height;
mHeaderViewParams.height = height;
mHeaderView.setLayoutParams(mHeaderViewParams);
}
/**
* 自動(dòng)隱藏動(dòng)畫
*/
class HideHeaderViewTask extends TimerTask{
@Override
public void run() {
if(mIsDown) {
cancel();
return;
}
mHeaderIncremental -= AUTO_INCREMENTAL;
if(mHeaderIncremental > 0){
mUIHandler.sendEmptyMessage(WHAT_SET_HEADER_HEIGHT);
}else{
mHeaderIncremental = 0;
mUIHandler.sendEmptyMessage(WHAT_SET_HEADER_HEIGHT);
cancel();
}
}
}
/**
* 自動(dòng)顯示動(dòng)畫
*/
class ShowHeaderViewTask extends TimerTask{
@Override
public void run() {
if(mIsDown) {
cancel();
return;
}
mHeaderIncremental -= AUTO_INCREMENTAL;
if(mHeaderIncremental > DEFAULT_HEADER_VIEW_HEIGHT){
mUIHandler.sendEmptyMessage(WHAT_SET_HEADER_HEIGHT);
}else{
mHeaderIncremental = DEFAULT_HEADER_VIEW_HEIGHT;
mUIHandler.sendEmptyMessage(WHAT_SET_HEADER_HEIGHT);
if(!mIsRefreshing){
mIsRefreshing = true;
mUIHandler.sendEmptyMessage(WHAT_ON_REFRESH);
}
cancel();
}
}
}
private Handler mUIHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case WHAT_DID_LOAD_DATA:{
mHeaderViewParams.height = 0;
mHeaderLoadingView.setVisibility(View.GONE);
mHeaderTextView.setText("下拉可以刷新");
mHeaderViewDateView = (TextView) mHeaderView.findViewById(R.id.pulldown_header_date);
mHeaderViewDateView.setVisibility(View.VISIBLE);
mHeaderViewDateView.setText("更新于:" + dateFormat.format(new Date(System.currentTimeMillis())));
mHeaderArrowView.setVisibility(View.VISIBLE);
showFooterView();
return;
}
case WHAT_ON_REFRESH:{
// 要清除掉動(dòng)畫,否則無法隱藏
mHeaderArrowView.clearAnimation();
mHeaderArrowView.setVisibility(View.INVISIBLE);
mHeaderLoadingView.setVisibility(View.VISIBLE);
mOnPullDownListener.onRefresh();
return;
}
case WHAT_DID_REFRESH :{
mIsRefreshing = false;
mHeaderViewState = HEADER_VIEW_STATE_IDLE;
mHeaderArrowView.setVisibility(View.VISIBLE);
mHeaderLoadingView.setVisibility(View.GONE);
mHeaderViewDateView.setText("更新于:" + dateFormat.format(new Date(System.currentTimeMillis())));
setHeaderHeight(0);
showFooterView();
return;
}
case WHAT_SET_HEADER_HEIGHT :{
setHeaderHeight(mHeaderIncremental);
return;
}
case WHAT_DID_MORE :{
mIsFetchMoreing = false;
mFooterTextView.setText("更多");
mFooterLoadingView.setVisibility(View.GONE);
}
}
}
};
/**
* 顯示腳步腳部文件
*/
private void showFooterView(){
if(mListView.getFooterViewsCount() == 0 && isFillScreenItem()){
mListView.addFooterView(mFooterView);
mListView.setAdapter(mListView.getAdapter());
}
}
/**
* 條目是否填滿整個(gè)屏幕
*/
private boolean isFillScreenItem(){
final int firstVisiblePosition = mListView.getFirstVisiblePosition();
final int lastVisiblePostion = mListView.getLastVisiblePosition() - mListView.getFooterViewsCount();
final int visibleItemCount = lastVisiblePostion - firstVisiblePosition + 1;
final int totalItemCount = mListView.getCount() - mListView.getFooterViewsCount();
if(visibleItemCount < totalItemCount) return true;
return false;
}
/*
* ==================================
* 實(shí)現(xiàn) OnScrollOverListener接口
*
*
* ==================================
*/
@Override
public boolean onListViewTopAndPullDown(int delta) {
if(mIsRefreshing || mListView.getCount() - mListView.getFooterViewsCount() == 0) return false;
int absDelta = Math.abs(delta);
final int i = (int) Math.ceil((double)absDelta / 2);
mHeaderIncremental += i;
if(mHeaderIncremental >= 0){ // && mIncremental <= mMaxHeight
setHeaderHeight(mHeaderIncremental);
checkHeaderViewState();
}
return true;
}
@Override
public boolean onListViewBottomAndPullUp(int delta) {
if(!mEnableAutoFetchMore || mIsFetchMoreing) return false;
// 數(shù)量充滿屏幕才觸發(fā)
if(isFillScreenItem()){
mIsFetchMoreing = true;
mFooterTextView.setText("加載更多中...");
mFooterLoadingView.setVisibility(View.VISIBLE);
mOnPullDownListener.onMore();
return true;
}
return false;
}
@Override
public boolean onMotionDown(MotionEvent ev) {
mIsDown = true;
mIsPullUpDone = false;
mMotionDownLastY = ev.getRawY();
return false;
}
@Override
public boolean onMotionMove(MotionEvent ev, int delta) {
//當(dāng)頭部文件回推消失的時(shí)候,不允許滾動(dòng)
if(mIsPullUpDone) return true;
// 如果開始按下到滑動(dòng)距離不超過誤差值,則不滑動(dòng)
final int absMotionY = (int) Math.abs(ev.getRawY() - mMotionDownLastY);
if(absMotionY < START_PULL_DEVIATION) return true;
final int absDelta = Math.abs(delta);
final int i = (int) Math.ceil((double)absDelta / 2);
// onTopDown在頂部,并上回推和onTopUp相對
if(mHeaderViewParams.height > 0 && delta < 0){
mHeaderIncremental -= i;
if(mHeaderIncremental > 0){
setHeaderHeight(mHeaderIncremental);
checkHeaderViewState();
}else{
mHeaderViewState = HEADER_VIEW_STATE_IDLE;
mHeaderIncremental = 0;
setHeaderHeight(mHeaderIncremental);
mIsPullUpDone = true;
}
return true;
}
return false;
}
@Override
public boolean onMotionUp(MotionEvent ev) {
mIsDown = false;
// 避免和點(diǎn)擊事件沖突
if(mHeaderViewParams.height > 0){
// 判斷頭文件拉動(dòng)的距離與設(shè)定的高度,小了就隱藏,多了就固定高度
int x = mHeaderIncremental - DEFAULT_HEADER_VIEW_HEIGHT;
Timer timer = new Timer(true);
if(x < 0){
timer.scheduleAtFixedRate(new HideHeaderViewTask(), 0, 10);
}else{
timer.scheduleAtFixedRate(new ShowHeaderViewTask(), 0, 10);
}
return true;
}
return false;
}
}

第七步:這個(gè)java文件就是封裝數(shù)據(jù),然后調(diào)用上兩個(gè)文件就好了。廢話不多說,上代碼:::::

public class PullDownActivity extends Activity implements OnPullDownListener, OnItemClickListener{
private static final int WHAT_DID_LOAD_DATA = 0;
private static final int WHAT_DID_REFRESH = 1;
private static final int WHAT_DID_MORE = 2;
private ListView mListView;
private ArrayAdapter<String> mAdapter;
private PullDownView mPullDownView;
private List<String> mStrings = new ArrayList<String>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pulldown);
/*
* 1.使用PullDownView
* 2.設(shè)置OnPullDownListener
* 3.從mPullDownView里面獲取ListView
*/
mPullDownView = (PullDownView) findViewById(R.id.pull_down_view);
mPullDownView.setOnPullDownListener(this);
mListView = mPullDownView.getListView();
mListView.setOnItemClickListener(this);
mAdapter = new ArrayAdapter<String>(this, R.layout.pulldown_item, mStrings);
mListView.setAdapter(mAdapter);
mPullDownView.enableAutoFetchMore(true, 1);
loadData();
}
private void loadData(){
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
List<String> strings = new ArrayList<String>();
for (String body : mStringArray) {
strings.add(body);
}
Message msg = mUIHandler.obtainMessage(WHAT_DID_LOAD_DATA);
msg.obj = strings;
msg.sendToTarget();
}
}).start();
}
@Override
public void onRefresh() {
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Message msg = mUIHandler.obtainMessage(WHAT_DID_REFRESH);
msg.obj = "After refresh " + System.currentTimeMillis();
msg.sendToTarget();
}
}).start();
}
@Override
public void onMore() {
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Message msg = mUIHandler.obtainMessage(WHAT_DID_MORE);
msg.obj = "After more " + System.currentTimeMillis();
msg.sendToTarget();
}
}).start();
}
private Handler mUIHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case WHAT_DID_LOAD_DATA:{
if(msg.obj != null){
List<String> strings = (List<String>) msg.obj;
if(!strings.isEmpty()){
mStrings.addAll(strings);
mAdapter.notifyDataSetChanged();
}
}
// 訴它數(shù)據(jù)加載完畢;
mPullDownView.notifyDidLoad();
break;
}
case WHAT_DID_REFRESH :{
String body = (String) msg.obj;
mStrings.add(0, body);
mAdapter.notifyDataSetChanged();
// 告訴它更新完畢
mPullDownView.notifyDidRefresh();
break;
}
case WHAT_DID_MORE:{
String body = (String) msg.obj;
mStrings.add(body);
mAdapter.notifyDataSetChanged();
// 告訴它獲取更多完畢
mPullDownView.notifyDidMore();
break;
}
}
}
};
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(this, "啊,你點(diǎn)中我了 " + position, Toast.LENGTH_SHORT).show();
}
// 模擬數(shù)據(jù)
private String[] mStringArray = {
"Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam", "Abondance", "Ackawi",
"Acorn", "Adelost", "Affidelice au Chablis", "Afuega'l Pitu", "Airag", "Airedale",
"Aisy Cendre", "Allgauer Emmentaler", "Alverca", "Ambert", "American Cheese"
};
} 

整個(gè)程序就這么完成了,總之,可以使用前兩個(gè)封裝好的文件,然后,調(diào)用就好了~~~~沒什么太難的地方。

以上所述是小編給大家介紹的Android程序開發(fā)之Listview下拉刷新上拉(滑動(dòng)分頁)加載更多,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!

相關(guān)文章

  • android實(shí)現(xiàn)在圖標(biāo)上顯示數(shù)字

    android實(shí)現(xiàn)在圖標(biāo)上顯示數(shù)字

    這篇文章主要為大家詳細(xì)介紹了android實(shí)現(xiàn)在圖標(biāo)上顯示數(shù)字,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • Android開發(fā)學(xué)習(xí)筆記 淺談WebView

    Android開發(fā)學(xué)習(xí)筆記 淺談WebView

    WebView(網(wǎng)絡(luò)視圖)能加載顯示網(wǎng)頁,可以將其視為一個(gè)瀏覽器。它使用了WebKit渲染引擎加載顯示網(wǎng)頁,實(shí)現(xiàn)WebView有以下兩種不同的方法
    2014-11-11
  • Android關(guān)于WebView中無法定位的問題解決

    Android關(guān)于WebView中無法定位的問題解決

    本篇文章主要介紹了Android關(guān)于WebView中無法定位的問題解決,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-10-10
  • ProtoBuf動(dòng)態(tài)拆分Gradle?Module解析

    ProtoBuf動(dòng)態(tài)拆分Gradle?Module解析

    這篇文章主要為大家介紹了ProtoBuf動(dòng)態(tài)拆分Gradle?Module解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • 分析Android App中內(nèi)置換膚功能的實(shí)現(xiàn)方式

    分析Android App中內(nèi)置換膚功能的實(shí)現(xiàn)方式

    這篇文章主要介紹了Android App中內(nèi)置換膚功能的實(shí)現(xiàn)方式,文中舉了一個(gè)類似QQ空間中換膚方式的例子作為說明,需要的朋友可以參考下
    2016-02-02
  • android 定位的4種方式介紹

    android 定位的4種方式介紹

    開發(fā)中對于地圖及地理位置的定位是我們經(jīng)常要用地,地圖功能的使用使得我們應(yīng)用功能更加完善,下面總結(jié)了一下網(wǎng)絡(luò)中現(xiàn)有對于介紹android定位的4種方式,希望對大家有幫助:
    2014-07-07
  • Android設(shè)備藍(lán)牙連接掃描槍獲取掃描內(nèi)容

    Android設(shè)備藍(lán)牙連接掃描槍獲取掃描內(nèi)容

    這篇文章主要為大家詳細(xì)介紹了Android設(shè)備藍(lán)牙連接掃描槍獲取掃描內(nèi)容,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • Android RecycleView滑動(dòng)停止后自動(dòng)吸附效果的實(shí)現(xiàn)代碼(滑動(dòng)定位)

    Android RecycleView滑動(dòng)停止后自動(dòng)吸附效果的實(shí)現(xiàn)代碼(滑動(dòng)定位)

    這篇文章主要介紹了Android RecycleView滑動(dòng)停止后自動(dòng)吸附效果的實(shí)現(xiàn)代碼(滑動(dòng)定位),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-10-10
  • android 顯示gif圖片實(shí)例詳解

    android 顯示gif圖片實(shí)例詳解

    本文主要介紹android 顯示gif圖片的知識(shí),這里整理相關(guān)資料及簡單實(shí)例代碼,有需要的小伙伴可以參考下
    2016-09-09
  • Android7.0 MessageQueue詳解

    Android7.0 MessageQueue詳解

    這篇文章主要為大家詳細(xì)介紹了Android7.0 MessageQueue的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-09-09

最新評論