一步一步的来封装自己的RecycleView
来源:互联网 发布:python中split函数 编辑:程序博客网 时间:2024/05/18 03:32
一步一步的来封装自己的RecycleView
项目中使用他人开源的RecycleView始终感觉不是很灵活,所以,自己动手,丰衣足食喽
还是菜鸟,所以,参考了好几个大牛的博客,摸索的一点一点的做,也希望有所提高。先是下拉刷新,主要想让刷新的view独立出来,并且可以自定义。看代码,看注释。
使用SRecycleView:
//定义一个自己要使用的adapterDataAdapter dataAdapter = new DataAdapter(this);dataAdapter.setData(list);sRecycleView.setLayoutManager(new LinearLayoutManager(this));//使用封装好的adapter包裹一下要使用的adapterSRecycleViewAdapter adapter = new SRecycleViewAdapter(this,dataAdapter);//自定义刷新ViewRefreshView refreshView = new RefreshView(this);adapter.setHeaderView(refreshView);sRecycleView.setAdapter(adapter);
自定义刷新view 只需要继承上类封装好的RefreshViewAbs,根据方法就可以动态实现view的效果 :
/** * Created by shen on 2016/8/19. */public class RefreshView extends RefreshViewAbs { private TextView tv; private View view; public RefreshView(Context context) { super(context); init(); } public void init(){ tv = (TextView) refreshView.findViewById(R.id.tv); } @Override protected int getEmptyHeight() { return ((int) (DensityUtils.dp2px(context,50))); } //自定义刷新使用的布局 @Override protected int getLayoutView() { return R.layout.refresh_view; } @Override public void refresh() { tv.setText("正在刷新...."); } @Override public void refreshComplete() { tv.setText("刷新完成!"); } @Override public void releaseToRefresh() { tv.setText("松开刷新"); } @Override public void noState() { tv.setText("下拉刷新"); }}
封装好的刷新view的抽象类:
/** * Created by shen on 2016/8/19. */public abstract class RefreshViewAbs extends LinearLayout { private int EMPTY_HEIGHT = 0;//刷新顶部空白高度 protected LinearLayout refreshView; protected Context context; private int measureHeight; private RefreshViewState currentState = RefreshViewState.NO_STATE; public abstract void refresh(); public abstract void refreshComplete(); public abstract void releaseToRefresh(); public abstract void noState(); private OnRefreshViewPullDownListening onRefreshViewPullDownListening; public interface OnRefreshViewPullDownListening{ void scrolled(float dy); } public void setOnRefreshViewPullDownListening( OnRefreshViewPullDownListening onRefreshViewPullDownListening){ this.onRefreshViewPullDownListening = onRefreshViewPullDownListening; } public void mationActionUp(float rawY) { if (getCurrentState() == RefreshViewAbs.RefreshViewState.RELEASE_TO_REFRESH) { setState(RefreshViewAbs.RefreshViewState.IS_REFRESHING); smoothScrollTo(getMeasureHeight()); refresh(); } if (getCurrentState() == RefreshViewAbs.RefreshViewState.NO_STATE) { smoothScrollTo(0); } if (getCurrentState() == RefreshViewAbs.RefreshViewState.IS_REFRESHING && getVisibleHeight() >= measureHeight) { smoothScrollTo(getMeasureHeight()); } } public void setRefreshComplete() { setState(RefreshViewAbs.RefreshViewState.NO_STATE); refreshComplete(); new Handler().postDelayed(new Runnable() { @Override public void run() { smoothScrollTo(0); } },300); } public enum RefreshViewState{ RELEASE_TO_REFRESH,NO_STATE,IS_REFRESHING } public RefreshViewState getCurrentState(){ return currentState; } public void setState(RefreshViewState state) { this.currentState = state; } public RefreshViewAbs(Context context) { super(context); this.context = context; init(); } private void init() { refreshView = (LinearLayout) LayoutInflater.from(context).inflate(getLayoutView(), null); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); params.setMargins(0,0,0,0); this.setLayoutParams(params); this.setPadding(0,0,0,0); //初始化设置高度为零 this.addView(refreshView,new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,0)); measure(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT); measureHeight = getMeasuredHeight(); EMPTY_HEIGHT = getEmptyHeight(); } protected abstract int getEmptyHeight(); //刷新view 的实际高度 public int getMeasureHeight(){ return measureHeight; } protected abstract int getLayoutView(); /** * 当手指下滑时被调用 * */ public void putDown(float dy){ float countPullDown = getVisibleHeight() + dy/2; L.d("refresh_view","countPullDown:"+countPullDown+"dy:"+dy+"measureHeight:"+measureHeight+"EMPTY_HEIGHT:"+EMPTY_HEIGHT); if(countPullDown <0){ setRefreshViewHeight(0); return; } if(countPullDown > measureHeight + EMPTY_HEIGHT){ countPullDown = measureHeight + EMPTY_HEIGHT; return; } setRefreshViewHeight((int) (countPullDown)); if(onRefreshViewPullDownListening != null){ onRefreshViewPullDownListening.scrolled(dy); } if(currentState == RefreshViewState.IS_REFRESHING){ return; } if(countPullDown >= measureHeight){ setState(RefreshViewState.RELEASE_TO_REFRESH); releaseToRefresh(); } else if(countPullDown >=0){ setState(RefreshViewState.NO_STATE); noState(); } } /** * 设置Refreshview 的可见高度 * */ private void setRefreshViewHeight(int dy) { ViewGroup.LayoutParams layoutParams = refreshView.getLayoutParams(); layoutParams.height = dy; refreshView.setLayoutParams(layoutParams); } //移动 public void smoothScrollTo(int destHeight) { if(destHeight < 0){ return; } ValueAnimator animator = ValueAnimator.ofInt(getVisibleHeight(), destHeight); animator.setDuration(200).start(); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { setRefreshViewHeight((int) animation.getAnimatedValue()); } }); animator.start(); } public int getVisibleHeight() { return refreshView.getLayoutParams().height; } public int getTotalHeight(){ return measureHeight + EMPTY_HEIGHT; }}
然后是封装过的Adapter,主要是利用type值的不同使position=0时是刷新的view:
/** * Created by shen on 2016/8/16. */public class SRecycleViewAdapter extends RecyclerView.Adapter { private static final int TYPE_HEADER = 1; private static final int TYPE_NORMAL = 2; private Context context; private RefreshViewAbs refreshView; private RecyclerView.Adapter innerAdapter; public SRecycleViewAdapter(Context context, RecyclerView.Adapter innerAdapter) { this.context = context; setAdapter(innerAdapter); } public void setHeaderView(RefreshViewAbs refreshView) { this.refreshView = refreshView; } public RefreshViewAbs getRefreshView(){ return refreshView; } @Override public int getItemViewType(int position) { if(position == 0){ return TYPE_HEADER; } else{ return TYPE_NORMAL; } } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if(viewType == TYPE_HEADER && refreshView != null){ return new HeaderHolder(refreshView); } return innerAdapter.onCreateViewHolder(parent,viewType); } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if(position == 0){ return; } int newPosition = holder.getLayoutPosition() -1; innerAdapter.onBindViewHolder(holder,newPosition); } @Override public int getItemCount() { Log.d("recycleview","count:"+innerAdapter.getItemCount()+1); return innerAdapter.getItemCount()+1; } public void setAdapter(RecyclerView.Adapter adapter) { if (adapter != null) { if (!(adapter instanceof RecyclerView.Adapter)) throw new RuntimeException("your adapter must be a RecyclerView.Adapter"); } if (innerAdapter != null) { notifyItemRangeRemoved(1, innerAdapter.getItemCount()); innerAdapter.unregisterAdapterDataObserver(mDataObserver); } this.innerAdapter = adapter; innerAdapter.registerAdapterDataObserver(mDataObserver); notifyItemRangeInserted(1, innerAdapter.getItemCount()); } class HeaderHolder extends RecyclerView.ViewHolder { public HeaderHolder(View itemView) { super(itemView); } } /** * 监听传经来的adapter的变化,通知自己随之变化 * */ public RecyclerView.AdapterDataObserver mDataObserver = new RecyclerView.AdapterDataObserver() { @Override public void onChanged() { super.onChanged(); notifyDataSetChanged(); } @Override public void onItemRangeChanged(int positionStart, int itemCount) { notifyItemRangeChanged(positionStart + 1, itemCount); } @Override public void onItemRangeInserted(int positionStart, int itemCount) { notifyItemRangeInserted(positionStart +1, itemCount); } @Override public void onItemRangeRemoved(int positionStart, int itemCount) { notifyItemRangeRemoved(positionStart + 1, itemCount); } @Override public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) { notifyItemRangeChanged(fromPosition + 1, toPosition + 1+ itemCount); } };}
SRecycleView,重点处理ontouch方法:
/** * Created by shen on 2016/8/19. */public class SRecycleView extends RecyclerView { private static final int IS_REFRESHING = 1000; private static final int NORMAL = 1001; private int currentRecycleViewState = NORMAL; private RefreshViewAbs refreshView; private SRecycleViewAdapter sRecycleViewAdapter; private ISRecycleView.OnSRecycleViewListener onSRecycleViewListener; private ISRecycleView.OnSRecycleViewScrollListening onSRecycleViewScrollListening; public void setOnSRecycleViewListener(ISRecycleView.OnSRecycleViewListener onSRecycleViewListener) { this.onSRecycleViewListener = onSRecycleViewListener; } public void setOnSRecycleViewScrollListening(ISRecycleView.OnSRecycleViewScrollListening onSRecycleViewScrollListening) { this.onSRecycleViewScrollListening = onSRecycleViewScrollListening; } public SRecycleView(Context context) { this(context, null); } public SRecycleView(Context context, @Nullable AttributeSet attrs) { this(context, attrs, -1); } public SRecycleView(Context context, @Nullable AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } private void init() { } @Override public void setAdapter(Adapter adapter) { super.setAdapter(adapter); sRecycleViewAdapter = (SRecycleViewAdapter) getAdapter(); refreshView = sRecycleViewAdapter.getRefreshView(); } float lastY = -1; float lastX = -1; @Override public boolean onTouchEvent(MotionEvent e) { switch (e.getAction()) { case MotionEvent.ACTION_DOWN: lastY = e.getRawY(); lastX = e.getRawX(); break; case MotionEvent.ACTION_MOVE: final float intervalY = e.getRawY() - lastY; final float intervalX = e.getRawX() - lastX; lastY = e.getRawY(); lastX = e.getRawX(); if (isOnTop()) { if (refreshView.getCurrentState() == RefreshViewAbs.RefreshViewState.IS_REFRESHING) { if(intervalY > 0){ refreshView.putDown(intervalY); } } else { refreshView.putDown(intervalY); if (refreshView.getVisibleHeight() > 0) {//当refreshview出现时,静止recycleview本身的滑动,只是改变refreshview高度 return false; } } } break; case MotionEvent.ACTION_UP: L.d("state", "state:" + refreshView.getCurrentState()); refreshView.mationActionUp(e.getRawY()); if (refreshView.getCurrentState() == RefreshViewAbs.RefreshViewState.IS_REFRESHING) { if (onSRecycleViewListener != null && SRecycleView.this.getRecycleViewState() != IS_REFRESHING) { setRecycleViewState(IS_REFRESHING); onSRecycleViewListener.refresh(); } } break; } return super.onTouchEvent(e); } private void setRecycleViewState(int state) { this.currentRecycleViewState = state; } public int getRecycleViewState() { return currentRecycleViewState; } private boolean isOnTop() { if (refreshView.getParent() != null) { return true; } else { return false; } } @Override public void onScrolled(int dx, int dy) { if(onSRecycleViewScrollListening != null){ onSRecycleViewScrollListening.onScrolled(dx,dy); } } public void refreshComplete() { setRecycleViewState(NORMAL); refreshView.setRefreshComplete(); }}
0 0
- 一步一步的来封装自己的RecycleView
- 一步一步封装自己的Recycleview,上拉加载
- 一步一步封装自己的HtmlHelper组件:BootstrapHelper
- RecycleView Adapter的封装
- RecycleView适配器的封装
- Recycleview的adapter封装
- ReCycleView的 Adapter的封装
- android recycleView的进一步封装
- RecycleView.Adapt的简单封装
- 自己封装的工具类,使用原生SwipeRefreshLayout+RecycleView实现下拉刷新和加载更多
- android:RecycleView的简单封装使用
- 比较好用的RecycleView封装
- 自己写的一个recycleview下拉加载
- 一步一步完成自己的梦想
- 一步一步写自己的相册
- 一步一步打造自己的GestureImageView
- 一步一步打造自己的VIM
- 一步一步实现自己的GAN
- JVM内幕:Java虚拟机详解
- 转 python中包含UTF-8编码中文的列表或字典的输出
- 46.使用Jsoup解析html获取数据
- mini2451上madplayer的移植
- Spark 大数据中文分词统计(三) Scala语言实现分词统计
- 一步一步的来封装自己的RecycleView
- Oracle 数据库中的索引
- 【Leetcode】110. Balanced Binary Tree 【DFS】
- Codeforces Round #368 (Div. 2) C
- B树、B-树、B+树、B*树
- android:ellipsize的使用
- jsp与servlet
- Struts2框架9.拦截器配置
- iOS swift-UIView随键盘弹出/隐藏而改变位置