1. 程式人生 > >Android 自定義下拉重新整理和上拉載入

Android 自定義下拉重新整理和上拉載入

完整程式碼在最下面。。

頭佈局xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="50dp">

        <LinearLayout
            android:id="@+id/layout"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:gravity="center"
            android:orientation="vertical">

            <TextView
                android:id="@+id/txt_xia_la"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="下拉重新整理"
                android:textSize="18sp" />

            <TextView
                android:id="@+id/txt_last_time"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="18sp" />
        </LinearLayout>

        <ImageView
            android:id="@+id/jian_tou"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:layout_centerVertical="true"
            android:layout_marginEnd="16dp"
            android:layout_toLeftOf="@+id/layout"
            android:src="@mipmap/up" />

        <ProgressBar
            android:id="@+id/progress"
            android:layout_width="20dp"
            android:layout_height="20dp"
            android:layout_centerVertical="true"
            android:layout_marginEnd="16dp"
            android:layout_toLeftOf="@+id/layout"
            android:visibility="gone" />
    </RelativeLayout>
</LinearLayout>

新增頭佈局並隱藏

 private void initView(Context context) {
        header = LayoutInflater.from(context).inflate(R.layout.refresh_header, null);
        measureView(header);
        headerHeight = header.getMeasuredHeight();
        topPadding(-headerHeight);
        addHeaderView(header);
        setOnScrollListener(this);
    }

設定上邊距

/**
     * 設定header上邊距
     *
     * @param topPadding 上邊距
     */

    private void topPadding(int topPadding) {
        header.setPadding(header.getPaddingLeft(), topPadding,
                header.getPaddingRight(), header.getPaddingBottom());
        header.invalidate();
    }

隱藏頭佈局得告訴父佈局頭佈局佔多大寬高

 /**
     * 通知父佈局佔多大寬高
     */
    private void measureView(View view) {
        ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
        if (layoutParams == null) {
            layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT);
        }
        int width = ViewGroup.getChildMeasureSpec(0, 0, layoutParams.width);
        int height;
        int tempHeight = layoutParams.height;
        if (tempHeight > 0) {
            // 高度不是0的時候,要填充
            height = MeasureSpec.makeMeasureSpec(tempHeight, MeasureSpec.EXACTLY);
        } else {
            // 高度是0的時候不要填充
            height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
        }
        view.measure(width, height);
    }

給佈局新增滾動事件

/**
     * 滾動事件
     *
     * @param view             當前可見的view
     * @param firstVisibleItem 當前介面第一個可見的item的位置
     * @param visibleItemCount
     * @param totalItemCount
     */
    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
                         int totalItemCount) {
        this.firstVisibleItem = firstVisibleItem;
    }

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        this.scrollState = scrollState;
    }

按下時的三個事件

 /**
     * 觸控事件
     */
    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                // 判斷介面是不是在最頂端
                if (firstVisibleItem == 0) {
                    isRemark = true;
                    startY = (int) ev.getY();
                }
                break;
            case MotionEvent.ACTION_MOVE:
                onMove(ev);
                break;
            case MotionEvent.ACTION_UP:
                if (state == RELESE) {
                    state = REFRESHING;
                    //載入最新資料
                    refreshViewByState();
                    mListener.onRefresh();
                } else if (state == PULL) {
                    state = NONE;
                    isRemark = false;
                    refreshViewByState();
                }
                break;
        }
        return super.onTouchEvent(ev);
    }

手指移動的操作

 /**
     * 判斷移動過程中的操作
     */
    private void onMove(MotionEvent ev) {
        if (!isRemark) {
            return;
        }
        //當前已經移動到什麼位置
        int tempY = (int) ev.getY();
        //手指移動的距離
        int space = tempY - startY;
        int topPadding = space - headerHeight;
        switch (state) {
            case NONE:
                if (space > 0) {
                    state = PULL;
                    refreshViewByState();
                }
                break;
            case PULL:
                topPadding(topPadding);
                if (space > headerHeight + 30 && scrollState == SCROLL_STATE_TOUCH_SCROLL) {
                    state = RELESE;
                    refreshViewByState();
                }
                break;
            case RELESE:
                topPadding(topPadding);
                if (space < headerHeight + 30) {
                    state = PULL;
                    refreshViewByState();
                } else if (space <= 0) {
                    state = NONE;
                    isRemark = false;
                    refreshViewByState();
                }
                break;
            case REFRESHING:

                break;
        }
    }

手指移動改變文字,這裡用了兩個不同的動畫用於旋轉下拉箭頭

 /**
     * 根據當前狀態改變介面顯示
     */
    private void refreshViewByState() {
        TextView textView = header.findViewById(R.id.txt_xia_la);
        ImageView imageView = header.findViewById(R.id.jian_tou);
        ProgressBar progressBar = header.findViewById(R.id.progress);

//        RotateAnimation animation1 = new RotateAnimation(0, 180,
//                RotateAnimation.RELATIVE_TO_SELF, 0.5f,
//                RotateAnimation.RELATIVE_TO_SELF, 0.5f);
//        //設定時間間隔500ms
//        animation1.setDuration(500);
//        //當它完成時將會持續動畫執行 轉換
//        animation1.setFillAfter(true);
//        RotateAnimation animation2 = new RotateAnimation(180, 0,
//                RotateAnimation.RELATIVE_TO_SELF, 0.5f,
//                RotateAnimation.RELATIVE_TO_SELF, 0.5f);
//        animation2.setDuration(500);
//        animation2.setFillAfter(true);
        switch (state) {
            case NONE:
                topPadding(-headerHeight);
                imageView.clearAnimation();
                break;
            case PULL:
                imageView.setVisibility(VISIBLE);
                progressBar.setVisibility(GONE);
                textView.setText("下拉可以重新整理");
                imageView.clearAnimation();
                break;
            case RELESE:
                imageView.setVisibility(VISIBLE);
                progressBar.setVisibility(GONE);
                textView.setText("鬆開可以重新整理");
                imageView.clearAnimation();
//                imageView.setAnimation(animation1);
                ObjectAnimator.ofFloat(imageView, "rotation",
                        0, 180F).setDuration(500).start();
                break;
            case REFRESHING:
                topPadding(headerHeight);
                imageView.setVisibility(GONE);
                progressBar.setVisibility(VISIBLE);
                textView.setText("正在重新整理");
                imageView.clearAnimation();
                break;
        }
    }

獲取完資料

 /**
     * 獲取完資料
     */
    public void refreshComplete() {
        state = NONE;
        isRemark = false;
        refreshViewByState();
        TextView textView = header.findViewById(R.id.txt_last_time);
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        Date date = new Date(System.currentTimeMillis());
        String time = format.format(date);
        textView.setText(time);
    }

設定介面給activity用於重新整理後的操作

/**
     * 重新整理資料介面
     */
    public interface RefreshListener {
        void onRefresh();
    }

    public void setInterface(RefreshListener listener) {
        this.mListener = listener;
    }

MainActivity.class

public class PullToRefreshActivity extends AppCompatActivity implements PullToRefresh.RefreshListener {

    private PullToRefresh pullToRefreshView;
    //    private PullLoadRefresh pullLoadRefresh;
    private ListView listView;
    private ArrayAdapter<String> adapter;
    String items[] = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
            "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"};

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_pull_to_refresh);

        pullToRefreshView = (PullToRefresh) findViewById(R.id.refresh_view);
//        listView = (ListView) findViewById(R.id.refresh_list);

        adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, items);
        pullToRefreshView.setAdapter(adapter);

        pullToRefreshView.setInterface(this);
    }

    @Override
    public void onRefresh() {
        //獲取最新資料
        //顯示資料
        //重新整理資料
        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                if (!pullToRefreshView.isBottom) {
                    pullToRefreshView.refreshComplete();
                } else {
                    pullToRefreshView.refreshComplete2();
                }
                ToastUtil.showToast(PullToRefreshActivity.this, "sss");
            }
        }, 2000);
    }
}
activity_pull_to_refresh.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <com.example.xingzai.firstdemo.pullToRefresh.PullToRefresh
        android:id="@+id/refresh_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <!--<ListView-->
            <!--android:id="@+id/refresh_list"-->
            <!--android:layout_width="match_parent"-->
            <!--android:layout_height="match_parent" />-->
    </com.example.xingzai.firstdemo.pullToRefresh.PullToRefresh>
</LinearLayout>

至此下拉重新整理結束。

上拉載入和下拉重新整理原理都是一樣的。

底部佈局xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="50dp">

        <LinearLayout
            android:id="@+id/layout2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:gravity="center"
            android:orientation="vertical">

            <TextView
                android:id="@+id/txt_xia_la2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="上拉載入"
                android:textSize="18sp" />

            <TextView
                android:id="@+id/txt_last_time2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="18sp" />
        </LinearLayout>

        <ImageView
            android:id="@+id/jian_tou2"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:layout_centerVertical="true"
            android:layout_marginEnd="16dp"
            android:layout_toLeftOf="@+id/layout2"
            android:src="@mipmap/down" />

        <ProgressBar
            android:id="@+id/progress2"
            android:layout_width="20dp"
            android:layout_height="20dp"
            android:layout_centerVertical="true"
            android:layout_marginEnd="16dp"
            android:layout_toLeftOf="@+id/layout"
            android:visibility="gone" />
    </RelativeLayout>
</LinearLayout>

新增底部據並隱藏

 /**
     * 底佈局
     */
    private void initFootView(Context context) {
        footer = LayoutInflater.from(context).inflate(R.layout.activity_pull_loading, null);
        measureView(footer);
        footerHeight = footer.getMeasuredHeight();
        bottomPadding(-footerHeight);
        addFooterView(footer);
        setOnScrollListener(this);
    }

設定底部下邊距

 /**
     * 設定footer下邊距
     *
     * @param bottomPadding 下邊距
     */
    private void bottomPadding(int bottomPadding) {
        footer.setPadding(footer.getPaddingLeft(), footer.getPaddingTop(),
                footer.getPaddingRight(), bottomPadding);
        footer.invalidate();
    }

在滾動事件裡面判斷是不是位於最底部

 /**
     * 滾動事件
     *
     * @param view             當前可見的view
     * @param firstVisibleItem 當前介面第一個可見的item的位置
     * @param visibleItemCount 可見item數量
     * @param totalItemCount   總item數量
     */
    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
                         int totalItemCount) {
        this.firstVisibleItem = firstVisibleItem;
        if (firstVisibleItem + visibleItemCount == totalItemCount && totalItemCount > 0) {
            isBottom = true;
        } else {
            isBottom = false;
        }
    }

觸控事件

 /**
     * 觸控事件
     */
    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                // 判斷介面是不是在最頂端
                if (firstVisibleItem == 0) {
                    isRemark = true;
                    startY = (int) ev.getY();
                }
                // 判斷介面是不是在最底端
                if (isBottom) {
                    isRemark = true;
                    startY = (int) ev.getY();
                }
                break;
            case MotionEvent.ACTION_MOVE:
                if (!isBottom) {
                    onMove(ev);
                } else {
                    onMove2(ev);
                }
                break;
            case MotionEvent.ACTION_UP:
                if (state == RELEASE) {
                    state = REFRESHING;
                    //載入最新資料
                    refreshViewByState();
                    refreshViewByState2();
                    mListener.onRefresh();
                } else if (state == PULL) {
                    state = NONE;
                    isRemark = false;
                    refreshViewByState();
                    isBottom = false;
                    refreshViewByState2();
                }
                break;
        }
        return super.onTouchEvent(ev);
    }

上拉載入的移動事件

/**
     * 判斷移動過程中的操作-上拉載入
     */
    private void onMove2(MotionEvent ev) {
        if (!isRemark) {
            return;
        }
        //當前已經移動到什麼位置
        int tempY = (int) ev.getY();
        //手指移動的距離
        int space = startY - tempY;
        int bottomPadding = space - footerHeight;
        switch (state) {
            case NONE:
                if (space > 0) {
                    state = PULL;
                    refreshViewByState2();
                }
                break;
            case PULL:
                bottomPadding(bottomPadding);
                if (space > footerHeight + 30 && scrollState == SCROLL_STATE_TOUCH_SCROLL) {
                    state = RELEASE;
                    refreshViewByState2();
                }
                break;
            case RELEASE:
                bottomPadding(bottomPadding);
                if (space < footerHeight + 30) {
                    state = PULL;
                    refreshViewByState2();
                } else if (space <= 0) {
                    state = NONE;
                    isRemark = false;
                    refreshViewByState2();
                }
                break;
            case REFRESHING:
                break;
        }
    }

上拉載入的頁面改變

 /**
     * 根據當前狀態改變介面顯示-下拉載入
     */
    private void refreshViewByState2() {
        TextView textView = footer.findViewById(R.id.txt_xia_la2);
        ImageView imageView = footer.findViewById(R.id.jian_tou2);
        ProgressBar progressBar = footer.findViewById(R.id.progress2);
        switch (state) {
            case NONE:
                bottomPadding(-footerHeight);
                imageView.clearAnimation();
                break;
            case PULL:
                imageView.setVisibility(VISIBLE);
                progressBar.setVisibility(GONE);
                textView.setText("上拉可以載入");
                imageView.clearAnimation();
                break;
            case RELEASE:
                imageView.setVisibility(VISIBLE);
                progressBar.setVisibility(GONE);
                textView.setText("鬆開可以重新整理");
                imageView.clearAnimation();
//                imageView.setAnimation(animation1);
                ObjectAnimator.ofFloat(imageView, "rotation",
                        0, 180F).setDuration(500).start();
                break;
            case REFRESHING:
                bottomPadding(footerHeight);
                imageView.setVisibility(GONE);
                progressBar.setVisibility(VISIBLE);
                textView.setText("正在重新整理");
                imageView.clearAnimation();
                break;
        }
    }

重新整理結束的顯示

/**
     * 獲取完資料-上拉載入
     */
    public void refreshComplete2() {
        state = NONE;
        isRemark = false;
        isBottom = false;
        refreshViewByState2();
        TextView textView2 = footer.findViewById(R.id.txt_last_time2);
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        Date date = new Date(System.currentTimeMillis());
        String time = format.format(date);
        textView2.setText(time);
    }

pullToRefresh完整程式碼

import android.animation.ObjectAnimator;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.example.xingzai.firstdemo.R;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Created by wwx on 2018/9/6.
 * 下拉重新整理
 */

public class PullToRefresh extends ListView implements AbsListView.OnScrollListener {

    /**
     * 頂部佈局檔案
     */
    private View header;

    /**
     * 底部據檔案
     */
    private View footer;

    /**
     * 頂部佈局檔案高度
     */
    private int headerHeight;

    /**
     * 底部佈局檔案高度
     */
    private int footerHeight;

    /**
     * 標記是否在介面上按下
     */
    private boolean isRemark;

    /**
     * 是否在底部
     */
    public boolean isBottom;

    /**
     * 按下時的Y座標值
     */
    private int startY;

    /**
     * 當前介面第一個可見的item的位置
     */
    private int firstVisibleItem;

    /**
     * 當前滾動狀態
     */
    private int scrollState;

    /**
     * 當前狀態
     */
    private int state;

    private final int NONE = 0;         //正常狀態
    private final int PULL = 1;         //下拉重新整理狀態
    private final int RELEASE = 2;       //提示釋放狀態
    private final int REFRESHING = 3;   //正在重新整理狀態

    private RefreshListener mListener;  //重新整理資料介面

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

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

    public PullToRefresh(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        initHeaderView(context);
        initFootView(context);
    }

    /**
     * 頭佈局
     */
    private void initHeaderView(Context context) {
        header = LayoutInflater.from(context).inflate(R.layout.refresh_header, null);
        measureView(header);
        headerHeight = header.getMeasuredHeight();
        topPadding(-headerHeight);
        addHeaderView(header);
        setOnScrollListener(this);
    }

    /**
     * 底佈局
     */
    private void initFootView(Context context) {
        footer = LayoutInflater.from(context).inflate(R.layout.activity_pull_loading, null);
        measureView(footer);
        footerHeight = footer.getMeasuredHeight();
        bottomPadding(-footerHeight);
        addFooterView(footer);
        setOnScrollListener(this);
    }

    /**
     * 設定header上邊距
     *
     * @param topPadding 上邊距
     */
    private void topPadding(int topPadding) {
        header.setPadding(header.getPaddingLeft(), topPadding,
                header.getPaddingRight(), header.getPaddingBottom());
        header.invalidate();
    }

    /**
     * 設定footer下邊距
     *
     * @param bottomPadding 下邊距
     */
    private void bottomPadding(int bottomPadding) {
        footer.setPadding(footer.getPaddingLeft(), footer.getPaddingTop(),
                footer.getPaddingRight(), bottomPadding);
        footer.invalidate();
    }

    /**
     * 通知父佈局佔多大寬高
     */
    private void measureView(View view) {
        ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
        if (layoutParams == null) {
            layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT);
        }
        int width = ViewGroup.getChildMeasureSpec(0, 0, layoutParams.width);
        int height;
        int tempHeight = layoutParams.height;
        if (tempHeight > 0) {
            // 高度不是0的時候,要填充
            height = MeasureSpec.makeMeasureSpec(tempHeight, MeasureSpec.EXACTLY);
        } else {
            // 高度是0的時候不要填充
            height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
        }
        view.measure(width, height);
    }

    /**
     * 滾動事件
     *
     * @param view             當前可見的view
     * @param firstVisibleItem 當前介面第一個可見的item的位置
     * @param visibleItemCount 可見item數量
     * @param totalItemCount   總item數量
     */
    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
                         int totalItemCount) {
        this.firstVisibleItem = firstVisibleItem;
        if (firstVisibleItem + visibleItemCount == totalItemCount && totalItemCount > 0) {
            isBottom = true;
        } else {
            isBottom = false;
        }
    }

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        this.scrollState = scrollState;
    }

    /**
     * 觸控事件
     */
    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                // 判斷介面是不是在最頂端
                if (firstVisibleItem == 0) {
                    isRemark = true;
                    startY = (int) ev.getY();
                }
                // 判斷介面是不是在最底端
                if (isBottom) {
                    isRemark = true;
                    startY = (int) ev.getY();
                }
                break;
            case MotionEvent.ACTION_MOVE:
                if (!isBottom) {
                    onMove(ev);
                } else {
                    onMove2(ev);
                }
                break;
            case MotionEvent.ACTION_UP:
                if (state == RELEASE) {
                    state = REFRESHING;
                    //載入最新資料
                    refreshViewByState();
                    refreshViewByState2();
                    mListener.onRefresh();
                } else if (state == PULL) {
                    state = NONE;
                    isRemark = false;
                    refreshViewByState();
                    isBottom = false;
                    refreshViewByState2();
                }
                break;
        }
        return super.onTouchEvent(ev);
    }

    /**
     * 判斷移動過程中的操作-下拉重新整理
     */
    private void onMove(MotionEvent ev) {
        if (!isRemark) {
            return;
        }
        //當前已經移動到什麼位置
        int tempY = (int) ev.getY();
        //手指移動的距離
        int space = tempY - startY;
        int topPadding = space - headerHeight;
        switch (state) {
            case NONE:
                if (space > 0) {
                    state = PULL;
                    refreshViewByState();
                }
                break;
            case PULL:
                topPadding(topPadding);
                if (space > headerHeight + 30 && scrollState == SCROLL_STATE_TOUCH_SCROLL) {
                    state = RELEASE;
                    refreshViewByState();
                }
                break;
            case RELEASE:
                topPadding(topPadding);
                if (space < headerHeight + 30) {
                    state = PULL;
                    refreshViewByState();
                } else if (space <= 0) {
                    state = NONE;
                    isRemark = false;
                    refreshViewByState();
                }
                break;
            case REFRESHING:
                break;
        }
    }

    /**
     * 判斷移動過程中的操作-上拉載入
     */
    private void onMove2(MotionEvent ev) {
        if (!isRemark) {
            return;
        }
        //當前已經移動到什麼位置
        int tempY = (int) ev.getY();
        //手指移動的距離
        int space = startY - tempY;
        int bottomPadding = space - footerHeight;
        switch (state) {
            case NONE:
                if (space > 0) {
                    state = PULL;
                    refreshViewByState2();
                }
                break;
            case PULL:
                bottomPadding(bottomPadding);
                if (space > footerHeight + 30 && scrollState == SCROLL_STATE_TOUCH_SCROLL) {
                    state = RELEASE;
                    refreshViewByState2();
                }
                break;
            case RELEASE:
                bottomPadding(bottomPadding);
                if (space < footerHeight + 30) {
                    state = PULL;
                    refreshViewByState2();
                } else if (space <= 0) {
                    state = NONE;
                    isRemark = false;
                    refreshViewByState2();
                }
                break;
            case REFRESHING:
                break;
        }
    }

    /**
     * 根據當前狀態改變介面顯示-上拉重新整理
     */
    private void refreshViewByState() {
        TextView textView = header.findViewById(R.id.txt_xia_la);
        ImageView imageView = header.findViewById(R.id.jian_tou);
        ProgressBar progressBar = header.findViewById(R.id.progress);

        RotateAnimation animation1 = new RotateAnimation(0, 180,
                RotateAnimation.RELATIVE_TO_SELF, 0.5f,
                RotateAnimation.RELATIVE_TO_SELF, 0.5f);
        //設定時間間隔500ms
        animation1.setDuration(500);
        //當它完成時將會持續動畫執行 轉換
        animation1.setFillAfter(true);
        RotateAnimation animation2 = new RotateAnimation(180, 0,
                RotateAnimation.RELATIVE_TO_SELF, 0.5f,
                RotateAnimation.RELATIVE_TO_SELF, 0.5f);
        animation2.setDuration(500);
        animation2.setFillAfter(true);
        switch (state) {
            case NONE:
                topPadding(-headerHeight);
                imageView.clearAnimation();
                break;
            case PULL:
                imageView.setVisibility(VISIBLE);
                progressBar.setVisibility(GONE);
                textView.setText("下拉可以重新整理");
                imageView.clearAnimation();
                imageView.setAnimation(animation1);
                break;
            case RELEASE:
                imageView.setVisibility(VISIBLE);
                progressBar.setVisibility(GONE);
                textView.setText("鬆開可以重新整理");
                imageView.clearAnimation();
                imageView.setAnimation(animation2);
//                ObjectAnimator.ofFloat(imageView, "rotation",
//                        0, 180F).setDuration(500).start();
                break;
            case REFRESHING:
                topPadding(headerHeight);
                imageView.setVisibility(GONE);
                progressBar.setVisibility(VISIBLE);
                textView.setText("正在重新整理");
                imageView.clearAnimation();
                break;
        }
    }

    /**
     * 根據當前狀態改變介面顯示-下拉載入
     */
    private void refreshViewByState2() {
        TextView textView = footer.findViewById(R.id.txt_xia_la2);
        ImageView imageView = footer.findViewById(R.id.jian_tou2);
        ProgressBar progressBar = footer.findViewById(R.id.progress2);
        switch (state) {
            case NONE:
                bottomPadding(-footerHeight);
                imageView.clearAnimation();
                break;
            case PULL:
                imageView.setVisibility(VISIBLE);
                progressBar.setVisibility(GONE);
                textView.setText("上拉可以載入");
                imageView.clearAnimation();
                break;
            case RELEASE:
                imageView.setVisibility(VISIBLE);
                progressBar.setVisibility(GONE);
                textView.setText("鬆開可以重新整理");
                imageView.clearAnimation();
//                imageView.setAnimation(animation1);
                ObjectAnimator.ofFloat(imageView, "rotation",
                        0, 180F).setDuration(500).start();
                break;
            case REFRESHING:
                bottomPadding(footerHeight);
                imageView.setVisibility(GONE);
                progressBar.setVisibility(VISIBLE);
                textView.setText("正在重新整理");
                imageView.clearAnimation();
                break;
        }
    }

    /**
     * 獲取完資料-下拉重新整理
     */
    public void refreshComplete() {
        state = NONE;
        isRemark = false;
        refreshViewByState();
        TextView textView = header.findViewById(R.id.txt_last_time);
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        Date date = new Date(System.currentTimeMillis());
        String time = format.format(date);
        textView.setText(time);
    }

    /**
     * 獲取完資料-上拉載入
     */
    public void refreshComplete2() {
        state = NONE;
        isRemark = false;
        isBottom = false;
        refreshViewByState2();
        TextView textView2 = footer.findViewById(R.id.txt_last_time2);
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        Date date = new Date(System.currentTimeMillis());
        String time = format.format(date);
        textView2.setText(time);
    }

    /**
     * 重新整理資料介面
     */
    public interface RefreshListener {
        void onRefresh();
    }

    public void setInterface(RefreshListener listener) {
        this.mListener = listener;
    }
}

至此,下拉重新整理和上拉載入全部完成。