聊天中的时间分割线 结合recylerview

效果:



实现的方式有很多种 可以在耽搁item布局中隐藏或者显示 但是耦合度太高 不灵活(网易云信IM demo) 下面介绍用recylerview的分割线来动态画


import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.util.TypedValue;
import android.view.View;

/**
 * Description  聊天界面 时间分割线  间隔5分钟
 * author  youxuan  E-mail:xuanyouwu@163.com
 * date createTime:2017/4/29
 * version 1.0.0
 */
public class ChatItemDecoration extends RecyclerView.ItemDecoration {


    private Paint mPaint;
    private Rect mBounds;
    private float mTextSize;
    private static final int DEFAULE_COLOR_TEXT = 0xFFA6A6A6;
    private static final int DEFAULE_COLOR_LINE = DEFAULE_COLOR_TEXT;
    private float lineHeight;//线条高度
    private float dividerHeight;//整个分割线高度

    private float sp2px(@NonNull Context context, int sp) {
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, context.getResources().getDisplayMetrics());
    }

    private float dp2px(@NonNull Context context, int dp) {
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.getResources().getDisplayMetrics());
    }

    public ChatItemDecoration(@NonNull Context context) {
        mPaint = new Paint();
        mPaint.setTextSize(mTextSize = sp2px(context, 16));
        mPaint.setColor(DEFAULE_COLOR_TEXT);
        mPaint.setAntiAlias(true);
        mBounds = new Rect();
        lineHeight = dp2px(context, 1);
        dividerHeight = mTextSize * 3;
    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        //super.onDraw(c, parent, state);
        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) parent.getChildAt(i)
                    .getLayoutParams();
            int position = params.getViewLayoutPosition();
            if (position % 5 != 0) continue;//注意 这里为模拟 找到你adapter中的时间分割点
            final View child = parent.getChildAt(i);
            String tag = "上午 10:36";//模拟数据
            mPaint.setColor(DEFAULE_COLOR_TEXT);
            mPaint.getTextBounds(tag, 0, tag.length(), mBounds);
            if (mBounds.width() >= child.getWidth()) {
                c.drawText(tag, 0, child.getBottom(), mPaint);
            } else {
                float txtStartX = (child.getWidth() - mBounds.width()) / 2;
                float txtEndX = txtStartX + mBounds.width();
                float dividerCenterY = dividerHeight / 2 + child.getBottom();

                //画中间文本
                c.drawText(tag, txtStartX, dividerCenterY + mTextSize * 0.25f, mPaint);

                float lineWidth = mTextSize * 2;
                float lineTxtMargin = mTextSize;

                float leftLineStartX = txtStartX - lineWidth - lineTxtMargin;
                float leftLineEndX = leftLineStartX + lineWidth;

                float rightLineStartX = txtEndX + lineTxtMargin;
                float rightLineEndX = rightLineStartX + lineWidth;

                //画两边的线条
                if (leftLineStartX > 0 && rightLineEndX < child.getWidth()) {
                    mPaint.setColor(DEFAULE_COLOR_LINE);
                    c.drawRect(leftLineStartX, dividerCenterY - lineHeight * 0.5f, leftLineEndX, dividerCenterY + lineHeight * 0.5f, mPaint);
                    mPaint.setColor(DEFAULE_COLOR_LINE);
                    c.drawRect(rightLineStartX, dividerCenterY - lineHeight * 0.5f, rightLineEndX, dividerCenterY + lineHeight * 0.5f, mPaint);
                }
            }
        }
    }


    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);
        outRect.set(0, 0, 0, (int) dividerHeight);
    }
}


用法:

 recyclerView.addItemDecoration(new ChatItemDecoration(getContext()));





进一步完善 对于消息 adapter 最适合做管理者 他明确知道对应位置对应的消息对象 进而能控制时间是否显示,所有我声明了一个接口

import android.support.annotation.NonNull;

/**
 * Description  {@link ChatItemDecoration}
 * author  youxuan  E-mail:xuanyouwu@163.com
 * date createTime:2017/4/29
 * version 1.0.0
 */
public interface ITimeDividerInterface {
    /**
     * 是否展示时间分割线
     *
     * @param pos
     * @return
     */
    boolean isShowTimeDivider(int pos);

    /**
     * 展示的时间
     *
     * @param pos
     * @return
     */
    @NonNull
    String getShowTime(int pos);


}

让你的adpter实现这个接口,直接用:

linearLayoutManager = new LinearLayoutManager(getContext());
        recyclerView.setLayoutManager(linearLayoutManager);
        recyclerView.setHasFixedSize(true);
        recyclerView.setAdapter(chatAdapter = new ChatAdapter(getLoadedLoginToken()));
        recyclerView.addItemDecoration(new ChatItemDecoration(getContext(), chatAdapter));


adapter 代码如下:


import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Set;

import static com.netease.nimlib.sdk.msg.constant.MsgDirectionEnum.In;
import static com.netease.nimlib.sdk.msg.constant.MsgDirectionEnum.Out;

/**
 * Description
 * author  youxuan  E-mail:xuanyouwu@163.com
 * date createTime:2017/4/24
 * version 1.0.0
 */
public class ChatAdapter extends BaseArrayRecyclerAdapter<IMCustomerMessageEntity> implements ITimeDividerInterface {
    private Set<Long> timeShowArray = new HashSet<>();//时间分割线消息
    private Comparator<Long> longComparator = new Comparator<Long>() {
        @Override
        public int compare(Long o1, Long o2) {
            if (o1 != null && o2 != null) {
                return o1.compareTo(o2);
            }
            return 0;
        }
    };
    private final int TIME_DIVIDER = 5 * 60 * 1_000;


    /**
     * 处理时间分割线
     *
     * @param imMessage
     * @param position
     */
    private void addTimeDividerArray(IMCustomerMessageEntity imMessage, int position) {
        if (imMessage == null) return;
        if (imMessage.imMessage == null) return;

        //消息时间本身已经有序

        //用云信的时间
        if (timeShowArray.isEmpty()) {
            timeShowArray.add(imMessage.imMessage.getTime());
        } else {
            if (!timeShowArray.contains(imMessage.imMessage.getTime())) {
                if (imMessage.imMessage.getTime() - Collections.max(timeShowArray, longComparator).longValue() >= TIME_DIVIDER) {
                    timeShowArray.add(imMessage.imMessage.getTime());
                } else if (Collections.min(timeShowArray, longComparator).longValue() - imMessage.imMessage.getTime() >= TIME_DIVIDER) {
                    timeShowArray.add(imMessage.imMessage.getTime());
                }
            }
        }
    }

    /**
     * 是否显示时间 时间间隔5分钟
     *
     * @param pos
     * @return
     */
    @Override
    public boolean isShowTimeDivider(int pos) {
        IMCustomerMessageEntity item = getItem(pos);
        return item != null && item.imMessage != null && timeShowArray.contains(item.imMessage.getTime());
    }

    /**
     * 显示的时间字符串 isShowTimeDivider=true 不可以返回null
     *
     * @param pos
     * @return
     */
    @NonNull
    @Override
    public String getShowTime(int pos) {
        IMCustomerMessageEntity item = getItem(pos);
        return item != null && item.imMessage != null ?
                DateUtils.getTimeShowString(item.imMessage.getTime(), true) : "null";
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

亚洲小炫风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值