可上拉刷新下拉加载的recyclerView
来源:互联网 发布:手机图文排版软件 编辑:程序博客网 时间:2024/06/05 07:13
效果图
先是adapter:
import android.content.Context;import android.support.v7.widget.GridLayoutManager;import android.support.v7.widget.RecyclerView;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.TextView;import com.example.refreshrecylerview.R;import java.util.ArrayList;import java.util.List;/** * Created by yebin on 2016/12/7. */public class MyAdapeter extends RecyclerView.Adapter<MyAdapeter.MyHolder> { private RecyclerView mRecyclerView; private List<String> data = new ArrayList<>(); private Context mContext; private View VIEW_FOOTER; private View VIEW_HEADER; //Type private int TYPE_NORMAL = 1000; private int TYPE_HEADER = 1001; private int TYPE_FOOTER = 1002; public MyAdapeter(List<String> data,Context mContext){ this.data=data; this.mContext=mContext; } @Override public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) { if(viewType==TYPE_HEADER){ return new MyHolder(VIEW_HEADER); }else if(viewType==TYPE_FOOTER){ return new MyHolder(VIEW_FOOTER); }else { return new MyHolder(LayoutInflater.from(mContext).inflate(R.layout.item_recylerview,parent,false)); } } @Override public void onBindViewHolder(MyHolder holder, int position) { if(!isHeaderView(position)&&!isFooterView(position)){ if(haveHeaderView()){ position--; } TextView textView = (TextView) holder.itemView.findViewById(R.id.item_content); textView.setText(data.get(position)); } } @Override public int getItemCount() { int count=(data==null?0:data.size()); if(haveHeaderView()){ count++; } if(haveFooterView()){ count++; } return count; } @Override public int getItemViewType(int position) { if(isHeaderView(position)){ return TYPE_HEADER; }else if(isFooterView(position)){ return TYPE_FOOTER; }else { return TYPE_NORMAL; } } public void addHeaderView(View headerView){ if (haveHeaderView()) { throw new IllegalStateException("hearview has already exists!"); } else { ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); headerView.setLayoutParams(params); VIEW_HEADER=headerView; ifGridLayoutManager(); notifyItemInserted(0); } } public void addFooterView(View footerView){ if (haveFooterView()) { throw new IllegalStateException("footerView has already exists!"); } else { ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); footerView.setLayoutParams(params); VIEW_FOOTER=footerView; ifGridLayoutManager(); notifyItemInserted(getItemCount()-1); } } private boolean isHeaderView(int position) { return haveHeaderView()&&position==0; } private boolean isFooterView(int position) { return haveFooterView()&&position==getItemCount()-1; } private boolean haveHeaderView() { return VIEW_HEADER!=null; } private boolean haveFooterView() { return VIEW_FOOTER!=null; } public static class MyHolder extends RecyclerView.ViewHolder{ public MyHolder(View view){ super(view); } } @Override public void onAttachedToRecyclerView(RecyclerView recyclerView) { try { if(mRecyclerView==null||mRecyclerView!=recyclerView){ mRecyclerView=recyclerView; } ifGridLayoutManager(); }catch (Exception e){ e.printStackTrace(); } } private void ifGridLayoutManager() { if(mRecyclerView==null){ return; } final RecyclerView.LayoutManager layoutManager = mRecyclerView.getLayoutManager(); if(layoutManager instanceof GridLayoutManager){ GridLayoutManager.SpanSizeLookup originSpanSizeLookup = ((GridLayoutManager) layoutManager).getSpanSizeLookup(); ((GridLayoutManager) layoutManager).setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { return isHeaderView(position)||isFooterView(position)? ((GridLayoutManager) layoutManager).getSpanCount():1; } }); } } public View getHeaderView(){ return VIEW_HEADER; } public View getFooterView(){ return VIEW_FOOTER; }}
然后就是RefreshRecyclerView 这里只写了垂直方向的线性列表 没有考虑网格等其他布局
import android.content.Context;import android.graphics.drawable.AnimationDrawable;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.util.Log;import android.view.MotionEvent;import android.view.View;import android.widget.ImageView;import android.widget.LinearLayout;import android.widget.TextView;import com.example.refreshrecylerview.R;/** * Created by yebin on 2016/12/7. */public class RefreshRecyclerView extends RecyclerView { //就是刷新的头 private LinearLayout headerView; //刷新的头中可以隐藏部分 private View mPullDownHeaderView; //隐藏部分高度 private int headerViewHeight; private ImageView headerViewProgess; private TextView headerViewMessage; private View footerView; private int footerViewHeight; //headerView中的第二布局,用于添加其他头布局 private View secondHeaderView; //监听 private onRefreshListner mOnRefreshListner; private final int PULL_DOWN_REFRESH = 0; // 下拉刷新 private final int RELEASE_REFRESH = 1; // 释放更新 private final int REFRESHING = 2; // 加载中 private int currentState = PULL_DOWN_REFRESH; // 当前状态 private Boolean isLoardingMore=false; private int mRecyclerViewYOnScreen=-1; private int downY = -1; private LinearLayoutManager mLinearLayoutManager; private MyAdapeter mMyAdapeter; public RefreshRecyclerView(Context context){ this(context,null); } public RefreshRecyclerView(Context context, AttributeSet attrs) { super(context, attrs); //默认只能是垂直的。 mLinearLayoutManager = new LinearLayoutManager(context); mLinearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); setLayoutManager(mLinearLayoutManager); } @Override public void setAdapter(Adapter adapter) { super.setAdapter(adapter); if(adapter instanceof MyAdapeter){ mMyAdapeter= ((MyAdapeter) adapter); initHeaderView(mMyAdapeter); initFooterView(mMyAdapeter); } } private void initFooterView(MyAdapeter adapter) { footerView=adapter.getFooterView(); footerView.measure(0,0); footerViewHeight=footerView.getMeasuredHeight(); footerView.setPadding(0,-footerViewHeight,0,0); this.setOnScrollListener(new MyScrollListner()); } private void initHeaderView(MyAdapeter adapter) { headerView= (LinearLayout) adapter.getHeaderView(); if(headerView!=null){ headerViewProgess = (ImageView) headerView.findViewById(R.id.progress_view_loading); headerViewMessage = (TextView) headerView.findViewById(R.id.progress_view_message); mPullDownHeaderView= headerView.findViewById(R.id.ll_pull_down_header_view); mPullDownHeaderView.measure(0,0); headerViewHeight=mPullDownHeaderView.getMeasuredHeight(); mPullDownHeaderView.setPadding(0,-headerViewHeight,0,0); } } public void addSecondHeaderView(View secondHeaderView){ this.secondHeaderView=secondHeaderView; headerView.addView(secondHeaderView); } @Override public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: downY = (int) ev.getY(); break; case MotionEvent.ACTION_MOVE: if (downY == -1) { downY = (int) ev.getY(); } int moveY= (int) ev.getY(); int diffY=moveY-downY; if (currentState == REFRESHING) { break; } if (!isDisplaySecondHeaderView()) { break; } if(diffY>0){ int paddingTop=-headerViewHeight+diffY/3; if(paddingTop>0&¤tState!=RELEASE_REFRESH){ currentState=RELEASE_REFRESH; refreshHeadViewState(); }else if(paddingTop<0&¤tState!=PULL_DOWN_REFRESH){ currentState=PULL_DOWN_REFRESH; refreshHeadViewState(); } mPullDownHeaderView.setPadding(0,paddingTop,0,0); } break; case MotionEvent.ACTION_UP: downY=-1; if(currentState==PULL_DOWN_REFRESH){ mPullDownHeaderView.setPadding(0,-headerViewHeight,0,0); }else if(currentState==RELEASE_REFRESH){ currentState=REFRESHING; refreshHeadViewState(); mPullDownHeaderView.setPadding(0,0,0,0); if(mOnRefreshListner!=null){ mOnRefreshListner.onPullDownRefresh(); } } break; default: break; } return super.onTouchEvent(ev); } public boolean isDisplaySecondHeaderView() { int[] laction=new int[2]; if(mRecyclerViewYOnScreen==-1){ getLocationOnScreen(laction); mRecyclerViewYOnScreen=laction[1]; } secondHeaderView.getLocationOnScreen(laction); int secondHeaderViewYOnScreen = laction[1]; return mRecyclerViewYOnScreen<=secondHeaderViewYOnScreen; } private void refreshHeadViewState(){ switch (currentState){ case PULL_DOWN_REFRESH: stopProgress(); headerViewMessage.setText("下拉刷新"); break; case REFRESHING: startProgress(); headerViewMessage.setText("加载中。。。。"); break; case RELEASE_REFRESH: stopProgress(); headerViewMessage.setText("释放更新"); break; default: break; } } public interface onRefreshListner{ public void onPullDownRefresh(); public void onLoardingMore(); } public void setOnRefreshListner(onRefreshListner listner){ this.mOnRefreshListner=listner; } /** * 获取第一条展示的位置 * * @return */ private int getFirstVisiblePosition() { int position; if (getLayoutManager() instanceof LinearLayoutManager) { position = ((LinearLayoutManager) getLayoutManager()).findFirstVisibleItemPosition(); } else if (getLayoutManager() instanceof GridLayoutManager) { position = ((GridLayoutManager) getLayoutManager()).findFirstVisibleItemPosition(); } else if (getLayoutManager() instanceof StaggeredGridLayoutManager) { StaggeredGridLayoutManager layoutManager = (StaggeredGridLayoutManager) getLayoutManager(); int[] lastPositions = layoutManager.findFirstVisibleItemPositions(new int[layoutManager.getSpanCount()]); position = getMinPositions(lastPositions); } else { position = 0; } return position; } /** * 获取最后一条展示的位置 * * @return */ private int getLastVisiblePosition() { int position; if (getLayoutManager() instanceof LinearLayoutManager) { position = ((LinearLayoutManager) getLayoutManager()).findLastVisibleItemPosition(); } else if (getLayoutManager() instanceof GridLayoutManager) { position = ((GridLayoutManager) getLayoutManager()).findLastVisibleItemPosition(); } else if (getLayoutManager() instanceof StaggeredGridLayoutManager) { StaggeredGridLayoutManager layoutManager = (StaggeredGridLayoutManager) getLayoutManager(); int[] lastPositions = layoutManager.findLastVisibleItemPositions(new int[layoutManager.getSpanCount()]); position = getMaxPosition(lastPositions); } else { position = getLayoutManager().getItemCount() - 1; } return position; } /** * 获得最大的位置 * * @param positions * @return */ private int getMaxPosition(int[] positions) { int size = positions.length; int maxPosition = Integer.MIN_VALUE; for (int i = 0; i < size; i++) { maxPosition = Math.max(maxPosition, positions[i]); } return maxPosition; } /** * 获得当前展示最小的position * * @param positions * @return */ private int getMinPositions(int[] positions) { int size = positions.length; int minPosition = Integer.MAX_VALUE; for (int i = 0; i < size; i++) { minPosition = Math.min(minPosition, positions[i]); } return minPosition; } private void startProgress(){ AnimationDrawable animations = (AnimationDrawable) headerViewProgess.getBackground(); animations.start(); } private void stopProgress(){ AnimationDrawable animations = (AnimationDrawable) headerViewProgess.getBackground(); animations.stop(); } public void onRefreshfinish(boolean isSuccess){ stopProgress(); if(isLoardingMore){ footerView.setPadding(0,-footerViewHeight,0,0); isLoardingMore=false; }else { mPullDownHeaderView.setPadding(0,-headerViewHeight,0,0); currentState=PULL_DOWN_REFRESH; headerViewMessage.setText("下拉刷新"); if(isSuccess){ }else { } } } class MyScrollListner extends OnScrollListener{ @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); if(newState==RecyclerView.SCROLL_STATE_IDLE||newState==RecyclerView.SCROLL_STATE_DRAGGING){ if(getLastVisiblePosition()==mMyAdapeter.getItemCount()-1&&!isLoardingMore){ Log.e("AAAAAA","getLastVisiblePosition="+getLastVisiblePosition()+",getCount="+mMyAdapeter.getItemCount()); isLoardingMore=true; footerView.setPadding(0,0,0,0); if(mOnRefreshListner!=null){ mOnRefreshListner.onLoardingMore(); } } } } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); } }}
布局:
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <com.example.refreshrecylerview.widght.RefreshRecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent"> </com.example.refreshrecylerview.widght.RefreshRecyclerView></RelativeLayout>
还有一个是动画集:
<?xml version="1.0" encoding="utf-8"?> <animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false" > <item android:drawable="@mipmap/loading_refresh1" android:duration="50"></item> <item android:drawable="@mipmap/loading_refresh2" android:duration="50"></item> <item android:drawable="@mipmap/loading_refresh3" android:duration="50"></item> <item android:drawable="@mipmap/loading_refresh4" android:duration="50"></item> <item android:drawable="@mipmap/loading_refresh5" android:duration="50"></item> <item android:drawable="@mipmap/loading_refresh6" android:duration="50"></item> <item android:drawable="@mipmap/loading_refresh7" android:duration="50"></item> <item android:drawable="@mipmap/loading_refresh8" android:duration="50"></item> <item android:drawable="@mipmap/loading_refresh9" android:duration="50"></item> <item android:drawable="@mipmap/loading_refresh10" android:duration="50"></item> <item android:drawable="@mipmap/loading_refresh11" android:duration="50"></item> <item android:drawable="@mipmap/loading_refresh12" android:duration="50"></item> <item android:drawable="@mipmap/loading_refresh13" android:duration="50"></item> <item android:drawable="@mipmap/loading_refresh14" android:duration="50"></item> <item android:drawable="@mipmap/loading_refresh15" android:duration="50"></item> <item android:drawable="@mipmap/loading_refresh16" android:duration="50"></item></animation-list>
最后是使用:
import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.LayoutInflater;import android.view.View;import com.example.refreshrecylerview.decoration.DividerItemDecoration;import com.example.refreshrecylerview.widght.MyAdapeter;import com.example.refreshrecylerview.widght.RefreshRecyclerView;import java.util.ArrayList;public class MainActivity extends AppCompatActivity { private ArrayList<String> datas=new ArrayList<>(); private RefreshRecyclerView recyclerView; private MyAdapeter myAdapeter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); recyclerView = (RefreshRecyclerView) this.findViewById(R.id.recyclerView); //此处添加分割线 recyclerView.addItemDecoration(new DividerItemDecoration(this,DividerItemDecoration.VERTICAL_LIST)); String str=new String(); for (int i = 0; i < 30; i++) { str="我是第 "+i+" 个条目"; datas.add(str); } myAdapeter = new MyAdapeter(datas, this); myAdapeter.addHeaderView(LayoutInflater.from(this).inflate(R.layout.refresh_listview_header,null)); myAdapeter.addFooterView(LayoutInflater.from(this).inflate(R.layout.refresh_listview_footer,null)); recyclerView.setAdapter(myAdapeter); //下面这句代码一点要写,主要是考虑到头布局里可以加入一些其他布局,如ViewPager等 recyclerView.addSecondHeaderView(new View(this)); recyclerView.setOnRefreshListner(new RefreshRecyclerView.onRefreshListner() { @Override public void onPullDownRefresh() { refreshData(); } @Override public void onLoardingMore() { loardingData(); } }); } public void refreshData(){ new Thread(new Runnable() { @Override public void run() { datas.clear(); String str; for (int i = 0; i < 30; i++) { str="我是第 "+i+" 个条目"; datas.add(str); } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } runOnUiThread(new Runnable() { @Override public void run() { recyclerView.onRefreshfinish(true); myAdapeter.notifyDataSetChanged(); } }); } }).start(); } public void loardingData(){ new Thread(new Runnable() { @Override public void run() { int size = datas.size(); String str; for (int i = size; i < size+10; i++) { str="我是第 "+i+" 个条目"; datas.add(str); } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } runOnUiThread(new Runnable() { @Override public void run() { recyclerView.onRefreshfinish(true); myAdapeter.notifyDataSetChanged(); } }); } }).start(); }}
分割线:
public class DividerItemDecoration extends RecyclerView.ItemDecoration { private static final int[] ATTRS = new int[]{ android.R.attr.listDivider }; public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL; public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL; private Drawable mDivider; private int mOrientation; public DividerItemDecoration(Context context, int orientation) { final TypedArray a = context.obtainStyledAttributes(ATTRS); mDivider = a.getDrawable(0); a.recycle(); setOrientation(orientation); } public void setOrientation(int orientation) { if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) { throw new IllegalArgumentException("invalid orientation"); } mOrientation = orientation; } @Override public void onDraw(Canvas c, RecyclerView parent) { if (mOrientation == VERTICAL_LIST) { drawVertical(c, parent); } else { drawHorizontal(c, parent); } } public void drawVertical(Canvas c, RecyclerView parent) { final int left = parent.getPaddingLeft(); final int right = parent.getWidth() - parent.getPaddingRight(); final int childCount = parent.getChildCount(); for (int i = 0; i < childCount; i++) { final View child = parent.getChildAt(i); final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child .getLayoutParams(); final int top = child.getBottom() + params.bottomMargin + Math.round(ViewCompat.getTranslationY(child)); final int bottom = top + mDivider.getIntrinsicHeight(); mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } } public void drawHorizontal(Canvas c, RecyclerView parent) { final int top = parent.getPaddingTop(); final int bottom = parent.getHeight() - parent.getPaddingBottom(); final int childCount = parent.getChildCount(); for (int i = 0; i < childCount; i++) { final View child = parent.getChildAt(i); final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child .getLayoutParams(); final int left = child.getRight() + params.rightMargin + Math.round(ViewCompat.getTranslationX(child)); final int right = left + mDivider.getIntrinsicHeight(); mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } } @Override public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) { if (mOrientation == VERTICAL_LIST) { outRect.set(0, 0, 0, mDivider.getIntrinsicHeight()); } else { outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0); } }}
1 0
- 可上拉刷新下拉加载的recyclerView
- RecyclerView的上拉加载,下拉刷新
- 支持下拉加载刷新的RecyclerView
- 自定义的RecyclerView, 下拉刷新,加载更多.
- RecyclerView的下拉刷新
- android 打造真正的下拉刷新上拉加载recyclerview(三):下拉刷新上拉加载
- android 打造真正的下拉刷新上拉加载recyclerview(三):下拉刷新上拉加载
- 揭露RecyclerView的下拉刷新上拉加载的原理
- 支持下拉刷新、上拉加载的RecyclerView,基于PullToRefresh
- 上拉加载下拉刷新的RecyclerView可添加headerView
- RecyclerView之下拉刷新、下拉加载的实现
- RecyclerView的简单使用,实现下拉刷新、上拉加载
- 可以下拉刷新,上拉加载更多的RecyclerView
- recyclerView的下拉刷新和上拉加载
- RecyclerView的上拉刷新与下拉加载
- YRecyclerView自定义下拉刷新上拉加载更多的RecyclerView
- RecyclerView的下拉刷新数据 与上拉加载更多
- RecyclerView 最简单的 下拉刷新 上拉加载
- Android下自定义的jar库文件编译和调用
- 【分享集成】如何使用友盟分享面板进行自定义
- react+webpack+webstorm开发环境搭建
- Matlab rms与std的区别
- c语言函数与指针
- 可上拉刷新下拉加载的recyclerView
- MySQL函数
- 2.2 深度学习环境配置分部详解
- argc 和 argv 详解与经典实例
- CodeForces 739C Alyona and towers
- 列表分页(PHP)
- [做题笔记] 2016/12/1
- 蓝桥杯: Cowboys
- 将一个数插入到有序的数列中,插入后的数列仍然有序