English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Metodo di implementazione della funzione di caricamento in basso e aggiornamento in basso di RecyclerView in Android

RecyclerView esiste da molto tempo, ma nei progetti precedenti ho sempre usato ListView, recentemente i nuovi progetti hanno usato in gran parte RecycleView. Soprattutto per il refresh in basso delle cascate, non ho trovato nulla di adatto su internet, quindi ho fatto una mia sommatoria.

Prima di tutto, vediamo alcune immagini:

 

 

Ho due metodi per implementare le funzioni di caricamento in basso e aggiornamento in basso con RecyclerView:

1. Utilizzare il SwipeRefreshLayout di Android.support.v4.widget integrato nel sistema.

2. Un componente personalizzato che contiene RecyleView.

Aggiungere un header in RecycleView non è molto semplice, prima quando usavo ListView potevo aggiungere header e footer, ma RecycleView sembra non essere così facile da gestire. Per il primo metodo che utilizza il SwipeRefreshLayout di Android.support.v4.widget, è anche molto utile, ma i prodotti generalmente non amano questo tipo di aggiornamento con scorrimento in basso, per sembrare più forti, spesso creano un loro con animazioni, il che è piuttosto ridicolo... quindi devo usare il metodo 2.

In estrema sintesi, il metodo 2 di implementazione: il layout genitore è.ViewGroup, all'interno aggiungi View, il primo è il componente header, il secondo è RecycleView, mentre il tentativo di caricamento in basso attraverso l'Adapter di RecycleView.

Con la idea in mente, mettiamoci all'opera:

package com.krain.srecyclerview.fruitview;
import android.content.Context;
import android.graphics.drawable.AnimationDrawable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import com.krain.srecyclerview.R;
/**
* Creato da dafuShao il 9/9/2016 0009.
*
*/
public class ElizabethView extends FrameLayout {
private ImageView imageView;
private AnimationDrawable animationDrawable;
public ElizabethView(Context context) {
super(context);
initview(context);
}
public ElizabethView(Context context, AttributeSet attrs) {
super(context, attrs);
initview(context);
}
public ElizabethView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initview(context);
}
private void initview(Context context){
View view = LayoutInflater.from(context).inflate(R.layout.elizabeth_item, null);
imageView = (ImageView) view.findViewById(R.id.elizabeth_im);
animationDrawable= (AnimationDrawable) imageView.getBackground();
addView(view);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
//Inizia l'animazione
public void startAnim(){
animationDrawable.start();
}
//Ferma l'animazione
public void stopAnim(){
animationDrawable.stop();
}
}

Questo è un componente di testa molto semplice, contiene un piccolo occhio di uccello e un piccolo effetto di schiacciamento a destra e a sinistra, non allego l'immagine.

Ecco il codice del componente personalizzato che contiene RecyclerView:

package com.krain.srecyclerview.srecyclerview;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.support.v4.view.MotionEventCompat;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.Scroller;
import android.widget.TextView;
import com.krain.srecyclerview.R;
import com.krain.srecyclerview.fruitview.ElizabethView;
public class SRecyclerView extends ViewGroup {
Context context;
RecyclerView mRecyclerView;
ElizabethView mHeaderView;
TextView mFootViewTips; // The text display of footview
AdapterWrapper mAdapter;
boolean mIsTop = true; // Whether to slide to the top
RecyclerView.LayoutManager mLayoutManager;
int mLastVisibleItem;
int mFirstVisibleItem;
OnRecyclerStatusChangeListener mRecyclerChangeListener;
int mStatus; // Current status
int mHeadviewHeight; // The height of headview
Scroller mScroller;
int mFirstScollerY; // The initial getScrollY
boolean mHasFooter; // Whether to have the function of pull-up loading
boolean mShowFootVisible; // Whether to display FOOTER view when mHasFooter is true
boolean mHasRefresh = true; // Whether to support pull-to-refresh
private final int DEFAULT_MIN_PAGEINDEX = 1; // Default minimum page number
int mMaxPage = DEFAULT_MIN_PAGEINDEX; // Total number of pages for pagination
int mCurrentPage = DEFAULT_MIN_PAGEINDEX; // Current page number, starting from 1
private final int STATUS_NORMAL = 0, STATUS_REFRESH = 1, STATUS_LOAD = 2;
private final int MSG_LOAD_COMPLETE = 1, MSG_REFRESH_COMPLETE = 0; // handle's constants
private final int DELAY_LOAD_COMPLETE = 1000, DELAY_REFRESH_COMPLETE = 1000; // Tempo di recupero differito per il completamento del caricamento e dell'aggiornamento
public SRecyclerView(Context context) {
super(context);
init(context);
}
public SRecyclerView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public SRecyclerView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
/**
* Imposta il numero massimo di pagine
*
* @param maxPage
*/
public void setMaxPage(int maxPage) {
this.mMaxPage = maxPage;
}
/**
* Se supporta il caricamento in basso
*
* @param hasLoadmore
*/
public void setLoadmore(boolean hasLoadmore) {
mHasFooter = hasLoadmore;
}
public void setRecyclerViewLayoutManage(RecyclerView.LayoutManager mLayoutManage){
this.mLayoutManager=mLayoutManage;
}
/**
* Chiudi la funzione di aggiornamento scorrevole
*/
public void disableRefresh() {
mHasRefresh = false;
}
public void setAdapter(BaseRecyclerViewAdapter adapter) {
int height = 0;
if (mMaxPage == DEFAULT_MIN_PAGEINDEX) {
mHasFooter = false;
}
mAdapter = new AdapterWrapper(context, adapter);
mRecyclerView.setAdapter(mAdapter);
}
private int getViewHeight(View view) {
int measure = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
view.measure(measure, measure);
return view.getMeasuredHeight();
}
/**
* Ottiene il RecyclerView all'interno del viewgroup
*
* @return
*/
public RecyclerView getRecyclerView() {
return mRecyclerView;
}
public void setOnRecyclerChangeListener(OnRecyclerStatusChangeListener listener) {
mRecyclerChangeListener = listener;
}
/**
* Imposta l'animazione per l'aggiunta e la rimozione degli item nel RecyclerView
*
* @param animator
*/
public void setItemAnimator(RecyclerView.ItemAnimator animator) {
mRecyclerView.setItemAnimator(animator);
}
public void notifyDataSetChanged() {
mStatus = STATUS_NORMAL; // Riesegui set dati rappresentando che il carico in più è terminato, al momento tornare allo stato normale
mAdapter.notifyDataSetChanged();
}
public void notifyDataInsert(int positionStart, int itemCount) {
mStatus = STATUS_NORMAL; // Riesegui set dati rappresentando che il carico in più è terminato, al momento tornare allo stato normale
mAdapter.notifyItemRangeInserted(positionStart, itemCount);
}
public void notifyDataRemove(int position) {
mStatus = STATUS_NORMAL; // Riesegui set dati rappresentando che il carico in più è terminato, al momento tornare allo stato normale
mAdapter.notifyItemRemoved(position);
}
/**
* Operazione di inizializzazione
*
* @param context
*/
void init(Context context) {
this.context = context;
mScroller = new Scroller(context);
// if (mLayoutManager!=null){
// addChildView(context,mLayoutManager);
// }else{
// addChildView(context, new LinearLayoutManager(context));
// }
addChildView(context);
}
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
postInvalidate();
}
}
/**
* 增加子View
*
* @param context
*/
void addChildView(Context context, RecyclerView.LayoutManager mLayoutManager) {
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
mHeaderView = new ElizabethView(context);
mRecyclerView = new RecyclerView(context);
addView(mHeaderView);
addView(mRecyclerView);
// mLayoutManager = new LinearLayoutManager(context);
// mLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(mLayoutManager);
// Impostare l'animazione predefinita per l'aggiunta e la rimozione degli item
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
mRecyclerView.addOnScrollListener(onScrollListener);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutParams(params);
}
void addChildView(Context contex) {
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
mHeaderView = new ElizabethView(context);
mRecyclerView = new RecyclerView(context);
addView(mHeaderView);
addView(mRecyclerView);
// mLayoutManager = new LinearLayoutManager(context);
mLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(mLayoutManager);
// Impostare l'animazione predefinita per l'aggiunta e la rimozione degli item
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
mRecyclerView.addOnScrollListener(onScrollListener);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutParams(params);
}
/**
* 屏蔽Recyclerview的触摸事件(下拉刷新的时候)
*/
float lastY;
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
final int action = MotionEventCompat.getActionMasked(ev);
switch (action) {
case MotionEvent.ACTION_DOWN:
lastY = ev.getRawY();
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
return false;
case MotionEvent.ACTION_MOVE:
if (mHasRefresh && mIsTop && ev.getRawY() > lastY)
return true;
break;
}
return false;
}
float offsetY = 0;
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
offsetY = Math.abs(event.getRawY() - lastY); //Valore assoluto della differenza Y
if (offsetY > 0)
scrollToOffset(offsetY);
else {
mIsTop = false;
}
break;
case MotionEvent.ACTION_UP:
if (getScrollY() <= 0) {
doRefresh();
mHeaderView.stopAnim();
mHeaderView.startAnim();
} else complete();
break;
}
return super.onTouchEvent(event);
}
/**
* Fai scorrere questa vista alla posizione di scorrimento della mano
*
* @param offsetY Valore di offset Y
*/
void scrollToOffset(float offsetY) {
//Se stai aggiornando e lo scrolly attuale è uguale al valore iniziale, significa che sei pronto per iniziare il riavvio della discesa e eseguire una sola volta
if (getScrollY() == mFristScollerY && mRecyclerChangeListener != null)
mRecyclerChangeListener.startRefresh();
int value = Math.round(offsetY / 2.0F);
value = mFristScollerY - value;
scrollTo(0, value);
}
/**
* Esegui l'operazione di aggiornamento, muoviti alla posizione dell'intestazione appena comparsa
*/
void doRefresh() {
mStatus = STATUS_REFRESH;
int currentY = getScrollY();
mScroller.startScroll(0, currentY, 0, (mFristScollerY - mHeadviewHeight) - currentY);
invalidate();
if (mRecyclerChangeListener != null) mRecyclerChangeListener.onRefresh();
handler.sendEmptyMessageDelayed(MSG_REFRESH_COMPLETE, DELAY_REFRESH_COMPLETE);
}
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == MSG_LOAD_COMPLETE) {
View footview = mAdapter.getFootView();
if (footview != null)
mRecyclerView.smoothScrollBy(0, -footview.getMeasuredHeight());
} else if (msg.what == MSG_REFRESH_COMPLETE)
complete();
}
};
/**
* header返回原处完全隐藏
*/
public void complete() {
mCurrentPage = DEFAULT_MIN_PAGEINDEX;//完成之后当前的page恢复默认值
if (mFootViewTips != null)
mFootViewTips.setText(context.getString(R.string.loading));//更改foot提示为正在加载中
if (mRecyclerChangeListener != null) mRecyclerChangeListener.refreshComplete();
mStatus = STATUS_NORMAL;
int currentY = getScrollY();
mScroller.startScroll(0, currentY, 0, mFristScollerY - currentY);
mHeaderView.stopAnim();
invalidate();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = 0;
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
measureChild(child, widthMeasureSpec, heightMeasureSpec);
height += child.getMeasuredHeight();
}
setMeasuredDimension(width, height);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int left = getPaddingLeft();
int top = getPaddingTop();
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
if (i == 0) { // Quando è la header, mostra al centro
int headerLeft = getMeasuredWidth() / 2 - child.getMeasuredWidth() / 2;
child.layout(headerLeft, top, headerLeft + child.getMeasuredWidth(), top + child.getMeasuredHeight());
} else
child.layout(left, top, left + child.getMeasuredWidth(), top + child.getMeasuredHeight());
top += child.getMeasuredHeight();
}
mHeadviewHeight = getPaddingTop() + mHeaderView.getMeasuredHeight();
scrollTo(0, mHeadviewHeight); // Spostarsi sotto la header per mostrare il recyleview
mFristScollerY = getScrollY();
}
/**
* Evento di scorrimento di RecyclerView
*/
RecyclerView.OnScrollListener onScrollListener = new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
//滑动到了顶部
if (mFirstVisibleItem == 0) {
mIsTop = true;
} else {
mIsTop = false;
if (mStatus != STATUS_LOAD && mShowFootVisible && mLastVisibleItem + 1 == mAdapter.getItemCount()) {
if (mCurrentPage == mMaxPage) {
//当前页面是最后一页的时候
mFootViewTips = (TextView) mAdapter.getFootView().findViewById(R.id.footer_tips);
mFootViewTips.setText(context.getString(R.string.last_page_tips));
handler.sendEmptyMessageDelayed(MSG_LOAD_COMPLETE, DELAY_LOAD_COMPLETE);
} else {
mStatus = STATUS_LOAD;
if (mRecyclerChangeListener != null) {
mRecyclerChangeListener.onLoadMore();
mCurrentPage++;
}
}
}
}
}
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (mLayoutManager instanceof LinearLayoutManager) {
mLastVisibleItem = ((LinearLayoutManager) mLayoutManager).findLastVisibleItemPosition();
mFirstVisibleItem = ((LinearLayoutManager) mLayoutManager).findFirstCompletelyVisibleItemPosition();
setFootviewVisible();
} else if (mLayoutManager instanceof GridLayoutManager) {
mLastVisibleItem = ((GridLayoutManager) mLayoutManager).findLastVisibleItemPosition();
mFirstVisibleItem = ((GridLayoutManager) mLayoutManager).findFirstCompletelyVisibleItemPosition();
setFootviewVisible();
} else if (mLayoutManager instanceof StaggeredGridLayoutManager) {
// A causa della particolarità di StaggeredGridLayoutManager, potrebbe esserci più item visualizzati per ultimi, quindi qui viene presa un'array
// Ottenere questo array e poi prendere il valore di position più grande dell'array è il valore di position visualizzato per ultimo
int[] lastPositions = new int[((StaggeredGridLayoutManager) mLayoutManager).getSpanCount()];
((StaggeredGridLayoutManager) mLayoutManager).findLastVisibleItemPositions(lastPositions);
mLastVisibleItem = findMax(lastPositions);
mFirstVisibleItem = ((StaggeredGridLayoutManager) mLayoutManager).findFirstVisibleItemPositions(lastPositions)[0];
setFootviewVisible();
}
}
};
void setFootviewVisible() {
// Quando è stato impostato il caricamento in basso ma i elementi della prima pagina non sono sufficienti per riempire il Recyclerview, nascondere il footer
if (mHasFooter && mFirstVisibleItem == 0) {
/**
* qui viene aggiunto un mShowFootVisible che diventa efficace quando la funzione di caricamento in basso è attivata, per controllare che il numero di elementi non sia sufficiente per riempire
* recyclerview altezza in momento di nascosto footview, in caso di numero di elementi superiore all'altezza della vista
*/
if (mLastVisibleItem + 1 == mAdapter.getItemCount()) {
mShowFootVisible = false;
} else mShowFootVisible = true;
notifyDataSetChanged();
}
}
private int findMax(int[] positions) {
int max = positions[0];
for (int value : positions) {
if (value > max) {
max = value;
}
}
return max;
}
private class AdapterWrapper extends RecyclerView.Adapter {
private static final int TYPE_ITEM = 0;
private static final int TYPE_FOOTER = 1;
private RecyclerView.Adapter mAdapter;
private Context mContext;
View footer;
public AdapterWrapper(Context context, RecyclerView.Adapter wrappedAdapter) {
this.mContext = context;
this.mAdapter = wrappedAdapter;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
RecyclerView.ViewHolder holder = null;
switch (viewType) {
case TYPE_ITEM:
holder = mAdapter.onCreateViewHolder(parent, viewType);
break;
case TYPE_FOOTER:
footer = LayoutInflater.from(mContext).inflate(R.layout.lib_recyle_footview, null);
LinearLayout linearLayout= (LinearLayout) footer.findViewById(R.id.loading_layout);
StaggeredGridLayoutManager.LayoutParams layoutParams =
new StaggeredGridLayoutManager.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
layoutParams.setFullSpan(true);
linearLayout.setLayoutParams(layoutParams);
holder = new FooterViewHolder(footer);
break;
}
return holder;
}
public View getFootView() {
return footer;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (!mHasFooter || position + 1 != getItemCount()) {
mAdapter.onBindViewHolder(holder, position);
}
}
@Override
public int getItemCount() {
return mShowFootVisible ? mAdapter.getItemCount() + 1 : mAdapter.getItemCount();
}
@Override
public int getItemViewType(int position) {
if (mShowFootVisible && position + 1 == getItemCount()) {
return TYPE_FOOTER;
} else {
return TYPE_ITEM;
}
}
private class FooterViewHolder extends RecyclerView.ViewHolder {
public ProgressBar progressBar;
public TextView tvLoading;
public LinearLayout llyLoading;
public FooterViewHolder(View itemView) {
super(itemView);
progressBar = (ProgressBar) itemView.findViewById(R.id.progress_loading);
tvLoading = (TextView) itemView.findViewById(R.id.footer_tips);
llyLoading = (LinearLayout) itemView.findViewById(R.id.loading_layout);
}
}
}
}

Infine, c'è anche il codice dell'Adapter: }}

package com.krain.srecyclerview.srecyclerview;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
public abstract class BaseRecyclerViewAdapter<VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> {
private OnItemClickLisener mItemListener;
@Override
public VH onCreateViewHolder(ViewGroup parent, int viewType) {
View view = getItemView(viewType, parent);
VH vh = getViewHolder(view);
view.setOnClickListener(new OnRecyclerAdapterclickListener(vh, viewType));
view.setOnLongClickListener(new OnRecyclerAdapterclickListener(vh, viewType));
return vh;
}
public abstract VH getViewHolder(View itemView);
/**
* Restituisce la view dell'item
*
* @return
*/
public abstract View getItemView(int viewType, ViewGroup parent);
/**
* Restituisce i dati di ogni item dell'Adapter, opzionale
*/
public Object getItem(int position) {
return null;
}
/**
* interfaccia di evento di clic su item
*
* @param mItemListener
*/
public void setOnItemListener(OnItemClickLisener mItemListener) {
this.mItemListener = mItemListener;
}
@Override
public abstract void onBindViewHolder(VH holder, int position);
@Override
public abstract int getItemCount();
class OnRecyclerAdapterclickListener implements View.OnClickListener, View.OnLongClickListener {
VH viewholder;
int viewType;
public OnRecyclerAdapterclickListener(VH viewholder, int viewType) {
this.viewholder = viewholder;
this.viewType = viewType;
}
@Override
public void onClick(View v) {
if (mItemListener != null && viewholder.getAdapterPosition() != RecyclerView.NO_POSITION) {
mItemListener.onItemClick(viewholder.getAdapterPosition(), viewType, viewholder, v);
}
}
@Override
public boolean onLongClick(View v) {
if (mItemListener != null && viewholder.getAdapterPosition() != RecyclerView.NO_POSITION) {
mItemListener.onItemLongClick(viewholder.getAdapterPosition(), viewType, viewholder, v);
}
return false;
}
}
}

Occorre prestare attenzione a:

Se si desidera modificare il modo di layout di Reciview, fare questa modifica

void addChildView(Context contex) {
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
mHeaderView = new ElizabethView(context);
mRecyclerView = new RecyclerView(context);
addView(mHeaderView);
addView(mRecyclerView);
// mLayoutManager = new LinearLayoutManager(context);
mLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(mLayoutManager);
// Impostare l'animazione predefinita per l'aggiunta e la rimozione degli item
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
mRecyclerView.addOnScrollListener(onScrollListener);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutParams(params);
}

mLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL); questa riga è quella da modificare, correggere correttamente, qui non è stato encapsulato, e verrà encapsulato nei prossimi giorni.

Occorre notare anche che nel giudizio dello scrolling se è l'ultima riga, se è un waterfall, è necessario prestare attenzione al modo di giudizio diverso dagli altri

if (mLayoutManager instanceof StaggeredGridLayoutManager) {
// A causa della particolarità di StaggeredGridLayoutManager, potrebbe esserci più item visualizzati per ultimi, quindi qui viene presa un'array
// Ottenere questo array e poi prendere il valore di position più grande dell'array è il valore di position visualizzato per ultimo
int[] lastPositions = new int[((StaggeredGridLayoutManager) mLayoutManager).getSpanCount()];
((StaggeredGridLayoutManager) mLayoutManager).findLastVisibleItemPositions(lastPositions);
mLastVisibleItem = findMax(lastPositions);
mFirstVisibleItem = ((StaggeredGridLayoutManager) mLayoutManager).findFirstVisibleItemPositions(lastPositions)[0];
setFootviewVisible();
}

因为StaggeredGridLayoutManager的特殊性可能导致最后显示的item存在多个,所以这里取到的是一个数组,得到这个数组后再取到数组中position值最大的那个就是最后显示的position值了再去设置最后一行加载更多的显示。

以上所述是小编给大家介绍的Android RecyclerView 上拉加载更多及下拉刷新功能的实现方法,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的,在此也非常感谢大家对呐喊教程网址的支持!

Dichiarazione: il contenuto di questo articolo è stato tratto da Internet, il copyright spetta ai rispettivi proprietari. Il contenuto è stato contribuito e caricato autonomamente dagli utenti di Internet, il sito web non detiene i diritti di proprietà, non è stato editato manualmente e non assume alcuna responsabilità legale. Se trovi contenuti sospetti di violazione del copyright, ti preghiamo di inviare una email a: notice#oldtoolbag.com (al momento dell'invio dell'email, sostituisci # con @) per segnalare il problema e fornire prove pertinenti. Una volta verificata la veridicità, il sito web eliminerà immediatamente i contenuti sospetti di violazione del copyright.

Ti potrebbe interessare