1. 程式人生 > >RecyclerView新增頭腳佈局,使用SwipeRefreshLayout的實現

RecyclerView新增頭腳佈局,使用SwipeRefreshLayout的實現

上篇文章記錄了將viewpager抽取出來,那麼這篇文章我們繼續來實現,將viewpager做為頭佈局新增給RecyclerView。這使用到了一種設計模式 - 包裝類設計模式,大家可以先了解下這個模式更有利於理解,我也會把本篇實現的思路給出個思維導圖的。
看下效果圖吧:
這裡寫圖片描述

首先來個bean物件,等下封裝資料使用:

public class Item {

    private String maintitle;
    private String subtitle;

    public Item(String maintitle, String subtitle){
        this
.maintitle = maintitle; this.subtitle = subtitle; } public String getMaintitle() { return maintitle; } public String getSubtitle() { return subtitle; } }

然後我們建立一個類WrapRecyclerView繼承自RecyclerView:

// 將recycle進行封裝
public class WrapRecyclerView extends RecyclerView
{
private ArrayList<View> mHeadViewList = new ArrayList<View>(); private ArrayList<View> mFootViewList = new ArrayList<View>(); private Adapter mAdapter; public WrapRecyclerView(Context context) { super(context); } public WrapRecyclerView(Context context, AttributeSet attrs) { super
(context, attrs); } public WrapRecyclerView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public void addHeaderView(View view){ mHeadViewList.clear(); mHeadViewList.add(view); if (mAdapter != null){ if (!(mAdapter instanceof RecylerWrapAdapter)){ mAdapter = new RecylerWrapAdapter(mHeadViewList,mFootViewList,mAdapter); } } } public void addFootView(View view){ mFootViewList.clear(); mFootViewList.add(view); if (mAdapter != null){ if (!(mAdapter instanceof RecylerWrapAdapter)){ mAdapter = new RecylerWrapAdapter(mHeadViewList,mFootViewList,mAdapter); } } } @Override public void setAdapter(Adapter adapter) { if (mHeadViewList.isEmpty() && mFootViewList.isEmpty()){ super.setAdapter(adapter); }else{ adapter = new RecylerWrapAdapter(mHeadViewList,mFootViewList,adapter); super.setAdapter(adapter); } mAdapter = adapter; } }
//在佈局使用,使用系統的SwipeRefreshLayout包裹下
<android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/srl_refresh"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    <com.wb.head.widget.WrapRecyclerView
        android:id="@+id/recycler"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    </android.support.v4.widget.SwipeRefreshLayout>
//然後在MainActivity的onCreate中獲取例項,進行初始化。還是我們上篇的那個MainActivity
 recycler = (WrapRecyclerView) findViewById(R.id.recycler);
 refresh = (SwipeRefreshLayout) findViewById(R.id.srl_refresh);
 initRecycler();
 initRefresh();
private void initRecycler(){
        ll_headparent.removeView(rl_head);
        recycler.addHeaderView(rl_head);

        TextView textView = new TextView(this);
        textView.setText("我是腳佈局");
        textView.setBackgroundColor(getResources().getColor(R.color.colorAccent));
        ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,50);
        textView.setGravity(Gravity.CENTER);
        textView.setLayoutParams(params);
        recycler.addFootView(textView);

        mRecylerAdpater = new RecylerAdpater(loadData(0,6));
        recycler.setAdapter(mRecylerAdpater);
        recycler.setLayoutManager(new LinearLayoutManager(this));
        recycler.setHasFixedSize(true);
        onRecyclerClick();
    }
// 如果連續快速點選,條目的動畫會有一個bug,所以使用了一個標記來禁止點選連續點選
boolean isClick = false;
    private void onRecyclerClick(){
        mRecylerAdpater.setOnItemClickLitener(new RecylerAdpater.OnItemClickLitener() {
            @Override
            public void onItemClick(View view, int position) {
                if (!isClick){
                    isClick = true;
                    Toast.makeText(MainActivity.this, "點了我position" + position, Toast.LENGTH_SHORT).show();
                    ViewCompat.animate(view).setDuration(200).scaleX(0.9f).scaleY(0.9f).setInterpolator(new CycleInterpolator())
                            .setListener(new ViewPropertyAnimatorListener() {

                                @Override
                                public void onAnimationStart(View view) {}

                                @Override
                                public void onAnimationEnd(View view) {
                                    isClick = false;
                                }

                                @Override
                                public void onAnimationCancel(View view) {}
                            }).withLayer().start();
                }
            }
            @Override
            public void onItemLongClick(View view, int position) {
                Toast.makeText(MainActivity.this, "長按了我position" + position, Toast.LENGTH_SHORT).show();
            }
        });
    }

    private class CycleInterpolator implements android.view.animation.Interpolator {

        private final float mCycles = 0.5f;

        @Override
        public float getInterpolation(final float input) {
            return (float) Math.sin(2.0f * mCycles * Math.PI * input);
        }
    }

ArrayList<Item> items = new ArrayList<Item>();
private ArrayList loadData(int start,int end){
    items.clear();
    for (int i = start; i < end; i++) {
        items.add(new Item("Item title :" + i,"This is the Item number :" + i));
    }
    return items;
}
// 模仿訪問網路,進行重新整理資料
private void initRefresh(){
        refresh.setColorSchemeResources(android.R.color.holo_blue_light,
                android.R.color.holo_red_light,android.R.color.holo_orange_light,
                android.R.color.holo_green_light);
        refresh.setProgressBackgroundColorSchemeColor(getResources().getColor(android.R.color.white));
        refresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        items.clear();
                        mRecylerAdpater = new RecylerAdpater(loadData(10, 16));
                        recycler.setAdapter(mRecylerAdpater);
                        mRecylerAdpater.notifyDataSetChanged();
                        onRecyclerClick();
                        refresh.setRefreshing(false);
                    }
                }, 4000);
            }
        });
    }

然後我們在建立個類RecylerWrapAdapter繼承自RecyclerView.Adapter對adapter進行包裝:

public class RecylerWrapAdapter extends RecyclerView.Adapter{

    private RecyclerView.Adapter mAdapter;
    private ArrayList<View> mHeaderViews;
    private ArrayList<View> mFootViews;
    private final ArrayList<View> EMPTY_INFO_LIST = new ArrayList<View>();
    private int mCurrentPosition;

    public RecylerWrapAdapter(ArrayList<View> mHeaderViews,ArrayList<View> mFootViews,RecyclerView.Adapter mAdapter){
        this.mAdapter = mAdapter;
        if (mHeaderViews == null){
            this.mHeaderViews = EMPTY_INFO_LIST;
        }else{
            this.mHeaderViews = mHeaderViews;
        }

        if (mFootViews == null){
            this.mFootViews = EMPTY_INFO_LIST;
        }else{
            this.mFootViews = mFootViews;
        }
    }

    public int getHeaderCount(){
        return mHeaderViews.size();
    }

    public int getFootCount(){
        return mFootViews.size();
    }

    /**
     * 返回該position對應的item的id
     * @param position
     * @return
     */
    @Override
    public long getItemId(int position) {
        int heads = getHeaderCount();
        if (mAdapter != null && position >= heads){
            int adjposition = position - heads; //減去頭佈局的當前位置
            int adapterCount = mAdapter.getItemCount(); //總共有多少條目
            if (adjposition < adapterCount){ // 當前位置如果是在條目中的
                return mAdapter.getItemId(adjposition);
            }
        }
        return -1;
    }

    @Override
    public int getItemCount() {
        if (mAdapter != null){
            return getHeaderCount() + getFootCount() + mAdapter.getItemCount();
        }else{
            return getHeaderCount() +getFootCount();
        }
    }

    /**
     * 判斷應該返回的是頭佈局還是正常子佈局還是腳佈局 在onCreateViewHolder中使用
     * @param position
     * @return
     */
    @Override
    public int getItemViewType(int position) {
        mCurrentPosition = position;
        int heads = getHeaderCount();
        // 也就是說recycle的第一個條目位置為頭佈局
        if (position < heads){
            // 返回型別為頭佈局
            return RecyclerView.INVALID_TYPE;
        }
        int adjposition = position - heads; //減去頭佈局後當前佈局的位置
        int adapterCount = 0;
        if (mAdapter != null){
            adapterCount = mAdapter.getItemCount();
            if (adjposition < adapterCount){
                //返回型別為正常佈局
                return mAdapter.getItemViewType(adjposition);
            }
        }
        // 返回型別為腳佈局
        return RecyclerView.INVALID_TYPE - 1;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == RecyclerView.INVALID_TYPE){
            // 返回頭佈局
            return new HeaderViewHolder(mHeaderViews.get(0));
        }else if (viewType == RecyclerView.INVALID_TYPE - 1){
            // 返回腳佈局
            return new HeaderViewHolder(mFootViews.get(0));
        }
        // 返回正常佈局
        return mAdapter.onCreateViewHolder(parent,viewType);
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        int heads = getHeaderCount();
        if (position < heads) return;
        int adjPosition = position - heads;
        int adapterCount = 0;
        if (mAdapter != null){
            adapterCount = mAdapter.getItemCount();
            if (adjPosition < adapterCount){
                // 繫結正常條目資料
                mAdapter.onBindViewHolder(holder,adjPosition);
                return;
            }
        }
    }

    private class HeaderViewHolder extends RecyclerView.ViewHolder{

        public HeaderViewHolder(View itemView) {
            super(itemView);
        }
    }
}

現在包裝類寫完了,但我們的RecyclerView還沒有Adapter的,那我們就建立吧,和使用普通RecyclerView的Adapter一樣:

public class RecylerAdpater extends RecyclerView.Adapter<RecylerAdpater.MyViewHolder> {

    private List items;

    public RecylerAdpater(List list){
        super();
        items = list;
    }

    @Override
    public int getItemCount() {
        return items.size();
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item,parent,false);
        return new MyViewHolder(v);
    }

    @Override
    public void onBindViewHolder(final MyViewHolder holder, int position) {
        Item item = (Item)items.get(position);
        holder.mTitle.setText(item.getMaintitle());
        holder.mSubtitle.setText(item.getSubtitle());

        if (mOnItemClickLitener != null){
            // 設定點選事件  通過系統view類的回撥設定我們的回撥
            holder.ll_item.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    int pos = holder.getLayoutPosition();
                    mOnItemClickLitener.onItemClick(holder.ll_item,pos);
                }
            });

            // 設定長按事件 通過系統view類的回撥設定我們的回撥
            holder.ll_item.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {
                    int pos = holder.getLayoutPosition();
                    mOnItemClickLitener.onItemLongClick(holder.ll_item,pos);
                    return true;
                }
            });
        }
    }

    class MyViewHolder extends RecyclerView.ViewHolder{

        TextView mTitle;
        TextView mSubtitle;
        LinearLayout ll_item;

        public MyViewHolder(View itemView) {
            super(itemView);
            mTitle = (TextView) itemView.findViewById(R.id.maintitle);
            mSubtitle = (TextView) itemView.findViewById(R.id.subtitle);
            ll_item = (LinearLayout) itemView.findViewById(R.id.ll_item);
        }
    }

    //回撥介面用於點選事件
    public interface OnItemClickLitener{
        void onItemClick(View view,int position);
        void onItemLongClick(View view,int position);
    }

    private OnItemClickLitener mOnItemClickLitener;

    public void setOnItemClickLitener(OnItemClickLitener mOnItemClickLitener){
        this.mOnItemClickLitener = mOnItemClickLitener;
    }
}

OK,現在大功告成,我們已經在MainActivity的initRecycler()方法中使用了,執行就可以看到效果了。
對包裝類設計模式不熟悉的朋友可能會有些疑問,下面給大家貼出我做的思維導圖:
這裡寫圖片描述
最好的方法還是自己寫出來,斷點下就清楚這個設計模式和執行流程了。如有哪裡不足,歡迎指教。