@TOC

目录

一、控件概述

1.1、介绍

CommentView是一个简洁、高效、可自定义的开源的Android评论控件,反对盖楼评论回复模式下拉刷新评论上拉加载更多评论加载更多回复等性能,可自定义(款式、数据模型、布局)、可轻松按需要扩大性能。

1.2、性能特点

性能特点
反对下拉刷新评论
反对上拉加载更多评论
反对加载更多回复
反对盖楼评论回复模式
可设置空数据视图、谬误视图
反对自定义数据模型
反对自定义款式配置器
反对自定义布局

1.3、效果图

GIF压缩后成果变差,想亲自体验能够到上面的仓库下载安装包。

想要什么的款式成果能够自定义实现

默认款式成果(GIF)

自定义款式成果(自定义仿微信公众号评论)(GIF)

1.4、源码仓库

仓库网址
码云https://gitee.com/jidcoo/CommentView
GitHubhttps://github.com/Jidcoo/CommentView
Jcenter(Maven)https://bintray.com/longyun/maven/CommentView

二、框架类解析

2.1、我的项目目录构造


2.2、我的项目整体框架

CommentView只负责对外提供业务办法,所有的业务实现和外围代码都在com.jidcoo.android.widget.commentview.operator包和com.jidcoo.android.widget.commentview.adapter包。com.jidcoo.android.widget.commentview.callback包是业务和控件的桥接包。

2.3、框架合成

2.3.1、数据模型类(Model)

整体框架

2.3.1.1、PagerEnable(分页)
/** * 分页模型<br> * <br> * 在Android端只实现为对分页数据的Get/Set操作<br> * <br> * 具体的分页逻辑应该由后端实现,客户端只负责对数据的解决<br> * <br> * @author Jidcoo */public class PagerEnable {    /**     * 以后页码     */    public int currentPage;    /**     * 每一页数据的大小     */    private int pageSize;    /**     * 总页数     */    public int totalPages;    /**     * 数据总数     */    public int totalDataSize;    /**     * 下一个页码     */    public int nextPage;    /**     * 上一个页码     */    public int prefPage;    //    //省略大量Get()/Set() 办法    //}

PagerEnable类是一个分页模型,是我的项目数据模型中十分重要的一个基类,评论数据抽象模型AbstractCommentModel、CommentEnable都继承自PagerEnable类。在业务类的外围代码中都须要用到PagerEnable类中的页码数据和办法。

在Android端不波及具体分页逻辑,具体分页逻辑在后端实现。留神:在理论应用中,如果要实现分页加载(更多评论数据、更多回复数据),那么要展现的数据必须蕴含这些分页数据字段。 比方在json数据中必须蕴含这些数据,分页性能能力真正无效。也就是说无论你用什么作为数据,都必须在数据中蕴含相干分页数据字段。继承了PagerEnable类的所有类对于的数据都要蕴含相干分页数据字段

2.3.1.2、ReplyEnable(回复数据基类)
/** * 自定义回复模型必须继承自此类 * @author Jidcoo */public class ReplyEnable { }

ReplyEnable类是回复数据模型的基类,自定义回复模型必须继承自此类。能够看出此类没有任何的继承关系

可能有人会问,回复数据不是须要分页吗?为什么ReplyEnable类没有继承自PagerEnable分页模型类?没有分页数据回复数据如何分页?首先如果要实现回复数据分页加载,那么回复数据是须要分页的。然而回复数据的分页数据应该属于它所在评论(CommentEnable)的那一级中,而不是在回复数据自身上,因为在分页数据在回复模型中没有任何意义。是通过回复数据所在的那个评论模型(CommentEnable)中体现回复数据的分页状况

所有回复数据的分页加载都是基于它所在的评论模型所决定和管制的。而CommentEnable类正是继承自PagerEnable类,继承自PagerEnable类的惟一目标就是用来管制回复数据的分页性能。了解这段话就可能晓得为什么ReplyEnable类只是一个空类了。

自定义回复数据模型例子:

/** * 首先继承自ReplyEnable类 * 而后设置回复模型中所须要的数据就能够了 */public class Reply extends ReplyEnable {      public String userName;      public String reply;      .....      设置更多具体的属性,比方工夫、点赞数之类的数据      .....}
2.3.1.3、CommentEnable(评论数据抽象类)
/** * <p>自定义评论模型抽象类</p> * 自定义评论模型必须继承自此抽象类 * @author Jidcoo */public abstract class CommentEnable extends PagerEnable{    /**     * 必须实现该办法并确保返回值非NULL     * @return     */    public abstract <R extends ReplyEnable> List<R> getReplies();}

CommentEnable是一个继承自PagerEnable类的抽象类。继承自PagerEnable类的惟一目标就是用来管制回复数据的分页性能,所以继承自此类的实体类就具能够反对所在评论的回复数据的分页加载。

自定义评论数据模型必须继承自CommentEnable类并实现getReplies()形象办法getReplies()办法十分重要,必须实现。该办法返回一个List<? extend ReplyEnable>的list,这个list的元素是继承自ReplyEnable的自定义的回复数据模型实体类。如第二点中的例子Reply类。

自定义评论数据模型例子:

/** * 首先继承自CommentEnable类 * 而后实现形象办法getReplies(),返回一个回复数据的List * 而后设置回复模型中所须要的数据就能够了 */public class Comment extends CommentEnable{      public List<Reply> replies;      public String userName;      public String comment;      .....      设置更多具体的属性,比方工夫、点赞数之类的数据      .....      /*@Override      public List<R> getReplies() {            return null;      }*/      //必须实现getReplies()办法。      @Override      public  List<Reply> getReplies() {            return replies;      }      /**       * 首先继承自ReplyEnable类       * 而后设置回复模型中所须要的数据就能够了       */      public class Reply extends ReplyEnable {            public String userName;            public String reply;            .....            设置更多具体的属性,比方工夫、点赞数之类的数据            .....      }}

留神:CommentEnable类中getReplies()的原型是这样的:

@Overridepublic List<R> getReplies() {            return null;      }

所以实现getReplies()办法的时候只须要把泛型R改为本人定义的回复数据模型类就能够了,而后在办法中返回这个实体类的汇合。

2.3.1.4、AbstractCommentModel(评论数据总抽象类)
/** * 数据抽象模型<p></p> * 自定义模型必须继承此形象模型,并实现其中的办法<p></p> * <u>留神:应用自定义数据类型就必须自定义布局实现,否则会抛出数据模型的java.lang.ClassCastException异样</u><br></br> * AbstractCommentModel中传入的泛型<C extends CommentEnable>必须继承自CommentEnable,查看{@link CommentEnable} * @param <C> 自定义的评论数据模型 * @author Jidcoo */public  abstract class AbstractCommentModel <C extends CommentEnable> extends PagerEnable{    /**     * 必须实现该办法并确保返回值非NULL     * @return     */    public abstract List<C> getComments() ;}

AbstractCommentModel类是评论模型抽象类,继承自PagerEnable类用来管制评论数据的分页性能。同时它是一个泛型抽象类,泛型承受的类必须是继承自CommentEnable的类,比方第三点中的例子Comment类。

同样的,实现自定义的数据模型必须继承自AbstractCommentModel类并实现getComments形象办法(设计思维与CommentEnable类一样)。getComments()办法十分重要,必须实现。该办法返回一个List<? extend CommentEnable>的list,这个list的元素是继承自CommentEnable的自定义的评论数据模型实体类。如第三点中的例子Comment类。
留神:应用自定义数据类型就必须自定义布局实现,否则会抛出数据模型的java.lang.ClassCastException异样。起因能够查看defaults包下的DefaultItemBuilder类对于默认布局的实现办法。

AbstractCommentModel实际上是业务办法中应用到的最外层的数据模型类了。查看CommentView的源码中的业务办法就能够晓得,次要的无关数据的业务办法承受的参数都是AbstractCommentModel,也就是说承受继承自此抽象类的数据模型。

自定义模型例子:

/** * 首先继承自形象泛型类AbstractCommentModel<C> * 其中泛型C用自定义的评论模型类替换就能够了 * 而后实现形象办法getComments(),返回一个评论数据的List */public class CommentModel extends AbstractCommentModel<CommentModel.Comment> {    public List<Comment> comments;    //必须实现getComments()办法并确保返回值非NULL    @Override    public List<Comment> getComments() {        return comments;    }    /** * 首先继承自CommentEnable类 * 而后实现形象办法getReplies(),返回一个回复数据的List * 而后设置回复模型中所须要的数据就能够了 */public class Comment extends CommentEnable{      public String userName;      public String comment;      public List<Reply> replies;      /*@Override      public List<R> getReplies() {            return null;      }*/      @Override      public  List<Reply> getReplies() {            return replies;      }      /**       * 首先继承自ReplyEnable类       * 而后设置回复模型中所须要的数据就能够了       */      public class Reply extends ReplyEnable {            public String userName;            public String reply;      }}}

在自定义模型中要继承自形象泛型类AbstractCommentModel < C extends CommentEnable>

public class CommentModel extends AbstractCommentModel<C>
    @Override    public List<C> getComments() {        return null;    }

这里的泛型C用自定义的评论数据模型类(如第三点的例子Comment类)替换就能够了。

其实在自定义模型类中做的事件并不多,因为须要的Comment类、Reply类之前都曾经自定义好了。所以当初就只须要在自定义模型类中继承自 AbstractCommentModel<C>,并把泛型C替换成本人Comment类,最初实现形象办法getComments()就能够了。留神:getComments()办法必须实现并返回对应的List,被确保返回的这个List非null

2.3.1.5、总结

好了,到当初为止,CommentView控件的数据模型就剖析完了。好长篇幅。为什么呢?因为这个数据模型对于整个框架来说太重要了。必须了解好数据模型能力轻松应用这个控件。所以必须详细分析整个数据模型。

2.3.2、ViewHolder类

ViewHolder类是一个抽象类,是对于自定义回复布局的时候应用的,自定义评论布局不须要继承自此类。ViewHolder位于com.jidcoo.android.widget.commentview.view包下。

自定义评论布局ViewHolder类没有任何限度和要求不须要任何继承。所以这里不展现例子代码了,例子能够查看defaults包下的DefaultCommentHolder类。

然而对于自定义回复布局,有四点必须不按要求就报错):
1、必须应用ViewHolder机制
2、应用的ViewHolder必须继承自com.jidcoo.android.widget.commentview.view包下ViewHolder抽象类。
3、自定义的回复布局中最外层布局必须为LinearLayout
4、并且这个最外层的LinearLayout的android:id属性必须设置为“reply_rootView”,即android:id="@+id/reply_rootView"

这四点必须怎么来的呢,上面看ViewHolder类的代码:

/** * 自定义回复布局必须继承此抽象类并在构造方法中调用父类构造方法,否则会报错。<p> * <br></br> * 在自定义回复布局中最外层必须应用LinearLayout并将布局id设置为“reply_rootView”,否则会报错。<p> * @author Jidcoo */public abstract class ViewHolder {    /**     * 自定义布局这个view必须为非空     */    public LinearLayout rootView;    public ViewHolder(View view){        try {            rootView=view.findViewById(R.id.reply_rootView);        }catch (Exception e){            throw  new RuntimeException("If you use a custom layout, the outermost layout must be a LinearLayout, and you need to set its id attribute value to \"reply_rootView\"");        }    }}

在ViewHolder这个抽象类中有一个LinearLayout变量rootView,而后在构造方法中会在传进来的自定义布局的view外面通过findViewById()实例化rootView。所以当找不到这个id或者这个id对应的类型不是LinearLayout的时候会抛出RuntimeException异样

至于为什么要实例化rootView这个变量,能够看com.jidcoo.android.widget.commentview.adapter包下的ViewAdapter类的具体代码实现就晓得了。这里不具体开展。

自定义回复布局时应用的ViewHolder的例子:

/** * 创立类继承自抽象类ViewHolder * 而后在带参构造方法中显式调用父级构造方法super(view)把view传进去 * 而后再实例化本人自定义的布局控件 */public class ReplyItemViewHolder extends ViewHolder {    public TextView replyTextView;    //……增加本人须要的控件    //……    //……增加本人须要的控件        public ReplyItemViewHolder(View view) {        super(view);        //实例化对应的控件        replyTextView=view.findViewById(R.id.replyTextView);            }}

2.3.3、回调类(Callback)

2.3.3.1、CustomCommentItemCallback(自定义评论布局回调)
/** * 自定义评论布局的回调<p></p> * 相当于Adapter的getView()办法<p></p> * 与Adapter的getView()办法应用一样<p></p> * 泛型接口中的泛型对应评论数据模型,即继承在CommentEnable,查看{@link CommentEnable} * @author Jidcoo */public interface CustomCommentItemCallback<C extends CommentEnable> {    /**     * 相当于adapter中的getView()办法     * @param groupPosition Item所在groupPosition     * @param comment 泛型评论数据     * @param inflater  LayoutInflater实例(非空)     * @param convertView View     * @param parent     * @return     */    View buildCommentItem(int groupPosition, C comment, LayoutInflater inflater, View convertView, ViewGroup parent);}

CustomCommentItemCallback是一个自定义评论布局的泛型回调,非必须回调,当须要自定义评论布局的时候实现这个回调,回调中的buildCommentItem()办法相当于Adapter中的getView()办法,在buildCommentItem()中应用自定义的布局即可。

CustomCommentItemCallback< C extends CommentEnable>中的泛型C是你应用的评论数据模型,即该回调承受的类必须继承自CommentEnable。引入自定义布局须要的LayoutInflater实例曾经保障是非null的,间接应用即可,不须要外创立一个新的实例升高性能。留神:在实现该办法时尽量应用ViewHolder机制,否则控件的性能可能会降落。

当须要自定义评论布局的时候实现这个回调。

例子

/** * 自定义评论布局 * 实现CustomCommentItemCallback<C>回调 * 把自定义评论模型Comment放入泛型参数中 * 而后实现buildCommentItem()办法进行自定义布局 */public class CustomCommentItem implements CustomCommentItemCallback<Comment> {    @Override    public View buildCommentItem(int groupPosition,Comment comment, LayoutInflater inflater, View convertView, ViewGroup parent) {        //应用ViewHolder机制        //自定义评论布局的ViewHolder没有任何要求,不须要任何继承        //为了更好的性能,尽量应用ViewHolder机制        CommentViewHolder commentViewHolder=null;        if(convertView==null){            //引入自定义布局            convertView=inflater.inflate(R.layout.my_commentItem_layout);            //实例化CommentViewHolder            commentViewHolder=new CommentViewHolder(convertView);            convertView.setTag(commentViewHolder);        }else{            commentViewHolder=(CommentViewHolder)convertView.getTag();        }        //对控件进行操作        //setText()……        //对控件进行操作        return convertView;    }}
2.3.3.2、CustomReplyItemCallback(自定义回复布局回调)
/** * 自定义回复布局的回调<p></p> * 相当于Adapter的getView()办法<p></p> * 与Adapter的getView()办法应用一样<p></p> * 泛型接口中的泛型对应回复数据模型,即继承在ReplyEnable,查看{@link ReplyEnable}<p></p> * 留神: * <br></br> * 布局:<p> * 1、自定义布局xml中最外层布局必须是LinearLayout并且把最外层布局id设置为reply_rootView<p> * ViewHolder:<p> * 1、在buildReplyItem()中自定义布局初始化时,必须应用ViewHolder机制<p> * 2、初始化过程中,自定义Holder必须继承自com.jidcoo.android.widget.commentview.view.ViewHolder,查看{@link ViewHolder}<p> * @author Jidcoo */public interface CustomReplyItemCallback<R extends ReplyEnable> {    /**     * 相当于adapter中的getView()办法     * @param groupPosition 所在父级地位     * @param childPosition 所在位置     * @param isLastReply 是否是最初一条评论     * @param convertView View     * @param reply 泛型回复数据     * @param inflater  LayoutInflater实例(非空)     * @param parent     * @return     */    View buildReplyItem(int groupPosition, int childPosition, boolean isLastReply, R reply, LayoutInflater inflater, View convertView, ViewGroup parent);}

CustomReplyItemCallback是一个自定义回复布局的泛型回调,非必须回调,当须要自定义回复布局的时候实现这个回调,回调中的buildReplyItem()办法相当于Adapter中的getView()办法,在buildReplyItem()中应用自定义的布局即可。

CustomReplyItemCallback< R extends ReplyEnable>中的泛型R是你应用的回复数据模型,即该回调承受的类必须继承自ReplyEnable。引入自定义布局须要的LayoutInflater实例曾经保障是非null的,间接应用即可,不须要外创立一个新的实例升高性能。留神:在实现buildReplyItem()办法时有四点必须(不按要求就报错):

1、必须应用ViewHolder机制
2、应用的ViewHolder必须继承自com.jidcoo.android.widget.commentview.view包下ViewHolder抽象类。
3、自定义的回复布局中最外层布局必须为LinearLayout
4、并且这个最外层的LinearLayout的android:id属性必须设置为“reply_rootView”,即android:id="@+id/reply_rootView"

这里的ViewHolder上边说过了,这里不再反复。在ViewAdapter中有一段代码是用来对ViewHolder做校验的:

        if(convertView.getTag() == null) {            throw new RuntimeException("You should call convertView.getTag() method to use Holder instance as the tag of convertView");        }else{            Object object = convertView.getTag();            if(object instanceof ViewHolder) {                //some core code            }else{                throw new RuntimeException("The ReplyHolder must extent from ViewHolder");            }        }

当应用自定义布局时,它会依据你返回的的自定义convertView进行getTag(),如果返回null,就抛出异样,所以在应用自定义布局时必须应用convertView.setTag()把Holder保存起来(ViewHolder机制)

当getTag()不为空的时候,又会去判断返回的对象是不是继承自ViewHolder,如果不是,就抛出异样

当须要自定义回复布局的时候实现这个回调。

例子

/** * 自定义评论布局 * 实现CustomReplyItemCallback<R>回调 * 把自定义回复模型Reply放入泛型参数中 * 而后实现buildReplyItem()办法进行自定义布局 */public class CustomReplyItem implements CustomReplyItemCallback<Reply> {    @Override    public View buildReplyItem(int groupPosition, int childPosition, boolean isLastReply, Reply reply, LayoutInflater inflater, View convertView, ViewGroup parent) {        //必须应用ViewHolder机制        //自定义ReplyItemViewHolder必须继承自com.jidcoo.android.widget.commentview.view.ViewHolder        //在自定义回复布局中最外层必须应用LinearLayout        //并将这个LinearLayout的id设置为“reply_rootView”,否则会报错。        ReplyItemViewHolder replyItemViewHolder=null;        if(convertView==null){            //引入自定义布局            convertView=inflater.inflate(R.layout.my_replyItem_layout);            //实例化ReplyItemViewHolder            replyItemViewHolder=new ReplyItemViewHolder(convertView);            //必须把ReplyItemViewHolder缓存在convertView中            //否则报错            convertView.setTag(replyItemViewHolder);            //必须把ReplyItemViewHolder缓存在convertView中        }else{            replyItemViewHolder=(ReplyItemViewHolder)convertView.getTag();        }        //对控件进行操作        //setText()……        //对控件进行操作        return convertView;    }}
2.3.3.3、OnPullRefreshCallback(下拉刷新回调)
/** * CommentView下拉刷新回调 * @author Jidcoo */public interface OnPullRefreshCallback {    /**     * 刷新回调     */    void refreshing();    /**     * 刷新实现回调     */    void complete();    /**     * 刷新失败     * @param msg 错误信息     */    void failure(String msg);}

OnPullRefreshCallback是下拉刷新回调,非必须回调。当实现了这个回调后能够进行下拉刷新,不实现就无奈下拉刷新。看具体需要。

须要下拉刷新性能时实现这个回调。

例子:

public class MyOnPullRefreshCallback implements OnPullRefreshCallback {    @Override    public void refreshing() {        //该办法被调用,示意控件正在刷新状态        //实现你的刷新逻辑        //commentView.refreshComplete(AbstractCommentModel model): 刷新数据实现后调用        //commentView.refreshFailed(String,boolean): 刷新呈现谬误时调用,能够管制是否显示谬误视图    }    @Override    public void complete() {    }    @Override    public void failure(String msg) {        //当刷新失败后显示调用commentView.refreshFailed(String,boolean)办法后        //这个办法会被调用        //msg是refreshFailed()办法中传进来的错误信息    }}
2.3.3.4、OnCommentLoadMoreCallback(上拉加载更多回调)
/** * CommentView加载更多评论回调 * @author Jidcoo */public interface OnCommentLoadMoreCallback{    /**     * 上拉加载更多评论回调     * @param currentPage 以后页码     * @param willLoadPage 下一个页码     * @param isLoadedAllPages 是否曾经加载完所有数据     */    void loading(int currentPage,int willLoadPage,boolean isLoadedAllPages);    /**     * 上拉加载更多评论实现     */    void complete();    /**     * 加载失败     * @param msg 错误信息     */    void failure(String msg);}

OnCommentLoadMoreCallback是上拉加载更多评论回调,非必须回调。当实现了这个回调后能够进行上拉加载更多评论,不实现就无奈上拉加载更多评论。看具体需要。

须要上拉加载更多评论性能时实现这个回调就能够了,和OnPullRefreshCallback的例子基本一致。具体应用例子能够查看相干源码。

2.3.3.5、OnReplyLoadMoreCallback(加载更多回复回调)
/** * CommentView加载更多回复回调<p></p> * 泛型接口中的泛型R是回复数据模型,必须继承自ReplyEnable,查看{@link ReplyEnable} * @author Jidcoo */public interface OnReplyLoadMoreCallback<R extends ReplyEnable> {    /**     * 加载更多回复回调     * @param reply 对应回复的数据     * @param willLoadPage     */    void loading(R reply, int willLoadPage);    /**     * 加载更多回复实现回调     */    void complete();    /**     * 加载失败     * @param msg 错误信息     */    void failure(String msg);}

OnReplyLoadMoreCallback是一个泛型回调,是加载更多回复回调,非必须回调。OnReplyLoadMoreCallback< R extends ReplyEnable>承受一个继承自ReplyEnable类的自定义回复数据模型类。具体应用例子能够查看相干源码。

2.3.3.6、OnScrollCallback(滚动事件回调)
/** * CommentView 滚动事件回调 * @author Jidcoo */public interface OnScrollCallback {    /**     * 滚动回调     * @param view     * @param firstVisibleItem     * @param visibleItemCount     * @param totalItemCount     */    void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int            totalItemCount);    /**     * 滚动状态回调     * @param view     * @param scrollState     */    void onScrollStateChanged(AbsListView view,int scrollState);    /**     * 滚动回调     * @param v     * @param scrollX     * @param scrollY     * @param oldScrollX     * @param oldScrollY     */    void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);}

OnScrollCallback提供了控件的所有滚动事件的回调,非必须回调。能够通过实现这个回调来监听控件滚动事件。

2.3.3.7、OnItemClickCallback(Item点击事件回调)
/** * CommentView中评论Item和回复Item点击事件回调 * 泛型接口中的C、R泛型:<p></p> * 1、C是评论数据模型,必须继承自CommentEnable,查看{@link CommentEnable}<p></p> * 2、R是回复数据模型,必须继承自ReplyEnable,查看{@link ReplyEnable}<p></p> * @author Jidcoo */public interface OnItemClickCallback<C extends CommentEnable,R extends ReplyEnable> {    /**     * 评论Item点击回调事件     * @param position 被点击Item的地位     * @param comment 被点击Item所对应的数据     * @param view 被点击Item的View     */    void commentItemOnClick(int position, C comment, View view);    /**     * 回复Item点击回调事件     * @param c_position 被点击Item所在的父级地位     * @param r_position 被点击Item所在位置     * @param reply 被点击Item所对应的数据     * @param view 被点击Item的View     */    void replyItemOnClick(int c_position, int r_position, R reply, View view);}

OnItemClickCallback类是一个承受泛型参数的Item点击事件回调,OnItemClickCallback<C extends CommentEnable,R extends ReplyEnable>中泛型C、R对应的就是自定义评论数据模型和回复数据模型。当控件中评论Item和回复Item被点击时,回调中绝对应的commentItemOnClick和replyItemOnClick办法就会被调用。

须要监听控件Item的点击事件就实现这个接口。具体应用例子能够查看相干源码。

2.3.3.8、CallbackBuilder(回调集)
    public final class CallbackBuilder {        ///////***Callback***//////        public OnPullRefreshCallback onPullRefreshCallback;//下拉刷新回调        public OnCommentLoadMoreCallback onCommentLoadMoreCallback;//加载更多评论回调        public OnReplyLoadMoreCallback onReplyLoadMoreCallback;//加载更多回复回调        public OnItemClickCallback onItemClickCallback;//点击事件回调        public OnScrollCallback onScrollCallback;//滚动事件回调        public CustomCommentItemCallback customCommentItemCallback;//自定义评论布局回调        public CustomReplyItemCallback customReplyItemCallback;//自定义回复布局回调        ///////***Callback***//////        public CallbackBuilder setOnPullRefreshCallback(OnPullRefreshCallback onPullRefreshCallback) {            this.onPullRefreshCallback = onPullRefreshCallback;            return this;        }        public CallbackBuilder setOnCommentLoadMoreCallback(OnCommentLoadMoreCallback onCommentLoadMoreCallback) {            this.onCommentLoadMoreCallback = onCommentLoadMoreCallback;            return this;        }        public CallbackBuilder setOnReplyLoadMoreCallback(OnReplyLoadMoreCallback onReplyLoadMoreCallback) {            this.onReplyLoadMoreCallback = onReplyLoadMoreCallback;            return this;        }        public CallbackBuilder setOnItemClickCallback(OnItemClickCallback onItemClickCallback) {            this.onItemClickCallback = onItemClickCallback;            return this;        }        public CallbackBuilder setOnScrollCallback(OnScrollCallback onScrollCallback) {            this.onScrollCallback = onScrollCallback;            return this;        }        public CallbackBuilder customCommentItem(CustomCommentItemCallback customCommentItemCallback) {            this.customCommentItemCallback = customCommentItemCallback;            return this;        }        public CallbackBuilder customReplyItem(CustomReplyItemCallback customReplyItemCallback) {            this.customReplyItemCallback = customReplyItemCallback;            return this;        }        public CommentView buildCallback() {            return initialize(this);        }    }

CallbackBuilder是一个构建控件的所有回调的Builder类,是CommentView类中的外部类。下面说到的所有的Callback都须要通过这个Builder类进行设置,构建回调须要获取这个Builder类的实例,而后再往这个Builder类设置须要的回调。

获取这个Builder类的实例通过CommentView.callbackBuilder()办法获取。当Builder实例为NULL时返回一个新实例,不为NULL就返回原来构建的实例。

能够看到,在buildCallback()办法中会调用CommentView的initialize()办法对Builder类的回调实例进行初始化和进一步装载。留神:无论是否须要设置回调,buildCallback()办法必须调用,如果不调用buildCallback()办法,控件处于未初始化状态,不会展现任何数据和成果。。具体起因可自行查看com.jidcoo.android.widget.commentview.operator包下的CommentViewOperator类源码。

也就是说,就算在不须要设置任何回调的状况下,buildCallback()都必须调用。调用如下:

commentView.callbackBuilder().buildCallback();

初始化回调例子:

CommentView commentView;commentView.callbackBuilder()           .setOnPullRefreshCallback(你的回调实例)           .onItemClickCallback(你的回调实例)           ......           //设置实现后必须调用CallbackBuilder的buildCallback()办法,否则设置的回调有效,控件也无奈失常显示。           //无论是否设置回调,buildCallback()办法都必须调用。           .buildCallback();
2.3.3.9、总结

好了,到当初为止,CommentView控件的回调类根本介绍实现。写的时候感觉非常啰嗦,但最初还是写下来了。因为这些回调类尽管都是非必须回调,然而想实现更多功能都须要用到这些回调

2.4、款式配置器

/** * 非可自定义控件款式配置器 * <p>该款式配置器针对非自定义控件的款式的具体配置</p> * <p>可依据具体需要配置这部分的控件的款式</p> * <p>自定义款式配置器必须继承自本类</p> * <br></br> * <h3>款式变量阐明:</h3> * <p>1、refreshViewColor </p> * <p>类型:String</p> * <p>阐明:下拉刷新后呈现的圆形滚动条的色彩</p> * <p>赋值样例:#000000</p> * <p>2、lmv_showText(失常显示状态) </p> * <p>类型:String</p> * <p>阐明:当回复数据Item能够加载更多(分页加载)时,在最初一条回复Item的View上面显示的文字</p> * <p>赋值样例:开展更多回复</p> * <p>3、lmv_textSize </p> * <p>类型:int</p> * <p>阐明:第二条阐明中的文字大小</p> * <p>赋值样例:14</p> * <p>4、lmv_textColor </p> * <p>类型:String</p> * <p>阐明:第二条阐明中的文字色彩</p> * <p>赋值样例:#000000</p> * <p>5、lmv_textStyle </p> * <p>类型:Typeface,查看{@link Typeface}</p> * <p>阐明:第二条阐明中的文字款式(失常、斜体、加粗)</p> * <p>赋值样例:Typeface.defaultFromStyle(Typeface.NORMAL)</p> * <p>6、lmv_loading_showText(加载中状态) </p> * <p>类型:String</p> * <p>阐明:当回复数据Item能够加载更多(分页加载)时,在最初一条回复Item的加载更多View被点击后显示的文字</p> * <p>赋值样例:加载中</p> * <p>7、lmv_loading_textSize </p> * <p>类型:int</p> * <p>阐明:第六条阐明中的文字大小</p> * <p>赋值样例:14</p> * <p>8、lmv_loading_textColor </p> * <p>类型:String</p> * <p>阐明:第六条阐明中的文字色彩</p> * <p>赋值样例:#000000</p> * <p>9、lmv_loading_textStyle </p> * <p>类型:Typeface,查看{@link Typeface}</p> * <p>阐明:第六条阐明中的文字款式(失常、斜体、加粗)</p> * <p>赋值样例:Typeface.defaultFromStyle(Typeface.NORMAL)</p> * <p>10、lmv_loading_progressBarColor </p> * <p>类型:String</p> * <p>阐明:当最初一条回复ItemView的可加载更多View状态为正在加载状态时, * 第六条阐明中的文字左边会显示一个圆形progressBar以加强UI加载成果, * 该属性是这个progressBar的色彩值</p> * <p>赋值样例:#000000</p> * <p>11、lmv_loading_progressBarSize </p> * <p>类型:int(要求单位:px,因为须要把(dp/dip值转换为px值))</p> * <p>阐明:第十条阐明中的progressBar控件的大小尺寸</p> * <p>赋值样例:ViewUtil.dpToPx(14)</p> * <p>12、lmv_adjustMargins </p> * <p>类型:Boolean(默认为false)</p> * <p>阐明:是否调整最初一条回复Item的加载更多View的边距,如果自定义回复布局,可能须要 * 调整这个View的边距来使布局更好看,个别状况下都须要调整边距,所以这个属性个别都为true</p> * <p>赋值样例:true</p> * <p>13、lmv_adjustMarginsLeft </p> * <p>类型:int(要求单位:px,因为须要把(dp/dip值转换为px值))</p> * <p>阐明:第十二条阐明中的view的右边距,如果lmv_adjustMargins为false,则此属性有效</p> * <p>赋值样例:ViewUtil.dpToPx(14)</p> * <p>14、lmv_adjustMarginsTop </p> * <p>类型:int(要求单位:px,因为须要把(dp/dip值转换为px值))</p> * <p>阐明:第十二条阐明中的view的上边距,如果lmv_adjustMargins为false,则此属性有效</p> * <p>赋值样例:ViewUtil.dpToPx(14)</p> * <p>15、lmv_adjustMarginsRight </p> * <p>类型:int(要求单位:px,因为须要把(dp/dip值转换为px值))</p> * <p>阐明:第十二条阐明中的view的左边距,如果lmv_adjustMargins为false,则此属性有效</p> * <p>赋值样例:ViewUtil.dpToPx(14)</p> * <p>16、lmv_adjustMarginsBottom </p> * <p>类型:int(要求单位:px,因为须要把(dp/dip值转换为px值))</p> * <p>阐明:第十二条阐明中的view的下边距,如果lmv_adjustMargins为false,则此属性有效</p> * <p>赋值样例:ViewUtil.dpToPx(14)</p> * <p>17、dividerColor </p> * <p>类型:String</p> * <p>阐明:控件Item的分割线色彩(蕴含一级分割线和二级分割线)</p> * <p>赋值样例:#000000</p> * <p>18、dividerHeight </p> * <p>类型:int(要求单位:px,因为须要把(dp/dip值转换为px值))</p> * <p>阐明:控件Item的分割线高度(蕴含一级分割线和二级分割线)</p> * <p>赋值样例:ViewUtil.dpToPx(1),高度个别为1dp</p> * <p>19、isDrawChildDivider </p> * <p>类型:Boolean(默认为false)</p> * <p>阐明:是否绘制某一条评论下的最初一条回复Item与下一条评论的Item的<u>分割线</u>,默认不绘制, * 可依据具体须要抉择是否绘制</p> * <p>赋值样例:true</p> * <p>20、c_divider_adjustMargins </p> * <p>类型:Boolean(默认为false)</p> * <p>阐明:是否调整第十七条阐明中的分割线的边距,如果isDrawDivider为false,则此属性有效。 * 因为第十九条阐明中的分割线宽度固定为match_parent(即铺满全屏),然而能够通过调整分割线的边距 * 来间接调整分割线的宽度和地位,可依据具体须要抉择是否调整分割线的边距</p> * <p>赋值样例:true</p> * <p>21、c_divider_adjustMarginsLeft </p> * <p>类型:int(要求单位:px,因为须要把(dp/dip值转换为px值))</p> * <p>阐明:第十九条阐明中的分割线的右边距,如果divider_adjustMargins为false,则此属性有效</p> * <p>赋值样例:ViewUtil.dpToPx(1)</p> * <p>22、c_divider_adjustMarginsTop </p> * <p>类型:int(要求单位:px,因为须要把(dp/dip值转换为px值))</p> * <p>阐明:第十九条阐明中的分割线的上边距,如果divider_adjustMargins为false,则此属性有效</p> * <p>赋值样例:ViewUtil.dpToPx(1)</p> * <p>23、c_divider_adjustMarginsRight </p> * <p>类型:int(要求单位:px,因为须要把(dp/dip值转换为px值))</p> * <p>阐明:第十九条阐明中的分割线的左边距,如果divider_adjustMargins为false,则此属性有效</p> * <p>赋值样例:ViewUtil.dpToPx(1)</p> * <p>24、c_divider_adjustMarginsBottom </p> * <p>类型:int(要求单位:px,因为须要把(dp/dip值转换为px值))</p> * <p>阐明:第十九条阐明中的分割线的下边距,如果divider_adjustMargins为false,则此属性有效</p> * <p>赋值样例:ViewUtil.dpToPx(1)</p> * <p>25、f_divider_adjustMargins </p> * <p>类型:Boolean(默认为false)</p> * <p>阐明:是否调整评论item的分割线的边距</p> * <p>赋值样例:true</p> * <p>26、f_divider_adjustMarginsLeft </p> * <p>类型:int(要求单位:px,因为须要把(dp/dip值转换为px值))</p> * <p>阐明:评论item的分割线的右边距</p> * <p>赋值样例:ViewUtil.dpToPx(1)</p> * <p>27、f_divider_adjustMarginsTop </p> * <p>类型:int(要求单位:px,因为须要把(dp/dip值转换为px值))</p> * <p>阐明:评论item的分割线的上边距</p> * <p>赋值样例:ViewUtil.dpToPx(1)</p> * <p>28、f_divider_adjustMarginsRight </p> * <p>类型:int(要求单位:px,因为须要把(dp/dip值转换为px值))</p> * <p>阐明:评论item的分割线的左边距</p> * <p>赋值样例:ViewUtil.dpToPx(1)</p> * <p>29、f_divider_adjustMarginsBottom </p> * <p>类型:int(要求单位:px,因为须要把(dp/dip值转换为px值))</p> * <p>阐明:评论item的分割线的下边距</p> * <p>赋值样例:ViewUtil.dpToPx(1)</p> * <p>30、lm_footerProgressBarSize </p> * <p>类型:int(要求单位:px,因为须要把(dp/dip值转换为px值))</p> * <p>阐明:上拉刷新时,控件底部会有一个圆形ProgressBar来减少加载中的UI成果,此属性为ProgressBar的大小</p> * <p>赋值样例:ViewUtil.dpToPx(1)</p> * <p>31、lm_footerProgressBarColor </p> * <p>类型:String</p> * <p>阐明:第三十条阐明中的ProgressBar的色彩</p> * <p>赋值样例:#000000</p> * <p>32、lm_footerProgressBar_adjustMargins </p> * <p>类型:Boolean(默认为false)</p> * <p>阐明:是否调整第三十条阐明中的ProgressBar的边距</p> * <p>赋值样例:true</p> * <p>33、lm_footerProgressBar_adjustMarginsLeft </p> * <p>类型:int(要求单位:px,因为须要把(dp/dip值转换为px值))</p> * <p>阐明:第三十条阐明中的ProgressBar的右边距,如果lm_footerProgressBar_adjustMargins为false,则此属性有效</p> * <p>赋值样例:ViewUtil.dpToPx(14)</p> * <p>34、lm_footerProgressBar_adjustMarginsTop </p> * <p>类型:int(要求单位:px,因为须要把(dp/dip值转换为px值))</p> * <p>阐明:第三十条阐明中的ProgressBar的上边距,如果lm_footerProgressBar_adjustMargins为false,则此属性有效</p> * <p>赋值样例:ViewUtil.dpToPx(14)</p> * <p>35、lm_footerProgressBar_adjustMarginsRight </p> * <p>类型:int(要求单位:px,因为须要把(dp/dip值转换为px值))</p> * <p>阐明:第三十条阐明中的ProgressBar的左边距,如果lm_footerProgressBar_adjustMargins为false,则此属性有效</p> * <p>赋值样例:ViewUtil.dpToPx(14)</p> * <p>36、lm_footerProgressBar_adjustMarginsBottom </p> * <p>类型:int(要求单位:px,因为须要把(dp/dip值转换为px值))</p> * <p>阐明:第三十条阐明中的ProgressBar的下边距,如果lm_footerProgressBar_adjustMargins为false,则此属性有效</p> * <p>赋值样例:ViewUtil.dpToPx(14)</p> * <p>37、lm_footer_text</p> * <p>类型:String</p> * <p>阐明:当所有数据加载实现后控件底部textView显示的文字</p> * <p>赋值样例:哈哈,所有评论都在这了</p> * <p>38、lm_footer_textColor</p> * <p>类型:String</p> * <p>阐明:第三十七条阐明中的textView文字的色彩</p> * <p>赋值样例:#666666</p> * <p>39、lm_footer_textSize</p> * <p>类型:int</p> * <p>阐明:第三十七条阐明中的textView文字的大小</p> * <p>赋值样例:14</p> * <p>40、lm_footer_textStyle</p> * <p>类型:Typeface</p> * <p>阐明:第三十七条阐明中的textView文字的款式(失常,斜体、加粗)</p> * <p>赋值样例:Typeface.defaultFromStyle(Typeface.NORMAL)</p> * <p>41、lm_footer_text_adjustMargins </p> * <p>类型:Boolean(默认为false)</p> * <p>阐明:是否调整第三十七条阐明中的textView的边距</p> * <p>赋值样例:true</p> * <p>42、lm_footer_text_adjustMarginsLeft </p> * <p>类型:int(要求单位:px,因为须要把(dp/dip值转换为px值))</p> * <p>阐明:第三十七条阐明中的textView的右边距,如果lm_footer_text_adjustMargins为false,则此属性有效</p> * <p>赋值样例:ViewUtil.dpToPx(14)</p> * <p>43、lm_footer_text_adjustMarginsTop </p> * <p>类型:int(要求单位:px,因为须要把(dp/dip值转换为px值))</p> * <p>阐明:第三十七条阐明中的textView的上边距,如果lm_footer_text_adjustMargins为false,则此属性有效</p> * <p>赋值样例:ViewUtil.dpToPx(14)</p> * <p>44、lm_footer_text_adjustMarginsRight </p> * <p>类型:int(要求单位:px,因为须要把(dp/dip值转换为px值))</p> * <p>阐明:第三十七条阐明中的textView的左边距,如果lm_footer_text_adjustMargins为false,则此属性有效</p> * <p>赋值样例:ViewUtil.dpToPx(14)</p> * <p>45、lm_footer_text_adjustMarginsBottom </p> * <p>类型:int(要求单位:px,因为须要把(dp/dip值转换为px值))</p> * <p>阐明:第三十七条阐明中的textView的下边距,如果lm_footer_text_adjustMargins为false,则此属性有效</p> * <p>赋值样例:ViewUtil.dpToPx(14)</p> * <br><br> * @author Jidcoo */public abstract class ViewStyleConfigurator{    /**     * 下拉刷新控件色彩     */    public  String refreshViewColor;    //*********//回复加载更多控件款式//*************//    //Part1//    public  String lmv_showText;    public  int lmv_textSize;    public  String lmv_textColor;    public  Typeface lmv_textStyle;    //Part2//    public  String lmv_loading_showText;    public  int lmv_loading_textSize;    public  String lmv_loading_textColor;    public  Typeface lmv_loading_textStyle;    public  String lmv_loading_progressBarColor;    public  int lmv_loading_progressBarSize;    //Part3//    public  boolean lmv_adjustMargins;    public  int lmv_adjustMarginsLeft;//dp    public  int lmv_adjustMarginsTop;//dp    public  int lmv_adjustMarginsRight;//dp    public  int lmv_adjustMarginsBottom;//dp    //*********//回复加载更多控件款式//*************//    //*********//分割线总款式//*************//    public  String dividerColor;    public  int dividerHeight;//dp    //*********//分割线总款式//*************//    //*********//回复Item最初一项的下划线(分款式)//*************//    public boolean isDrawChildDivider;    public  boolean c_divider_adjustMargins;    public  int c_divider_adjustMarginsLeft;//dp    public  int c_divider_adjustMarginsTop;//dp    public  int c_divider_adjustMarginsRight;//dp    public  int c_divider_adjustMarginsBottom;//dp    //*********//回复Item最初一项的下划线(分款式)//*************//    //*********//评论Item的分割线(分款式)//*************//    /**     * 评论Item的分割线色彩、高度与回复Item的分割线一样     */    public boolean  f_divider_adjustMargins;    public  int f_divider_adjustMarginsLeft;//dp    public  int f_divider_adjustMarginsTop;//dp    public  int f_divider_adjustMarginsRight;//dp    public  int f_divider_adjustMarginsBottom;//dp    //*********//评论Item的分割线(分款式)//*************//    //*********//底部上拉加载更多圆形ProgressBar的大小和色彩//*************//    public int lm_footerProgressBarSize=12;//dp    public String lm_footerProgressBarColor;    public boolean  lm_footerProgressBar_adjustMargins;    public  int lm_footerProgressBar_adjustMarginsLeft;//dp    public  int lm_footerProgressBar_adjustMarginsTop;//dp    public  int lm_footerProgressBar_adjustMarginsRight;//dp    public  int lm_footerProgressBar_adjustMarginsBottom;//dp    //*********//底部上拉加载更多圆形ProgressBar的大小和色彩//*************//    //*********//底部上拉加载更多实现后的textView//*************//    //文本,色彩、大小、款式、边距    public String lm_footer_text;    public String lm_footer_textColor;    public int lm_footer_textSize=12;    public Typeface lm_footer_textStyle;    public boolean  lm_footer_text_adjustMargins;    public  int lm_footer_text_adjustMarginsLeft;//dp    public  int lm_footer_text_adjustMarginsTop;//dp    public  int lm_footer_text_adjustMarginsRight;//dp    public  int lm_footer_text_adjustMarginsBottom;//dp    //*********//底部上拉加载更多实现后的textView//*************//    }

ViewStyleConfigurator是款式配置器抽象类。该款式配置器针对固有控件的款式的具体配置。抽象类中的所有变量都是用来设置固有控件的款式。所有的款式变量的解释和阐明都有具体充沛的正文。在这就不一一阐明了。

在自定义款式的时候创立一个类继承自这个抽象类,而后对须要自定义的款式变量赋值就能够了。

例子:(这里贴出的是我的项目中的默认款式配置器,自定义款式配置器能够参照defaults包下的DefaultViewStyleConfigurator类)

/** * 默认款式配置器 * <p>此配置器为规范模板</p> * <p>自定义款式配置器必须继承自ViewStyleConfigurator,查看{@link ViewStyleConfigurator}</p> * <p>款式变量阐明,请查看{@link ViewStyleConfigurator}</p> * <p>实际上,自定义款式配置器能够间接复制本类,而后再依据具体把款式批改就好了</p> * @author Jidcoo */public class DefaultViewStyleConfigurator extends ViewStyleConfigurator {       public DefaultViewStyleConfigurator(Context context) {        /**         * 下拉刷新控件色彩         */        refreshViewColor = "#D81B60";        //*********//回复加载更多控件款式//*************//        //Part1//        lmv_showText = "开展更多回复";        lmv_textSize = 14;        lmv_textColor = "#D81B60";        lmv_textStyle = Typeface.defaultFromStyle(Typeface.NORMAL);        //Part2//        lmv_loading_showText = "加载中";        lmv_loading_textSize = 14;        lmv_loading_textColor = "#666666";        lmv_loading_textStyle = Typeface.defaultFromStyle(Typeface.NORMAL);        lmv_loading_progressBarColor = "#666666";        lmv_loading_progressBarSize = ViewUtil.dpToPx(14, context);        //Part3//        lmv_adjustMargins = true;        lmv_adjustMarginsLeft = ViewUtil.dpToPx(88, context);//dp        lmv_adjustMarginsTop = ViewUtil.dpToPx(5, context);//dp        lmv_adjustMarginsRight = 0;//dp        lmv_adjustMarginsBottom = ViewUtil.dpToPx(5, context);//dp        //*********//回复加载更多控件款式//*************//        //*********//分割线总款式//*************//        dividerColor = "#f0f0f0";        dividerHeight = ViewUtil.dpToPx(1, context);//dp        //*********//分割线总款式//*************//        //*********//回复Item最初一项的下划线//*************//        isDrawChildDivider = true;        c_divider_adjustMargins = true;        c_divider_adjustMarginsLeft = ViewUtil.dpToPx(88, context);//dp        c_divider_adjustMarginsTop = ViewUtil.dpToPx(5, context);//dp        c_divider_adjustMarginsRight = 0;//dp        c_divider_adjustMarginsBottom = ViewUtil.dpToPx(5, context);//dp        //*********//回复Item最初一项的下划线//*************//        //*********//评论Item的分割线//*************//        f_divider_adjustMargins = false;        f_divider_adjustMarginsLeft = 0;//dp        f_divider_adjustMarginsTop = 0;//dp        f_divider_adjustMarginsRight = 0;//dp        f_divider_adjustMarginsBottom = 0;//dp        //*********//评论Item的分割线//*************//        //*********//底部上拉加载更多圆形ProgressBar的大小和色彩//*************//        lm_footerProgressBarSize = ViewUtil.dpToPx(20, context);//dp        lm_footerProgressBarColor = "#c3c8cb";        lm_footerProgressBar_adjustMargins = false;        lm_footerProgressBar_adjustMarginsLeft = 0;//dp        lm_footerProgressBar_adjustMarginsTop = 0;//dp        lm_footerProgressBar_adjustMarginsRight = 0;//dp        lm_footerProgressBar_adjustMarginsBottom = 0;//dp        //*********//底部上拉加载更多圆形ProgressBar的大小和色彩//*************//        //*********//底部上拉加载更多实现后的textView//*************//        //文本,色彩、大小、款式、边距        lm_footer_text = "评论都给你看完了哦~";        lm_footer_textColor = "#c3c8cb";        lm_footer_textSize = 14;        lm_footer_textStyle = Typeface.defaultFromStyle(Typeface.NORMAL);        lm_footer_text_adjustMargins = false;        lm_footer_text_adjustMarginsLeft = 0;//dp        lm_footer_text_adjustMarginsTop = 0;//dp        lm_footer_text_adjustMarginsRight = 0;//dp        lm_footer_text_adjustMarginsBottom = 0;//dp        //*********//底部上拉加载更多实现后的textView//*************//    }}

2.5、总结

超长的篇幅解释阐明应用控件中须要用到的框架类,能够说是应用CommentView的实践局部。超长超啰嗦,然而这些阐明都是十分重要的,也是必须的。为什么这么说呢?因为下面的这些框架类的阐明和例子都是在应用CommentView过程中业务层须要用到的,也就是说了解了下面简明扼要的解释后,应用CommentView就非常简单了

所以只管非常啰嗦,然而有些货色须要特地阐明一下。以上都是实践局部(非常干燥、又长又臭……)有了上述这些对整个控件框架的整体理解,应用这个控件库就非常容易了

留神:我的项目是应用AndroidX库开发,局部控件是AndroidX库的控件,如果你的我的项目没有迁徙到AndroidX库开发,能够把CommentView控件库中的那些AndroidX库控件批改为你以后我的项目的Android库的控件就能够了。

上面就要讲CommentView理论应用局部了(了解了下面的实践,说实话应用没有任何技术含量)。

三、控件的应用

3.1、控件办法介绍

以下是控件对外颁布的所有业务办法。
办法参数阐明
.callbackBuilder()\获取CallbackBuilder实例设置须要的回调, 无论是否设置回调,都必须调用.callbackBuilder().buildCallback()办法实现初始化。并且初始化必须在loadComplete()调用之前实现。
.loadComplete()AbstractCommentModel首次加载数据时调用此办法, 留神:设置回调,设置空数据视图、设置谬误视图、设置自定义款式配置器,设置头布局,这5个办法都必须要在loadComplete()这个办法调用之前调用,否则这5个办法生效。
.loadFailed()boolean isShowErrorView首次加载数据失败时调用,boolean参数示意是否显示谬误视图。
.refreshComplete()AbstractCommentModel刷新数据实现后调用,传入刷新后的数据实体类。该办法调用后OnPullRefreshCallback的complete()办法会被调用。
.refreshFailed()String msg,boolean isShowErrorView数据刷新失败时调用,msg示意错误信息,boolean参数示意是否显示谬误视图。该办法调用后OnPullRefreshCallback的failure(String msg)办法会被调用。
.loadMoreComplete()AbstractCommentModel加载更多评论数据实现后调用,传入一个数据实体类。该办法调用后OnCommentLoadMoreCallback的complete()办法会被调用。
.loadMoreFailed()String msg,boolean isShowErrorView加载更多评论数据失败时调用,msg示意错误信息,boolean参数示意是否显示谬误视图。该办法调用后OnCommentLoadMoreCallback的failure(String msg)办法会被调用。
.loadMoreReplyComplete()AbstractCommentModel加载更多回复数据实现后调用,传入一个数据实体类。该办法调用后OnReplyLoadMoreCallback的complete()办法会被调用。
.loadMoreReplyFailed()String msg,boolean isShowErrorView加载更多评论数据失败时调用,msg示意错误信息,boolean参数示意是否显示谬误视图。该办法调用后OnReplyLoadMoreCallback的failure(String msg)办法会被调用。
.getCommentList()\获取所有评论数据返回List
.getReplyList()int position依据position所在的评论获取所在评论的所有回复数据返回List
.addComment()C<?extend CommentEnable> comment增加一条评论数据到以后的评论数据汇合中
.addReply()R<?extend ReplyEnable> comment,int position增加一条回复数据到position所在的评论的回复数据汇合中
.setEmptyView()View view为控件设置空数据视图,留神:此办法必须在loadComplete()办法调用前调用,也就是说要在首次加载数据前调用,否则此办法有效。
.setErrorView()View view为控件设置谬误视图,留神:此办法必须在loadComplete()办法调用前调用,也就是说要在首次加载数据前调用,否则此办法有效。
.addHeaderView()View view,boolean canClickable为控件增加头视图,并且设置该视图是否响应点击事件。留神:此办法倡议在loadComplete()办法调用前调用。
.removeHeaderView()View view移除以后控件的对应的头视图
.setViewStyleConfigurator()ViewStyleConfigurator设置自定义的款式配置器,留神:此办法必须在loadComplete()办法调用前调用,也就是说要在首次加载数据前调用,否则此办法有效。

3.2、根本应用

第一步:引入控件库:

有两种办法:

1、近程仓库

在module的build.gradle中增加jcenter仓库:

buildscript {    repositories {        jcenter()    }}

而后在dependencies模块中增加依赖即可:

implementation 'com.jidcoo.android.widget.commentview:CommentView:1.0.0'

2、本地仓库

把源码包下载下来,把commentview库放在与以后module的同级。

而后在dependencies模块中增加本地依赖即可:

implementation project(path: ':commentview')

第二步:引入控件:

控件的引入办法有两种:

1、XML布局文件中引入

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical" android:layout_width="match_parent"    android:id="@+id/container"    android:layout_height="match_parent">  <com.jidcoo.android.widget.commentview.CommentView      android:id="@+id/commentView"      android:layout_width="match_parent"      android:layout_height="match_parent"/></LinearLayout>

而后在Activity中实例化控件。

2、Java代码中动态创建

//控件容器LinearLayout mContainer;CommentView commentView=new CommentView(this,mContainer);

CommentView的构造方法:
public CommentView(Context context, ViewGroup attachTo)

第一个参数是Activity的上下文。第二个参数是ViewGroup,也就是将控件挂靠在这个指定的布局上。留神:当attachTo参数为空时,须要手动把控件增加到布局中,否则控件将不会显示

第三步:初始化控件:

设置自定义款式配置器

如果应用默认款式的话就不须要调用这个办法,如果应用自定义款式配置器时调用该办法必须在loadComplete()调用前调用,否则该办法有效。

commentView.setViewStyleConfigurator(你的款式配置器);

设置空数据视图
如果不须要设置空数据视图就不须要调用这个办法,如果须要设置空数据视图时调用该办法必须在loadComplete()调用前调用,否则该办法有效。

commentView.setEmptyView(你的空数据视图);

设置谬误视图
如果不须要设置谬误视图就不须要调用这个办法,如果须要设置谬误视图时调用该办法必须在loadComplete()调用前调用,否则该办法有效。

commentView.setErrorView(你的谬误视图);

增加控件头视图
如果不须要增加控件头视图就不须要调用这个办法,如果须要增加控件头视图时调用该办法倡议在loadComplete()调用前调用。

commentView.addHeaderView(你的谬误视图,是否响应点击事件);

第四步:初始化回调(十分重要,必须初始化):

无论是否须要设置回调,都要调用.buildCallback()办法实现初始化。

并且初始化回调的工作必须要在loadComplete()办法调用之前(即首次加载数据之前)实现,否则控件将无奈失常应用。

反对的回调:
1、CustomCommentItemCallback:自定义评论布局回调
2、CustomReplyItemCallback:自定义回复布局回调
3、OnPullRefreshCallback:上拉刷新回调
4、OnCommentLoadMoreCallback:下拉加载更多评论回调
5、OnReplyLoadMoreCallback:加载更多回复回调
6、OnItemClickCallback:Item的点击事件回调
7、OnScrollCallback:控件滚动事件回调

当须要设置回调时:

设置完回调后必须调用.buildCallback()办法,否则回调不会失效,控件也无奈失常应用。

commentView.callbackBuilder()           .setOnPullRefreshCallback(你的回调实例)           .onItemClickCallback(你的回调实例)           ......设置更多回调           ......设置更多回调           //设置实现后必须调用CallbackBuilder的buildCallback()办法,否则设置的回调有效,控件也无奈失常显示。           //无论是否设置回调,buildCallback()办法都必须调用。           .buildCallback();

当不须要设置回调时:

必须调用.buildCallback()办法,否则控件也无奈失常应用。

commentView.callbackBuilder().buildCallback();

第五步:设置数据:

当所有的初始化工作都实现后,就能够申请后盾返回评论数据或加载本地数据为控件设置数据了。实现设置数据后,控件就能正确显示评论数据了。

commentView.loadComplete(你的数据模型实体类);

3.3、具体实例(自定义仿微信公众号文章评论)

布局文件:custom_use.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical"     android:layout_width="match_parent"    android:background="#f0f0f0"    android:layout_height="match_parent">  <com.jidcoo.android.widget.commentview.CommentView      android:id="@+id/commentView"      android:layout_width="match_parent"      android:layout_height="match_parent"/></LinearLayout>

自定义评论布局:custom_item_comment.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:orientation="horizontal">    <com.jidcoo.android.widgettest.custom.SampleCircleImageView        android:id="@+id/ico"        android:layout_width="28dp"        android:layout_height="28dp"        android:layout_marginLeft="14dp"        android:layout_marginTop="18dp"        app:radius="2dp"        app:src="@drawable/teaser" />    <RelativeLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_marginTop="16dp"        android:layout_marginRight="14dp"        android:layout_marginBottom="4dp">        <TextView            android:id="@+id/user"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_marginLeft="8dp"            android:textColor="#666666"            android:textSize="13sp" />        <ImageView            android:id="@+id/comment_item_like"            android:layout_width="18dp"            android:layout_height="18dp"            android:layout_alignParentRight="true"            android:layout_marginRight="30dp"            android:padding="3dp"            android:src="@drawable/pxjh"            android:visibility="visible" />        <TextView            android:id="@+id/prizes"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_alignParentRight="true"            android:textColor="#666666"            android:textSize="13sp" />        <TextView            android:id="@+id/data"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_marginLeft="8dp"            android:layout_marginTop="18dp"            android:textColor="#1C1C1C" />    </RelativeLayout></LinearLayout>

自定义回复布局:custom_item_reply.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout    xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:id="@+id/reply_rootView"    android:layout_height="wrap_content"    android:orientation="vertical"><RelativeLayout    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:orientation="horizontal">    <View        android:id="@+id/line"        android:layout_width="2dp"        android:layout_height="wrap_content"        android:layout_alignTop="@id/right"        android:layout_alignBottom="@id/right"        android:layout_marginLeft="52dp"        android:layout_marginTop="2dp"        android:layout_marginBottom="2dp"        android:background="#c3c8cb" />    <RelativeLayout        android:id="@+id/right"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_marginTop="10dp"        android:layout_marginRight="14dp"        android:layout_marginBottom="4dp"        android:layout_toRightOf="@id/line">        <TextView            android:id="@+id/user"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_marginLeft="6dp"            android:textColor="#666666"            android:textSize="13sp" />        <ImageView            android:id="@+id/comment_item_like"            android:layout_width="18dp"            android:layout_height="18dp"            android:layout_alignParentRight="true"            android:layout_marginRight="30dp"            android:padding="3dp"            android:src="@drawable/pxjh"            android:visibility="visible" />        <TextView            android:id="@+id/prizes"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_alignParentRight="true"            android:textColor="#666666"            android:textSize="13sp" />        <TextView            android:id="@+id/data"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_marginLeft="6dp"            android:layout_marginTop="18dp"            android:textColor="#1C1C1C" />    </RelativeLayout></RelativeLayout></LinearLayout>

自定义数据模型:CustomCommentModel.java

import com.jidcoo.android.widget.commentview.model.AbstractCommentModel;import com.jidcoo.android.widget.commentview.model.CommentEnable;import com.jidcoo.android.widget.commentview.model.ReplyEnable;import java.util.List;public class CustomCommentModel extends AbstractCommentModel<CustomCommentModel.CustomComment> {    public List<CustomComment> comments;    @Override    public List<CustomComment> getComments() {        return comments;    }    public class CustomComment extends CommentEnable{        public List<CustomReply> replies;        public String posterName;        public String data;        public CustomComment() {                }                public void setReplies(List<CustomReply> replies) {            this.replies = replies;        }        public String getPosterName() {            return posterName;        }        public void setPosterName(String posterName) {            this.posterName = posterName;        }        public String getData() {            return data;        }        public void setData(String data) {            this.data = data;        }                @Override        public  List<CustomReply> getReplies() {            return replies;        }        public class CustomReply extends ReplyEnable{            public String replierName;            public String data;            public CustomReply() {            }            public String getReplierName() {                return replierName;            }            public void setReplierName(String replierName) {                this.replierName = replierName;            }            public String getData() {                return data;            }            public void setData(String data) {                this.data = data;            }        }    }}

评论布局ViewHolder:CustomCommentViewHolder.java

import android.view.View;import android.widget.TextView;import com.jidcoo.android.widgettest.R;public class CustomCommentViewHolder {      public TextView userName,prizes,comment;      public SampleCircleImageView ico;    public CustomCommentViewHolder(View view) {        userName=view.findViewById(R.id.user);        prizes=view.findViewById(R.id.prizes);        comment=view.findViewById(R.id.data);       ico=view.findViewById(R.id.ico);    }}

回复布局ViewHolder:CustomReplyViewHolder.java

import android.view.View;import android.widget.TextView;import com.jidcoo.android.widget.commentview.view.ViewHolder;import com.jidcoo.android.widgettest.R;public class CustomReplyViewHolder extends ViewHolder {    public TextView userName,prizes,reply;    public CustomReplyViewHolder(View view) {        super(view);        userName=view.findViewById(R.id.user);        prizes=view.findViewById(R.id.prizes);        reply=view.findViewById(R.id.data);    }}

自定义款式配置器:CustomViewStyleConfigurator.java

import android.content.Context;import android.graphics.Typeface;import com.jidcoo.android.widget.commentview.utils.ViewUtil;import com.jidcoo.android.widget.commentview.view.ViewStyleConfigurator;public class CustomViewStyleConfigurator extends ViewStyleConfigurator {    public CustomViewStyleConfigurator(Context context) {        /**         * 下拉刷新控件色彩         */        refreshViewColor = "#D81B60";        //*********//回复加载更多控件款式//*************//        //Part1//        lmv_showText = "开展更多回复";        lmv_textSize = 14;        lmv_textColor = "#D81B60";        lmv_textStyle = Typeface.defaultFromStyle(Typeface.NORMAL);        //Part2//        lmv_loading_showText = "加载中";        lmv_loading_textSize = 14;        lmv_loading_textColor = "#666666";        lmv_loading_textStyle = Typeface.defaultFromStyle(Typeface.NORMAL);        lmv_loading_progressBarColor = "#666666";        lmv_loading_progressBarSize = ViewUtil.dpToPx(14, context);        //Part3//        lmv_adjustMargins = true;        lmv_adjustMarginsLeft = ViewUtil.dpToPx(52, context);//dp        lmv_adjustMarginsTop = ViewUtil.dpToPx(5, context);//dp        lmv_adjustMarginsRight = 0;//dp        lmv_adjustMarginsBottom = ViewUtil.dpToPx(5, context);//dp        //*********//回复加载更多控件款式//*************//        //*********//分割线总款式//*************//        dividerColor = "#00000000";        dividerHeight = ViewUtil.dpToPx(1, context);//dp        //*********//分割线总款式//*************//        //*********//回复Item最初一项的下划线//*************////        isDrawChildDivider = false;//        c_divider_adjustMargins = true;//        c_divider_adjustMarginsLeft = ViewUtil.dpToPx(88, context);//dp//        c_divider_adjustMarginsTop = ViewUtil.dpToPx(5, context);//dp//        c_divider_adjustMarginsRight = 0;//dp//        c_divider_adjustMarginsBottom = ViewUtil.dpToPx(5, context);//dp//        //*********//回复Item最初一项的下划线//*************////        //*********//评论Item的分割线//*************////        f_divider_adjustMargins = false;//        f_divider_adjustMarginsLeft = 0;//dp//        f_divider_adjustMarginsTop = 0;//dp//        f_divider_adjustMarginsRight = 0;//dp//        f_divider_adjustMarginsBottom = 0;//dp        //*********//评论Item的分割线//*************//        //*********//底部上拉加载更多圆形ProgressBar的大小和色彩//*************//        lm_footerProgressBarSize = ViewUtil.dpToPx(20, context);//dp        lm_footerProgressBarColor = "#666666";        lm_footerProgressBar_adjustMargins = false;        lm_footerProgressBar_adjustMarginsLeft = 0;//dp        lm_footerProgressBar_adjustMarginsTop = 0;//dp        lm_footerProgressBar_adjustMarginsRight = 0;//dp        lm_footerProgressBar_adjustMarginsBottom = 0;//dp        //*********//底部上拉加载更多圆形ProgressBar的大小和色彩//*************//        //*********//底部上拉加载更多实现后的textView//*************//        //文本,色彩、大小、款式、边距        lm_footer_text = "到底了(⊙o⊙)!";        lm_footer_textColor = "#c3c8cb";        lm_footer_textSize = 14;        lm_footer_textStyle = Typeface.defaultFromStyle(Typeface.NORMAL);        lm_footer_text_adjustMargins = false;        lm_footer_text_adjustMarginsLeft = 0;//dp        lm_footer_text_adjustMarginsTop = 0;//dp        lm_footer_text_adjustMarginsRight = 0;//dp        lm_footer_text_adjustMarginsBottom = 0;//dp        //*********//底部上拉加载更多实现后的textView//*************//    }}

Avtivity:CustomUseInLocalActivity.java

import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.Toast;import androidx.annotation.Nullable;import androidx.appcompat.app.AppCompatActivity;import com.google.gson.Gson;import com.jidcoo.android.widget.commentview.CommentView;import com.jidcoo.android.widget.commentview.callback.CustomCommentItemCallback;import com.jidcoo.android.widget.commentview.callback.CustomReplyItemCallback;import com.jidcoo.android.widget.commentview.callback.OnCommentLoadMoreCallback;import com.jidcoo.android.widget.commentview.callback.OnItemClickCallback;import com.jidcoo.android.widget.commentview.callback.OnPullRefreshCallback;import com.jidcoo.android.widget.commentview.callback.OnReplyLoadMoreCallback;import com.jidcoo.android.widgettest.R;import com.jidcoo.android.widgettest.simple.LocalServer;import java.lang.ref.WeakReference;/** * 对于CommentView的自定义数据类型和布局的应用实例(应用本地测试数据) * 应用自定义款式配置器,自定义数据模型,自定义布局 * <u>留神:应用自定义数据类型就必须自定义布局实现,否则会抛出数据模型的java.lang.ClassCastException异样</u><br></br> * @author Jidcoo */public class CustomUseInLocalActivity extends AppCompatActivity {    private CommentView commentView;    private Gson gson;    private LocalServer localServer;    //    private static class ActivityHandler extends Handler {        private final WeakReference<CustomUseInLocalActivity> mActivity;        public ActivityHandler(CustomUseInLocalActivity activity) {            mActivity = new WeakReference<CustomUseInLocalActivity>(activity);        }        @Override        public void handleMessage(Message msg) {            CustomUseInLocalActivity activity = mActivity.get();            if (activity != null) {                switch (msg.what){                    case 1:                        //commentView.loadFailed(true);//理论网络申请中如果加载失败调用此办法                        activity.commentView.loadComplete(activity.gson.fromJson((String)msg.obj,CustomCommentModel.class));                        break;                    case 2:                        //commentView.refreshFailed();//理论网络申请中如果加载失败调用此办法                        activity.commentView.refreshComplete(activity.gson.fromJson((String)msg.obj, CustomCommentModel.class));                        break;                    case 3:                        //commentView.loadFailed();//理论网络申请中如果加载失败调用此办法                        activity.commentView.loadMoreComplete(activity.gson.fromJson((String)msg.obj,CustomCommentModel.class));                        break;                    case 4:                        //commentView.loadMoreReplyFailed();//理论网络申请中如果加载失败调用此办法                        activity.commentView.loadMoreReplyComplete(activity.gson.fromJson((String)msg.obj,CustomCommentModel.class));                        break;                }            }        }    }    private final ActivityHandler activityHandler = new ActivityHandler(this);    //     @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.custom_use);        gson=new Gson();        localServer=new LocalServer(this,"api2");        commentView=findViewById(R.id.commentView);         //设置空视图         //commentView.setEmptyView(view);         //设置谬误视图         //commentView.setErrorView(view);         //增加控件头布局        // commentView.addHeaderView();        commentView.setViewStyleConfigurator(new CustomViewStyleConfigurator(this));        commentView.callbackBuilder()                //自定义评论布局(必须应用ViewHolder机制)--CustomCommentItemCallback<C> 泛型C为自定义评论数据类                .customCommentItem(new CustomCommentItemCallback<CustomCommentModel.CustomComment>() {                    @Override                    public View buildCommentItem(int groupPosition, CustomCommentModel.CustomComment comment, LayoutInflater inflater, View convertView, ViewGroup parent) {                        //应用办法就像adapter外面的getView()办法一样                        final CustomCommentViewHolder holder;                        if(convertView==null){                            //应用自定义布局                            convertView=inflater.inflate(R.layout.custom_item_comment,parent,false);                            holder=new CustomCommentViewHolder(convertView);                            //必须应用ViewHolder机制                            convertView.setTag(holder);                        }else {                            holder= (CustomCommentViewHolder) convertView.getTag();                        }                        holder.prizes.setText("100");                        holder.userName.setText(comment.getPosterName());                        holder.comment.setText(comment.getData());                        return convertView;                    }                })                //自定义评论布局(必须应用ViewHolder机制)                // 并且自定义ViewHolder类必须继承自com.jidcoo.android.widget.commentview.view.ViewHolder                // --CustomReplyItemCallback<R> 泛型R为自定义回复数据类                .customReplyItem(new CustomReplyItemCallback<CustomCommentModel.CustomComment.CustomReply>() {                    @Override                    public View buildReplyItem(int groupPosition, int childPosition, boolean isLastReply, CustomCommentModel.CustomComment.CustomReply reply, LayoutInflater inflater, View convertView, ViewGroup parent) {                        //应用办法就像adapter外面的getView()办法一样                        //此类必须继承自com.jidcoo.android.widget.commentview.view.ViewHolder,否则报错                        CustomReplyViewHolder holder=null;                        //此类必须继承自com.jidcoo.android.widget.commentview.view.ViewHolder,否则报错                        if(convertView==null){                            //应用自定义布局                            convertView=inflater.inflate(R.layout.custom_item_reply,parent,false);                            holder=new CustomReplyViewHolder(convertView);                            //必须应用ViewHolder机制                            convertView.setTag(holder);                        }else {                            holder= (CustomReplyViewHolder) convertView.getTag();                        }                        holder.userName.setText(reply.getReplierName());                        holder.reply.setText(reply.getData());                        holder.prizes.setText("100");                        return convertView;                    }                })                //下拉刷新回调                .setOnPullRefreshCallback(new MyOnPullRefreshCallback())                //评论、回复Item的点击回调(点击事件回调)                .setOnItemClickCallback(new MyOnItemClickCallback())                //回复数据加载更多回调(加载更多回复)                .setOnReplyLoadMoreCallback(new MyOnReplyLoadMoreCallback())                //上拉加载更多回调(加载更多评论数据)                .setOnCommentLoadMoreCallback(new MyOnCommentLoadMoreCallback())                //设置实现后必须调用CallbackBuilder的buildCallback()办法,否则设置的回调有效                .buildCallback();         load(1,1);    }    private void load(int code,int handlerId){        localServer.get(code,activityHandler,handlerId);    }    /**     * 下拉刷新回调类     */    class MyOnPullRefreshCallback implements OnPullRefreshCallback {        @Override        public void refreshing() {            load(1,2);        }        @Override        public void complete() {            //加载实现后的操作        }        @Override        public void failure(String msg) {        }    }    /**     * 上拉加载更多回调类     */    class MyOnCommentLoadMoreCallback implements OnCommentLoadMoreCallback {        @Override        public void loading(int currentPage, int willLoadPage, boolean isLoadedAllPages) {            //因为测试数据写死了,所以这里的逻辑也是写死的            if (!isLoadedAllPages){                if(willLoadPage==2){                    load(2,3);                }else if(willLoadPage==3){                    load(3,3);                }            }        }        @Override        public void complete() {            //加载实现后的操作        }        @Override        public void failure(String msg) {        }    }    /**     * 回复加载更多回调类     */    class MyOnReplyLoadMoreCallback implements OnReplyLoadMoreCallback<CustomCommentModel.CustomComment.CustomReply> {        @Override        public void loading(CustomCommentModel.CustomComment.CustomReply reply, int willLoadPage) {                if(willLoadPage==2){                    load(5,4);                }else if(willLoadPage==3){                    load(6,4);            }        }        @Override        public void complete() {        }        @Override        public void failure(String msg) {        }    }    /**     * 点击事件回调     */    class MyOnItemClickCallback implements OnItemClickCallback<CustomCommentModel.CustomComment, CustomCommentModel.CustomComment.CustomReply> {        @Override        public void commentItemOnClick(int position, CustomCommentModel.CustomComment comment, View view) {              Toast.makeText(CustomUseInLocalActivity.this,"你点击的评论:"+comment.getData(),Toast.LENGTH_SHORT).show();        }        @Override        public void replyItemOnClick(int c_position, int r_position, CustomCommentModel.CustomComment.CustomReply reply, View view) {            Toast.makeText(CustomUseInLocalActivity.this,"你点击的回复:"+reply.getData(),Toast.LENGTH_SHORT).show();        }    }}

3.4、总结

以上就是控件的应用办法和具体应用例子,更多用法能够查看测试利用的源码中的例子。到这里,文章就差不多要结尾了。

四、后话

哈哈,有人可能会问为什么要做这个控件呀?

因为前一段时间做我的项目的时候须要开发文章的评论性能,而后须要用到相似的控件,原本想在网上找找有没有开源的,然而全网搜遍当前没有发现适合的。所以就本人手动写了一个。

然而我用在我的项目中的是这个开源的CommentView再进行深度优化和深度定制过的。也就是说目前这个开源进去的版本其实是比拟通用适配版本的,能够优化的中央还有很多很多很多。同时也存在不少BUG。还有那个测试用例WidgetTest也有很多能够优化的中央,只是当初没有太多工夫去专门做优化,有空我会再去优化。大家有趣味的能够一起到github优化这个控件,也能够提出对这个控件的一些问题、想法以及可优化的点。哈哈,欢送大家一起来把这个开源控件库做的更好更弱小。

前面有工夫的话,这个开源控件库的安顿:
1、优化
2、优化
3、扩充自定义开发的范畴
4、联合市面上的APP评论模块开发更多通用的款式框架
5、增加更多功能(嵌套滑动等等更多实用功能)
6、更多的往架构为一个轮子倒退,成为可能适配绝大多数需要的控件库
……
……
6、优化

有趣味、有工夫的能够一起退出这个我的项目的欠缺,十分欢送大家呀!!

顺便提一下,目前用在我工作的我的项目中的版本显示10000+的数据性能都挺高的,在大数据量时内存开销也稳固在一个绝对的值。毕竟是在这个开源版本根底上做了很多的深度优化。所以说,所以说,如果应用的场景是数据量比拟大的状况下,优化是很有必要的哦,不然数据量比拟大很容易OOM。

五、对于作者

我叫Jidcoo,一名理工男,一个专一于Java后端同时又酷爱Android开发的花心大萝卜。我酷爱浏览、酷爱算法、酷爱分享……喜爱交换、喜爱团队单干。

有任何无关这个我的项目或者有任何其余问题、想法,都能够POST我:

我的邮箱:jidcoo@163.com

我的GitHub: https://github.com/Jidcoo/