程序员

RecyclerView – 显示上拉加载状态

本程序代码参考自开源中国App。数据获取方式:Bmob云存储。本程序已实现下拉刷新和上拉加载,并显示上拉加载状态。

01 效果图

PullDownload.png

02 Layout

recycler_footer_view.xml


    
    

02 RecyclerView的Adapter

public class TweetAdapter extends RecyclerView.Adapter{
    private Context mContext;
    protected ArrayList mItems;

    public static final int VIEW_TYPE_NORMAL = 0;
    public static final int VIEW_TYPE_FOOTER = -1;

    public static final int STATE_HIDE = 1;
    public static final int STATE_LOADING = 2;
    public static final int STATE_NO_MORE = 3;
    public static final int STATE_LOAD_ERROR = 4;

    private int mState;

    public TweetAdapter(Context context, ArrayList items){
        this.mContext = context;
        if(items == null){
            items = new ArrayList<>();
        }
        this.mItems = items;
        mState = STATE_HIDE;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if(viewType == VIEW_TYPE_FOOTER){
            return new FooterViewHolder(LayoutInflater.from(mContext).inflate(R.layout.recycler_footer_view, parent, false));
        }
        else {
            return new ViewHolder(LayoutInflater.from(mContext).inflate(R.layout.item_list_tweet, parent, false));
        }
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if(holder.getItemViewType() == VIEW_TYPE_FOOTER){
            FooterViewHolder fvh = (FooterViewHolder) holder;
            fvh.itemView.setVisibility(View.VISIBLE);
            switch (mState) {
                case STATE_LOADING:
                    fvh.tv_footer.setText(mContext.getResources().getString(R.string.state_loading));
                    fvh.pb_footer.setVisibility(View.VISIBLE);
                    break;
                case STATE_NO_MORE:
                    fvh.tv_footer.setText(mContext.getResources().getString(R.string.state_not_more));
                    fvh.pb_footer.setVisibility(View.GONE);
                    break;
                case STATE_LOAD_ERROR:
                    fvh.tv_footer.setText(mContext.getResources().getString(R.string.state_load_error));
                    fvh.pb_footer.setVisibility(View.GONE);
                    break;
                case STATE_HIDE:
                    fvh.itemView.setVisibility(View.GONE);
                    break;
            }
        }
        else{
            ViewHolder viewHolder = (ViewHolder) holder;
            Tweet item = mItems.get(position);

            Glide.with(mContext)
                    .load(item.getAuthor().getPortrait())
                    .asBitmap()
                    .placeholder(R.mipmap.widget_face)
                    .error(R.mipmap.widget_face)
                    .into(viewHolder.mViewPortrait);

            viewHolder.mViewName.setText(item.getAuthor().getName());
            viewHolder.mViewTime.setText(StringUtil.formatSomeAgo(item.getPubDate()));
            viewHolder.mViewPlatform.setText(getAppClientName(item.getAppClient()));
            viewHolder.mViewLikeCount.setText(String.valueOf(item.getLikeCount()));
            viewHolder.mViewCommentCount.setText(String.valueOf(item.getCommentCount()));

            String content = "";
            if (!TextUtils.isEmpty(item.getContent())) {
                content = item.getContent().replaceAll("[\n\\s]+", " ");
            }

            Spannable spannable = AssimilateUtil.assimilateOnlyTag(mContext, content);
            spannable = AssimilateUtil.assimilateOnlyLink(mContext, spannable);
            viewHolder.mViewContent.setText(spannable);
            viewHolder.mViewContent.setMovementMethod(LinkMovementMethod.getInstance());
            viewHolder.mViewContent.setFocusable(false);
            viewHolder.mViewContent.setLongClickable(false);

            viewHolder.mViewLikeState.setImageResource(item.getLiked() ? R.mipmap.thumb_up_active : R.mipmap.thumb_up_normal);
            viewHolder.mViewLikeState.setTag(position);
        }
    }

    @Override
    public int getItemCount() {
        return mItems.size() + 1;
    }

    @Override
    public int getItemViewType(int position) {
        if(position + 1 == getItemCount()){
            return VIEW_TYPE_FOOTER;
        }
        else{
            return VIEW_TYPE_NORMAL;
        }
    }

    public static class ViewHolder extends RecyclerView.ViewHolder{
        @BindView(R.id.iv_tweet_face) CircleImageView mViewPortrait;
        @BindView(R.id.tv_tweet_name) TextView mViewName;
        @BindView(R.id.tv_tweet_time) TextView mViewTime;
        @BindView(R.id.tv_tweet_platform) TextView mViewPlatform;
        @BindView(R.id.tv_tweet_like_count) TextView mViewLikeCount;
        @BindView(R.id.tv_tweet_comment_count) TextView mViewCommentCount;
        @BindView(R.id.tweet_item) TextView mViewContent;
        @BindView(R.id.iv_like_state) ImageView mViewLikeState;

        public ViewHolder(View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);
        }
    }

    public static class FooterViewHolder extends RecyclerView.ViewHolder {
        @BindView(R.id.pb_footer) ProgressBar pb_footer;
        @BindView(R.id.tv_footer) TextView tv_footer;

        public FooterViewHolder(View view) {
            super(view);
            ButterKnife.bind(this, view);
        }
    }

    public void setState(int state) {
        if(this.mState != state){
            this.mState = state;
            updateItem(getItemCount() - 1);
        }
    }

    public void updateItem(int position) {
        if (getItemCount() > position) {
            notifyItemChanged(position);
        }
    }

    public void addAll(List items) {
        if (items != null) {
            this.mItems.addAll(items);
            notifyItemRangeInserted(this.mItems.size(), items.size());
        }
    }

    public void clear() {
        this.mItems.clear();
        notifyDataSetChanged();
    }

    private String getAppClientName(int appClient){
        String appClientName = "";
        switch (appClient){
            case 3 :
                appClientName = "Android";
                break;
            case 4 :
                appClientName = "iPhone";
                break;
        }
        return appClientName;
    }
}

03 源代码

下载地址

04 App

数据来自Bmob云存储,可以直接下载App运行看效果。