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


评论在很多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()主要是对每一个楼层的位置进行一点小的改变,这样就可以呈现出楼层的效果了,不然就是竖着的一排。

@Override
protected 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()方法,对布局进行一下排版

点我查看完成代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值