Android帶刷新時(shí)間顯示的PullToRefresh上下拉刷新
用過很多上下拉刷新,找到一個(gè)讓自己滿意的確實(shí)不容易,有些好的刷新控件,也并不是公司所需要的,在這里我給大家推薦一下我所喜歡的上下拉控件,實(shí)現(xiàn)也挺簡(jiǎn)單,需要的不妨來用一下,效果一看便知

加載就是一個(gè)圓形進(jìn)度條,一個(gè)正在加載Textview,我就不上圖了
這個(gè)是刷新的頭布局
<?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="horizontal" > <FrameLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="10dip" > <ImageView android:id="@+id/iv_listview_header_arrow" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:minWidth="30dip" android:src="@mipmap/ic_launcher" /> <ProgressBar android:id="@+id/pb_listview_header" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:indeterminateDrawable="@drawable/common_progressbar" android:visibility="gone" /> </FrameLayout> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:gravity="center_horizontal" android:orientation="vertical" > <TextView android:id="@+id/tv_listview_header_state" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="下拉刷新" android:textColor="#FF0000" android:textSize="18sp" /> <TextView android:id="@+id/tv_listview_header_last_update_time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="5dip" android:text="最后刷新時(shí)間: 2014-10-10 12:56:12" android:textSize="14sp" /> </LinearLayout> </LinearLayout>
這個(gè)是加載的底部局
<?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" > <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_margin="10dip" android:gravity="center_vertical" android:orientation="horizontal" > <ProgressBar android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:indeterminateDrawable="@drawable/common_progressbar" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dip" android:text="加載更多..." android:textColor="#FF0000" android:textSize="18sp" /> </LinearLayout> </LinearLayout>
下面是運(yùn)行布局嵌套的listview布局,如果使用請(qǐng)換一下包名
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="jiexinkeji.com.shuaxin.MainActivity"> <jiexinkeji.com.shuaxin.RefreshListView android:id="@+id/refreshlistview" android:layout_width="match_parent" android:layout_height="match_parent"></jiexinkeji.com.shuaxin.RefreshListView> </android.support.constraint.ConstraintLayout>
下面是在drawable文件夾下面創(chuàng)建的一個(gè)文件:
<?xml version="1.0" encoding="utf-8"?> <rotate xmlns:android="http://schemas.android.com/apk/res/android" android:fromDegrees="0" android:pivotX="50%" android:pivotY="50%" android:toDegrees="360" > <shape android:innerRadiusRatio="3" android:shape="ring" android:useLevel="false" > <gradient android:centerColor="#FF6666" android:endColor="#FF0000" android:startColor="#FFFFFF" android:type="sweep" /> </shape> </rotate>
這個(gè)是定義的一個(gè)接口,有刷新和加載兩個(gè)方法
package jiexinkeji.com.shuaxin;
public interface OnRefreshListener {
/**
* 下拉刷新
*/
void onDownPullRefresh();
/**
* 上拉加載更多
*/
void onLoadingMore();
}
下面的類是繼承自ListView,來實(shí)現(xiàn)下拉刷新上啦加載
package jiexinkeji.com.shuaxin;
import android.content.Context;
import android.support.v4.widget.SwipeRefreshLayout;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import java.text.SimpleDateFormat;
public class RefreshListView extends ListView implements AbsListView.OnScrollListener {
private static final String TAG = "RefreshListView";
private int firstVisibleItemPosition; // 屏幕顯示在第一個(gè)的item的索引
private int downY; // 按下時(shí)y軸的偏移量
private int headerViewHeight; // 頭布局的高度
private View headerView; // 頭布局的對(duì)象
private final int DOWN_PULL_REFRESH = 0; // 下拉刷新狀態(tài)
private final int RELEASE_REFRESH = 1; // 松開刷新
private final int REFRESHING = 2; // 正在刷新中
private int currentState = DOWN_PULL_REFRESH; // 頭布局的狀態(tài): 默認(rèn)為下拉刷新狀態(tài)
private Animation upAnimation; // 向上旋轉(zhuǎn)的動(dòng)畫
private Animation downAnimation; // 向下旋轉(zhuǎn)的動(dòng)畫
private ImageView ivArrow; // 頭布局的剪頭
private ProgressBar mProgressBar; // 頭布局的進(jìn)度條
private TextView tvState; // 頭布局的狀態(tài)
private TextView tvLastUpdateTime; // 頭布局的最后更新時(shí)間
private OnRefreshListener mOnRefershListener;
private boolean isScrollToBottom; // 是否滑動(dòng)到底部
private View footerView; // 腳布局的對(duì)象
private int footerViewHeight; // 腳布局的高度
private boolean isLoadingMore = false; // 是否正在加載更多中
public RefreshListView(Context context, AttributeSet attrs) {
super(context, attrs);
initHeaderView();
initFooterView();
this.setOnScrollListener(this);
}
/**
* 初始化腳布局
*/
private void initFooterView() {
footerView = View.inflate(getContext(), R.layout.listview_footer, null);
footerView.measure(0, 0);
footerViewHeight = footerView.getMeasuredHeight();
footerView.setPadding(0, -footerViewHeight, 0, 0);
this.addFooterView(footerView);
}
/**
* 初始化頭布局
*/
private void initHeaderView() {
headerView = View.inflate(getContext(), R.layout.listview_header, null);
ivArrow = (ImageView) headerView
.findViewById(R.id.iv_listview_header_arrow);
mProgressBar = (ProgressBar) headerView
.findViewById(R.id.pb_listview_header);
tvState = (TextView) headerView
.findViewById(R.id.tv_listview_header_state);
tvLastUpdateTime = (TextView) headerView
.findViewById(R.id.tv_listview_header_last_update_time);
// 設(shè)置最后刷新時(shí)間
tvLastUpdateTime.setText("最后刷新時(shí)間: " + getLastUpdateTime());
headerView.measure(0, 0); // 系統(tǒng)會(huì)幫我們測(cè)量出headerView的高度
headerViewHeight = headerView.getMeasuredHeight();
headerView.setPadding(0, -headerViewHeight, 0, 0);
this.addHeaderView(headerView); // 向ListView的頂部添加一個(gè)view對(duì)象
initAnimation();
}
/**
* 獲得系統(tǒng)的最新時(shí)間
*
* @return
*/
private String getLastUpdateTime() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.format(System.currentTimeMillis());
}
/**
* 初始化動(dòng)畫
*/
private void initAnimation() {
upAnimation = new RotateAnimation(0f, -180f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
0.5f);
upAnimation.setDuration(500);
upAnimation.setFillAfter(true); // 動(dòng)畫結(jié)束后, 停留在結(jié)束的位置上
downAnimation = new RotateAnimation(-180f, -360f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
0.5f);
downAnimation.setDuration(500);
downAnimation.setFillAfter(true); // 動(dòng)畫結(jié)束后, 停留在結(jié)束的位置上
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN :
downY = (int) ev.getY();
break;
case MotionEvent.ACTION_MOVE :
int moveY = (int) ev.getY();
// 移動(dòng)中的y - 按下的y = 間距.
int diff = (moveY - downY) / 2;
// -頭布局的高度 + 間距 = paddingTop
int paddingTop = -headerViewHeight + diff;
// 如果: -頭布局的高度 > paddingTop的值 執(zhí)行super.onTouchEvent(ev);
if (firstVisibleItemPosition == 0
&& -headerViewHeight < paddingTop) {
if (paddingTop > 0 && currentState == DOWN_PULL_REFRESH) { // 完全顯示了.
Log.i(TAG, "松開刷新");
currentState = RELEASE_REFRESH;
refreshHeaderView();
} else if (paddingTop < 0
&& currentState == RELEASE_REFRESH) { // 沒有顯示完全
Log.i(TAG, "下拉刷新");
currentState = DOWN_PULL_REFRESH;
refreshHeaderView();
}
// 下拉頭布局
headerView.setPadding(0, paddingTop, 0, 0);
return true;
}
break;
case MotionEvent.ACTION_UP :
// 判斷當(dāng)前的狀態(tài)是松開刷新還是下拉刷新
if (currentState == RELEASE_REFRESH) {
Log.i(TAG, "刷新數(shù)據(jù).");
// 把頭布局設(shè)置為完全顯示狀態(tài)
headerView.setPadding(0, 0, 0, 0);
// 進(jìn)入到正在刷新中狀態(tài)
currentState = REFRESHING;
refreshHeaderView();
if (mOnRefershListener != null) {
mOnRefershListener.onDownPullRefresh(); // 調(diào)用使用者的監(jiān)聽方法
}
} else if (currentState == DOWN_PULL_REFRESH) {
// 隱藏頭布局
headerView.setPadding(0, -headerViewHeight, 0, 0);
}
break;
default :
break;
}
return super.onTouchEvent(ev);
}
/**
* 根據(jù)currentState刷新頭布局的狀態(tài)
*/
private void refreshHeaderView() {
switch (currentState) {
case DOWN_PULL_REFRESH : // 下拉刷新狀態(tài)
tvState.setText("下拉刷新");
ivArrow.startAnimation(downAnimation); // 執(zhí)行向下旋轉(zhuǎn)
break;
case RELEASE_REFRESH : // 松開刷新狀態(tài)
tvState.setText("松開刷新");
ivArrow.startAnimation(upAnimation); // 執(zhí)行向上旋轉(zhuǎn)
break;
case REFRESHING : // 正在刷新中狀態(tài)
ivArrow.clearAnimation();
ivArrow.setVisibility(View.GONE);
mProgressBar.setVisibility(View.VISIBLE);
tvState.setText("正在刷新中...");
break;
default :
break;
}
}
/**
* 當(dāng)滾動(dòng)狀態(tài)改變時(shí)回調(diào)
*/
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == SCROLL_STATE_IDLE
|| scrollState == SCROLL_STATE_FLING) {
// 判斷當(dāng)前是否已經(jīng)到了底部
if (isScrollToBottom && !isLoadingMore) {
isLoadingMore = true;
// 當(dāng)前到底部
Log.i(TAG, "加載更多數(shù)據(jù)");
footerView.setPadding(0, 0, 0, 0);
this.setSelection(this.getCount());
if (mOnRefershListener != null) {
mOnRefershListener.onLoadingMore();
}
}
}
}
/**
* 當(dāng)滾動(dòng)時(shí)調(diào)用
*
* @param firstVisibleItem
* 當(dāng)前屏幕顯示在頂部的item的position
* @param visibleItemCount
* 當(dāng)前屏幕顯示了多少個(gè)條目的總數(shù)
* @param totalItemCount
* ListView的總條目的總數(shù)
*/
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
firstVisibleItemPosition = firstVisibleItem;
if (getLastVisiblePosition() == (totalItemCount - 1)) {
isScrollToBottom = true;
} else {
isScrollToBottom = false;
}
}
/**
* 設(shè)置刷新監(jiān)聽事件
*
* @param listener
*/
public void setOnRefreshListener(OnRefreshListener listener) {
mOnRefershListener = listener;
}
/**
* 隱藏頭布局
*/
public void hideHeaderView() {
headerView.setPadding(0, -headerViewHeight, 0, 0);
ivArrow.setVisibility(View.VISIBLE);
mProgressBar.setVisibility(View.GONE);
tvState.setText("下拉刷新");
tvLastUpdateTime.setText("最后刷新時(shí)間: " + getLastUpdateTime());
currentState = DOWN_PULL_REFRESH;
}
/**
* 隱藏腳布局
*/
public void hideFooterView() {
footerView.setPadding(0, -footerViewHeight, 0, 0);
isLoadingMore = false;
}
}
接下來再運(yùn)行主Activity使用就行了
package jiexinkeji.com.shuaxin;
import android.app.Activity;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.SystemClock;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends Activity implements OnRefreshListener {
private List<String> textList;
private MyAdapter adapter;
private RefreshListView rListView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
rListView = (RefreshListView) findViewById(R.id.refreshlistview);
textList = new ArrayList<String>();
for (int i = 0; i < 25; i++) {
textList.add("這是一條ListView的數(shù)據(jù)" + i);
}
adapter = new MyAdapter();
rListView.setAdapter(adapter);
rListView.setOnRefreshListener(this);
}
private class MyAdapter extends BaseAdapter {
@Override
public int getCount() {
// TODO Auto-generated method stub
return textList.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return textList.get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
TextView textView = new TextView(MainActivity.this);
textView.setText(textList.get(position));
textView.setTextSize(18.0f);
return textView;
}
}
@Override
public void onDownPullRefresh() {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
SystemClock.sleep(2000);
for (int i = 0; i < 2; i++) {
textList.add(0, "這是下拉刷新出來的數(shù)據(jù)" + i);
}
return null;
}
@Override
protected void onPostExecute(Void result) {
adapter.notifyDataSetChanged();
rListView.hideHeaderView();
}
}.execute(new Void[]{});
}
@Override
public void onLoadingMore() {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
SystemClock.sleep(5000);
textList.add("這是加載更多出來的數(shù)據(jù)1");
textList.add("這是加載更多出來的數(shù)據(jù)2");
textList.add("這是加載更多出來的數(shù)據(jù)3");
return null;
}
@Override
protected void onPostExecute(Void result) {
adapter.notifyDataSetChanged();
// 控制腳布局隱藏
rListView.hideFooterView();
}
}.execute(new Void[]{});
}
}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android實(shí)現(xiàn)簡(jiǎn)單的下拉刷新控件
- android RecycleView實(shí)現(xiàn)下拉刷新和上拉加載
- Android自定義View仿騰訊TIM下拉刷新View
- Android巧用XListView實(shí)現(xiàn)萬能下拉刷新控件
- Android自定義控件ListView下拉刷新的代碼
- Android ExpandableListView實(shí)現(xiàn)下拉刷新和加載更多效果
- Android 使用SwipeRefreshLayout控件仿抖音做的視頻下拉刷新效果
- Android實(shí)踐之帶加載效果的下拉刷新上拉加載更多
- android使用SwipeRefreshLayout實(shí)現(xiàn)ListView下拉刷新上拉加載
- Android 基于Bitmap的四種圖片壓縮方式
相關(guān)文章
Android的App啟動(dòng)時(shí)白屏的問題解決辦法
這篇文章主要介紹了Android的App啟動(dòng)時(shí)白屏的問題相關(guān)資料,在App啟動(dòng)的第一次的時(shí)候白屏?xí)欢螘r(shí)間,這里提供了解決辦法,需要的朋友可以參考下2017-08-08
用xutils3.0進(jìn)行下載項(xiàng)目更新
這篇文章主要介紹了用xutils3.0進(jìn)行下載項(xiàng)目更新的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-08-08
Android6.0藍(lán)牙出現(xiàn)無法掃描設(shè)備或閃退問題解決辦法
這篇文章主要介紹了Android6.0藍(lán)牙出現(xiàn)無法掃描設(shè)備或閃退問題解決辦法的相關(guān)資料,需要的朋友可以參考下2017-02-02
Ubuntu下android adb環(huán)境變量配置方法
這篇文章主要介紹了Ubuntu下android adb環(huán)境變量配置方法,本文給出了操作步驟,按步驟操作即可,需要的朋友可以參考下2015-04-04
android實(shí)現(xiàn)簡(jiǎn)易登錄注冊(cè)界面及邏輯設(shè)計(jì)
這篇文章主要為大家詳細(xì)介紹了android實(shí)現(xiàn)簡(jiǎn)易登錄注冊(cè)界面及邏輯設(shè)計(jì),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-06-06
Android程序報(bào)錯(cuò)程序包org.apache.http不存在問題的解決方法
這篇文章主要介紹了Android程序報(bào)錯(cuò)"程序包org.apache.http不存在——Android 6.0已經(jīng)不支持HttpClient" 問題的解決方法,感興趣的小伙伴們可以參考一下2016-06-06

