1. 程式人生 > >XRecyclerView實現RecyclerView下拉重新整理上來載入 自己做了部分修改,使程式碼更簡潔易用

XRecyclerView實現RecyclerView下拉重新整理上來載入 自己做了部分修改,使程式碼更簡潔易用

首先感謝 開源作者

/**
 * Created by jianghejie on 15/11/26.
 */
的無私奉獻  我是在他的基礎上做的修改

以前一直是用的XListView   可是 測試發現有一個奇奇怪怪的BUG,我們還無法解決。最嚴重的是 XListView   裡面用的新增頭addHeaderView方法在17以前有概率崩潰。後來在同事的專案裡看到PullToZoomListViewEx開原始碼,實現的很好,但是程式碼太難懂,感覺擴充套件性不好。

最後在RecyclerView的強大功能下,還是覺得要用整合RecyclerView的下拉重新整理上拉載入的控制元件才好。

好用整合RecyclerView下拉功能的控制元件都用到了SwipeRefreshLayout佈局,使得下拉樣式很官方,不滿足產品大大的需求。(其實官方多好的)

後來找到了這款開源的控制元件XRecyclerView  git地址:https://github.com/jianghejie/XRecyclerView     可以看動畫效果 

掩飾不住內心高興的心情,下載下來,發現功能太強的了

但是也有很多不足的地方,不必 很多 選擇重新整理和載入的樣式類。其實一般不需要

主要原理就是把重寫的Adapter  把我們的mHeader和mFooter  (如果需要還有   headviews)重組到Adapter  裡面。並且也重寫了監聽。

這個設計簡直就是棒棒噠

還不寫人不知到怎麼引用  RecyclerView  的架包   其實要完成以上的執行需要 RecyclerView  V7中的資原始檔   所以是要引用.arr 檔案  並不是.jar

至於他們有什麼區別   請去百度(弄好了那些   可以用在低版本上喲  我的API就是19)

對了  其實對於這個功能的開發 首先要注意有多少狀態      作者對重新整理狀態分了4種  載入 3種。而我自己應為需求只把重新整理和載入都要比作者少一種

廢話不多說了 下面上程式碼   我還自己加了很多註釋喲   

XRecyclerView類

package com.expect.zbjpulltorefresht.xlayoutview;

import android.content.Context;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;

import com.expect.zbjpulltorefresht.LaoZiDe.XRecyclerViewFooter;
import com.expect.zbjpulltorefresht.LaoZiDe.XRecyclerViewHeader;

import java.util.ArrayList;

/**
 * Created by expect_xh on 2016/3/22.
 */
public class XRecyclerView extends RecyclerView {
    private Context mContext;//上下文
    private ArrayList<View> mHeaderViews = new ArrayList<View>();//標頭檔案列表
    private XRecyclerViewHeader mHeader;
    private XRecyclerViewFooter mFooter;
    private Adapter mAdapter;//傳入的Adapter
    private Adapter mWrapAdapter;//組合的Adapter
    private float mLastY = -1; //記錄的Y座標
    private static final float DRAG_RATE = 3;//阻力率
    private LoadingListener mLoadingListener;//滑動監聽
    private boolean pullRefreshEnabled = true;   //重新整理狀態
    private boolean loadingMoreEnabled = true;   //上拉狀態

    private static final int TYPE_REFRESH_HEADER = -5; //新增重新整理頭
    private static final int TYPE_HEADER = -4;  //新增頭部
    private static final int TYPE_NORMAL = 0;
    private static final int TYPE_FOOTER = -3;//新增上拉載入佈局
    private int previousTotal = 0;//  記錄ITEM的條數


    public XRecyclerView(Context context) {
        this(context, null);
    }

    public XRecyclerView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public XRecyclerView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context);
    }

    private void init(Context context) {
        mContext = context;
        if (pullRefreshEnabled) {
            XRecyclerViewHeader xRecyclerViewHeader = new XRecyclerViewHeader(mContext);
            mHeaderViews.add(0, xRecyclerViewHeader);
            mHeader = xRecyclerViewHeader;
        }
        mFooter = new XRecyclerViewFooter(mContext);
        mFooter.setVisibility(GONE);
    }

    //新增頭部檔案的時候 判斷有沒有重新整理頭
    public void addHeaderView(View view) {
        if (pullRefreshEnabled && !(mHeaderViews.get(0) instanceof XRecyclerViewHeader)) {
            XRecyclerViewHeader xRecyclerViewHeader = new XRecyclerViewHeader(mContext);
            mHeaderViews.add(0, xRecyclerViewHeader);
            mHeader = xRecyclerViewHeader;
        }
        mHeaderViews.add(view);
    }

    public void loadMoreComplete() {//上拉載入完成後的   隱藏上拉載入佈局
        if (previousTotal < getLayoutManager().getItemCount()) {
            mFooter.setState(XRecyclerViewFooter.STATE_COMPLETE);
        }
        previousTotal = getLayoutManager().getItemCount();
    }

    public void refreshComplete() {//下拉重新整理完成後的  隱藏下拉載入 佈局
        mHeader.refreshComplate();
    }

    public void setPullRefreshEnabled(boolean enabled) {//設定是否可以重新整理
        pullRefreshEnabled = enabled;
    }

    public void setLoadingMoreEnabled(boolean enabled) {//設定是否可以上拉
        loadingMoreEnabled = enabled;
        if (!enabled) {
            mFooter.setVisibility(GONE);
        }
//        if (enabled){
//            mFooter.setVisibility(VISIBLE);
//        }else {
//            mFooter.setVisibility(GONE);
//        }
//        mWrapAdapter.notifyDataSetChanged();
    }

    @Override
    public void setAdapter(Adapter adapter) {
        mAdapter = adapter;
        mWrapAdapter = new WrapAdapter(mHeaderViews, mFooter, adapter);
        super.setAdapter(mWrapAdapter);
        mAdapter.registerAdapterDataObserver(mDataObserver);
    }

    /**
     * 活動監聽  判斷是否到底,用於載入
     */
    @Override
    public void onScrollStateChanged(int state) {
        super.onScrollStateChanged(state);
        if (state == RecyclerView.SCROLL_STATE_IDLE && mLoadingListener != null && loadingMoreEnabled) {
            LayoutManager layoutManager = getLayoutManager();
            int lastVisibleItemPosition;  //最後可見的Item的position的值
            if (layoutManager instanceof GridLayoutManager) {   //網格佈局的中lastVisibleItemPosition的取值
                lastVisibleItemPosition = ((GridLayoutManager) layoutManager).findLastVisibleItemPosition();
            } else if (layoutManager instanceof StaggeredGridLayoutManager) {//瀑布流佈局中lastVisibleItemPosition的取值
                int[] into = new int[((StaggeredGridLayoutManager) layoutManager).getSpanCount()];
                ((StaggeredGridLayoutManager) layoutManager).findLastVisibleItemPositions(into);
                lastVisibleItemPosition = findMax(into);
            } else {   //剩下只有線性佈局(listview)中lastVisibleItemPosition的取值
                lastVisibleItemPosition = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
            }
            if (layoutManager.getChildCount() > 0
                    && lastVisibleItemPosition >= layoutManager.getItemCount() - 1 && layoutManager.getItemCount() > layoutManager.getChildCount()
                    && mHeader.getState() < XRecyclerViewHeader.STATE_REFRESHING) {

                mFooter.setState(XRecyclerViewFooter.STATE_LOADING);

                mLoadingListener.onLoadMore();
            }
        }
    }

    /**
     * 監聽手勢活動  判斷有沒有到頂,用於重新整理
     */
    @Override
    public boolean onTouchEvent(MotionEvent e) {
        if (mLastY == -1) {
            mLastY = e.getRawY();
        }
        switch (e.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mLastY = e.getRawY();
                break;
            case MotionEvent.ACTION_MOVE:
                final float deltaY = e.getRawY() - mLastY;
                mLastY = e.getRawY();
                if (isOnTop() && pullRefreshEnabled) {
                    mHeader.onMove(deltaY / DRAG_RATE);
                    if (mHeader.getVisiableHeight() > 0 && mHeader.getState() < XRecyclerViewHeader.STATE_REFRESHING) {
                        Log.i("getVisiableHeight", "getVisiableHeight = " + mHeader.getVisiableHeight());
                        Log.i("getVisiableHeight", " mHeader.getState() = " + mHeader.getState());
                        return false;
                    }
                }
                break;
            default:
                mLastY = -1; // reset
                if (isOnTop() && pullRefreshEnabled) {
                    if (mHeader.releaseAction()) {
                        if (mLoadingListener != null) {
                            mLoadingListener.onRefresh();
                            previousTotal = 0;
                        }
                    }
                }
                break;
        }
        return super.onTouchEvent(e);

    }

    //判斷是不是在頂部
    private boolean isOnTop() {
        if (mHeaderViews == null || mHeaderViews.isEmpty()) {
            return false;
        }

        View view = mHeaderViews.get(0);
        if (view.getParent() != null) {
            return true;
        } else {
            return false;
        }
    }

    //瀑布流裡面用到的計算公式
    private int findMax(int[] lastPositions) {
        int max = lastPositions[0];
        for (int value : lastPositions) {
            if (value > max) {
                max = value;
            }
        }
        return max;
    }

    /**
     * adapter資料觀察者
     */
    private final RecyclerView.AdapterDataObserver mDataObserver = new RecyclerView.AdapterDataObserver() {
        @Override
        public void onChanged() {
            mWrapAdapter.notifyDataSetChanged();
        }

        @Override
        public void onItemRangeInserted(int positionStart, int itemCount) {
            mWrapAdapter.notifyItemRangeInserted(positionStart, itemCount);
        }

        @Override
        public void onItemRangeChanged(int positionStart, int itemCount) {
            mWrapAdapter.notifyItemRangeChanged(positionStart, itemCount);
        }

        @Override
        public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {
            mWrapAdapter.notifyItemRangeChanged(positionStart, itemCount, payload);
        }

        @Override
        public void onItemRangeRemoved(int positionStart, int itemCount) {
            mWrapAdapter.notifyItemRangeRemoved(positionStart, itemCount);
        }

        @Override
        public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
            mWrapAdapter.notifyItemMoved(fromPosition, toPosition);
        }
    };

    /**
     * 設配器重組
     */
    private class WrapAdapter extends RecyclerView.Adapter<ViewHolder> {

        private RecyclerView.Adapter adapter;

        private ArrayList<View> mHeaderViews;

        private XRecyclerViewFooter mFootView;

        private int headerPosition = 1;

        public WrapAdapter(ArrayList<View> headerViews, XRecyclerViewFooter footView, RecyclerView.Adapter adapter) {
            this.adapter = adapter;
            this.mHeaderViews = headerViews;
            this.mFootView = footView;
        }

        @Override
        public void onAttachedToRecyclerView(RecyclerView recyclerView) {
            super.onAttachedToRecyclerView(recyclerView);
            RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
            if (manager instanceof GridLayoutManager) {
                final GridLayoutManager gridManager = ((GridLayoutManager) manager);
                gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                    @Override
                    public int getSpanSize(int position) {
                        return (isHeader(position) || isFooter(position))
                                ? gridManager.getSpanCount() : 1;
                    }
                });
            }
        }

        @Override
        public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) {
            super.onViewAttachedToWindow(holder);
            ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams();
            if (lp != null
                    && lp instanceof StaggeredGridLayoutManager.LayoutParams
                    && (isHeader(holder.getLayoutPosition()) || isFooter(holder.getLayoutPosition()))) {
                StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) lp;
                p.setFullSpan(true);
            }
        }

        public boolean isHeader(int position) {
            return position >= 0 && position < mHeaderViews.size();
        }

        public boolean isFooter(int position) {
            return position < getItemCount() && position >= getItemCount() - 1;
        }

        public boolean isRefreshHeader(int position) {
            return position == 0;
        }

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

        public int getFootersCount() {
            return 1;
        }

        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            if (viewType == TYPE_REFRESH_HEADER) {
                return new SimpleViewHolder(mHeaderViews.get(0));
            } else if (viewType == TYPE_HEADER) {
                return new SimpleViewHolder(mHeaderViews.get(headerPosition++));
            } else if (viewType == TYPE_FOOTER) {
                return new SimpleViewHolder(mFootView);
            }
            return adapter.onCreateViewHolder(parent, viewType);
        }

        @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
            if (isHeader(position)) {
                return;
            }
            int adjPosition = position - getHeadersCount();
            int adapterCount;
            if (adapter != null) {
                adapterCount = adapter.getItemCount();
                if (adjPosition < adapterCount) {
                    adapter.onBindViewHolder(holder, adjPosition);
                    return;
                }
            }
        }

        @Override
        public int getItemCount() {
            if (adapter != null) {
                return getHeadersCount() + getFootersCount() + adapter.getItemCount();
            } else {
                return getHeadersCount() + getFootersCount();
            }
        }

        @Override
        public int getItemViewType(int position) {
            if (isRefreshHeader(position)) {
                return TYPE_REFRESH_HEADER;
            }
            if (isHeader(position)) {
                return TYPE_HEADER;
            }
            if (isFooter(position)) {
                return TYPE_FOOTER;
            }
            int adjPosition = position - getHeadersCount();
            ;
            int adapterCount;
            if (adapter != null) {
                adapterCount = adapter.getItemCount();
                if (adjPosition < adapterCount) {
                    return adapter.getItemViewType(adjPosition);
                }
            }
            return TYPE_NORMAL;
        }

        @Override
        public long getItemId(int position) {
            if (adapter != null && position >= getHeadersCount()) {
                int adjPosition = position - getHeadersCount();
                int adapterCount = adapter.getItemCount();
                if (adjPosition < adapterCount) {
                    return adapter.getItemId(adjPosition);
                }
            }
            return -1;
        }

        @Override
        public void unregisterAdapterDataObserver(AdapterDataObserver observer) {
            if (adapter != null) {
                adapter.unregisterAdapterDataObserver(observer);
            }
        }

        @Override
        public void registerAdapterDataObserver(AdapterDataObserver observer) {
            if (adapter != null) {
                adapter.registerAdapterDataObserver(observer);
            }
        }

        private class SimpleViewHolder extends RecyclerView.ViewHolder {
            public SimpleViewHolder(View itemView) {
                super(itemView);
            }
        }
    }

    /**
     * 監聽介面
     */
    public void setLoadingListener(LoadingListener listener) {
        mLoadingListener = listener;
    }

    public interface LoadingListener {

        void onRefresh();

        void onLoadMore();
    }
}

XRecyclerViewHeader重新整理頭這個類
package com.expect.zbjpulltorefresht.LaoZiDe;

import android.animation.ValueAnimator;
import android.content.Context;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.expect.zbjpulltorefresht.R;

import java.util.Date;

/**
 * Created by expect_xh on 2016/3/23.
 */
public class XRecyclerViewHeader extends LinearLayout{
    private LinearLayout mContainer;//佈局指向
    private Context mContext;//上下文引用

    public final static int STATE_NORMAL = 0;// 初始狀態
    public final static int STATE_RELEASE_TO_REFRESH = 1;	// 釋放重新整理
    public final static int STATE_REFRESHING = 2;	// 正在重新整理

    private ImageView mArrowImageView;//箭頭呀
    private ImageView mProgressBar;    // 正在重新整理的圖示
    private TextView mStatusTextView;//狀態文字
    private int mState = STATE_NORMAL;  // 當前狀態(臨時儲存用)
    private TextView mHeaderTimeView;//重新整理時間文字

    //以下是箭頭圖示動畫
    private Animation mRotateUpAnim;
    private Animation mRotateDownAnim;

    private final int ROTATE_ANIM_DURATION = 180;//旋轉角度
    public int mMeasuredHeight;//佈局的原始高度,用於做狀態改變的標誌
    // 均勻旋轉動畫
    private RotateAnimation refreshingAnimation;
    public XRecyclerViewHeader(Context context) {
        super(context);
        initView(context);
    }

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

    public XRecyclerViewHeader(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initView(context);
    }
    //初始化
    private void initView(Context context) {
        mContext = context;
        // 初始情況,設定下拉重新整理view高度為0
        mContainer= (LinearLayout) LayoutInflater.from(context).inflate(R.layout.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);
        mStatusTextView = (TextView)findViewById(R.id.refresh_status_textview);
        mProgressBar= (ImageView) findViewById(R.id.listview_header_progressbar);
        mHeaderTimeView = (TextView)findViewById(R.id.last_refresh_time);

        //箭頭改變動畫
        mRotateUpAnim = new RotateAnimation(0.0f, -180.0f,
                Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
                0.5f);
        mRotateUpAnim.setDuration(ROTATE_ANIM_DURATION);
        mRotateUpAnim.setFillAfter(true);
        mRotateDownAnim = new RotateAnimation(-180.0f, 0.0f,
                Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
                0.5f);
        mRotateDownAnim.setDuration(ROTATE_ANIM_DURATION);
        mRotateDownAnim.setFillAfter(true);
        ///新增勻速轉動動畫
        refreshingAnimation = (RotateAnimation) AnimationUtils.loadAnimation(
                context, R.anim.rotating);
        LinearInterpolator lir = new LinearInterpolator();
        refreshingAnimation.setInterpolator(lir);


        measure(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);
        mMeasuredHeight=getMeasuredHeight();
    }
    //設定狀態
    public void setState(int state){
        if (state==mState){
            return;
        }
        //判斷顯示
        switch (state){
            case STATE_NORMAL:
            case STATE_RELEASE_TO_REFRESH:
                mProgressBar.clearAnimation();
                mArrowImageView.setVisibility(VISIBLE);
                mProgressBar.setVisibility(INVISIBLE);
                break;
            case STATE_REFRESHING:
                mArrowImageView.clearAnimation();
                mArrowImageView.setVisibility(View.INVISIBLE);
                mProgressBar.setVisibility(View.VISIBLE);
                break;
            default:
                break;
        }
        //判斷動畫的新增
        switch (state){
            case STATE_NORMAL:
                if (mState==STATE_RELEASE_TO_REFRESH){
                    mArrowImageView.startAnimation(mRotateDownAnim);
                }
                if (mState==STATE_REFRESHING){
                    mArrowImageView.clearAnimation();
                }
                mStatusTextView.setText(R.string.listview_header_hint_normal);
                break;
            case STATE_RELEASE_TO_REFRESH:
                if (mState!=STATE_RELEASE_TO_REFRESH){
                    mArrowImageView.clearAnimation();
                    mArrowImageView.startAnimation(mRotateUpAnim);
                    mStatusTextView.setText(R.string.listview_header_hint_release);
                }
                break;
            case STATE_REFRESHING:
                mProgressBar.startAnimation(refreshingAnimation);
                mStatusTextView.setText(R.string.refreshing);
                break;
            default:
                break;
        }
        mState=state;
    }
    //返回當前狀態
    public int getState(){
        return mState;
    }
    //完成重新整理
    public void refreshComplate(){
        //註釋的是時間文字  有需要可以去掉  也是在佈局裡改可見屬性
//        mHeaderTimeView.setText(friendlyTime(new Date()));
        smoothScrollTo(0);
        setState(STATE_NORMAL);
    }

    /**
     * 重新整理頭滑動改變
     */
    public void onMove(float dalta){
        if (getVisiableHeight()>0||dalta>0){
            setVisiableHeight((int)dalta+getVisiableHeight());
            if (mState<=STATE_RELEASE_TO_REFRESH){// 未處於重新整理狀態,更新箭頭
                if (getVisiableHeight()>mMeasuredHeight){
                    setState(STATE_RELEASE_TO_REFRESH);
                }else {
                    setState(STATE_NORMAL);
                }
            }
        }
    }

    /**
     *釋放重新整理頭的時候,是否滿足重新整理的要求
     */
    public boolean releaseAction() {
        boolean isOnRefresh = false;
        int height=getVisiableHeight();
        if (height==0){
            isOnRefresh=false;
        }
        //重新整理時改變狀態
        if (getVisiableHeight()>mMeasuredHeight&&mState<STATE_REFRESHING){
            setState(STATE_REFRESHING);
            isOnRefresh=true;
        }
        //重新整理時回滾到原始高度
        int destHeight=0;
        if (mState==STATE_REFRESHING){
            destHeight=mMeasuredHeight;
        }
        smoothScrollTo(destHeight);
        return  isOnRefresh;
    }

    //回滾到頂部
    private void smoothScrollTo(int destHeight) {
        ValueAnimator animator = ValueAnimator.ofInt(getVisiableHeight(), destHeight);
        animator.setDuration(300).start();
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation)
            {
                setVisiableHeight((Integer) animation.getAnimatedValue());
            }
        });
        animator.start();
    }
    //設定重新整理頭可見的高度
    public void setVisiableHeight(int height) {
        if (height < 0)
            height = 0;
        LayoutParams lp = (LayoutParams) mContainer
                .getLayoutParams();
        lp.height = height;
        mContainer.setLayoutParams(lp);
    }
    //獲得重新整理頭可見的高度
    public int getVisiableHeight() {
        int height = 0;
        LayoutParams lp = (LayoutParams) mContainer
                .getLayoutParams();
        height = lp.height;
        return height;
    }
    //重新整理時間計算
    public static String friendlyTime(Date time) {
        //獲取time距離當前的秒數
        int ct = (int)((System.currentTimeMillis() - time.getTime())/1000);

        if(ct == 0) {
            return "剛剛";
        }

        if(ct > 0 && ct < 60) {
            return ct + "秒前";
        }

        if(ct >= 60 && ct < 3600) {
            return Math.max(ct / 60,1) + "分鐘前";
        }
        if(ct >= 3600 && ct < 86400)
            return ct / 3600 + "小時前";
        if(ct >= 86400 && ct < 2592000){ //86400 * 30
            int day = ct / 86400 ;
            return day + "天前";
        }
        if(ct >= 2592000 && ct < 31104000) { //86400 * 30
            return ct / 2592000 + "月前";
        }
        return ct / 31104000 + "年前";
    }
}

XRecyclerViewFooter 載入佈局
package com.expect.zbjpulltorefresht.LaoZiDe;

import android.content.Context;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.view.animation.AnimationUtils;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.expect.zbjpulltorefresht.R;

/**
 * Created by expect_xh on 2016/3/23.
 */
public class XRecyclerViewFooter extends LinearLayout{
    private LinearLayout mContainer;//佈局指向
    private Context mContext;//上下文引用

    public final static int STATE_LOADING = 0; //正在載入
    public final static int STATE_COMPLETE = 1;  //載入完成

    private ImageView mProgressBar;    // 正在重新整理的圖示

    // 均勻旋轉動畫
    private RotateAnimation refreshingAnimation;
    public XRecyclerViewFooter(Context context) {
        super(context);
        initView(context);
    }

    public XRecyclerViewFooter(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initView(context);
    }

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

    //初始化
    private void initView(Context context) {
        mContext=context;
        mContainer= (LinearLayout) LayoutInflater.from(context).inflate(R.layout.listview_footer,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, LayoutParams.WRAP_CONTENT));
        setGravity(Gravity.CENTER);

        mProgressBar= (ImageView) findViewById(R.id.listview_foot_progress);

        ///新增勻速轉動動畫
        refreshingAnimation = (RotateAnimation) AnimationUtils.loadAnimation(
                context, R.anim.rotating);
        LinearInterpolator lir = new LinearInterpolator();
        refreshingAnimation.setInterpolator(lir);

        measure(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);
    }

    public void  setState(int state) {
        switch (state){
            case STATE_LOADING:
                this.setVisibility(VISIBLE);
                mProgressBar.setAnimation(refreshingAnimation);
                break;
            case STATE_COMPLETE:
                mProgressBar.clearAnimation();
                this.setVisibility(GONE);
                break;
            default:
                break;
        }
    }
}
最後的最後我把整個資源專案打包  獻上   如果有什麼 做的不好的地方  請大家多多指正

好吧 CSDN傳了幾次 傳不上      坑壁  我用百度了

資源連結  http://pan.baidu.com/s/1bogV6Bt       包名不用管哈  懶得改了