之前因為需求上啦加載要配合swip下拉刷新瞬测,結果網(wǎng)上找了幾個框架都不能滿足我的需求,最后終于找到個吧但是屏蔽了他的下拉事件也導致了不能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="-- 網(wǎng)絡異常,請刷新重試 --"
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<>(); //數(shù)據(jù)源
private boolean isShowFooter = false; //是否顯示腳布局的標記
public RecLoadMoreAdapter() {
}
/**
* 添加數(shù)據(jù)
* @param
*/
public void add(List<T> data){
mModule.addAll(data);
this.notifyDataSetChanged();
}
/**
* 清除數(shù)據(jù)源
*/
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);
}
//此處子類必須實現(xiàn)子 返回自身的holder
return superSelfViewHolder(parent,viewType);
}
/**
* 子類必須實現(xiàn)自身的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);
}
}
/**
* 子類選擇性實現(xiàn) 為自身控件賦值
* @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);
}
滾動監(jiān)聽
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; //上一次的加載數(shù)量
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();//第一次請求數(shù)據(jù)或是下拉刷新的時候
}
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);
}
/**
* 從服務器獲取數(shù)據(jù)
* @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>