RecyclerView相比listView和GridView更加灵活高效,之前一直在用ListView,结合自定义ViewHolder做一些界面,用RecyclerView之后感觉二者十分相似,RecyclerView省去了ListView中getViewV()方法的setTag和getTag函数调用。

 假期准备比赛第一次用RecyclerView,实现了类似QQ动态详情页的评论列表,点击评论图标发表评论,点击评论字段发送二级评论,点击二级评论可以进行回复,先看一下效果图:

recycleview获取某个位置item recyclerview获取子view_android

RecyclerView的动态更新,更新前要判定在哪里添加评论,是添加评论Item还是更新Item中的子评论,

同时要注意是否是回复评论人。处理方法是声明3个标记变量,分别对应上述的情况,在监听方法中更改变量,发表新评论就根据

变量的取值对RecyclerView进行更新。

布局文件就是一个简单的RecyclerView,为其设置一个ViewHeader,这个ViewHeader就是所要评论的动态内容。

以下是activity代码:

package com.eztt.dtour.activity;

import android.content.ClipboardManager;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.ImageView;
import android.widget.TextView;

import com.bumptech.glide.Glide;
import com.eztt.dtour.DTourHelper;
import com.eztt.dtour.R;
import com.eztt.dtour.adapter.CommentAdapter;
import com.eztt.dtour.adapter.ImageAdapter;
import com.eztt.dtour.adapter.VideoAdapter;
import com.eztt.dtour.base.BaseActivity;
import com.eztt.dtour.bean.CommentListBean;
import com.eztt.dtour.bean.CommentUserBean;
import com.eztt.dtour.bean.CommentsBean;
import com.eztt.dtour.fragment.DynamicFragment;
import com.eztt.dtour.utils.EmojiUtils;
import com.eztt.dtour.utils.NineUtils;
import com.hyphenate.easeui.domain.EaseEmojicon;
import com.hyphenate.easeui.widget.EaseChatInputMenu;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;

import java.util.ArrayList;
import java.util.List;

import cn.jzvd.JZVideoPlayer;
import de.hdodenhof.circleimageview.CircleImageView;

public class DynamicDetail extends BaseActivity{

    public static final String TAG = DynamicDetail.class.getSimpleName();
    private RecyclerView commmentList;
    private CommentAdapter commentAdapter;
    private TextView UserName;
    private TextView Content;
    private CircleImageView Avatar;
    private RecyclerView Images;
    private TextView Location;
    private TextView Time;
    private TextView CommentNum;
    private TextView ThumbNum;
    private ImageView Likeimg;
    private ImageView commentimg;
    private EaseChatInputMenu inputMenu;
    private InputMethodManager inputManager;
    private ClipboardManager clipboard;
    private DisplayImageOptions options;
    private static final int main_comment_type = 0;//添加新的评论
    private static final int second_comment_type = 1;//点击评论字段发表二级评论
    private static final int third_comment_type = 2;//点击二级评论回复
    private int current_comment_location;
    private int Current_commentItem_location;
    private List<CommentsBean> temp_Datas;
    private int current_comment_type;

    List<CommentListBean> testlist;//评论列表的数据源
    @Override
    public int getLayoutId() {
        return R.layout.dynamic_comment_details;
    }

    @Override
    public void initViews() {
        inputMenu = findView(R.id.comment_input_menu);
        inputManager = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
        clipboard = (ClipboardManager)getSystemService(Context.CLIPBOARD_SERVICE);
        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
        testlist=new ArrayList<CommentListBean>() ;
        commentAdapter=new CommentAdapter(testlist,this);
        commmentList = findView(R.id.recycler_view_comment);
        LinearLayoutManager layoutManager = new LinearLayoutManager(DynamicDetail.this);
        commmentList.setLayoutManager(layoutManager);
        setHeaderView(commmentList);
        commmentList.setAdapter(commentAdapter);
    }
private void setHeaderView(RecyclerView view){
        View header = LayoutInflater.from(this).inflate(R.layout.dynamic_detail, view, false);
        UserName=header.findViewById(R.id.dynamic_detail_username);
        Content=header.findViewById(R.id.dynamic_detail_content);
        Avatar=header.findViewById(R.id.dynamic_detail_avatar);
        Images=header.findViewById(R.id.dynamic_detail_images);
        Location=header.findViewById(R.id.dynamic_detail_location);
        Time=header.findViewById(R.id.dynamic_detail_time);
        CommentNum=header.findViewById(R.id.dynamic_detail_commentnum);
        ThumbNum=header.findViewById(R.id.dynamic_detail_likenum);
        Likeimg=header.findViewById(R.id.dynamic_detail_likeimg);
        commentimg=header.findViewById(R.id.dynamic_detail_commentimg);
        commentAdapter.setHeaderView(header);
    }
    @RequiresApi(api = Build.VERSION_CODES.M)
    @Override
    public void initListener() {

        inputMenu.init(null);
        inputMenu.onCommentHide();
        hideKeyboard();
        inputMenu.hideExtendMenuContainer();
        inputMenu.setVisibility(View.GONE);
        inputMenu.setChatInputMenuListener(new EaseChatInputMenu.ChatInputMenuListener() {
            @Override
            public void onSendMessage(String content) {
                switch (current_comment_type)//判断更新位置
                {
                    case main_comment_type:
                        CommentListBean b=new CommentListBean();
                        b.setComment_text(content);
                        b.setName(DTourHelper.getInstance().getCurrentUsernName());
                        b.setHeadimg("http://p0.so.qhimgs1.com/t0150ebefcc359a1724.jpg");
                        testlist.add(0,b);
                        commentAdapter.notifyItemChanged(1);
                        break;
                    case second_comment_type:
                        Log.d(TAG,"刷新第"+current_comment_location+"条评论");

                        CommentListBean temp = testlist.get(current_comment_location);
                        temp.getComments().add(new CommentsBean(content,
                                new CommentUserBean(current_comment_location,
                                        DTourHelper.getInstance().getCurrentUsernName()),null));
                        testlist.set(current_comment_location,temp);
                        commentAdapter.notifyItemChanged(current_comment_location+1);
                        break;
                    case third_comment_type:
                        CommentsBean item = temp_Datas.get(Current_commentItem_location);
                        CommentUserBean replyUser = item.getReplyUser();
                        CommentsBean reply;
                        if (replyUser != null) {
                            reply = new CommentsBean(content,new CommentUserBean(Current_commentItem_location,
                                    DTourHelper.getInstance().getCurrentUsernName()),replyUser);
                        }
                        else {
                            reply = new CommentsBean(content,new CommentUserBean(Current_commentItem_location,
                                    DTourHelper.getInstance().getCurrentUsernName()),item.getCommentsUser());
                        }

                        temp_Datas.add(Current_commentItem_location+1,reply);
                        commentAdapter.notifyDataSetChanged();
                        break;
                }

                for(int i=0;i<testlist.size();i++)
                {
                    for(int j=0;j<testlist.get(i).getComments().size();j++)
                    {
                        Log.d(TAG,"第"+i+"部分"+testlist.get(i).getComments().get(j).getContent());
                    }
                }
                hideKeyboard();
                inputMenu.hideExtendMenuContainer();
                inputMenu.setVisibility(View.GONE);
            }

            @Override
            public void onBigExpressionClicked(EaseEmojicon emojicon) {

            }

            @Override
            public boolean onPressToSpeakBtnTouch(View v, MotionEvent event) {
                return false;
            }
        });

        commentAdapter.setOnRecyclerViewListener(new CommentAdapter.OnRecyclerViewListener() {
            @Override
            public void onItemClick(int position) {
                current_comment_type = second_comment_type;
                current_comment_location = position;
                Log.d(TAG,"点击第"+position+"条评论");
                inputMenu.setVisibility(View.VISIBLE);
            }

            @Override
            public void onCommentItemClick(int position, int y, List<CommentsBean> Data) {
                current_comment_type = third_comment_type;
                Current_commentItem_location = position;
                temp_Datas = Data;
                inputMenu.setVisibility(View.VISIBLE);
                int[] position2 = new int[2];
                inputMenu.getLocationOnScreen(position2);
                Log.d(TAG, "commmentList.x = " + position2[0]);
                Log.d(TAG, "commmentList.y = " + position2[1]);
                commmentList.scrollBy(0, y - position2[1]);
            }

            @Override
            public boolean onItemLongClick(int position) {
                return false;
            }
        });

        commmentList.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                hideKeyboard();
                inputMenu.hideExtendMenuContainer();
                inputMenu.setVisibility(View.GONE);
                return false;
            }
        });

        commentimg.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                current_comment_type = main_comment_type;
                inputMenu.setVisibility(View.VISIBLE);
            }
        });

        commmentList.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                switch(newState)
                {
                    case 0:
                        Glide.with(DynamicDetail.this).resumeRequests();
        
                        break;
                    case 1:
                        Glide.with(DynamicDetail.this).resumeRequests();
                        
                        break;
                    case 2:
                        Glide.with(DynamicDetail.this).pauseRequests();
                        
                        break;
                }
            }
        });
    }
    @Override
    public void initData() {
        InitConfig();
        final com.eztt.dtour.bean.Dynamic.DynamicBean bean = (com.eztt.dtour.bean.Dynamic.DynamicBean) getIntent().getSerializableExtra("Dynamic");
        final int position=(int)getIntent().getIntExtra("position",0);
        UserName.setText(bean.getUsername());
        EmojiUtils.setText(Content, bean.getContent());
        Location.setText(bean.getLocation());
        Time.setText(bean.getTime());
        //显示头像
        ImageLoader.getInstance().displayImage(bean.getAvatar(), Avatar, options);
        CommentNum.setText( ""+bean.getComment());
        ThumbNum.setText("" + bean.getLike());
        if(bean.getHasFavor()==0){
            Likeimg.setImageResource(R.drawable.dynamic_like);
        }
        else {
            Likeimg.setImageResource(R.drawable.dynamic_unlike);
        }
        Likeimg.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //没点赞则进行点赞
                if(DynamicFragment.dynamic.get(position).getHasFavor()==0){
                    Likeimg.setImageResource(R.drawable.dynamic_unlike);
                    //点赞的数量+1
                    int i=DynamicFragment.dynamic.get(position).getLike()+1;
                    //改变值
                    DynamicFragment.dynamic.get(position).setLike(i);
                    ThumbNum.setText(""+i);
                    DynamicFragment.dynamic.get(position).setHasFavor(1);
                }
                else{
                    Likeimg.setImageResource(R.drawable.dynamic_like);
                    int i=DynamicFragment.dynamic.get(position).getLike()-1;
                    DynamicFragment.dynamic.get(position).setLike(i);
                    ThumbNum.setText(""+i);
                    DynamicFragment.dynamic.get(position).setHasFavor(0);
                }
            }
        });

        //展示九宫格
        GridLayoutManager manager = new GridLayoutManager(DynamicDetail.this, 3);
        Images.setLayoutManager(manager);
        if (bean.getFlag() == 0) {
            int imageCount = bean.getImageUrls() == null ? 0 : bean.getImageUrls().size();
            if (imageCount == 0) {
                //没有图片的时候不显示
                Images.setVisibility(View.GONE);
            } else {
                Images.setVisibility(View.VISIBLE);
                //刷新图片数据
                ImageAdapter mAdapter = new ImageAdapter(bean.getImageUrls(), DynamicDetail.this);
                Images.setAdapter(mAdapter);
                ViewGroup.LayoutParams layoutParams = Images.getLayoutParams();
                if (imageCount == 1) {
                    manager.setSpanCount(1);
                    layoutParams.width = ViewGroup.LayoutParams.WRAP_CONTENT;
                } else if (imageCount == 4) {
                    manager.setSpanCount(2);
                    //两个图片的宽度
                    layoutParams.width = NineUtils.getGridWidth() * 2;
                } else {
                    manager.setSpanCount(3);
                    layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
                }
            }
        } else {
            int videoCount = bean.getVideoUrls() == null ? 0 : bean.getVideoUrls().size();
            if (videoCount == 0) {
                //没有图片的时候不显示
                Images.setVisibility(View.GONE);
            } else {
                Images.setVisibility(View.VISIBLE);
                //刷新图片数据
                VideoAdapter mAdapter = new VideoAdapter(bean.getVideoUrls(), DynamicDetail.this, bean.getCover());
                Images.setAdapter(mAdapter);
                ///mAdapter.setNewData(item.getImageUrls());
                //动态指定图片宫格的宽高和recycleview的宽高
                //1张图片->1列
                //4张图片 ->2列
                //其他  ->3列
                //目前只支持显示一个视频,所以等于4以及其他情况是摆设
                ViewGroup.LayoutParams layoutParams = Images.getLayoutParams();
                if (videoCount == 1) {
                    manager.setSpanCount(1);
                    layoutParams.width = ViewGroup.LayoutParams.WRAP_CONTENT;
                } else if (videoCount == 4) {
                    manager.setSpanCount(2);
                    //两个图片的宽度
                    layoutParams.width = NineUtils.getGridWidth() * 2;
                } else {
                    manager.setSpanCount(3);
                    layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
                }
            }

        }
    }
    @Override
    public void processClick(View v) {

    }
    private void InitConfig(){
        options = new DisplayImageOptions.Builder()
                // 加载中显示的默认图片
                .showImageOnLoading(R.drawable.ic_launcher)
                // 设置加载失败的默认图片
                .showImageOnFail(R.drawable.ic_launcher)
                // 内存缓存
                .cacheInMemory(true)
                // sdcard缓存
                .cacheOnDisk(true)
                // 设置最低配置
                .bitmapConfig(Bitmap.Config.RGB_565)
                .build();
    }
    //动态视频播放需要实现
    @Override
    public void onBackPressed() {
        if (JZVideoPlayer.backPress()) {
            return;
        }
        super.onBackPressed();
    }
    //动态视频播放需要实现
    @Override
    protected void onPause() {
        super.onPause();
        JZVideoPlayer.releaseAllVideos();
    }

    protected void hideKeyboard() {
        if (getWindow().getAttributes().softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN) {
            if (getCurrentFocus() != null)
                inputManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(),
                        InputMethodManager.HIDE_NOT_ALWAYS);
        }
    }

    public void back(View view)
    {
        onBackPressed();
    }
}

 布局就是一个RecyclerView,不放代码了。RecyclerView的数据源是一个List,其中每个Item对应一条评论,

每个Item中又包含一个List,list中保存每条评论的子评论。

package com.eztt.dtour.bean;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by think on 2018/2/5.
 */

public class  CommentListBean implements Serializable {

    private int id;
    private String name;
    private String headimg;
    private String time;
    private String comment_text;
    private int good;
    private List<CommentsBean> comments;

    public CommentListBean()
    {
        comments = new ArrayList<CommentsBean>();
    }

    public void setComments(List<CommentsBean> comments) { this.comments = comments; }

    public List<CommentsBean> getComments() { return comments; }

    public void setId(int id) { this.id = id; }

    public int getId() { return id; }

    public void setName(String name) { this.name = name; }

    public String getName() { return name; }

    public void setHeadimg(String url) { this.headimg = url; }

    public String getHeadimg() { return headimg; }

    public void setTime(String time) { this.time = time; }

    public String getTime() {return time; }

    public void setComment_text(String text) { this.comment_text = text; }

    public String getComment_text() { return comment_text; }

    public void setGood(int good) { this.good = good; }

    public int getGood() { return good; }
}

 适配器代码:

package com.eztt.dtour.adapter;

import android.content.Context;
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.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.bumptech.glide.Glide;
import com.eztt.dtour.R;
import com.eztt.dtour.bean.CommentListBean;
import com.eztt.dtour.bean.CommentsBean;
import com.eztt.dtour.widget.CommentsView;
import com.orhanobut.logger.Logger;

import java.util.List;

/**
 * Created by think on 2018/2/5.
 */

public class CommentAdapter extends RecyclerView.Adapter {

    public static final String Tag = CommentAdapter.class.getSimpleName();

    public static final int TYPE_HEADER = 0;
    public static final int TYPE_NORMAL = 1;
    private Context context;
    private View headerView;

    public void setHeaderView(View headerView) {
        this.headerView = headerView;
        notifyItemInserted(0);
    }

    public int getItemViewType(int position) {
        if (headerView == null){
            return TYPE_NORMAL;
        }
        if (position == 0){
            return TYPE_HEADER;
        }
        return TYPE_NORMAL;
    }

    public static interface OnRecyclerViewListener {
        void onItemClick(int position);
        void onCommentItemClick(int position, int y, List<CommentsBean> Data);
        boolean onItemLongClick(int position);
    }

    private OnRecyclerViewListener onRecyclerViewListener;

    public void setOnRecyclerViewListener(OnRecyclerViewListener onRecyclerViewListener) {
        this.onRecyclerViewListener = onRecyclerViewListener;
    }

    private static final String TAG = CommentAdapter.class.getSimpleName();
    private List<CommentListBean> list;

    public CommentAdapter(List<CommentListBean> list,Context context) {
        this.list = list;
        this.context = context;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        Logger.d(TAG, "onCreateViewHolder, i: " + i);
        if(headerView != null && i == TYPE_HEADER) {
            return new CommentViewHolder(headerView);
        }
        View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_dynamic_comment, null);
        LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        view.setLayoutParams(lp);
        return new CommentViewHolder(view);
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int i) {
        Logger.d(TAG, "onBindViewHolder, i: " + i + ", viewHolder: " + viewHolder);
        if(getItemViewType(i)==TYPE_NORMAL) {
            CommentViewHolder holder = (CommentViewHolder) viewHolder;
            holder.position = i-1;
            CommentListBean commentItem = list.get(i-1);
            if(commentItem.getComment_text()!=null)
                holder.comment_text.setText(commentItem.getComment_text());
            if(commentItem.getName()!=null)
                holder.name.setText(commentItem.getName());
            if(commentItem.getHeadimg()!=null) {
                if(!holder.initHeadImg) {
                    Glide.with(context).load(commentItem.getHeadimg())
                            .into(holder.headimg);
                    holder.initHeadImg = true;
                }
            }
            Log.d("匹配评论信息:", (i-1)+ "");
            holder.comment_list.setList(commentItem.getComments());
            holder.comment_list.notifyDataSetChanged();
        }
    }

    @Override
    public int getItemCount() {
        return headerView == null? list.size():list.size()+1;
    }

    class CommentViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener
    {
        public de.hdodenhof.circleimageview.CircleImageView headimg;
        public ImageView likeimag;
        public TextView comment_text;
        public CommentsView comment_list;
        public TextView name;
        public TextView time;
        public boolean initHeadImg;
        public int good_count;
        public int position;

        public CommentViewHolder(View itemView) {
            super(itemView);
            if(itemView == headerView)
                return;
            headimg = itemView.findViewById(R.id.comment_avatar);
            likeimag = itemView.findViewById(R.id.comment_likeimg);
            comment_text = itemView.findViewById(R.id.comment_text) ;
            name = itemView.findViewById(R.id.comment_name);
            time = itemView.findViewById(R.id.comment_time);
            comment_list = itemView.findViewById(R.id.comments_list);
            comment_text.setOnClickListener(this);
            comment_text.setOnLongClickListener(this);
            comment_list.setOnItemClickListener(new CommentsView.onItemClickListener() {
                @Override
                public void onItemClick(int p, int y, List<CommentsBean> Data) {
                    if (null != onRecyclerViewListener) {
                        onRecyclerViewListener.onCommentItemClick(p,y,Data);
                    }
                }
            });
        }

        @Override
        public void onClick(View v) {
            if (null != onRecyclerViewListener) {
                onRecyclerViewListener.onItemClick(position);
            }
        }

        @Override
        public boolean onLongClick(View v) {
            if(null != onRecyclerViewListener){
                return onRecyclerViewListener.onItemLongClick(position);
            }
            return false;
        }
    }

}