(六)安卓框架搭建之RecyclerView和Adapter以及列表案例

recycalview和adapter
recycleview 的出现就是来替代listview,并且其性能上做了很多优化。今天用的这个是取自第三方的Xrecycleview,没错,这次又是站在了巨人的肩膀上。选Xrecycleview的原因是之前用这个写过一个自定义的头部刷新view.而且它在github上,评价也蛮好。

有点小遗憾就是刷新效果很老气。所以我决定重新写一个RefresHeader.如下

package com.example.burro.demo.appframework.recyclerview.xrecyclerview.custom;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.drawable.AnimationDrawable;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;

import com.example.burro.demo.appframework.R;
import com.example.burro.demo.appframework.recyclerview.xrecyclerview.BaseRefreshHeader;
import com.example.burro.demo.appframework.recyclerview.xrecyclerview.SimpleViewSwitcher;

/**自定义刷新view
 *Created by ex.zhong on 2017/9/17.
 */
public class CustomerRefreshHeader extends LinearLayout implements BaseRefreshHeader {

    private LinearLayout mContainer;
    private ImageView mArrowImageView;
    private SimpleViewSwitcher mProgressBar;
    private int mState = STATE_NORMAL;

    public int mMeasuredHeight;
    private AnimationDrawable mAnimationDrawable;

    public CustomerRefreshHeader(Context context) {
        super(context);
        initView();
    }

    /**
     * @param context
     * @param attrs
     */
    public CustomerRefreshHeader(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView();
    }

    private void initView() {
        // 初始情况,设置下拉刷新view高度为0
        mContainer = (LinearLayout) LayoutInflater.from(getContext()).inflate(
                R.layout.custom_listview_header, null);
        LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
        lp.setMargins(0, 0, 0, 0);
        this.setLayoutParams(lp);
        this.setPadding(0, 0, 0, 0);

        addView(mContainer, new LayoutParams(LayoutParams.MATCH_PARENT, 0));
        setGravity(Gravity.BOTTOM);

        mArrowImageView = (ImageView)findViewById(R.id.listview_header_arrow);

        //init the progress view
        mProgressBar = (SimpleViewSwitcher)findViewById(R.id.listview_header_progressbar);

        ImageView progressView= new ImageView(getContext());
        progressView.setImageResource(R.drawable.refresh_headview);
        mAnimationDrawable=(AnimationDrawable)progressView.getDrawable();
        mProgressBar.setView(progressView);
        measure(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        mMeasuredHeight = getMeasuredHeight();
    }

    public void setProgressStyle(int style) {

    }
    //设置要动画图片
    public void setProgressStyle(ImageView imageView) {
        if(imageView != null&&imageView.getDrawable()!=null){
            mProgressBar.setView(imageView);
            mAnimationDrawable= (AnimationDrawable) imageView.getDrawable();
        }
    }
    //设置背景图片
    public void setRefreshBackground(int color) {
        mContainer.setBackgroundColor(color);
    }
    public void setArrowImageView(int resid){
        mArrowImageView.setImageResource(resid);
    }

    public void setState(int state) {
        if (state == mState) return ;

        if (state == STATE_REFRESHING) {    // 显示进度
            mArrowImageView.clearAnimation();
            mArrowImageView.setVisibility(View.INVISIBLE);
            mProgressBar.setVisibility(View.VISIBLE);
            mAnimationDrawable.start();
            smoothScrollTo(mMeasuredHeight);
        } else if(state == STATE_DONE) {
            mArrowImageView.setVisibility(View.VISIBLE);
            mProgressBar.setVisibility(View.INVISIBLE);
            mAnimationDrawable.stop();
        } else {    // 显示箭头图片
            mArrowImageView.setVisibility(View.VISIBLE);
            mProgressBar.setVisibility(View.INVISIBLE);
            mAnimationDrawable.stop();
        }

        mState = state;
    }

    public int getState() {
        return mState;
    }

    @Override
    public void refreshComplete(){
        setState(STATE_DONE);
        new Handler().postDelayed(new Runnable(){
            public void run() {
                reset();
            }
        }, 200);
    }

    public void setVisibleHeight(int height) {
        if (height < 0) height = 0;
        LayoutParams lp = (LayoutParams) mContainer .getLayoutParams();
        lp.height = height;
        mContainer.setLayoutParams(lp);
    }

    public int getVisibleHeight() {
        LayoutParams lp = (LayoutParams) mContainer.getLayoutParams();
        return lp.height;
    }

    @Override
    public void onMove(float delta) {
        if(getVisibleHeight() > 0 || delta > 0) {
            setVisibleHeight((int) delta + getVisibleHeight());
            if (mState <= STATE_RELEASE_TO_REFRESH) { // 未处于刷新状态,更新箭头
                if (getVisibleHeight() > mMeasuredHeight) {
                    setState(STATE_RELEASE_TO_REFRESH);
                }else {
                    setState(STATE_NORMAL);
                }
            }
        }
    }

    @Override
    public boolean releaseAction() {
        boolean isOnRefresh = false;
        int height = getVisibleHeight();
        if (height == 0) // not visible.
            isOnRefresh = false;

        if(getVisibleHeight() > mMeasuredHeight &&  mState < STATE_REFRESHING){
            setState(STATE_REFRESHING);
            isOnRefresh = true;
        }
        // refreshing and header isn't shown fully. do nothing.
        if (mState == STATE_REFRESHING && height <=  mMeasuredHeight) {
            //return;
        }
        if (mState != STATE_REFRESHING) {
            smoothScrollTo(0);
        }

        if (mState == STATE_REFRESHING) {
            int destHeight = mMeasuredHeight;
            smoothScrollTo(destHeight);
        }

        return isOnRefresh;
    }

    public void reset() {
        smoothScrollTo(0);
        new Handler().postDelayed(new Runnable() {
            public void run() {
                setState(STATE_NORMAL);
            }
        }, 500);
    }

    private void smoothScrollTo(int destHeight) {
        ValueAnimator animator = ValueAnimator.ofInt(getVisibleHeight(), destHeight);
        animator.setDuration(300).start();
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation)
            {
                setVisibleHeight((int) animation.getAnimatedValue());
            }
        });
        animator.start();
    }
}

修改的思路起始很简单。只是把以前刷新时的旋转动画换成了帧动画。当下拉或刷新结束时。设置静态图片。当然要对核心的XRecyclerViewy也要稍加修改,使其适配我的CustomerRefreshHeader.布局请到demo中查看

adapter

XRecyclerViewy封装的很好,但是没有对他的兄弟adapter进行封装优化。BaseRecyclerViewAdapter是adapter的基类,直接贴上封装内容:
BaseRecyclerViewAdapter

package com.example.burro.demo.appframework.adapter;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import java.util.ArrayList;
import java.util.List;

/**Adapter基类
 * Created by ex.zhong on 2017/9/29.
 */
public abstract class BaseRecyclerViewAdapter extends RecyclerView.Adapter{
    protected Context mContext;
    private LayoutInflater inflater;
    private List datas;
    private int layoutId;
    protected OnItemClickListner onItemClickListner;//单击事件
    protected OnItemLongClickListner onItemLongClickListner;//长按单击事件

    public BaseRecyclerViewAdapter(Context context, OnItemClickListner onItemClickListner) {
        this.mContext = context;
        this.datas = new ArrayList<>();
        this.layoutId = initLayoutInflater();
        this.inflater = LayoutInflater.from(context);
        this.onItemClickListner=onItemClickListner;
    }

    protected abstract int initLayoutInflater();
    @Override
    public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        BaseViewHolder holder = new BaseViewHolder(inflater.inflate(layoutId, parent, false));
        //可全局在此设置增加外层效果布局
//        MaterialRippleLayout.on(holder.getView(R.id.ll_all))
//                .rippleOverlay(true)
//                .rippleAlpha(0.2f)
//                .rippleColor(context.getResources().getColor(R.color.colorAccent))
//                .rippleHover(true)
//                .create();
        return holder;
    }

    @Override
    public void onBindViewHolder(final BaseViewHolder holder, final int position) {
        holder.getRootView().setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(onItemClickListner!=null) onItemClickListner.onItemClickListner(v,position);
            }
        });
        bindData(holder, datas.get(position), position);
    }

    protected abstract void bindData(BaseViewHolder holder, T data, int position);

    @Override
    public int getItemCount() {
        return datas == null ? 0 : datas.size();
    }

    //单击事件接口
    public interface OnItemClickListner {
        void onItemClickListner(View v, int position);
    }

    //长按事件接口
    public interface OnItemLongClickListner {
        void onItemLongClickListner(View v, int position);
    }

    //更新数据
    public void updateData(List list) {
        datas.clear();
        if(list!=null){
            datas.addAll(list);
        }
        notifyDataSetChanged();
    }
    //增加更多
    public void addMoreData(List list){
        if(list!=null){
            datas.addAll(list);
        }
        notifyDataSetChanged();
    }
    //获取数据集合数据
    public List getDataList(){
        return datas;
    }
}

BaseViewHolder

package com.example.burro.demo.appframework.adapter;

import android.support.v7.widget.RecyclerView;
import android.util.SparseArray;
import android.view.View;

/**全能的ViewHolder
 * Created by ex.zhong on 2017/9/29.
 */
public class BaseViewHolder extends RecyclerView.ViewHolder{
    private SparseArray views;

    public BaseViewHolder(View view) {
        super(view);
        this.views = new SparseArray<>();
    }

    public  T getView(int viewId) {
        View view = views.get(viewId);
        if (view == null) {
            view = itemView.findViewById(viewId);
            views.put(viewId, view);
        }
        return (T) view;
    }

    public View getRootView() {
        return itemView;
    }
}

我是不推荐直接的引用第三方的包,试想如果需求要调整,那岂不是每个页面都要去改动?所以!当然!要封装一个公用的类来继承它。我这里写一个类ComRecyclerView继承自XRecyclerView,各位也可以根据具体使用情况自由发挥!

package com.example.burro.demo.appframework.recyclerview;

import android.content.Context;
import android.support.v7.widget.LinearLayoutManager;
import android.util.AttributeSet;

import com.example.burro.demo.appframework.R;
import com.example.burro.demo.appframework.recyclerview.xrecyclerview.ProgressStyle;
import com.example.burro.demo.appframework.recyclerview.xrecyclerview.XRecyclerView;

/**通用ComRecyclerView
 * Created by ex.zhong on 2017/9/27.
 */
public class ComRecyclerView extends XRecyclerView {
    public ComRecyclerView(Context context) {
        super(context);
        initView(context);
    }

    public ComRecyclerView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView(context);
    }

    public ComRecyclerView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initView(context);
    }
    private void initView(Context context) {
        //  headerView的添加,可更具需要,在页面上动态设置
//        View header = LayoutInflater.from(context).inflate(R.layout.recyclerview_header, (ViewGroup)findViewById(android.R.id.content),false);
//        mRecyclerView.addHeaderView(header);
        //添加刷新动画
        //默认线性布局,如需gridView,可重新设置
        LinearLayoutManager layoutManager = new LinearLayoutManager(context);
        layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        this.setLayoutManager(layoutManager);

        this.setRefreshProgressStyle(ProgressStyle.BallSpinFadeLoader);
        this.setLoadingMoreProgressStyle(ProgressStyle.BallRotate);
        this.setArrowImageView(R.mipmap.mloading_0);
    }
}

先前写过的电影列表中用到的Adapter,看看是不是很简洁!

(六)安卓框架搭建之RecyclerView和Adapter以及列表案例_第1张图片
电影列表适配adapter

为了保证demo的完整性,结合之前所写以及上述RecyclerView和Adapter的封装,接下来完善一下列表页面。我把test部分的内容全部移进movie里面。并增加了详情页面,页面跳转、MainActivity里增加新建的MovieListFragment等。由于这部分主要是业务内容。不多作说明,可以到源码中查看

(六)安卓框架搭建之RecyclerView和Adapter以及列表案例_第2张图片

下一篇将进一步完善框架

相关链接

(七)安卓框架搭建之其他必备要素的封装或引入

github源码地址

你可能感兴趣的:((六)安卓框架搭建之RecyclerView和Adapter以及列表案例)