一步一步的来封装自己的RecycleView

一步一步的来封装自己的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();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值