一步一步的来封装自己的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();
}
}