本文是仿微信聊天程序专栏的第九篇文章,主要记录了【聊天信息】的逻辑实现,下面涉及代码是《仿微信聊天程序 - 09. 聊天窗口》的基础上进行完善的。

实现效果

在《仿微信聊天程序 - 09. 聊天窗口》章节中,已经实现了基本的聊天界面框架,《09. 聊天信息》这里只是补充实现聊天内容部分功能。

界面布局

聊天内容使用的是WebView来显示,所以这里的布局就是HTML来渲染双方的聊天信息,下面一个简单对话的聊天内容布局代码:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="main.css">
    <script src="main.js"></script>
</head>
<body>
<div id="content">
    <!--
    <div class="message-item">
        <div class="user">
            <span class="nickname">自己的昵称</span>
            <span>时间</span>
        </div>
        <div class="content">
            这是内容
        </div>
    </div>
    <div class="message-item">
        <div class="contacts">
            <span class="nickname">好友的昵称</span>
            <span>时间</span>
        </div>
        <div class="content">
            这是内容
        </div>
    </div>
    -->
</div>
</body>
</html>

样式美化

聊天内容使用的是HTML渲染聊天内容,所以CSS就是也是HTML标准的CSS,完整的CSS代码如下:

#content {
  padding: 15px;
}
.message-item {
  padding: 5px 0;
}
.nickname {
  margin-right: 8px;
}
.user {
  color: green;
}
.contacts {
  color: blue;
}
.content {
  padding: 5px 0;
}

内容管理

聊天内容的管理使用JavaScript实现的,也就是说通过Java调用JavaScript的代码实现对聊天内容的插入和删除,下面是JavaScript实现的功能代码:

var main = {};

main.append = function (html) {
  var ele = document.createElement("div");
  ele.innerHTML = html;
  document.getElementById("content").appendChild(ele);
  window.scrollTo(0, document.body.scrollHeight);
};

main.clear = function () {
  document.getElementById("content").innerHTML = "";
};

逻辑控制

调整原来ChatMainController的代码,使用WebView引擎构建JavaScript对象,使用JavaScript对象实现对聊天内容的管理:

/**
 * @author michong
 */
public class ChatMainController implements UserDataController {
    public Label nicknameLabel;
    public WebView chatWebView;
    public TextArea messageTextArea;

    private JSObject js;
    private Long contactsId;

    @Override
    public void initialize(Object data) {
        contactsId = (Long) data;
        initializeUI();
        initializeEvent();
    }

    void initializeUI() {
        chatWebView.setContextMenuEnabled(false);
        chatWebView.setBlendMode(BlendMode.DARKEN);
        WebEngine engine = chatWebView.getEngine();
        engine.setJavaScriptEnabled(true);
        engine.getLoadWorker().stateProperty().addListener((obj, ov, nv) -> {
            if (nv == Worker.State.SUCCEEDED) {
                js = (JSObject) engine.executeScript("window.main");
                renderDebugData();
            }
        });
        engine.load(Objects.requireNonNull(getClass().getResource("/html/main.html")).toExternalForm());
    }

    void initializeEvent() {
        messageTextArea.setOnKeyPressed(e -> {
            if (e.isControlDown() && e.getCode() == KeyCode.ENTER) {
                onSendClick(null);
            }
        });
    }

    void renderDebugData() {
        nicknameLabel.setText("WxID: " + contactsId);
        MessageVO from = new MessageVO();
        from.setNickname("米虫1001");
        from.setMessage("仿微信聊天程序源码可以搜索微信小程序“Coding鱼塘”获取下载地址");
        from.setTimestamp(new Date().getTime());
        append(from, true);
    }

    void append(MessageVO vo, boolean isContacts) {
        js.call("append", Html.of(vo.getNickname(), vo.getTimestamp(), vo.getMessage(), isContacts));
    }

    public void onClearClick(ActionEvent actionEvent) {
        js.call("clear");
    }

    public void onCloseClick(ActionEvent actionEvent) {
    }

    public void onSendClick(ActionEvent actionEvent) {
        String content = messageTextArea.getText();
        if (content.trim().length() == 0) {
            return;
        }

        MessageVO from = new MessageVO();
        from.setNickname("我");
        from.setMessage(content);
        from.setTimestamp(new Date().getTime());
        append(from, false);
        messageTextArea.clear();
    }

}

内容构建

聊天内容构建工具Html:

/**
 * @author michong
 */
public class Html {

    public static String of(String nickname, long timestamp, String content, boolean isContacts) {
        String time = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(new Date(timestamp));
        // @formatter:off
        return "<div class='message-item'>"
                + "<div class='" + (isContacts ? "user" : "contacts") + "'>"
                    + "<span class='nickname'>" + nickname + "</span>"
                    + "<span>" + time + "</span>"
                + "</div>"
                + "<div class='content'>" + escape(content) + "</div>"
             + "</div>";
        // @formatter:on
    }

    private static String escape(String content) {
        // @formatter:off
        return content.replace("&", "&amp;")
                .replace("\t", "&nbsp;&nbsp;")
                .replace("<", "&lt;")
                .replace(">", "&gt;")
                .replace(" ", "&nbsp;")
                .replace("'", "&#39;")
                .replace("\"", "&quot;")
                .replace("\r\n", "\n")
                .replace("\n", "<br>");
        // @formatter:on
    }
}
posted on 2023-07-16 16:55  ql1710  阅读(88)  评论(0编辑  收藏  举报