RecylerView下拉刷新与上拉加载(二)

效果图:

此篇博客是在上一篇: Recylerview上拉加载与下拉刷新(一)的升级版,如果有不清楚先看 Recylerview上拉加载与下拉刷新(一)

(p.s. 这是我正在写的一个毕业设计,前端App使用Rxjava + Retrofit  + EventBus; Java后台是 SSM

github地址:https://github.com/uweii/SHShop  每天都会更新代码)

1)上拉加载:

定义一个footview.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="40dp"
    android:layout_marginBottom="20dp">
    <View
        android:layout_width="0dp"
        android:layout_centerHorizontal="true"
        android:layout_height="0dp"
        android:id="@+id/tv_center"/>
    <ImageView
        android:layout_toLeftOf="@id/tv_center"
        android:layout_width="wrap_content"
        android:id="@+id/iv_loading"
        android:layout_centerVertical="true"
        android:layout_height="wrap_content"
        android:src="@drawable/load_mini"/>
    <TextView
        android:layout_toRightOf="@id/tv_center"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@color/search_hint"
        android:layout_centerVertical="true"
        android:layout_gravity="center_vertical"
        android:gravity="left|center_vertical"
        android:text="加载中..."/>
</RelativeLayout>

adapter:

package com.up.uwei.shshop.adapter;

import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
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.DecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import android.widget.ImageView;
import android.widget.TextView;

import com.squareup.picasso.Callback;
import com.squareup.picasso.Picasso;
import com.up.uwei.shshop.Configs;
import com.up.uwei.shshop.R;
import com.up.uwei.shshop.activity.GoodsDetailActivity;
import com.up.uwei.shshop.activity.RegActivity;
import com.up.uwei.shshop.fragment.ShopFragment;
import com.up.uwei.shshop.pojo.Goods;

import java.util.ArrayList;

public class ShopRecylerViewAdapter extends RecyclerView.Adapter {
    private int FOOTVIEW = 1;
    private int NORMALVIEW = 2;
    private ArrayList<Goods> mGoods = new ArrayList<>();
    private Context mContext;
    private Animation mAnimation ;
    public ShopRecylerViewAdapter(Context context){
        this.mContext = context;
        mAnimation = AnimationUtils.loadAnimation(context, R.anim.loading_anim);
        DecelerateInterpolator di = new DecelerateInterpolator();
        mAnimation.setInterpolator(di);
    }


    public ArrayList<Goods> getGoods() {
        return mGoods;
    }

    public void setGoods(ArrayList<Goods> goods) {
        mGoods = goods;
    }

    public void cleanGoods() {
        mGoods.clear();
    }

    public void addGoods(ArrayList<Goods> goods){
        mGoods.addAll(goods);
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
        if(viewType == NORMALVIEW){
            View   v = inflater.inflate(R.layout.item_shop,parent,false);
            return new ShopHolder(v);
        }else {
            View  v = inflater.inflate(R.layout.foot_view, parent, false);
            return new FootHolder(v);
        }
    }

    @Override
    public int getItemViewType(int position) {
        if (position +1 == getItemCount()){  //如果position到了最后一个显示 footview
            return FOOTVIEW;
        }else {
            return NORMALVIEW;
        }
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        if(holder instanceof  ShopHolder){
            ShopHolder hold = (ShopHolder) holder;
            Goods goods = mGoods.get(position);
            String[] imgs =  Configs.getImgs(goods.getImgs());
            String tag = Configs.getTag(goods.getTag());
            Picasso.with(holder.itemView.getContext()).load(Configs.BASE_URL + "/images/" + (imgs == null? "":imgs[0])).placeholder(R.drawable.placeholder).error(R.drawable.load_error).fit().into(((ShopHolder) holder).iv_photo);
            hold.tv_name.setText(goods.getName());
            hold.tv_tag.setText(tag);
            hold.tv_place.setText(goods.getPlace());
            hold.tv_price.setText("¥"+goods.getPrice());
            hold.tv_saleCount.setText(goods.getSalecount() + "人付款");
            hold.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Intent intent = new Intent(mContext, GoodsDetailActivity.class);
                    mContext.startActivity(intent);

                }
            });
        }else {
            //为Recylerview所在的fragment.java设置回调方法,用来控制footview的显示隐藏
            FootHolder h = (FootHolder) holder;
            ShopFragment.CallBack callBack = new ShopFragment.CallBack() {
                @Override
                public void onDismiss() {
                    holder.itemView.setVisibility(View.INVISIBLE);
                    h.mLoading.clearAnimation();
                }

                @Override
                public void onShow() {
                    holder.itemView.setVisibility(View.VISIBLE);
                    h.mLoading.startAnimation(mAnimation);
                }
            };
            ShopFragment.setMyCallBack(callBack);
        }
    }

    @Override
    public int getItemCount() {  //因为多了一个footview,所以在原来基础上加一
        return mGoods.size() + 1;
    }
    //正常商品holder
    class ShopHolder extends RecyclerView.ViewHolder{
        TextView tv_name, tv_price, tv_place, tv_tag, tv_saleCount;
        ImageView iv_photo;
        public ShopHolder(View itemView) {
            super(itemView);
            iv_photo = itemView.findViewById(R.id.iv_photo);
            tv_name = itemView.findViewById(R.id.tv_name);
            tv_tag = itemView.findViewById(R.id.tv_tag);
            tv_place = itemView.findViewById(R.id.tv_college);
            tv_price = itemView.findViewById(R.id.tv_price);
            tv_saleCount = itemView.findViewById(R.id.tv_saleCount);
           // tv_name = itemView.findViewByI
        }
    }
    //底部加载holder
    class FootHolder extends RecyclerView.ViewHolder{
        public TextView mTextView;
        public ImageView mLoading;
        public FootHolder(View itemView) {
            super(itemView);
            mLoading = itemView.findViewById(R.id.iv_loading);
        }
    }
}

fragment.java

package com.up.uwei.shshop.fragment;

import android.content.Intent;
import android.graphics.LinearGradient;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.Fragment;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.up.uwei.shshop.BaseFragment;
import com.up.uwei.shshop.Configs;
import com.up.uwei.shshop.R;
import com.up.uwei.shshop.activity.SearchActivity;
import com.up.uwei.shshop.adapter.ShopRecylerViewAdapter;
import com.up.uwei.shshop.event.Event;
import com.up.uwei.shshop.pojo.Goods;
import com.up.uwei.shshop.pojo.SearchBean;
import com.up.uwei.shshop.service.RetrofitService;
import com.up.uwei.shshop.utils.LogUtil;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.w3c.dom.Text;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Timer;
import java.util.TimerTask;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.Unbinder;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import okhttp3.ResponseBody;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

import static android.view.View.VISIBLE;

public class ShopFragment extends BaseFragment implements SwipeRefreshLayout.OnRefreshListener {
    @BindView(R.id.tv_search_hint)
    TextView mSearHint;
    @BindView(R.id.recylerView)
    RecyclerView mRecyclerView;
    @BindView(R.id.fab)
    FloatingActionButton mFab;
    @BindView(R.id.swipefresh)
    SwipeRefreshLayout mRefreshLayout;

    private boolean mRefresh = false;
    private GridLayoutManager manager;
    private int mLastPosition = 0;  //滑到这里开始加载
//    private int mCurrentOffset = 0;   //从后台查询数据库下标
//    private int mLength = 20;  //每次查询20条
    private Timer mTimer = null;
    private Unbinder mUnbinder;  //ButterKnife解绑
    private ArrayList<Goods> mGoods;
    private ShopRecylerViewAdapter mAdapter;
    private boolean isGettingNow = false;  //标志现在是否在请求数据
    public static ShopFragment newInstance(){
        ShopFragment fragment = new ShopFragment();
        Bundle bundle = new Bundle();
        fragment.setArguments(bundle);
        return fragment;
    }

    /*
    * 定义footview回调接口
    * 控制footview的显示和隐藏
    * */
    public interface CallBack{
        void onDismiss();
        void onShow();
    }
    private static CallBack myCallBack;
    public static void setMyCallBack(CallBack callBack){
        myCallBack = callBack;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EventBus.getDefault().register(this);
        SearchBean searchBean = new SearchBean(0,20,2,null,null);
        getGoods(searchBean);

    }

    private void getGoods(SearchBean searchBean){
        if(isGettingNow){
            return;
        }
        isGettingNow = true;
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(Configs.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();
        RetrofitService service = retrofit.create(RetrofitService.class);
        service.getGoods(searchBean.getOffset(), searchBean.getLength(),searchBean.getKey(),
                searchBean.getPlace(),searchBean.getSecondhand())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<ArrayList<Goods>>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(ArrayList<Goods> goods) {
                        if (mRefresh){
                            mAdapter.cleanGoods();
                            mAdapter.notifyDataSetChanged();
                        }
                        LogUtil.d("getGoods============");
                        if(goods.size() > 0){
                            mTimer.schedule(new TimerTask() {
                                @Override
                                public void run() {
                                    Event event = new Event("add",2);
                                    event.setGoods(goods);
                                    EventBus.getDefault().post(event);
                                    isGettingNow = false;
                                    if (mRefreshLayout.isRefreshing()){
                                        mRefreshLayout.setRefreshing(false);
                                        mRefresh = false;
                                    }
                                }
                            },1000);

                        }

                        isGettingNow = false;
                    }

                    @Override
                    public void onError(Throwable e) {
                        Event event = new Event("dismiss", 3);
                        mTimer.schedule(new TimerTask() {
                            @Override
                            public void run() {
                                EventBus.getDefault().post(event); //没有获取到数据,隐藏footview
                                isGettingNow = false;
                            }
                        },1000);
                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }

    @Subscribe(threadMode = ThreadMode.BACKGROUND)
    public void setTimer(Event event){
        if (event.getMessage().equals("timer") && event.getTime() == 1){
            SearchBean searchBean = new SearchBean(manager.getItemCount(), 20, 2,null,null);
            getGoods(searchBean);
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void addGoods(Event event){
        if (event.getMessage().equals("add") && event.getTime() == 2){
            mAdapter.addGoods(event.getGoods());
            mAdapter.notifyDataSetChanged();
        }else if(event.getMessage().equals("dismiss") && event.getTime() == 3){
            myCallBack.onDismiss();
        }
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            View  v = inflater.inflate(R.layout.shop_fragment, container,false);
            mUnbinder = ButterKnife.bind(this, v);
            mRecyclerView = v.findViewById(R.id.recylerView);
             init();
        manager = new GridLayoutManager(getActivity(), 2);
            manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                @Override
                public int getSpanSize(int position) {
                    boolean isFooter = position == mAdapter.getItemCount() - 1;
                    return isFooter ? 2:1;
                }
            });
            mRecyclerView.setLayoutManager(manager);
            mRecyclerView.setAdapter(mAdapter);
            return v;
    }

    private void init(){
        mTimer = new Timer();
        mAdapter = new ShopRecylerViewAdapter(getActivity());
        mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                if(newState == RecyclerView.SCROLL_STATE_IDLE){
                    if(mLastPosition + 1 == manager.getItemCount()){
                        //加载更多
                        myCallBack.onShow(); //在最后一个item处上拉时,显示footview
                        SearchBean searchBean = new SearchBean(manager.getItemCount(), 20, 2, null, null);
                        getGoods(searchBean);
                    }
                }
            }

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                mLastPosition = manager.findLastVisibleItemPosition();
                if (dy > 0 && mFab.getVisibility() == VISIBLE) {
                    mFab.hide();
                } else if (dy < 0 && mFab.getVisibility() != VISIBLE) {
                    mFab.show();
                }
            }
        });
    //设置显示刷新时的颜色
        mRefreshLayout.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);
        mRefreshLayout.setOnRefreshListener(this);  //添加监听,重写onFresh()方法
    }
    @OnClick({R.id.tv_search_hint, R.id.fab})
    public void click(View v){
        switch (v.getId()){
            case R.id.tv_search_hint:
                Intent intent = new Intent(getActivity(), SearchActivity.class);
                startActivity(intent);
                break;
            case R.id.fab:
                mRecyclerView.smoothScrollToPosition(0);  //滑动到第一项
                break;

        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mUnbinder.unbind();
        EventBus.getDefault().unregister(this);
        if (mTimer != null){
            mTimer.cancel();
            mTimer = null;
        }

    }

    @Override
    public void onRefresh() {
        mRefresh = true;
        mRefreshLayout.setRefreshing(true);
        SearchBean searchBean = new SearchBean(0,20,2,null,null);
        getGoods(searchBean);
    }
}

另外加载时使用了动画的

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android">
    <rotate
        android:drawable="@drawable/load_mini"
        android:fromDegrees="0"
        android:toDegrees="359"
        android:pivotX="50%"
        android:pivotY="50%"
        android:duration="500"
        android:repeatCount="-1"/>
</rotate>

记得,在隐藏footview时,先清除动画。

主要就是,在fragment的代码里定义回调接口,然后在adapter里显示item时来绑定接口,

之后便可以在fragment里控制,footview的显示和隐藏了。

判断上拉,

 mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                if(newState == RecyclerView.SCROLL_STATE_IDLE){
                    if(mLastPosition + 1 == manager.getItemCount()){ //当前显示最后一个item
                        //加载更多
                        myCallBack.onShow();
                        SearchBean searchBean = new SearchBean(manager.getItemCount(), 20, 2, null, null);
                        getGoods(searchBean);
                    }
                }
            }

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                mLastPosition = manager.findLastVisibleItemPosition(); //记录最后一个item位置
                if (dy > 0 && mFab.getVisibility() == VISIBLE) {
                    mFab.hide();
                } else if (dy < 0 && mFab.getVisibility() != VISIBLE) {
                    mFab.show();
                }
            }
        });

因为,代码里的注释很清楚了,就不多写了。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值