多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php開源 > 綜合技術 > RecyclerView學習(五)----SwipeRefreshLayout的下拉刷新與上拉加載

RecyclerView學習(五)----SwipeRefreshLayout的下拉刷新與上拉加載

來源:程序員人生   發布時間:2017-03-24 09:24:11 閱讀次數:4141次

SwipeRefreshLayout作為官方的下拉刷新控件,簡潔美觀的風格使其廣泛利用在項目中。美中不足的是SwipeRefreshLayout缺少上拉加載的效果,今天結合RecyclerView實現1個支持下拉刷新與上拉加載的SwipeRefreshLayout。

先看1下最后實現的效果圖:

這里寫圖片描述

整體效果如上所示,1起看看怎樣實現的:

1.準備工作

1.加載動畫實現:
示例圖中,上拉加載的進度動畫是1個自定義的View,這里側重分析1下實現方法,源碼末尾會給出:

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        canvas.translate(mWidth / 2, mHeight / 2);
        mPaint.setStyle(Paint.Style.FILL);
        canvas.rotate(degree);
        for (int i = 0; i < 12; i++) {
            if (i == 0 || i == 1 || i == 2) {
                mPaint.setColor(Color.GRAY);
            } else {
                mPaint.setColor(Color.LTGRAY);
            }
            RectF rectF = new RectF(-mRadius / 4, -mRadius * 7 / 2, mRadius / 4, -mRadius * 2);
            canvas.drawRoundRect(rectF, mRadius / 8, mRadius / 8, mPaint);
            canvas.rotate(30);
            canvas.save();
        }
        canvas.restore();
    }

主要是畫布的1些操作,移動原點到中心,繪制圓角矩形,旋轉畫布,動畫效果是通過屬性動畫實現的:

    public void startAnimation() {

        degree = 0;
        degreeAnimation = ValueAnimator.ofFloat(0, 360);
        degreeAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                degree = (float) animation.getAnimatedValue();
                invalidate();
            }

        });
        degreeAnimation.setRepeatCount(ValueAnimator.INFINITE);
        degreeAnimation.setDuration(1000);
        degreeAnimation.start();
    }

    public void endAnimation() {
        degreeAnimation.end();
    }

    @Override
    public void onWindowFocusChanged(boolean hasWindowFocus) {
        super.onWindowFocusChanged(hasWindowFocus);
        if (!hasWindowFocus) {
            endAnimation();
        }
    }

需要注意的是,使用循環動畫時記得調用onWindowFocusChanged()方法來及時結束動畫。這是由于退出當前Activity或將當前Activity切入后臺時,如果沒有結束動畫,可能會致使Activity沒法釋放從而致使內存泄漏。

關于更多的自定義加載動畫,可以參考我這篇博客:

Android自定義加載動畫(延續更新中…)

2.上拉加載View的顯示:

ListView有直接添加頭部View與尾部View的方法,RecyclerView沒有直接提供這兩個方法,那我們上拉加載View放在哪里呢?處理方法是重寫RecyclerView.Adapter的 getItemViewType(int position)方法,根據getItemViewType傳入的viewType來返回不同類型的ViewHolder。不同的位置返回不同的類型,把最后1個位置預留出來,用來寄存加載更多的view。

關于這1塊的內容,可以參考我這篇博客:

RecyclerView學習(1)—-初步認知

2.下拉刷新的實現

        swipeRefreshLayout.post(new Runnable() {
            @Override
            public void run() {
                swipeRefreshLayout.setRefreshing(true);
            }
        });
        refresh();

        swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                refresh();
            }
        });

    private void refresh() {
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                getData();
                recyclerView.setAdapter(myAdapter);
                myAdapter.notifyDataSetChanged();
                swipeRefreshLayout.setRefreshing(false);
            }
        }, 1500);
    }

SwipeRefreshLayout的基本用法,這里有1點要注意的就是SwipeRefreshLayout進入頁面時自動刷新。直接使用 swipeRefreshLayout.setRefreshing(true)方法沒有效果,得像上面那樣設置才會有效果。

3.上拉加載的實現

    public class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {

        @Override
        public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

            View rootView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_refresh_recycler, parent, false);

            return new MyViewHolder(rootView);
        }

        @Override
        public void onBindViewHolder(MyViewHolder holder, int position) {
            holder.txt.setText(integerList.get(position));
        }

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

    public class MyViewHolder extends RecyclerView.ViewHolder {
        TextView txt;

        public MyViewHolder(View itemView) {
            super(itemView);
            txt = (TextView) itemView.findViewById(R.id.item_txt);
        }
    }

這是支持下拉刷新下RecyclerView的adapter,上面我們分析到,需要重寫 getItemViewType(int position)方法來寄存上拉加載View。那我們需要修改getItemViewType(),onCreateViewHolder(),onBindViewHolder(),getItemCount()等方法,并對viewType進行判斷。那末如何在不破壞原有Adapter實現的情況下完成呢?

這里引入裝潢器(Decorator)設計模式,該設計模式通過組合的方式,在不 破壞原有類代碼的情況下,對原有類的功能進行擴大。

參考資料:
RecyclerView 必知必會

看看怎樣實現的:

public class MyRefreshAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {


    private RecyclerView.Adapter adapter;
    private View footerView;
    public static final int NORMAL_VIEW_TYPE = 1;
    public static final int FOOTER_VIEW_TYPE = 2;

    public MyRefreshAdapter(RecyclerView.Adapter adapter) {
        this.adapter = adapter;
    }


    @Override
    public int getItemViewType(int position) {
        if (position == getItemCount() - 1) {
            return FOOTER_VIEW_TYPE;
        }
        return NORMAL_VIEW_TYPE;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == FOOTER_VIEW_TYPE) {
            return new RecyclerView.ViewHolder(footerView) {
            };
        } else {
            return adapter.onCreateViewHolder(parent, viewType);
        }
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if (position == getItemCount() - 1) {
            return;
        } else {
            adapter.onBindViewHolder(holder, position);
        }

    }

    @Override
    public int getItemCount() {
        return adapter.getItemCount() + 1;

    }

    public void addFooterView(View footerView) {
        this.footerView = footerView;
    }
}

getItemViewType()用于決定元素的布局使用哪一種類型,返回的是1個int值作為傳遞給onCreateViewHolder的第2個參數;onCreateViewHolder根據getItemViewType傳入的viewType來渲染構造不同的ViewHolder;ViewHolder用來寄存視圖與數據,通過返回不同類型的ViewHolder到達預期效果。

上拉加載view已找到寄存的地方,甚么時候顯示呢?

我這里的處理方法是自定義1個RecyclerView,添加滑動監聽,當滑動到底部時進行處理:

        this.addOnScrollListener(new OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                LinearLayoutManager manager = (LinearLayoutManager) recyclerView.getLayoutManager();
                //停止轉動時
                if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                    //獲得最后1個完全顯示Item的Position
                    int lastVisibleItem = manager.findLastCompletelyVisibleItemPosition();
                    int totalItemCount = manager.getItemCount();
                    // 判斷是不是轉動到底部,并且不在加載狀態
                    if (lastVisibleItem == (totalItemCount - 1) && !isLoadMore) {
                        isLoadMore = true;
                        loadTxt.setText("正在加載...");
                        circleProgressView.setVisibility(VISIBLE);
                        footerView.setVisibility(VISIBLE);
                        myLoadListener.onLoadMore();
                    }
                }
            }

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
            }
        });

當RecyclerView停止轉動時,獲得最后1個完全顯示Item的Position,判斷是不是轉動到底部,并且不在加載狀態,符合條件的情況就接口回調加載數據。

    public interface MyLoadListener {
        void onLoadMore();
    }

重寫setAdapter()方法,這樣我們的MyRefreshAdapter便能發揮它的功能:

    @Override
    public void setAdapter(Adapter adapter) {

        LinearLayout footerLayout = new LinearLayout(getContext());
        footerLayout.setGravity(Gravity.CENTER);
        footerLayout.setLayoutParams(new ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT, 160));

        circleProgressView = new CircleProgressView(getContext());
        circleProgressView.setLayoutParams(new LinearLayout.LayoutParams(80, 80));
        circleProgressView.startAnimation();
        footerLayout.addView(circleProgressView);
        loadTxt = new TextView(getContext());
        footerLayout.addView(loadTxt);
        footerView = footerLayout;
        footerView.setVisibility(GONE);
        myRefreshAdapter = new MyRefreshAdapter(adapter);
        myRefreshAdapter.addFooterView(footerView);
        super.setAdapter(myRefreshAdapter);
    }

動態添加上拉加載view,調用myRefreshAdapter.addFooterView()方法添加進去。Activity中使用:

MyAdapter myAdapter = new MyAdapter();
recyclerView.setAdapter(myAdapter);

       recyclerView.setMyLoadListener(new MyRefreshRecyclerView.MyLoadListener() {
            @Override
            public void onLoadMore() {
                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        if (integerList.size() > 14) {
                            recyclerView.setLoadMore(true);
                        } else {
                            int randomInt = new Random().nextInt(100);
                            integerList.add("上拉加載添加數字:" + randomInt);
                            myAdapter.notifyDataSetChanged();
                            recyclerView.setLoadMore(false);
                        }

                    }
                }, 1000);
            }
        });

額外在自定義的recyclerView中添加了1個判斷是不是加載完成的方法:

    public void setLoadMore(boolean complete) {
        if (complete) {
            loadTxt.setText("已全部加載完啦!");
            circleProgressView.setVisibility(GONE);
        } else {
            footerView.setVisibility(GONE);
        }
        isLoadMore = false;
    }

這樣,1個完全的下拉刷新與上拉加載就已完成了,希望看完本篇文章能對你有所幫助。

項目完全源碼已上傳到我的github上,源碼地址:

https://github.com/18722527635/MyRecyclerView

歡迎Star,fork,提issues,1起進步!

生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 欧美性高清video | 欧美性一区 | 国产精品jizz在线观看软件 | 五月天校园春色 | 亚洲综合片 | 成人区视频 | 欧美一区二区精品系列在线观看 | 久久性妇女精品免费 | 网友自拍视频悠悠在线 | 在线观看欧美亚洲 | 亚洲第一网站免费视频 | 欧乱色国产精品兔费视频 | 欧美精品黑人性xxxx | 最新中文字幕乱码在线 | 老女人做爰免费的视频 | 最好的中文字幕2018免费视频 | 亚州一二区 | 国产福利第一页 | 国精品日韩欧美一区二区三区 | 黄色福利网| 最近中文字幕无免费视频 | www.日本高清视频 | 久久久久久久综合 | 久久在精品线影院精品国产 | 久久久免费精品视频 | 色婷婷影院在线视频免费播放 | 日本不卡网 | 美国私人vps一夜爽毛片免费 | 伊人猫咪| 秋霞特色aa大片在线观看 | 图片区 小说区 | 在线观看视频高清视频 | 国产精品日产三级在线观看 | 欧美一欧美一区二三区性 | 日本资源在线 | 宇都宫紫苑野外中文字幕 | 亚洲一区精品伊人久久伊人 | 国产1区2区3区 | 免费看国产精品久久久久 | 亚洲精品国产成人99久久 | 今天免费中文字幕视频 |