Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 自定義RecycleView實現下拉刷新和上拉刷新

自定義RecycleView實現下拉刷新和上拉刷新

編輯:關於Android編程

MyRecycleView

package com.jiketuandui.antinetfraud.View;

import android.animation.ValueAnimator;
import android.content.Context;
import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.jiketuandui.antinetfraud.Adapter.MyWrapAdapter;
import com.jiketuandui.antinetfraud.R;

import java.util.ArrayList;

/**
 * Created by Notzuonotdied on 2016/9/3.
 * 自定義RecycleView實現下拉刷新和上拉刷新
 */
public class MyRecycleView extends RecyclerView {
    /**
     * 正在刷新
     */
    public final static int STATE_REFRESHING = 2;
    /**
     * 下拉刷新
     */
    private final static int STATE_NORMAL = 0;
    /**
     * 松開刷新
     */
    private final static int STATE_READY = 1;
    /**
     * 判斷用戶是否觸摸屏幕
     */
    boolean isOnTouching;
    /**
     * 判斷是否需要進行刷新
     */
    boolean isRefresh;
    /**
     * 判斷是否需要加載更多
     */
    boolean isLoadMore;
    /**
     * 拖動後X的最後位置
     */
    int lastX;
    /**
     * 拖動後Y的最後位置
     */
    int lastY;
    /**
     * 定義頭部的View
     */
    View headerView;
    /**
     * 定義尾部的View
     */
    View footerView;
    /**
     * 頭部的View的高度
     */
    int headerViewHeight;
    /**
     * 設置響應事件
     */
    private MyRecycleViewListener myRecycleViewListener;
    /**
     * 默認的狀態
     */
    private int mState = STATE_NORMAL;
    /**
     * 顯示文本信息的TextView
     */
    private TextView status;
    /**
     * 用於顯示頭部和尾部item的adapter
     */
    MyWrapAdapter myWrapAdapter;
    private String[] textViewString = {"松開刷新...", "下拉刷新...", "正在刷新..."};

    /**
     * Instantiates a new My recycle view.
     *
     * @param context the context
     */
    public MyRecycleView(Context context) {
        super(context);
    }

    /**
     * Instantiates a new My recycle view.
     *
     * @param context the context
     * @param attrs   the attrs
     */
    public MyRecycleView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    /**
     * Instantiates a new My recycle view.
     *
     * @param context  the context
     * @param attrs    the attrs
     * @param defStyle the def style
     */
    public MyRecycleView(Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    /**
     * On status change.
     *
     * @param status the status
     */
    public void onStatusChange(int status) {
        mState = status;
        switch (status) {
            case STATE_READY:
                this.status.setText(textViewString[STATE_READY]);
                break;
            case STATE_NORMAL:
                this.status.setText(textViewString[STATE_NORMAL]);
                break;
            case STATE_REFRESHING:
                this.status.setText(textViewString[STATE_REFRESHING]);
                if (myRecycleViewListener != null) {
                    myRecycleViewListener.onRefresh();
                }
                break;
        }
    }

    /**
     * Gets my recycle view listener.
     *
     * @return the my recycle view listener
     */
    public MyRecycleViewListener getMyRecycleViewListener() {
        return myRecycleViewListener;
    }

    /**
     * Sets my recycle view listener.
     *
     * @param myRecycleViewListener the my recycle view listener
     */
    public void setMyRecycleViewListener(MyRecycleViewListener myRecycleViewListener) {
        this.myRecycleViewListener = myRecycleViewListener;
    }

    @Override
    public boolean onTouchEvent(MotionEvent e) {
        int x = (int) e.getX();
        int y = (int) e.getY();

        switch (e.getAction()) {
            case MotionEvent.ACTION_DOWN:
                isOnTouching = true;
                break;
            case MotionEvent.ACTION_MOVE:
                // 判斷是否滑動到了頭部
                if (!canScrollVertically(-1)) {
                    if (Math.abs(lastY - y) > Math.abs(lastX - x)) {
                        isRefresh = true;
                        changeHeight(lastY - y);
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                isRefresh = false;
                isOnTouching = false;
                if (mState == STATE_READY) {
                    onStatusChange(STATE_REFRESHING);
                }
                autoSize();
                break;
        }
        lastX = x;
        lastY = y;

        return super.onTouchEvent(e);
    }

    /**
     * 下拉刷新拖動的屬性動畫效果
     * */
    private void autoSize() {
        // 當前的高度
        int currentHeight = headerView.getHeight();
        // View拖動後所在的高度
        int targetHeight = headerViewHeight;

        if (mState == STATE_READY || mState == STATE_REFRESHING) {
            targetHeight = headerViewHeight * 2;
        }

        if (mState == STATE_REFRESHING) {
            if (currentHeight < headerViewHeight * 2) {
                return;
            }
        }
        // 屬性動畫
        ValueAnimator valueAnimator = ValueAnimator.ofInt(currentHeight, targetHeight);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {

                int animateValue = (int) valueAnimator.getAnimatedValue();
                setStateByHeight(animateValue, true);
                headerView.getLayoutParams().height = animateValue;
                headerView.requestLayout();
            }
        });
        valueAnimator.start();
    }

    @Override
    public void setLayoutManager(LayoutManager layout) {
        super.setLayoutManager(layout);

        this.addOnScrollListener(new OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);

                if (isRefresh) {
                    return;
                }

                if (mState != STATE_NORMAL) {
                    return;
                }

                // 判斷是否是最後一個item
                LayoutManager layoutManager = getLayoutManager();

                // 可見的item數目
                int visibleChildCount = layoutManager.getChildCount();
                if (visibleChildCount > 0 && newState == RecyclerView.SCROLL_STATE_IDLE
                        && !isLoadMore) {
                    View lastVisibleView = recyclerView.getChildAt(recyclerView.getChildCount() - 1);
                    int lastVisiblePosition = recyclerView.getChildLayoutPosition(lastVisibleView);
                    if (lastVisiblePosition >= layoutManager.getItemCount() - 1) {
                        footerView.setVisibility(VISIBLE);
                        isLoadMore = true;
                        if (myRecycleViewListener != null) {
                            myRecycleViewListener.onLoadMore();
                        } else {
                            footerView.setVisibility(GONE);
                        }
                    }
                }
            }
        });
    }

    /**
     * 回拉效果
     * */
    private void changeHeight(int changeHeight) {
        headerView.getLayoutParams().height -= changeHeight;
        headerView.requestLayout();
        setStateByHeight(headerView.getHeight(), false);
    }

    /**
     * 根據拖動的高度進行判斷做出相應的響應
     * */
    private void setStateByHeight(int height, boolean isAuto) {
        if (mState == STATE_REFRESHING) {
            return;
        }

        if (height - headerViewHeight < headerViewHeight) {
            onStatusChange(STATE_NORMAL);
        } else if (height - headerViewHeight > headerViewHeight) {
            onStatusChange(STATE_READY);
        } else if (height - headerViewHeight == headerViewHeight &&
                !isOnTouching && !isAuto) {
            onStatusChange(STATE_REFRESHING);
        }
    }

    @Override
    public void setAdapter(Adapter adapter) {
        ArrayList headers = new ArrayList<>();
        ArrayList footers = new ArrayList<>();
        /**
         * 頭部
         * */
        View refreshView = LayoutInflater.from(getContext()).inflate(R.layout.my_refresh, null);
        headerView = refreshView;
        RelativeLayout headerLayout = new RelativeLayout(getContext());
        headerLayout.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.WRAP_CONTENT));
        headerLayout.addView(headerView, RelativeLayout.LayoutParams.MATCH_PARENT,
                RelativeLayout.LayoutParams.WRAP_CONTENT);
        headerLayout.setGravity(Gravity.BOTTOM);

        status = (TextView) refreshView.findViewById(R.id.status);
        // 內部更新UI
        headerView.post(new Runnable() {
            @Override
            public void run() {
                headerViewHeight = headerView.getHeight();
                RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams)
                        headerView.getLayoutParams();
                lp.setMargins(0, -headerViewHeight, 0, 0);
                headerView.requestLayout();
            }
        });
        headers.add(headerLayout);

        /**
         * 尾部
         * */
        LinearLayout footerLayout = new LinearLayout(getContext());
        footerLayout.setGravity(Gravity.CENTER);
        footerLayout.setLayoutParams(new ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
        footers.add(footerLayout);
        footerLayout.setPadding(0, 15, 0, 15);
        footerLayout.addView(new ProgressBar(getContext(), null, android.R.attr.progressBarStyleSmall));

        TextView text = new TextView(getContext());
        text.setText("正在加載...");
        footerLayout.addView(text);
        footerView = footerLayout;
        footerView.setVisibility(GONE);

        myWrapAdapter = new MyWrapAdapter(adapter, headers, footers);

        super.setAdapter(myWrapAdapter);
    }

    /**
     * Sets load more complete.
     */
    public void setLoadMoreComplete() {
        footerView.setVisibility(GONE);
        isLoadMore = false;
    }

    /**
     * Sets refresh complete.
     */
    public void setRefreshComplete() {
        onStatusChange(STATE_NORMAL);
        autoSize();
    }

    /**
     * 對外接口
     */
    public interface MyRecycleViewListener {
        /**
         * On refresh.
         */
        void onRefresh();

        /**
         * On load more.
         */
        void onLoadMore();
    }
}

MyWrapAdapter

package com.jiketuandui.antinetfraud.Adapter;

import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;

import java.util.ArrayList;

/**
 * 實現顯示頭部和尾部item的adapter,把頭部尾部的事情交給這個adapter來做,其他的交給子adapter
 */
public class MyWrapAdapter extends RecyclerView.Adapter {

    public ArrayList headerViews = new ArrayList<>();
    public ArrayList footViews = new ArrayList<>();
    public RecyclerView.Adapter adapter;

    public MyWrapAdapter(RecyclerView.Adapter adapter, ArrayList headerViews, ArrayList footViews) {
        this.adapter = adapter;
        this.headerViews = headerViews;
        this.footViews = footViews;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == RecyclerView.INVALID_TYPE) {
            //頭部item
            return new RecyclerView.ViewHolder(headerViews.get(0)) {

            };
        } else if (viewType == (RecyclerView.INVALID_TYPE - 1)) {
            //尾部item
            return new RecyclerView.ViewHolder(footViews.get(0)) {

            };
        }
        return adapter.onCreateViewHolder(parent, viewType);
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if (position >= 0 && position < headerViews.size()) {
            return;
        }

        if (adapter != null) {
            int p = position - headerViews.size();
            if (p < adapter.getItemCount()) {
                adapter.onBindViewHolder(holder, p);
            }
        }
    }

    @Override
    public int getItemViewType(int position) {
        if (position >= 0 && position < headerViews.size()) {
            //如果是頭部則返回一個不可用的標識,表示這是頭部item
            return RecyclerView.INVALID_TYPE;
        }

        if (adapter != null) {
            int p = position - headerViews.size();
            if (p < adapter.getItemCount()) {
                return adapter.getItemViewType(p);
            }
        }

        return RecyclerView.INVALID_TYPE - 1;//默認返回表示是尾部的item
    }

    @Override
    public int getItemCount() {
        return getCount();
    }

    public int getCount() {
        int count = headerViews.size() + footViews.size();
        if (adapter != null) {
            count += adapter.getItemCount();
        }
        return count;
    }

}

MyItemDecoration

package com.jiketuandui.antinetfraud.Adapter;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.support.v7.widget.RecyclerView;
import android.view.View;

/**
 * Created by baoyunlong
 * 這個是用來更改Item的顯示效果的,修改onDraw即可
 */
public class MyItemDecoration extends RecyclerView.ItemDecoration {
    private int size = 2;

    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        super.onDraw(c, parent, state);

        int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            View child = parent.getChildAt(i);

            Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
            paint.setColor(Color.parseColor("#eeeeee"));
            paint.setStyle(Paint.Style.FILL);
            paint.setStrokeWidth(2);

            int startY = child.getTop() - size;
            int startX = child.getLeft();
            int endY = child.getTop() - size;
            int enx = child.getRight();
            c.drawLine(startX, startY, enx, endY, paint);
        }

    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {

        outRect.set(0, size, 0, 0);

    }
}

my_refresh.xml




    

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved