之前因为需求上啦加载要配合swip下拉刷新,结果网上找了几个框架都不能满足我的需求,最后终于找到个吧但是屏蔽了他的下拉事件也导致了不能swip下拉刷新,所以就下决心自己写了一个上拉加载!
直接上代码有需要的可以直接撸走!改下名字就可以直接使用了! 具体流程大家运行起了自己看看代码就行了挺简单的!
先上脚布局视图
public class LoadingFooter extends RelativeLayout{
protected State mState = State.Normal;
private View mLoadingView;
private View mNetworkErrorView;
private View mTheEndView;
private ProgressBar mLoadingProgress;
private TextView mLoadingText;
public LoadingFooter(Context context) {
this(context, null);
}
public LoadingFooter(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public LoadingFooter(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
public void init(Context context) {
inflate(context, R.layout.view_recycler_footer, this);
setOnClickListener(null);
setState(State.Normal, true);
}
public State getState() {
return mState;
}
public void setState(State status) {
setState(status, true);
}
public void setState(State status, boolean showView) {
if (mState == status) {
return;
}
mState = status;
switch (status) {
case Normal:
setOnClickListener(null);
if (mLoadingView != null) {
mLoadingView.setVisibility(GONE);
}
if (mTheEndView != null) {
mTheEndView.setVisibility(GONE);
}
if (mNetworkErrorView != null) {
mNetworkErrorView.setVisibility(GONE);
}
break;
case Loading:
setOnClickListener(null);
if (mTheEndView != null) {
mTheEndView.setVisibility(GONE);
}
if (mNetworkErrorView != null) {
mNetworkErrorView.setVisibility(GONE);
}
if (mLoadingView == null) {
ViewStub viewStub = (ViewStub) findViewById(R.id.loading_viewstub);
mLoadingView = viewStub.inflate();
mLoadingProgress = (ProgressBar) mLoadingView.findViewById(R.id.pg_loading);
mLoadingText = (TextView) mLoadingView.findViewById(R.id.tv_loaddata);
} else {
mLoadingView.setVisibility(VISIBLE);
}
mLoadingView.setVisibility(showView ? VISIBLE : GONE);
mLoadingProgress.setVisibility(View.VISIBLE);
break;
case TheEnd:
setOnClickListener(null);
if (mLoadingView != null) {
mLoadingView.setVisibility(GONE);
}
if (mNetworkErrorView != null) {
mNetworkErrorView.setVisibility(GONE);
}
if (mTheEndView == null) {
ViewStub viewStub = (ViewStub) findViewById(R.id.end_viewstub);
mTheEndView = viewStub.inflate();
} else {
mTheEndView.setVisibility(VISIBLE);
}
mTheEndView.setVisibility(showView ? VISIBLE : GONE);
break;
case NetWorkError:
if (mLoadingView != null) {
mLoadingView.setVisibility(GONE);
}
if (mTheEndView != null) {
mTheEndView.setVisibility(GONE);
}
if (mNetworkErrorView == null) {
ViewStub viewStub = (ViewStub) findViewById(R.id.network_error_viewstub);
mNetworkErrorView = viewStub.inflate();
} else {
mNetworkErrorView.setVisibility(VISIBLE);
}
mNetworkErrorView.setVisibility(showView ? VISIBLE : GONE);
break;
default:
break;
}
}
public enum State {
Normal, TheEnd, Loading, NetWorkError
}
}
脚视图布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/loading_view"
android:layout_width="match_parent"
android:layout_height="60dp"
android:gravity="center"
android:orientation="vertical">
<ViewStub
android:id="@+id/loading_viewstub"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout="@layout/item_recycler_footer_loading" />
<ViewStub
android:id="@+id/end_viewstub"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout="@layout/item_recycler_footer_end" />
<ViewStub
android:id="@+id/network_error_viewstub"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout="@layout/item_recycler_footer_network_error" />
</LinearLayout>
item_recycler_footer_loading
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/loading_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:layout_gravity="center"
android:orientation="horizontal">
<ProgressBar
android:id="@+id/pg_loading"
android:layout_width="30dp"
android:layout_height="30dp" />
<TextView
android:textColor="#FF159121"
android:textSize="18sp"
android:layout_marginLeft="20dp"
android:id="@+id/tv_loaddata"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="loading..."
android:visibility="visible" />
</LinearLayout>
item_recycler_footer_end
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="horizontal">
<TextView
android:textColor="#FF159121"
android:id="@+id/loading_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="-- end --"
android:textSize="14sp" />
</LinearLayout>
item_recycler_footer_network_error
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="horizontal">
<TextView
android:id="@+id/loading_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FF159121"
android:text="-- 网络异常,请刷新重试 --"
android:textSize="14sp" />
</LinearLayout>
加载更多需要的adapter
public abstract class RecLoadMoreAdapter<T> extends RecyclerView.Adapter {
private static final int TYPE_LOAD_MORE = Integer.MIN_VALUE + 1; //脚布局类型标记
private FrameLayout mFooterParentView; //脚布局容器
private View mFooterView; //脚布局
protected List<T> mModule = new ArrayList<>(); //数据源
private boolean isShowFooter = false; //是否显示脚布局的标记
public RecLoadMoreAdapter() {
}
/**
* 添加数据
* @param
*/
public void add(List<T> data){
mModule.addAll(data);
this.notifyDataSetChanged();
}
/**
* 清除数据源
*/
public void clear(){mModule.clear();}
@Override
public int getItemViewType(int position) {
if (isShowFooter && position == getItemCount() - getFooterCount()){
return TYPE_LOAD_MORE;
}
return superItemViewType(position);
}
/**
* 返回正常类型的布局标记
* @param position
* @return
*/
private int superItemViewType(int position) {
return super.getItemViewType(position); //父类默认返回的就是0
}
private int getFooterCount() {
if (isShowFooter){
return 1;
}
return 0;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if(viewType == TYPE_LOAD_MORE){
if(mFooterParentView == null){
mFooterParentView = new FrameLayout(parent.getContext());
parent.addView(mFooterParentView);
if(mFooterView != null){
mFooterParentView.addView(mFooterView);
}
}
return new ViewHolderLoadMore(mFooterParentView);
}
//此处子类必须实现子 返回自身的holder
return superSelfViewHolder(parent,viewType);
}
/**
* 子类必须实现自身的viewholder
*
* @param parent
* @param viewType
* @return
*/
protected abstract RecyclerView.ViewHolder superSelfViewHolder(ViewGroup parent, int viewType);
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if(position != getItemCount() - getFooterCount()){
superOnBindViewholder(holder,position);
}
}
/**
* 子类选择性实现 为自身控件赋值
* @param holder
* @param position
*/
protected void superOnBindViewholder(RecyclerView.ViewHolder holder, int position) {
}
@Override
public int getItemCount() {
int count = mModule == null ? 0 : this.mModule.size();
return getFooterCount() + count;
}
static class ViewHolderLoadMore extends RecyclerView.ViewHolder{
ViewHolderLoadMore(View itemView) {
super(itemView);
}
}
/**
* 设置脚布局
* @param view
*/
public void setFooterView(View view){
mFooterView = view;
isShowFooter = true;
if(mFooterParentView != null && mFooterParentView.getChildCount() ==0){
mFooterParentView.addView(mFooterView);
}
}
/**
* 去除脚布局
*/
public void removeFooterView(){
isShowFooter = false;
notifyDataSetChanged();
}
}
加载更多时需要使用的接口
public interface OnLoadMore {
void onLoadMore(View view);
}
滚动监听
public class LoadMoreScrollLisenter extends RecyclerView.OnScrollListener implements OnLoadMore {
protected LayoutManagerType layoutManagerType;
private int[] lastPositions;
private int lastVisibleItemPosition;
private int currentScrollState = 0;
private int minPositionToEndless = 1;
public LoadMoreScrollLisenter(){ }
public LoadMoreScrollLisenter(int minPositionToEndless){
this.minPositionToEndless = minPositionToEndless;
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
if (layoutManagerType == null) {
if (layoutManager instanceof LinearLayoutManager) {
layoutManagerType = LayoutManagerType.LinearLayout;
} else if (layoutManager instanceof GridLayoutManager) {
layoutManagerType = LayoutManagerType.GridLayout;
} else if (layoutManager instanceof StaggeredGridLayoutManager) {
layoutManagerType = LayoutManagerType.StaggeredGridLayout;
} else {
throw new RuntimeException("Unsupported LayoutManager used. Valid ones are LinearLayoutManager, GridLayoutManager and StaggeredGridLayoutManager");
}
}
switch (layoutManagerType) {
case LinearLayout:
lastVisibleItemPosition = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
break;
case GridLayout:
lastVisibleItemPosition = ((GridLayoutManager) layoutManager).findLastVisibleItemPosition();
break;
case StaggeredGridLayout:
StaggeredGridLayoutManager staggeredGridLayoutManager = (StaggeredGridLayoutManager) layoutManager;
if (lastPositions == null) {
lastPositions = new int[staggeredGridLayoutManager.getSpanCount()];
}
staggeredGridLayoutManager.findLastVisibleItemPositions(lastPositions);
lastVisibleItemPosition = findMax(lastPositions);
break;
}
}
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
currentScrollState = newState;
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
int visibleItemCount = layoutManager.getChildCount();
int totalItemCount = layoutManager.getItemCount();
if ((visibleItemCount > 0 && currentScrollState == RecyclerView.SCROLL_STATE_IDLE && (lastVisibleItemPosition) >= totalItemCount - minPositionToEndless)) {
onLoadMore(recyclerView);
}
}
private int findMax(int[] lastPositions) {
int max = lastPositions[0];
for (int value : lastPositions) {
if (value > max) {
max = value;
}
}
return max;
}
@Override
public void onLoadMore(final View view) { }
public enum LayoutManagerType {
LinearLayout,
StaggeredGridLayout,
GridLayout
}
}
在Activity或者其他里面的正式使用
public class text extends Activity {
private RecyclerView mRc;
private List<String> mModule;
private LoadingFooter mFooter;
private AlreadyAdapter mAdapter;
private int lastPosition = 0; //上一次的加载数量
private int size = 10; //每次默认加载10个
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.text);
initData();
initUI();
}
private void initData() {
mModule = new ArrayList<>();
for(int x = 0 ; x < 50;x++){
mModule.add("订单~~~~~~~"+x);
}
}
private void initUI() {
mRc = (RecyclerView) findViewById(R.id.rc);
mRc.setOverScrollMode(View.OVER_SCROLL_NEVER);//去除阴影
mAdapter = new AlreadyAdapter();
LinearLayoutManager lineManger = new LinearLayoutManager(this);
lineManger.setOrientation(LinearLayoutManager.VERTICAL);
mRc.setLayoutManager(lineManger);
mRc.addOnScrollListener(mOnScrollListener);
mRc.setAdapter(mAdapter);
/**
* 添加脚布局
*/
if(mFooter == null && mModule.size() > 0){
mFooter = new LoadingFooter(UiUtils.getContext());
mAdapter.setFooterView(mFooter);
}
getFirstData();//第一次请求数据或是下拉刷新的时候
}
private void getFirstData() {
getData(true);
}
private void getData(final boolean isClear) {
if(mModule.size() == 0 ){
return;
}
if(mFooter.getState() == LoadingFooter.State.Loading || (!isClear && mFooter.getState()
== LoadingFooter.State.TheEnd)){
return;
}
if(!isClear){ //只有不是下拉刷新或者第一次进入的时候才显示脚布局 也可以讲判断条件去掉 那样一进入界面就会显示loading....中
mFooter.setState(LoadingFooter.State.Loading);
}
UiUtils.getHandler().postDelayed(new Runnable() {
@Override
public void run() {
if(isClear){
mAdapter.clear();
}
List<String> mData = getDataFromServer();
if(mData == null || mData.size() < size){
mFooter.setState(LoadingFooter.State.TheEnd,true);
}else{
mFooter.setState(LoadingFooter.State.Normal);
}
if(mData != null && mData.size() > 0){
mAdapter.add(mData);
lastPosition = lastPosition + mData.size() ;
}
}
},1000);
}
/**
* 从服务器获取数据
* @return
*/
protected List<String> getDataFromServer() {
try {
int end = lastPosition + size > mModule.size()? mModule.size() : lastPosition + size;
return mModule.subList(lastPosition,end);
}catch (Exception e){
Log.d("tag",e.toString());
}
return null;
}
private LoadMoreScrollLisenter mOnScrollListener = new LoadMoreScrollLisenter(1) {
@Override
public void onLoadMore(View view) {
super.onLoadMore(view);
getData(false);
}
};
class AlreadyAdapter extends RecLoadMoreAdapter<String> {
@Override
protected RecyclerView.ViewHolder superSelfViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(UiUtils.getContext()).inflate(R.layout.item_already,parent,false);
return new ViewHolders(view);
}
@Override
protected void superOnBindViewholder(RecyclerView.ViewHolder holder, int position) {
ViewHolders holders = (ViewHolders) holder;
holders.tv.setText(mModule.get(position));
}
class ViewHolders extends RecyclerView.ViewHolder{
TextView tv;
ViewHolders(View itemView) {
super(itemView);
tv = (TextView) itemView.findViewById(R.id.tv_already);
}
}
}
}
//布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/rc">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
网友评论