您的位置:首页 > 移动开发 > Android开发

一步一步的来封装自己的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();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息