一步一步的来封装自己的RecycleView
2016-08-20 23:05
375 查看
一步一步的来封装自己的RecycleView
项目中使用他人开源的RecycleView始终感觉不是很灵活,所以,自己动手,丰衣足食喽还是菜鸟,所以,参考了好几个大牛的博客,摸索的一点一点的做,也希望有所提高。先是下拉刷新,主要想让刷新的view独立出来,并且可以自定义。看代码,看注释。
使用SRecycleView:
//定义一个自己要使用的adapter DataAdapter dataAdapter = new DataAdapter(this); dataAdapter.setData(list); sRecycleView.setLayoutManager(new LinearLayoutManager(this)); //使用封装好的adapter包裹一下要使用的adapter SRecycleViewAdapter adapter = new SRecycleViewAdapter(this,dataAdapter); //自定义刷新View RefreshView 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(); } }
相关文章推荐
- 一步一步封装自己的HtmlHelper组件BootstrapHelper(二)
- 一步一步封装自己的HtmlHelper组件BootstrapHelper(三)
- 一步一步封装自己的HtmlHelper组件:BootstrapHelper
- C#进阶系列——一步一步封装自己的HtmlHelper组件:BootstrapHelper
- C#进阶系列——一步一步封装自己的HtmlHelper组件:BootstrapHelper(三:附源码)
- 一步一步封装自己的Recycleview,上拉加载
- 自己封装的一个最简单的ajax
- 自己封装的java db可以和spring 进行整合
- MapList 自己封装的
- 关于telnet协议的研究以及用java进行封装实现自己的telnet客户端
- PHP在yii2中封装SuperSlide 幻灯片编写自己的SuperSlideWidget的例子
- JS组件系列——封装自己的JS组件,你也可以
- C#封装自己的函数,并且引用
- 自己封装的轮播图
- 封装自己的控件库:iPhone静态库的应用
- Android 框架修炼-自己封装双缓存管理框架库
- 封装自己的flex工具_双击适应内容宽度的DataGrid
- 自己重新实现QTP封装的一些常用的方法
- Android6.0执行时权限解析,RxPermissions的使用,自己封装一套权限框架
- 用 JavaScript 写 ASP,似乎很爽啊,自己封装了一个 操作数据库 分页 以及 文件操作的函数