仿网易新闻评论的楼层效果

来源:互联网 发布:网络外宣是一种传销吗 编辑:程序博客网 时间:2024/04/25 18:13

评论在很多app中都会用到,最常见的就是网易新闻中的评论了,所以今天就研究了一下这个,先看看网易的效果图吧。
网易评论的效果
这么一个评论的列表,想必都会做吧。一个ListView之类的控件,里面的item也是一个较简单的布局。不过当有人回复评论之后,那么效果图就变成了这样:
楼层的效果
当有人回复评论之后,就出现了这样的楼层效果,今天主要就做做这个楼层的效果。
这里写图片描述
这里写图片描述

界面分析

通过效果图很容易看出,其实每一层楼的布局都是一样的,我们只需要把每一层每一层的布局拼接起来就好了。如果我们知道有多少个楼层,那么可以直接写一个LinearLayout,来包含多个楼层的布局就好了。但是在一开始不知道有多少楼层的情况下,我们只需要自定义一下LinearLayout,然后动态的添加楼层布局就好了。

代码编写

通过刚才的分析可以知道,每一个楼层里的布局是差不多的。所以,我们可以先写楼层的布局。楼层布局分为两种,一种是直接显示出了评论内容的,我这里的楼层只包含了人名,内容,楼层数,我们暂时叫它为ShowFloor;还有一种就是”展开隐藏楼层”,我们叫它为HideFloor。这两种布局都比较简单,所以就不贴出来了。
每一个楼层的布局写出来了,就可以开始自定义LinearLayout了,首先,我们创建一个FloorView类,让他继承LinearLayout,写出它的三个构造函数,然后初始化

this.setOrientation(LinearLayout.VERTICAL);

将它设置为垂直布局,然后就可以对数据进行显示布局了。

public void init() {    // 如果没有数据直接返回    if (null == datas.iterator())        return;    // 如果评论回复数小于7个,则直接显示完    if (datas.getFloorNum() < 7) {        for (Iterator<? extends Commentable> iterator = datas.iterator(); iterator                .hasNext(); ) {            View view = factory.buildSubFloor(iterator.next(), this);            addView(view);        }    } else {    // 如果评论回复数很多,则显示一个“显示隐藏楼层”的按钮        View view;        view = factory.buildSubFloor(datas.get(0), this);        addView(view);        view = factory.buildSubFloor(datas.get(1), this);        addView(view);        // 可以点击显示更多的楼层        view = factory.buildSubHideFloor(datas.get(2), this);        view.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                TextView hide_text = (TextView) v                        .findViewById(R.id.hide_text);                hide_text.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0,                        0);                v.findViewById(R.id.hide_pb).setVisibility(View.VISIBLE);                removeAllViews();                for (Iterator<? extends Commentable> iterator = datas.iterator(); iterator                        .hasNext(); ) {                    View view = factory.buildSubFloor(iterator.next(),                            FloorView.this);                    addView(view);                }                reLayoutChildren();            }        });        addView(view);        view = factory.buildSubFloor(datas.get(datas.size() - 1), this);        addView(view);    }    reLayoutChildren();}

init()这个方法就是排列出评论楼层的,datas是对评论的再次封装,里面包含了所有的回复内容,以及有多少个回复楼层。我们先对评论里面有多少个楼层进行判断,如果小于9个,那么就显示出全部的楼层,如果大于9个,那么就显示出前两个楼层和最后一个楼层,中间用”显示隐藏楼层”布局来替代。
其中的:

factory.buildSubFloor(datas, this);

是生成ShowFloor用的,和平常的LayoutInflater.inflate生成View没有什么两样。

factory.buildSubHideFloor(datas, this)

是生成HideFloor用的。
这样思路就很清晰了,要直接显示所有楼层的时候,就循环遍历有多少个楼层,然后给每一个楼层(ShowFloor)设置数据,并add到FloorView中。如果楼层太多,就显示部分楼层,中间的用HideFloor替代,再加入到FloorView中,然后给HideFloor设置一个点击监听,点击后先移除FloorView中的所有子View,然后显示所有的楼层

public void reLayoutChildren() {    int count = getChildCount();    for (int i = 0; i < count; i++) {        View view = getChildAt(i);        LayoutParams layout = new LayoutParams(LayoutParams.MATCH_PARENT,                LayoutParams.WRAP_CONTENT);        layout.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;        int margin = Math.min((count - i - 1), 4) * density;        layout.leftMargin = margin;        layout.rightMargin = margin;        if (i == count - 1) {            layout.topMargin = 0;        } else {            layout.topMargin = Math.min((count - i), 4) * density;        }        view.setLayoutParams(layout);    }}

reLayoutChildren()主要是对每一个楼层的位置进行一点小的改变,这样就可以呈现出楼层的效果了,不然就是竖着的一排。

@Overrideprotected void dispatchDraw(Canvas canvas) {    int i = getChildCount();    if (null != drawer && i > 0) {        for (int j = i - 1; j >= 0; j--) {            View view = getChildAt(j);            // drawable将在被绘制在canvas的哪个矩形区域内。            drawer.setBounds(view.getLeft(), view.getLeft(),                    view.getRight(), view.getBottom());            drawer.draw(canvas);        }    }    super.dispatchDraw(canvas);}

这个方法主要是给每一个楼层添加一个背景,就像一个框那样把楼层框起来。
最后再调用一下onLayout()和onMeasure()方法,对布局进行一下排版

点我查看完成代码

0 0
原创粉丝点击