依靠SwipeRefreshLayout實現android
1.在xml文件中,使用SwipeRefreshLayout佈局包裹bash
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/srl_base"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical">
<android.support.v7.widget.RecyclerView
android:id="@+id/rv_base"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
</android.support.v4.widget.SwipeRefreshLayout>
複製代碼
2.設置刷新的回調ide
mSwpBase.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
//具體的刷新邏輯
onFresh();
}
});
複製代碼
3.刷新結束後,將刷新狀態置爲false佈局
mSwpBase.setRefreshing(false);
複製代碼
4.其餘動畫
//設置進度圈的背景色。
setProgressBackgroundColor(int colorRes);ui
//設置進度動畫的顏色。
setColorSchemeResources(int… colorResIds);spa
//設置進度圈的大小,只有兩個值:DEFAULT、LARGE)
setSize(int size);code
1.使用自帶的addOnScrollListener監聽 添加:cdn
rcBase.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
//滑動狀態改變調用
onAdd(recyclerView, newState);
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
}
});
複製代碼
2.在onAdd方法中判斷是否加載到最後一個xml
public void onAdd(RecyclerView recyclerView, int newState){
if (newState == RecyclerView.SCROLL_STATE_IDLE && mManager.findLastVisibleItemPosition() == mAdapter.getItemCount()) {
new Thread(new Runnable() {
@Override
public void run() {
SystemClock.sleep(2000);
list.addAll(list);
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
mAdapter.notifyDataSetChanged();
Toast.makeText(getActivity(), "加載完成", Toast.LENGTH_SHORT).show();
}
});
}
}).start();
}
}
複製代碼
其中:
RecyclerView.SCROLL_STATE_IDLE :判斷手指是否離開屏幕
mManager.findLastVisibleItemPosition() :是不是最後一個(爲LinearLayoutManager中方法,GridLayoutManager 繼承 LinearLayoutManager)
與不含footiew上拉加載相似,但多了footview,在處理時要加些判斷。
RecyclerView沒有相似listview的addfootview的方法,可是在adapter中有getItemViewType方法,那麼咱們就能夠根據position的不一樣,讓holder在建立的時候建立不一樣的holder
1.在adapter中重寫getItemViewType方法:
@Override
public int getItemViewType(int position) {
if (position + 1 == getItemCount()) {
return TYPE_FOOTER;
} else {
return TYPE_ITEM;
}
}
複製代碼
其中:
position+1:添加了footview數量加1
一樣的在getItemCount中return的list.size()+1
//普通Item View
private static final int TYPE_ITEM = 0;
//底部FootView
private static final int TYPE_FOOTER = 1;
2.在ViewHolder的基礎上,在new一個FootHolder
class FootHolder extends RecyclerView.ViewHolder {
private final TextView tvFt;
public FootHolder(View itemView) {
super(itemView);
tvFt = (TextView) itemView.findViewById(R.id.tv_ft);
}
}
複製代碼
注:因爲有兩個ViewHolder在繼承的RecyclerView.Adapter的泛型裏面須要改爲公共父類RecyclerView.ViewHolder
3.在onCreateViewHolder中根據viewType建立不一樣的view,並返回不一樣的holder
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view;
if (viewType == TYPE_ITEM) {
view = getActivity().getLayoutInflater().inflate(R.layout.fragment_video, parent, false);
return new VideoHolder(view);
} else if (viewType == TYPE_FOOTER) {
view = getActivity().getLayoutInflater().inflate(R.layout.foot_view, parent, false);
return new FootHolder(view);
}
return null;
}
複製代碼
4.在onBindViewHoder中根據holder的類型加載不用的邏輯
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder instanceof VideoHolder) {
VideoBean videoBean = list.get(position);
VideoHolder videoHolder = (VideoHolder) holder;
videoHolder.fbVideo.setImageURI(videoBean.getImg());
videoHolder.tvTitle.setText(videoBean.getTitle());
//把數據當tag傳到view中,寫一個listener就能夠了
videoHolder.llVideo.setTag(videoBean);
videoHolder.llVideo.setOnClickListener(mListerner);
} else if (holder instanceof FootHolder) {
FootHolder footHolder = (FootHolder) holder;
switch (load_more_status) {
case PULLUP_LOAD_MORE:
footHolder.tvFt.setText("上拉加載更多");
break;
case LOADING_MORE:
footHolder.tvFt.setText("正在加載更多");
break;
}
}
}
複製代碼
使用instance判斷,而後強轉holder類
//上拉加載更多
public static final int PULLUP_LOAD_MORE = 0;
//正在加載中
public static final int LOADING_MORE = 1;
//上拉加載更多狀態-默認爲0
private int load_more_status = 0;
5.onScrollStateChanged修改
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
load_more_status = LOADING_MORE;
if (newState == RecyclerView.SCROLL_STATE_IDLE && getCount() + 1 == mAdapter.getItemCount()) {
new Thread(new Runnable() {
@Override
public void run() {
load_more_status = PULLUP_LOAD_MORE;
SystemClock.sleep(2000);
list.addAll(list);
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
mAdapter.notifyDataSetChanged();
Toast.makeText(getActivity(), "加載完成", Toast.LENGTH_SHORT).show();
}
});
}
}).start();
}
}
複製代碼
1.當GridLayoutManager添加footview時會形成佈局錯亂:
緣由:
GridLayoutManager manager = new GridLayoutManager(getActivity(), 3);
在咱們new GridLayoutManager的時候,傳進去的3
至關於把一行分紅了3份,一個items默認佔1份,也就是一行3個,你的footview也佔1份,因此不會居中。
知道了緣由,改也就好改了
介紹咱們關鍵的類:public static abstract class SpanSizeLookup (GridLayoutManager包下)
繼承後會重寫 getSpanSize方法 默認返回1,也就是一個佈局佔1份
class GridSpanSizeLookop extends GridLayoutManager.SpanSizeLookup {
@Override
public int getSpanSize(int position) {
return 1;
}
}
複製代碼
那麼,在這個方法裏面咱們就能夠判斷,當是footview的時候,返回一行就能夠解決問題了。
修改getSpanSize方法的返回值
class GridSpanSizeLookop extends GridLayoutManager.SpanSizeLookup {
@Override
public int getSpanSize(int position) {
// Log.d(TAG, position + "xx" + list.size() + 1);
if (position == list.size()) {
return mManager.getSpanCount();
}
return 1;
}
}
複製代碼
最後在adapter中重寫onAttachedToRecyclerView方法:
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
if (mGridSpanSizeLookup == null) {
mGridSpanSizeLookup = new GridSpanSizeLookop();
}
mManager.setSpanSizeLookup(mGridSpanSizeLookup);
}
複製代碼
另外,也能夠在new GridLayoutManager之後這麼寫:
mManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
return position == list.size() ? mManager.getSpanCount() : 1;
}
});
複製代碼
2.getSpanSize方法的其餘用法:
經過更改返回值實現下面的佈局
代碼:
mManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
return position == list.size() ? mManager.getSpanCount() : 3 - position % 3;
}
});
複製代碼
3.流式佈局處理 因爲StaggeredGridLayoutManager中沒有setSpanSizeLookup方法,沒法經過上述辦法實現上拉加載,可是StaggeredGridLayoutManager.LayoutParams中有setFullSpan方法能夠達到一樣的效果。
這時候重寫的再也不是onAttachedToRecyclerView方法而是onViewAttachedToWindow方法
//將上拉加載的佈局添加到正中間
@Override
public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) {
super.onViewAttachedToWindow(holder);
ViewGroup.LayoutParams layoutParams = holder.itemView.getLayoutParams();
if (layoutParams != null && layoutParams instanceof StaggeredGridLayoutManager.LayoutParams) {
//是不是最後一個
if (holder.getLayoutPosition() == list.size()) {
StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) holder.itemView.getLayoutParams();
p.setFullSpan(true);
//能夠上拉加載
mIsFresh = true;
}
}
}
複製代碼