日常备份,下载列表已做好
This commit is contained in:
@@ -12,7 +12,8 @@ import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import cn.lemon.view.adapter.Action;
|
||||
import cn.lemon.view.adapter.RecyclerAdapter;
|
||||
|
||||
@@ -20,13 +21,15 @@ import cn.lemon.view.adapter.RecyclerAdapter;
|
||||
/**
|
||||
* Created by linlongxin on 2016/1/24.
|
||||
*/
|
||||
public class RefreshRecyclerView extends FrameLayout {
|
||||
public class RefreshRecyclerView extends FrameLayout implements SwipeRefreshLayout.OnRefreshListener{
|
||||
|
||||
private final String TAG = "RefreshRecyclerView";
|
||||
private SwipeRefreshLayout mSwipeRefreshLayout;
|
||||
private RecyclerView mRecyclerView;
|
||||
private RecyclerAdapter mAdapter;
|
||||
private boolean loadMoreAble;
|
||||
private List<Action> mRefreshActions;
|
||||
private boolean mLoadMoreEnable;
|
||||
private boolean mShowNoMoreEnable;
|
||||
|
||||
public RefreshRecyclerView(Context context) {
|
||||
this(context, null);
|
||||
@@ -39,20 +42,29 @@ public class RefreshRecyclerView extends FrameLayout {
|
||||
public RefreshRecyclerView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
View view = inflate(context, R.layout.view_refresh_recycler, this);
|
||||
mRecyclerView = view.findViewById(cn.lemon.view.R.id.recycler_view);
|
||||
mSwipeRefreshLayout = view.findViewById(R.id.refresh_layout);
|
||||
mRecyclerView = (RecyclerView) view.findViewById(R.id.lemon_recycler_view);
|
||||
mSwipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.lemon_refresh_layout);
|
||||
|
||||
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RefreshRecyclerView);
|
||||
boolean refreshAble = typedArray.getBoolean(R.styleable.RefreshRecyclerView_refresh_able, true);
|
||||
loadMoreAble = typedArray.getBoolean(R.styleable.RefreshRecyclerView_load_more_able, true);
|
||||
if (!refreshAble) {
|
||||
mLoadMoreEnable = typedArray.getBoolean(R.styleable.RefreshRecyclerView_load_more_enable, true);
|
||||
mShowNoMoreEnable = typedArray.getBoolean(R.styleable.RefreshRecyclerView_show_no_more_enable, true);
|
||||
boolean refreshEnable = typedArray.getBoolean(R.styleable.RefreshRecyclerView_refresh_enable, true);
|
||||
if (!refreshEnable) {
|
||||
mSwipeRefreshLayout.setEnabled(false);
|
||||
} else {
|
||||
mSwipeRefreshLayout.setOnRefreshListener(this);
|
||||
}
|
||||
typedArray.recycle();
|
||||
}
|
||||
|
||||
public void setAdapter(RecyclerAdapter adapter) {
|
||||
if (adapter == null) {
|
||||
return;
|
||||
}
|
||||
mRecyclerView.setAdapter(adapter);
|
||||
mAdapter = adapter;
|
||||
mAdapter.loadMoreAble = loadMoreAble;
|
||||
mAdapter.setLoadMoreEnable(mLoadMoreEnable);
|
||||
mAdapter.setShowNoMoreEnable(mShowNoMoreEnable);
|
||||
}
|
||||
|
||||
public void setLayoutManager(final RecyclerView.LayoutManager layoutManager) {
|
||||
@@ -74,24 +86,32 @@ public class RefreshRecyclerView extends FrameLayout {
|
||||
}
|
||||
}
|
||||
|
||||
public void setRefreshAction(final Action action) {
|
||||
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
action.onAction();
|
||||
}
|
||||
});
|
||||
public void addRefreshAction(final Action action) {
|
||||
if (action == null) {
|
||||
return;
|
||||
}
|
||||
if (mRefreshActions == null) {
|
||||
mRefreshActions = new ArrayList<>();
|
||||
}
|
||||
mRefreshActions.add(action);
|
||||
}
|
||||
|
||||
public void setLoadMoreAction(final Action action) {
|
||||
Log.d(TAG, "setLoadMoreAction");
|
||||
if (mAdapter.isShowNoMore || !loadMoreAble) {
|
||||
if (mAdapter.isShowNoMoring() || !mLoadMoreEnable) {
|
||||
return;
|
||||
}
|
||||
mAdapter.loadMoreAble = true;
|
||||
mAdapter.setLoadMoreAction(action);
|
||||
}
|
||||
|
||||
public void setLoadMoreErrorAction(final Action action) {
|
||||
Log.d(TAG, "setLoadMoreErrorAction");
|
||||
if (mAdapter.isShowNoMoring() || !mLoadMoreEnable) {
|
||||
return;
|
||||
}
|
||||
mAdapter.setLoadMoreErrorAction(action);
|
||||
}
|
||||
|
||||
public void showNoMore() {
|
||||
mAdapter.showNoMore();
|
||||
}
|
||||
@@ -112,10 +132,6 @@ public class RefreshRecyclerView extends FrameLayout {
|
||||
return mSwipeRefreshLayout;
|
||||
}
|
||||
|
||||
public TextView getNoMoreView() {
|
||||
return mAdapter.mNoMoreView;
|
||||
}
|
||||
|
||||
public void setSwipeRefreshColorsFromRes(@ColorRes int... colors) {
|
||||
mSwipeRefreshLayout.setColorSchemeResources(colors);
|
||||
}
|
||||
@@ -134,4 +150,11 @@ public class RefreshRecyclerView extends FrameLayout {
|
||||
public void dismissSwipeRefresh() {
|
||||
mSwipeRefreshLayout.setRefreshing(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
for (Action a : mRefreshActions) {
|
||||
a.onAction();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,14 +13,21 @@ import android.view.ViewGroup;
|
||||
public class BaseViewHolder<T> extends RecyclerView.ViewHolder{
|
||||
|
||||
private final String TAG = "BaseViewHolder";
|
||||
private T mData;
|
||||
|
||||
public BaseViewHolder(ViewGroup parent, int layoutId) {
|
||||
this(LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false));
|
||||
}
|
||||
|
||||
public BaseViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
}
|
||||
|
||||
public BaseViewHolder(ViewGroup parent, int layoutId) {
|
||||
super(LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false));
|
||||
onInitializeView();
|
||||
itemView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
onItemViewClick(mData);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void onInitializeView() {
|
||||
@@ -28,24 +35,25 @@ public class BaseViewHolder<T> extends RecyclerView.ViewHolder{
|
||||
}
|
||||
|
||||
public <T extends View> T findViewById(@IdRes int resId) {
|
||||
return (T) itemView.findViewById(resId);
|
||||
if (itemView != null) {
|
||||
return (T) itemView.findViewById(resId);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void setData(final T data) {
|
||||
itemView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
onItemViewClick(data);
|
||||
}
|
||||
});
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
mData = data;
|
||||
}
|
||||
|
||||
public T getData() {
|
||||
return mData;
|
||||
}
|
||||
|
||||
public void onItemViewClick(T data) {
|
||||
|
||||
}
|
||||
|
||||
public void setTag(Object tag){
|
||||
itemView.setTag(tag);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,18 +2,17 @@ package cn.lemon.view.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
import android.util.SparseIntArray;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 复杂的数据类型列表 Adapter , 没有 Header , Footer 的概念,所有的 item 都对应一个 ViewHolder
|
||||
* 通过反射自动处理 onCreateViewHolder 过程,如需避免反射调用请使用 CustomMultiTypeAdapter
|
||||
*
|
||||
* Created by linlongxin on 2016/8/22.
|
||||
*/
|
||||
|
||||
@@ -21,79 +20,34 @@ public class MultiTypeAdapter extends RecyclerAdapter {
|
||||
|
||||
private final String TAG = "MultiTypeAdapter";
|
||||
private List<Object> mViewsData;
|
||||
private SparseIntArray mPositionViewType; //position --> ViewType
|
||||
private ViewHolderManager mViewHolderManager;
|
||||
|
||||
public MultiTypeAdapter(Context context) {
|
||||
super(context);
|
||||
mViewsData = new ArrayList<>();
|
||||
mPositionViewType = new SparseIntArray();
|
||||
mViewHolderManager = new ViewHolderManager();
|
||||
}
|
||||
|
||||
public <T> void add(Class<? extends BaseViewHolder<T>> viewHolder, T data) {
|
||||
if (isShowNoMore) {
|
||||
return;
|
||||
}
|
||||
mViewsData.add(data);
|
||||
mViewHolderManager.addViewHolder(viewHolder);
|
||||
int viewType = mViewHolderManager.getViewType(viewHolder);
|
||||
mPositionViewType.put(mViewCount - 1, viewType);//mViewCount从1开始
|
||||
int positionStart = mViewCount - 1;
|
||||
mViewCount++;
|
||||
notifyItemRangeInserted(positionStart, 1);
|
||||
}
|
||||
|
||||
public <T> void addAll(Class<? extends BaseViewHolder<T>> viewHolder, T[] data) {
|
||||
addAll(viewHolder, Arrays.asList(data));
|
||||
}
|
||||
|
||||
public <T> void addAll(Class<? extends BaseViewHolder<T>> viewHolder, List<T> data) {
|
||||
int size = data.size();
|
||||
if (isShowNoMore || size == 0) {
|
||||
return;
|
||||
}
|
||||
mViewsData.addAll(data);
|
||||
mViewHolderManager.addViewHolder(viewHolder);
|
||||
int viewType = mViewHolderManager.getViewType(viewHolder);
|
||||
int positionStart = mViewCount - 1;
|
||||
for (int i = 0; i < size; i++) {
|
||||
mPositionViewType.put(mViewCount - 1, viewType); //mViewCount从1开始
|
||||
mViewCount++;
|
||||
}
|
||||
notifyItemRangeInserted(positionStart, size);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
if (mViewsData == null) {
|
||||
log("clear() mData is null");
|
||||
return;
|
||||
}
|
||||
mViewsData.clear();
|
||||
mViewCount = 1;
|
||||
isShowNoMore = false;
|
||||
mLoadMoreView.setVisibility(View.GONE);
|
||||
mNoMoreView.setVisibility(View.GONE);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
if (position == mViewCount - 1) {
|
||||
if (hasEndStatusView() && position == mViewCount - 1) {
|
||||
return STATUS_TYPE;
|
||||
}
|
||||
return mPositionViewType.get(position);
|
||||
return mViewHolderManager.getViewType(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
log("onCreateViewHolder -- viewType : " + viewType);
|
||||
if (mViewHolderManager == null) {
|
||||
throw new ExceptionInInitializerError("mViewHolderManager is null , it need init");
|
||||
}
|
||||
if (viewType == STATUS_TYPE) {
|
||||
return new BaseViewHolder(mStatusView);
|
||||
}
|
||||
Class clazzViewHolder = mViewHolderManager.getViewHolder(viewType);
|
||||
Class clazzViewHolder = mViewHolderManager.getViewHolderClass(viewType);
|
||||
try {
|
||||
//这里只适配了ViewHolder构造函数只有ViewGroup.class参数或者无参情况的构造函数
|
||||
//这里只适配了 ViewHolder 构造函数只有 ViewGroup.class 参数 或者 无参 情况的构造函数,具体请看 Demo
|
||||
BaseViewHolder holder;
|
||||
Constructor constructor = clazzViewHolder.getDeclaredConstructor(new Class[]{ViewGroup.class});
|
||||
constructor.setAccessible(true);
|
||||
@@ -103,21 +57,10 @@ public class MultiTypeAdapter extends RecyclerAdapter {
|
||||
holder = (BaseViewHolder) constructor.newInstance();
|
||||
}
|
||||
return holder;
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
Log.e(TAG, "onCreateBaseViewHolder : " + e.getMessage());
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
Log.e(TAG, "onCreateBaseViewHolder : " + e.getMessage());
|
||||
} catch (InstantiationException e) {
|
||||
e.printStackTrace();
|
||||
Log.e(TAG, "onCreateBaseViewHolder : " + e.getMessage());
|
||||
} catch (InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "onCreateBaseViewHolder : " + e.getMessage());
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -128,17 +71,87 @@ public class MultiTypeAdapter extends RecyclerAdapter {
|
||||
@Override
|
||||
public void onBindViewHolder(BaseViewHolder holder, int position) {
|
||||
log("onBindViewHolder -- position : " + position);
|
||||
if (position == 0 && mViewCount == 1) {
|
||||
|
||||
} else if (position == mViewCount - 1) {
|
||||
// 显示加载更多
|
||||
if (loadMoreAble && mLoadMoreAction != null && !isShowNoMore) {
|
||||
mLoadMoreView.setVisibility(View.VISIBLE);
|
||||
// 显示加载更多
|
||||
if (!mIsNoMoring && mLoadMoreEnable && !mIsLoadMoring && isValidLoadMore(position)) {
|
||||
mIsLoadMoring = true;
|
||||
setViewVisible(mLoadMoreLayout, true);
|
||||
setViewVisible(mLoadMoreView, true);
|
||||
setViewVisible(mLoadMoreError, false);
|
||||
setViewVisible(mNoMoreView, false);
|
||||
log("load more");
|
||||
if (mLoadMoreAction != null ) {
|
||||
mLoadMoreAction.onAction();
|
||||
}
|
||||
} else {
|
||||
} else if (mViewsData != null && holder != null && position < mViewsData.size()){
|
||||
holder.setData(mViewsData.get(position));
|
||||
}
|
||||
}
|
||||
|
||||
public <T> void add(Class<? extends BaseViewHolder<T>> viewHolder, T data) {
|
||||
if (mIsNoMoring || data == null || viewHolder == null) {
|
||||
return;
|
||||
}
|
||||
mIsLoadMoring = false;
|
||||
mViewsData.add(data);
|
||||
mViewHolderManager.addViewHolder(viewHolder);
|
||||
int viewType = mViewHolderManager.getViewType(viewHolder);
|
||||
|
||||
int positionStart;
|
||||
|
||||
if (hasEndStatusView()) {
|
||||
//mViewCount从1开始
|
||||
positionStart = mViewCount - 1;
|
||||
} else {
|
||||
positionStart = mViewCount;
|
||||
}
|
||||
if (positionStart >= 0) {
|
||||
mViewHolderManager.putViewType(positionStart, viewType);
|
||||
mViewCount++;
|
||||
notifyItemRangeInserted(positionStart, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public <T> void addAll(Class<? extends BaseViewHolder<T>> viewHolder, T[] data) {
|
||||
addAll(viewHolder, Arrays.asList(data));
|
||||
}
|
||||
|
||||
public <T> void addAll(Class<? extends BaseViewHolder<T>> viewHolder, List<T> data) {
|
||||
if (mIsNoMoring || data == null || data.size() == 0) {
|
||||
return;
|
||||
}
|
||||
mIsLoadMoring = false;
|
||||
int size = data.size();
|
||||
mViewsData.addAll(data);
|
||||
mViewHolderManager.addViewHolder(viewHolder);
|
||||
int viewType = mViewHolderManager.getViewType(viewHolder);
|
||||
|
||||
int positionStart;
|
||||
if (hasEndStatusView()) {
|
||||
positionStart = mViewCount - 1;
|
||||
} else {
|
||||
positionStart = mViewCount;
|
||||
}
|
||||
if (positionStart >= 0) {
|
||||
for (int i = 0; i < size; i++) {
|
||||
mViewHolderManager.putViewType(positionStart + i, viewType);
|
||||
}
|
||||
mViewCount += size;
|
||||
notifyItemRangeInserted(positionStart, size);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
if (mViewsData == null) {
|
||||
log("clear() mData is null");
|
||||
return;
|
||||
}
|
||||
mViewsData.clear();
|
||||
mViewCount = hasEndStatusView() ? 1 : 0;
|
||||
mIsNoMoring = false;
|
||||
mIsLoadMoring = false;
|
||||
setViewVisible(mLoadMoreLayout, false);
|
||||
setViewVisible(mNoMoreView, false);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package cn.lemon.view.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Message;
|
||||
import android.support.annotation.LayoutRes;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.util.Log;
|
||||
@@ -8,7 +9,6 @@ import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
@@ -22,10 +22,16 @@ import cn.lemon.view.R;
|
||||
/**
|
||||
* Created by linlongxin on 2015/12/19.
|
||||
*/
|
||||
public abstract class RecyclerAdapter<T> extends RecyclerView.Adapter<BaseViewHolder<T>> {
|
||||
public abstract class RecyclerAdapter<T> extends RecyclerView.Adapter<BaseViewHolder<T>> implements IHandler {
|
||||
|
||||
private static final String TAG = "RecyclerAdapter";
|
||||
private boolean allowLog = false; //改成false关闭日志
|
||||
private static final String TAG = RecyclerAdapter.class.getSimpleName();
|
||||
|
||||
protected static final int MSG_SHOW_NO_MORE = 1 << 1;
|
||||
protected static final int MSG_SHOW_LOAD_MORE = 1 << 2;
|
||||
protected static final int MSG_SHOW_LOAD_MORE_ERROR = 1 << 3;
|
||||
|
||||
//改成false关闭日志
|
||||
private boolean allowLog = true;
|
||||
|
||||
public static final int HEADER_TYPE = 111;
|
||||
public static final int FOOTER_TYPE = 222;
|
||||
@@ -34,20 +40,32 @@ public abstract class RecyclerAdapter<T> extends RecyclerView.Adapter<BaseViewHo
|
||||
|
||||
private boolean hasHeader = false;
|
||||
private boolean hasFooter = false;
|
||||
public boolean isShowNoMore = false; //停止加载
|
||||
public boolean loadMoreAble = false; //是否可加载更多
|
||||
|
||||
// 是否可加载更多
|
||||
protected boolean mLoadMoreEnable = false;
|
||||
// 是否可显示 no more
|
||||
protected boolean mNoMoreEnable = false;
|
||||
// 是否正在显示 load more
|
||||
protected boolean mIsLoadMoring = false;
|
||||
// 是否正在显示 no more
|
||||
protected boolean mIsNoMoring = false;
|
||||
|
||||
protected Action mLoadMoreAction;
|
||||
protected Action mErrorAction;
|
||||
|
||||
private List<T> mData = new ArrayList<>();
|
||||
|
||||
private View headerView;
|
||||
private View footerView;
|
||||
protected View mStatusView;
|
||||
protected LinearLayout mLoadMoreView;
|
||||
public TextView mNoMoreView;
|
||||
protected View mLoadMoreLayout;
|
||||
protected View mLoadMoreView;
|
||||
protected TextView mLoadMoreError;
|
||||
protected TextView mNoMoreView;
|
||||
|
||||
private Context mContext;
|
||||
protected Context mContext;
|
||||
|
||||
private WeakHandler mHandler = new WeakHandler(this);
|
||||
|
||||
public void colseLog() {
|
||||
allowLog = false;
|
||||
@@ -55,9 +73,7 @@ public abstract class RecyclerAdapter<T> extends RecyclerView.Adapter<BaseViewHo
|
||||
|
||||
public RecyclerAdapter(Context context) {
|
||||
mContext = context;
|
||||
initStatusView(context);
|
||||
}
|
||||
|
||||
|
||||
public RecyclerAdapter(Context context, T[] data) {
|
||||
this(context, Arrays.asList(data));
|
||||
@@ -65,18 +81,44 @@ public abstract class RecyclerAdapter<T> extends RecyclerView.Adapter<BaseViewHo
|
||||
|
||||
public RecyclerAdapter(Context context, List<T> data) {
|
||||
mContext = context;
|
||||
initStatusView(context);
|
||||
this.mData = data;
|
||||
mViewCount += data.size();
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void initStatusView(Context context) {
|
||||
mStatusView = LayoutInflater.from(context).inflate(R.layout.view_status_last, null);
|
||||
mStatusView.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
mLoadMoreView = (LinearLayout) mStatusView.findViewById(R.id.load_more_view);
|
||||
mNoMoreView = (TextView) mStatusView.findViewById(R.id.no_more_view);
|
||||
mViewCount++;
|
||||
private void initEndStatusView() {
|
||||
if (hasEndStatusView() && mStatusView == null) {
|
||||
mStatusView = LayoutInflater.from(getContext()).inflate(R.layout.view_status_last, null);
|
||||
mStatusView.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
mLoadMoreLayout = mStatusView.findViewById(R.id.load_more_Layout);
|
||||
mLoadMoreView = mStatusView.findViewById(R.id.load_more_loading);
|
||||
mLoadMoreError = (TextView) mStatusView.findViewById(R.id.load_more_error);
|
||||
mNoMoreView = (TextView) mStatusView.findViewById(R.id.no_more_view);
|
||||
mViewCount++;
|
||||
mLoadMoreError.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
mHandler.sendEmptyMessage(MSG_SHOW_LOAD_MORE);
|
||||
if (mErrorAction != null) {
|
||||
mErrorAction.onAction();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void setLoadMoreEnable(boolean b) {
|
||||
mLoadMoreEnable = b;
|
||||
initEndStatusView();
|
||||
}
|
||||
|
||||
public void setShowNoMoreEnable(boolean b) {
|
||||
mNoMoreEnable = b;
|
||||
initEndStatusView();
|
||||
}
|
||||
|
||||
public boolean isShowNoMoring() {
|
||||
return mIsNoMoring;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -87,8 +129,9 @@ public abstract class RecyclerAdapter<T> extends RecyclerView.Adapter<BaseViewHo
|
||||
return new BaseViewHolder<>(footerView);
|
||||
} else if (viewType == STATUS_TYPE) {
|
||||
return new BaseViewHolder<>(mStatusView);
|
||||
} else
|
||||
} else {
|
||||
return onCreateBaseViewHolder(parent, viewType);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract BaseViewHolder<T> onCreateBaseViewHolder(ViewGroup parent, int viewType);
|
||||
@@ -99,54 +142,88 @@ public abstract class RecyclerAdapter<T> extends RecyclerView.Adapter<BaseViewHo
|
||||
*/
|
||||
@Override
|
||||
public void onBindViewHolder(BaseViewHolder<T> holder, int position) {
|
||||
// log("onBindViewHolder() viewCount : " + mViewCount + " position : " + position);
|
||||
if (position == 0) {
|
||||
// 最先加载 mStatusView 时不需要绑定数据
|
||||
if (mViewCount == 1 || hasHeader) {
|
||||
return;
|
||||
} else {
|
||||
if (mData.size() > 0)
|
||||
holder.setData(mData.get(0));
|
||||
else
|
||||
return;
|
||||
log("onBindViewHolder() viewCount : " + mViewCount + " position : " + position);
|
||||
if (holder == null || position < 0) {
|
||||
return;
|
||||
}
|
||||
int dataSize = mData.size();
|
||||
if (hasEndStatusView()) {
|
||||
if (!hasHeader && !hasFooter && position < dataSize) {
|
||||
//没有Header和Footer
|
||||
holder.setData(mData.get(position));
|
||||
} else if (hasHeader && !hasFooter && position > 0 && position < mViewCount - 1 && position - 1 < dataSize) {
|
||||
//有Header没有Footer
|
||||
holder.setData(mData.get(position - 1));
|
||||
} else if (!hasHeader && position < mViewCount - 2 && position < dataSize) {
|
||||
//没有Header,有Footer
|
||||
holder.setData(mData.get(position));
|
||||
} else if (position > 0 && position < mViewCount - 2 && position - 1 < dataSize) {
|
||||
//Header, Footer 都有
|
||||
holder.setData(mData.get(position - 1));
|
||||
}
|
||||
} else {
|
||||
if (!hasHeader && !hasFooter && position < dataSize) {
|
||||
//没有Header和Footer
|
||||
holder.setData(mData.get(position));
|
||||
} else if (hasHeader && !hasFooter && position > 0 && position < mViewCount && position - 1 < dataSize) {
|
||||
//有Header没有Footer
|
||||
holder.setData(mData.get(position - 1));
|
||||
} else if (!hasHeader && position < mViewCount - 1 && position < dataSize) {
|
||||
//没有Header,有Footer
|
||||
holder.setData(mData.get(position));
|
||||
} else if (position > 0 && position < mViewCount - 1 && position - 1 < dataSize) {
|
||||
//Header, Footer 都有
|
||||
holder.setData(mData.get(position - 1));
|
||||
}
|
||||
} else if (!hasHeader && !hasFooter && position < mData.size()) { //没有Header和Footer
|
||||
holder.setData(mData.get(position));
|
||||
} else if (hasHeader && !hasFooter && position > 0 && position < mViewCount - 1) { //有Header没有Footer
|
||||
holder.setData(mData.get(position - 1));
|
||||
} else if (!hasHeader && position < mViewCount - 2) { //没有Header,有Footer
|
||||
holder.setData(mData.get(position));
|
||||
} else if (position > 0 && position < mViewCount - 2) { //都有
|
||||
holder.setData(mData.get(position - 1));
|
||||
}
|
||||
|
||||
// 最后一个可见的 item 时 加载更多。解决 remove 时 bug
|
||||
int positionEnd;
|
||||
if ((hasHeader && hasFooter) || (!hasHeader && hasFooter)) {
|
||||
positionEnd = mViewCount - 3;
|
||||
} else {
|
||||
positionEnd = mViewCount - 2;
|
||||
}
|
||||
if (loadMoreAble && !isShowNoMore && position == positionEnd) {
|
||||
mLoadMoreView.setVisibility(View.VISIBLE);
|
||||
if (mLoadMoreEnable && !mIsNoMoring && !mIsLoadMoring && isValidLoadMore(position)) {
|
||||
mIsLoadMoring = true;
|
||||
setViewVisible(mLoadMoreLayout, true);
|
||||
setViewVisible(mLoadMoreView, true);
|
||||
setViewVisible(mLoadMoreError, false);
|
||||
setViewVisible(mNoMoreView, false);
|
||||
log("load more");
|
||||
if (mLoadMoreAction != null) {
|
||||
mLoadMoreAction.onAction();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* load more 当前位置 view 是否有效
|
||||
*/
|
||||
protected boolean isValidLoadMore(int position) {
|
||||
if (hasEndStatusView()) {
|
||||
// 倒数第二个 item 就load more ,提前触发。(解决一些极端 case 导致 bug 并提前加载数据,提高加载效率)
|
||||
if (hasHeader) {
|
||||
return position != 1 && position == mViewCount - 3 && mViewCount != 2;
|
||||
} else {
|
||||
return position != 0 && position == mViewCount - 2 && mViewCount != 1;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ViewHolder 更新 Item 的位置选择 ViewType , 和 UI 是同步的
|
||||
*/
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
if (hasHeader && position == 0) { //header
|
||||
// header
|
||||
if (hasHeader && position == 0) {
|
||||
return HEADER_TYPE;
|
||||
}
|
||||
if (hasFooter && position == mViewCount - 2) { //footer
|
||||
// footer
|
||||
if (hasFooter && hasEndStatusView() && position == mViewCount - 2) {
|
||||
return FOOTER_TYPE;
|
||||
} else if (hasFooter && !hasEndStatusView() && position == mViewCount - 1) {
|
||||
return FOOTER_TYPE;
|
||||
}
|
||||
if (position == mViewCount - 1) { //最后View的状态
|
||||
// status
|
||||
if (hasEndStatusView() && position == mViewCount - 1) {
|
||||
return STATUS_TYPE;
|
||||
}
|
||||
|
||||
@@ -162,37 +239,27 @@ public abstract class RecyclerAdapter<T> extends RecyclerView.Adapter<BaseViewHo
|
||||
}
|
||||
|
||||
public void showNoMore() {
|
||||
|
||||
isShowNoMore = true;
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mLoadMoreView.setVisibility(View.GONE);
|
||||
mNoMoreView.setVisibility(View.VISIBLE);
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
/*mLoadMoreView.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mLoadMoreView.setVisibility(View.GONE);
|
||||
mNoMoreView.setVisibility(View.VISIBLE);
|
||||
Log.i("调试","载入View:"+(mLoadMoreView.getVisibility()));
|
||||
}
|
||||
});*/
|
||||
if (!mNoMoreEnable) {
|
||||
return;
|
||||
}
|
||||
mIsNoMoring = true;
|
||||
mHandler.sendEmptyMessage(MSG_SHOW_NO_MORE);
|
||||
}
|
||||
|
||||
public void showLoadMoreError() {
|
||||
if (!mLoadMoreEnable) {
|
||||
return;
|
||||
}
|
||||
mHandler.sendEmptyMessage(MSG_SHOW_LOAD_MORE_ERROR);
|
||||
}
|
||||
|
||||
public void setLoadMoreErrorAction(Action action) {
|
||||
mErrorAction = action;
|
||||
}
|
||||
private android.os.Handler handler=new android.os.Handler();
|
||||
|
||||
public void openLoadMore() {
|
||||
isShowNoMore = false;
|
||||
mLoadMoreView.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mLoadMoreView.setVisibility(View.VISIBLE);
|
||||
mNoMoreView.setVisibility(View.GONE);
|
||||
}
|
||||
});
|
||||
mIsNoMoring = false;
|
||||
mHandler.sendEmptyMessage(MSG_SHOW_LOAD_MORE);
|
||||
}
|
||||
|
||||
public void setLoadMoreAction(Action action) {
|
||||
@@ -200,13 +267,18 @@ public abstract class RecyclerAdapter<T> extends RecyclerView.Adapter<BaseViewHo
|
||||
}
|
||||
|
||||
public void add(T object) {
|
||||
if (!isShowNoMore) {
|
||||
if (!mIsNoMoring && object != null) {
|
||||
mIsLoadMoring = false;
|
||||
mData.add(object);
|
||||
int position;
|
||||
if (hasFooter) {
|
||||
if (hasFooter && hasEndStatusView()) {
|
||||
position = mViewCount - 2;
|
||||
} else {
|
||||
} else if (hasFooter && !hasEndStatusView()) {
|
||||
position = mViewCount - 1;
|
||||
} else if (!hasFooter && hasEndStatusView()) {
|
||||
position = mViewCount - 1;
|
||||
} else {
|
||||
position = mViewCount;
|
||||
}
|
||||
mViewCount++;
|
||||
notifyItemInserted(position);
|
||||
@@ -214,7 +286,8 @@ public abstract class RecyclerAdapter<T> extends RecyclerView.Adapter<BaseViewHo
|
||||
}
|
||||
|
||||
public void insert(T object, int itemPosition) {
|
||||
if (mData != null && itemPosition < mViewCount) {
|
||||
int maxPosition = hasEndStatusView() ? mViewCount - 2 : mViewCount - 1;
|
||||
if (mData != null && itemPosition < maxPosition && object != null) {
|
||||
int dataPosition;
|
||||
if (hasHeader) {
|
||||
dataPosition = itemPosition - 1;
|
||||
@@ -228,14 +301,22 @@ public abstract class RecyclerAdapter<T> extends RecyclerView.Adapter<BaseViewHo
|
||||
}
|
||||
|
||||
public void addAll(List<T> data) {
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
int size = data.size();
|
||||
if (!isShowNoMore && size > 0) {
|
||||
if (!mIsNoMoring && size > 0) {
|
||||
mIsLoadMoring = false;
|
||||
mData.addAll(data);
|
||||
int positionStart;
|
||||
if (hasFooter) {
|
||||
if (hasFooter && hasEndStatusView()) {
|
||||
positionStart = mViewCount - 2;
|
||||
} else {
|
||||
} else if (hasFooter && !hasEndStatusView()) {
|
||||
positionStart = mViewCount - 1;
|
||||
} else if (!hasFooter && hasEndStatusView()) {
|
||||
positionStart = mViewCount - 1;
|
||||
} else {
|
||||
positionStart = mViewCount;
|
||||
}
|
||||
mViewCount += size;
|
||||
notifyItemRangeInserted(positionStart, size);
|
||||
@@ -248,7 +329,7 @@ public abstract class RecyclerAdapter<T> extends RecyclerView.Adapter<BaseViewHo
|
||||
}
|
||||
|
||||
public void replace(T object, int itemPosition) {
|
||||
if (mData != null) {
|
||||
if (mData != null && object != null) {
|
||||
int dataPosition;
|
||||
if (hasHeader) {
|
||||
dataPosition = itemPosition - 1;
|
||||
@@ -265,7 +346,7 @@ public abstract class RecyclerAdapter<T> extends RecyclerView.Adapter<BaseViewHo
|
||||
|
||||
//position start with 0
|
||||
public void remove(T object) {
|
||||
if (!mData.contains(object)) {
|
||||
if (object != null && !mData.contains(object)) {
|
||||
Toast.makeText(getContext(), "删除失败", Toast.LENGTH_SHORT).show();
|
||||
log("remove() without the object : " + object.getClass().getName());
|
||||
return;
|
||||
@@ -280,7 +361,9 @@ public abstract class RecyclerAdapter<T> extends RecyclerView.Adapter<BaseViewHo
|
||||
remove(itemPosition);
|
||||
}
|
||||
|
||||
//positionItem start with 0
|
||||
/**
|
||||
* positionItem start with 0
|
||||
*/
|
||||
public void remove(int itemPosition) {
|
||||
int dataPosition;
|
||||
int dataSize = mData.size();
|
||||
@@ -314,20 +397,25 @@ public abstract class RecyclerAdapter<T> extends RecyclerView.Adapter<BaseViewHo
|
||||
return;
|
||||
}
|
||||
mData.clear();
|
||||
mViewCount = 1;
|
||||
mViewCount = hasEndStatusView() ? 1 : 0;
|
||||
if (hasHeader) {
|
||||
mViewCount++;
|
||||
}
|
||||
if (hasFooter) {
|
||||
mViewCount++;
|
||||
}
|
||||
isShowNoMore = false;
|
||||
mLoadMoreView.setVisibility(View.GONE);
|
||||
mNoMoreView.setVisibility(View.GONE);
|
||||
mIsNoMoring = false;
|
||||
mIsLoadMoring = false;
|
||||
setViewVisible(mLoadMoreLayout, false);
|
||||
setViewVisible(mNoMoreView, false);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* header 不负责数据加载。。。。也就是不会掉用 onBindViewHolder
|
||||
*
|
||||
* @param header
|
||||
*/
|
||||
public void setHeader(View header) {
|
||||
hasHeader = true;
|
||||
headerView = header;
|
||||
@@ -352,6 +440,11 @@ public abstract class RecyclerAdapter<T> extends RecyclerView.Adapter<BaseViewHo
|
||||
mViewCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Footer 这里不负责数据的加载
|
||||
*
|
||||
* @param res
|
||||
*/
|
||||
public void setFooter(@LayoutRes int res) {
|
||||
setFooter(LayoutInflater.from(mContext).inflate(res, null));
|
||||
}
|
||||
@@ -366,7 +459,11 @@ public abstract class RecyclerAdapter<T> extends RecyclerView.Adapter<BaseViewHo
|
||||
public void removeFooter() {
|
||||
if (hasFooter) {
|
||||
hasFooter = false;
|
||||
notifyItemRemoved(mViewCount - 2);
|
||||
if (hasEndStatusView() && mViewCount > 1) {
|
||||
notifyItemRemoved(mViewCount - 2);
|
||||
} else if (!hasEndStatusView() && mViewCount > 0) {
|
||||
notifyItemRemoved(mViewCount - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -378,9 +475,47 @@ public abstract class RecyclerAdapter<T> extends RecyclerView.Adapter<BaseViewHo
|
||||
return mContext;
|
||||
}
|
||||
|
||||
protected void setViewVisible(View view, boolean visibile) {
|
||||
if (view != null) {
|
||||
view.setVisibility(visibile ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean hasEndStatusView() {
|
||||
return mLoadMoreEnable || mNoMoreEnable;
|
||||
}
|
||||
|
||||
public void log(String content) {
|
||||
if (allowLog) {
|
||||
Log.d(TAG, content);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handMsg(Message message) {
|
||||
switch (message.what) {
|
||||
case MSG_SHOW_LOAD_MORE_ERROR:
|
||||
// true 阻止 load more 执行
|
||||
mIsLoadMoring = true;
|
||||
setViewVisible(mLoadMoreLayout, true);
|
||||
setViewVisible(mLoadMoreView, false);
|
||||
setViewVisible(mLoadMoreError, true);
|
||||
setViewVisible(mNoMoreView, false);
|
||||
break;
|
||||
case MSG_SHOW_LOAD_MORE:
|
||||
mIsLoadMoring = true;
|
||||
setViewVisible(mLoadMoreLayout, true);
|
||||
setViewVisible(mLoadMoreView, true);
|
||||
setViewVisible(mLoadMoreError, false);
|
||||
setViewVisible(mNoMoreView, false);
|
||||
break;
|
||||
case MSG_SHOW_NO_MORE:
|
||||
mIsLoadMoring = false;
|
||||
setViewVisible(mLoadMoreLayout, false);
|
||||
setViewVisible(mNoMoreView, true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package cn.lemon.view.adapter;
|
||||
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import android.util.SparseIntArray;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.util.HashMap;
|
||||
@@ -14,35 +16,47 @@ public class ViewHolderManager {
|
||||
|
||||
private final String TAG = "ViewHolderManager";
|
||||
private int mViewType = 10;
|
||||
private Map<Class<? extends BaseViewHolder>, Integer> mHolderType;
|
||||
private Map<Integer,Class<? extends BaseViewHolder>> mTypeHolder;
|
||||
private Map<Class<? extends BaseViewHolder>, Integer> mHolderToTypeMap;
|
||||
private SparseArray<Class<? extends BaseViewHolder>> mTypeToHolderMap;
|
||||
//position to ViewType
|
||||
private SparseIntArray mPositionToTypeMap;
|
||||
|
||||
public ViewHolderManager() {
|
||||
mHolderType = new HashMap<>();
|
||||
mTypeHolder = new HashMap<>();
|
||||
mHolderToTypeMap = new HashMap<>();
|
||||
mTypeToHolderMap = new SparseArray<>();
|
||||
mPositionToTypeMap = new SparseIntArray();
|
||||
}
|
||||
|
||||
public void putViewType(int position, int type){
|
||||
mPositionToTypeMap.put(position, type);
|
||||
}
|
||||
|
||||
public int getViewType(int position) {
|
||||
return mPositionToTypeMap.get(position);
|
||||
}
|
||||
|
||||
public void addViewHolder(Class<? extends BaseViewHolder> viewHolder) {
|
||||
if (!mHolderType.containsKey(viewHolder)) {
|
||||
Class dataClass = (Class) ((ParameterizedType) viewHolder.getGenericSuperclass()).getActualTypeArguments()[0]; //获取ViewHolder的泛型数据class
|
||||
mViewType++;
|
||||
mHolderType.put(viewHolder, mViewType);
|
||||
mTypeHolder.put(mViewType,viewHolder);
|
||||
if (!mHolderToTypeMap.containsKey(viewHolder)) {
|
||||
//获取ViewHolder的泛型数据class
|
||||
Class dataClass = (Class) ((ParameterizedType) viewHolder.getGenericSuperclass()).getActualTypeArguments()[0];
|
||||
mViewType ++;
|
||||
mHolderToTypeMap.put(viewHolder, mViewType);
|
||||
mTypeToHolderMap.put(mViewType,viewHolder);
|
||||
Log.d(TAG, "addViewHolder dataClassType : " + dataClass.getName());
|
||||
}
|
||||
}
|
||||
|
||||
public int getViewType(Class<? extends BaseViewHolder> holder){
|
||||
if(!mHolderType.containsKey(holder)){
|
||||
throw new NullPointerException("please invoke addViewHolder method");
|
||||
if(!mHolderToTypeMap.containsKey(holder)){
|
||||
throw new IllegalArgumentException("please invoke add ViewHolder method");
|
||||
}
|
||||
return mHolderType.get(holder);
|
||||
return mHolderToTypeMap.get(holder);
|
||||
}
|
||||
|
||||
public Class<? extends BaseViewHolder> getViewHolder(int viewType){
|
||||
if(!mTypeHolder.containsKey(viewType)){
|
||||
throw new NullPointerException("please invoke addViewHolder method");
|
||||
public Class<? extends BaseViewHolder> getViewHolderClass(int viewType){
|
||||
if(mTypeToHolderMap.get(viewType) == null){
|
||||
throw new IllegalArgumentException("please invoke add ViewHolder method");
|
||||
}
|
||||
return mTypeHolder.get(viewType);
|
||||
return mTypeToHolderMap.get(viewType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.v4.widget.SwipeRefreshLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/refresh_layout"
|
||||
android:id="@+id/lemon_refresh_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<!-- 避免 id 命名冲突 -->
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/recycler_view"
|
||||
android:id="@+id/lemon_recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
|
||||
@@ -1,36 +1,53 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/load_more_view"
|
||||
<RelativeLayout
|
||||
android:id="@+id/load_more_Layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
android:padding="8dp"
|
||||
android:visibility="gone">
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible">
|
||||
|
||||
<ProgressBar
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
<LinearLayout android:id="@+id/load_more_loading"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center">
|
||||
|
||||
<ProgressBar
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:text="正在加载..."
|
||||
android:textSize="14sp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:text="正在加载..."
|
||||
android:textSize="14sp" />
|
||||
android:id="@+id/load_more_error"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/bg_button_retry_adapter"
|
||||
android:gravity="center"
|
||||
android:text="数据错误,点我重试"
|
||||
android:textSize="14sp"/>
|
||||
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/no_more_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:gravity="center"
|
||||
android:text=""
|
||||
android:text="没有更多了O(∩_∩)O~"
|
||||
android:textSize="14sp"
|
||||
android:visibility="gone" />
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<declare-styleable name="RefreshRecyclerView">
|
||||
<attr name="refresh_able" format="boolean"/>
|
||||
<attr name="load_more_able" format="boolean"/>
|
||||
<attr name="refresh_enable" format="boolean"/>
|
||||
<!-- 其中之一为 true,都能使用 加载更多 和 显示没有更多数据 功能 -->
|
||||
<attr name="load_more_enable" format="boolean"/>
|
||||
<attr name="show_no_more_enable" format="boolean"/>
|
||||
</declare-styleable>
|
||||
</resources>
|
||||
Reference in New Issue
Block a user