Android RecyclerView上拉加載更多功能回彈實現(xiàn)代碼
實現(xiàn)原理是使用RecyclerView的OnTouchListener方法監(jiān)聽滑動 在adapter里面增加兩項footview 其中date.size為顯示的加載條,可以自定義,date.size+1為空白的View,我們設(shè)置其高度為0 我們通過LinearLayoutManager的 findLastVisibleItemPosition判斷顯示的最后一條數(shù)據(jù),如果是空白view,表示加載條已經(jīng)完全展示,松開即可刷新。
回彈效果是通過在滑動時動態(tài)改變空白view的高度,達到阻尼效果 ,回彈時再動態(tài)將其改為0,達到回彈效果,通過loading防止加載過程中滑動導致顯示問題 這里的回調(diào)采用了Runnable傳參
public class RefreshFootAdapter extends
RecyclerView.Adapter<RecyclerView.ViewHolder> {
// 上拉加載更多
public static final int SATUS_PULLUP_LOAD_MORE = 0;
// 正在加載中
public static final int SATUS_LOADING_MORE = 1;
public static final int SATUS_UP_LOADING_MORE = 2;
// 上拉加載更多狀態(tài)-默認為0
private int load_more_status = 0;
private LayoutInflater mInflater;
private List<String> mTitles = null;
private static final int TYPE_ITEM = 0; // 普通Item View
private static final int TYPE_FOOTER = 1; // 底部FootView
private static final int TYPE_FOOTER_EMPTY = 2; // 底部空白View
private static int pagesize;
private int eview_height = 1;
private long TimeFlag;// 回彈時間
private RecyclerView parent;
private boolean loadmare;// 判斷當前是可加載更多
private boolean loading;// 判斷是否正在加載
private int startY, nowY;// 滑動判斷
<span style="white-space:pre"> </span>//構(gòu)造函數(shù) 處理滑動監(jiān)聽 更新等功能
public RefreshFootAdapter(Context context, RecyclerView parent,
final LinearLayoutManager linearLayoutManager, int pagesize,
final Runnable onloadmore) {
this.parent = parent;
this.mInflater = LayoutInflater.from(context);
this.mTitles = new ArrayList<String>();
for (int i = 0; i < 20; i++) {
int index = i + 1;
mTitles.add("item" + index);
}
this.pagesize = pagesize;
parent.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent ev) {
// TODO Auto-generated method stub
switch (ev.getAction()) {
case MotionEvent.ACTION_MOVE:
nowY = (int) ev.getY();
if (RefreshFootAdapter.this.getItemCount() == linearLayoutManager
.findLastVisibleItemPosition() + 1) {
if (startY == 0) {// 按下
startY = nowY;
}
int changeY = nowY - startY;
RefreshFootAdapter.this
.notifyEmptyView((int) (-changeY / 1.3f));
if (loading) {
return false;
}
RefreshFootAdapter.this
.changeMoreStatus(RefreshFootAdapter.this.SATUS_UP_LOADING_MORE);
loadmare = true;
} else {
loadmare = false;
if (loading) {
return false;
}
RefreshFootAdapter.this
.changeMoreStatus(RefreshFootAdapter.this.SATUS_PULLUP_LOAD_MORE);
// 普通的滑動
startY = 0;
}
break;
case MotionEvent.ACTION_UP:
RefreshFootAdapter.this.resetEmptyView();
if (loadmare) {
if (loading) {
return false;
} else {
RefreshFootAdapter.this
.changeMoreStatus(RefreshFootAdapter.this.SATUS_LOADING_MORE);
if (onloadmore != null && !loading) {
loading = true;
onloadmore.run();
}
}
}
startY = 0;
break;
default:
break;
}
return false;
}
});
}
/**
* item顯示類型
*
* @param parent
* @param viewType
* @return
*/
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// 進行判斷顯示類型,來創(chuàng)建返回不同的View
if (viewType == TYPE_ITEM) {
View view = mInflater.inflate(R.layout.item_recycler_layout,
parent, false);
// 這邊可以做一些屬性設(shè)置,甚至事件監(jiān)聽綁定
// view.setBackgroundColor(Color.RED);
ItemViewHolder itemViewHolder = new ItemViewHolder(view);
return itemViewHolder;
} else if (viewType == TYPE_FOOTER) {
View foot_view = mInflater.inflate(
R.layout.recycler_load_more_layout, parent, false);
// 這邊可以做一些屬性設(shè)置,甚至事件監(jiān)聽綁定
// view.setBackgroundColor(Color.RED);
FootViewHolder footViewHolder = new FootViewHolder(foot_view);
return footViewHolder;
} else if (viewType == TYPE_FOOTER_EMPTY) {
View foot_view_empty = mInflater.inflate(
R.layout.recycler_load_more_layout_empty, parent, false);
// 這邊可以做一些屬性設(shè)置,甚至事件監(jiān)聽綁定
// view.setBackgroundColor(Color.RED);
FootEmptyHolder footEmptyViewHolder = new FootEmptyHolder(
foot_view_empty);
return footEmptyViewHolder;
}
return null;
}
/**
* 數(shù)據(jù)的綁定顯示
*
* @param holder
* @param position
*/
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder instanceof ItemViewHolder) {
((ItemViewHolder) holder).item_tv.setText(mTitles.get(position));
holder.itemView.setTag(position);
} else if (holder instanceof FootViewHolder) {
FootViewHolder footViewHolder = (FootViewHolder) holder;
switch (load_more_status) {
case SATUS_PULLUP_LOAD_MORE:
footViewHolder.foot_view_item_tv.setText("上拉加載更多...");
break;
case SATUS_LOADING_MORE:
footViewHolder.foot_view_item_tv.setText("正在加載更多數(shù)據(jù)...");
break;
case SATUS_UP_LOADING_MORE:
footViewHolder.foot_view_item_tv.setText("松開加載更多數(shù)據(jù)...");
break;
}
} else if (holder instanceof FootEmptyHolder) {
FootEmptyHolder footViewHolder = (FootEmptyHolder) holder;
footViewHolder.empty.setLayoutParams(new ViewGroup.LayoutParams(
111, eview_height));
}
}
/**
* 進行判斷是普通Item視圖還是FootView視圖
*
* @param position
* @return
*/
@Override
public int getItemViewType(int position) {
// 最后一個item設(shè)置為footerView
if (position + 1 == getItemCount()) {
return TYPE_FOOTER_EMPTY;
} else if (position + 2 == getItemCount()) {
return TYPE_FOOTER;
} else {
return TYPE_ITEM;
}
}
<span style="white-space:pre"> </span>//如果是頁數(shù)的倍數(shù) itemcount+2
@Override
public int getItemCount() {
if (mTitles.size() % pagesize != 0) {
return mTitles.size();
} else {
return mTitles.size() + 2;
}
// return mTitles.size()+1;
}
// 自定義的ViewHolder,持有每個Item的的所有界面元素
public static class ItemViewHolder extends RecyclerView.ViewHolder {
public TextView item_tv;
public ItemViewHolder(View view) {
super(view);
item_tv = (TextView) view.findViewById(R.id.item_tv);
}
}
/**
* 底部FootView布局
*/
public static class FootViewHolder extends RecyclerView.ViewHolder {
private TextView foot_view_item_tv;
public FootViewHolder(View view) {
super(view);
foot_view_item_tv = (TextView) view
.findViewById(R.id.foot_view_item_tv);
}
}
<span style="white-space:pre"> </span>//空白項
public static class FootEmptyHolder extends RecyclerView.ViewHolder {
private View empty;
public FootEmptyHolder(View view) {
super(view);
empty = view.findViewById(R.id.empty);
}
}
// 添加數(shù)據(jù)
public void addItem(List<String> newDatas) {
// mTitles.add(position, data);
// notifyItemInserted(position);
newDatas.addAll(mTitles);
mTitles.removeAll(mTitles);
mTitles.addAll(newDatas);
notifyDataSetChanged();
}
<span style="white-space:pre"> </span>//更新添加數(shù)據(jù)
public void addMoreItem(List<String> newDatas) {
mTitles.addAll(newDatas);
notifyDataSetChanged();
}
<span style="white-space:pre"> </span>//更新空白項高度
private void notifyEmptyView(int height) {
this.eview_height = height;
notifyItemChanged(getItemCount() - 1);
}
<span style="white-space:pre"> </span>//空白回彈 偽回彈動畫
private void resetEmptyView() {
final int dx = eview_height;
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
final int time = 500;
final long startTime = new Date().getTime();
TimeFlag = startTime;
long nowTime = new Date().getTime();
while (startTime + time > nowTime && TimeFlag == startTime) {
nowTime = new Date().getTime();
final int dt = (int) (nowTime - startTime);
parent.post(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
eview_height = eview_height * (time - dt) / time;
notifyDataSetChanged();
}
});
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
parent.post(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
eview_height = 0;
notifyDataSetChanged();
}
});
}
}).start();
}
<span style="white-space:pre"> </span>//停止加載更多 重置loading狀態(tài)和顯示文本
public void stopLoadMore() {
notifyDataSetChanged();
loading = false;
RefreshFootAdapter.this
.changeMoreStatus(RefreshFootAdapter.this.SATUS_PULLUP_LOAD_MORE);
}
//改變加載條狀態(tài)
private void changeMoreStatus(int status) {
if (loading) {
return;
}
load_more_status = status;
notifyDataSetChanged();
}
}
圖1為滑動過程

圖2為松開加載

以上所述是小編給大家介紹的Android RecyclerView上拉加載更多功能回彈實現(xiàn)代碼,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
相關(guān)文章
Android中關(guān)于Notification及NotificationManger的詳解
本篇文章小編為大家介紹,Android中關(guān)于Notification及NotificationManger的詳解。需要的朋友參考下2013-04-04
Android實現(xiàn)3D翻轉(zhuǎn)動畫效果
這篇文章主要為大家詳細介紹了Android實現(xiàn)3D翻轉(zhuǎn)動畫效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-12-12
Android SQLite數(shù)據(jù)庫基本操作方法
本篇文章主要介紹了Android SQLite數(shù)據(jù)庫基本操作方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-02-02
Android開發(fā)實現(xiàn)popupWindow彈出窗口自定義布局與位置控制方法
這篇文章主要介紹了Android開發(fā)實現(xiàn)popupWindow彈出窗口自定義布局與位置控制方法,涉及Android彈出窗口功能、布局及屬性設(shè)置相關(guān)操作技巧,需要的朋友可以參考下2017-09-09
Android加載大分辨率圖片到手機內(nèi)存中的實例方法
有些圖片的分辨率比較高,把它直接加載到手機內(nèi)存中之后,會導致堆內(nèi)存溢出的問題,下面就講解一下Android的堆內(nèi)存以及如何在Android應(yīng)用中加載一個高分辨率的圖片的方法2013-11-11
Android開發(fā)中多進程共享數(shù)據(jù)簡析
這篇文章主要為大家簡單分析Android開發(fā)中多進程共享數(shù)據(jù),怎么做才能讓這兩邊共享數(shù)據(jù),感興趣的小伙伴們可以參考一下2016-04-04
如何正確實現(xiàn)Android啟動屏畫面的方法(避免白屏)
本篇文章主要介紹了如何正確實現(xiàn)Android啟動屏畫面的方法(避免白屏),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-02-02

