处理聊天UI细节问题
This commit is contained in:
parent
9405f4e42c
commit
8db4792e61
22
Visual_Novel_iOS/Assets.xcassets/Role/role_chat_bg_response.imageset/Contents.json
vendored
Normal file
22
Visual_Novel_iOS/Assets.xcassets/Role/role_chat_bg_response.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "role_chat_response@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "role_chat_response@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
Visual_Novel_iOS/Assets.xcassets/Role/role_chat_bg_response.imageset/role_chat_response@2x.png
vendored
Normal file
BIN
Visual_Novel_iOS/Assets.xcassets/Role/role_chat_bg_response.imageset/role_chat_response@2x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
BIN
Visual_Novel_iOS/Assets.xcassets/Role/role_chat_bg_response.imageset/role_chat_response@3x.png
vendored
Normal file
BIN
Visual_Novel_iOS/Assets.xcassets/Role/role_chat_bg_response.imageset/role_chat_response@3x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.8 KiB |
22
Visual_Novel_iOS/Assets.xcassets/Role/role_chat_bg_send.imageset/Contents.json
vendored
Normal file
22
Visual_Novel_iOS/Assets.xcassets/Role/role_chat_bg_send.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "role_chat_send@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "role_chat_send@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
Visual_Novel_iOS/Assets.xcassets/Role/role_chat_bg_send.imageset/role_chat_send@2x.png
vendored
Normal file
BIN
Visual_Novel_iOS/Assets.xcassets/Role/role_chat_bg_send.imageset/role_chat_send@2x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
BIN
Visual_Novel_iOS/Assets.xcassets/Role/role_chat_bg_send.imageset/role_chat_send@3x.png
vendored
Normal file
BIN
Visual_Novel_iOS/Assets.xcassets/Role/role_chat_bg_send.imageset/role_chat_send@3x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.9 KiB |
|
|
@ -7,6 +7,37 @@ final class StreamChatBubbleCell: UITableViewCell {
|
|||
private let bubbleView = UIView()
|
||||
private let messageLabel = UILabel()
|
||||
var onLongPress: (() -> Void)?
|
||||
|
||||
lazy var sendBgImgView: UIImageView = {
|
||||
guard let originalImage = UIImage(named: "role_chat_bg_send") else {
|
||||
return UIImageView()
|
||||
}
|
||||
// 发送消息:尖尖在右上角,focus 点应该在右上角附近
|
||||
// 假设图片尺寸,focus 点设置为右上角区域(距离右边和顶部一定距离)
|
||||
let imageSize = originalImage.size
|
||||
let focusX = imageSize.width - 20.0 // 距离右边 20pt
|
||||
let focusY = 20.0 // 距离顶部 20pt
|
||||
let stretchedImage = originalImage.makeStretchable(from: originalImage, focus: CGPoint(x: focusX, y: focusY))
|
||||
let imgV = UIImageView(image: stretchedImage)
|
||||
imgV.contentMode = .scaleToFill
|
||||
return imgV
|
||||
}()
|
||||
|
||||
lazy var respBgImgView: UIImageView = {
|
||||
guard let originalImage = UIImage(named: "role_chat_bg_response") else {
|
||||
return UIImageView()
|
||||
}
|
||||
// 接收消息:尖尖在左上角,focus 点应该在左上角附近
|
||||
// focus 点设置为左上角区域(距离左边和顶部一定距离)
|
||||
let imageSize = originalImage.size
|
||||
let focusX = 20.0 // 距离左边 20pt
|
||||
let focusY = 20.0 // 距离顶部 20pt
|
||||
let stretchedImage = originalImage.makeStretchable(from: originalImage, focus: CGPoint(x: focusX, y: focusY))
|
||||
let imgV = UIImageView(image: stretchedImage)
|
||||
imgV.contentMode = .scaleToFill
|
||||
return imgV
|
||||
}()
|
||||
|
||||
private lazy var longPressGesture: UILongPressGestureRecognizer = {
|
||||
let gesture = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress(_:)))
|
||||
gesture.minimumPressDuration = 0.4
|
||||
|
|
@ -34,8 +65,8 @@ final class StreamChatBubbleCell: UITableViewCell {
|
|||
|
||||
private func setupViews() {
|
||||
contentView.addSubview(bubbleView)
|
||||
bubbleView.layer.cornerRadius = 18
|
||||
bubbleView.layer.masksToBounds = true
|
||||
bubbleView.addSubview(sendBgImgView)
|
||||
bubbleView.addSubview(respBgImgView)
|
||||
bubbleView.setContentHuggingPriority(.defaultLow, for: .horizontal)
|
||||
bubbleView.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
|
||||
contentView.addGestureRecognizer(longPressGesture)
|
||||
|
|
@ -52,20 +83,30 @@ final class StreamChatBubbleCell: UITableViewCell {
|
|||
|
||||
func configure(message: StreamChatMessageModel) {
|
||||
messageLabel.text = message.text
|
||||
respBgImgView.isHidden = message.isSelf
|
||||
sendBgImgView.isHidden = !message.isSelf
|
||||
|
||||
if message.isSelf {
|
||||
bubbleView.backgroundColor = UIColor.c.cpn
|
||||
// 发送消息:深色背景,尖尖在右上角
|
||||
messageLabel.textColor = .white
|
||||
bubbleView.backgroundColor = .clear
|
||||
|
||||
bubbleView.snp.remakeConstraints { make in
|
||||
make.top.equalToSuperview().offset(6)
|
||||
make.bottom.equalToSuperview().offset(-6)
|
||||
make.width.lessThanOrEqualTo(UIScreen.width * 2.0 / 3.0)
|
||||
make.width.greaterThanOrEqualTo(60)
|
||||
make.width.greaterThanOrEqualTo(40)
|
||||
make.trailing.equalToSuperview().offset(-16)
|
||||
}
|
||||
|
||||
sendBgImgView.snp.remakeConstraints { make in
|
||||
make.edges.equalToSuperview()
|
||||
}
|
||||
} else {
|
||||
bubbleView.backgroundColor = UIColor.white.withAlphaComponent(0.2)
|
||||
messageLabel.textColor = .white
|
||||
// 接收消息:浅色背景,尖尖在左上角
|
||||
messageLabel.textColor = UIColor(hex: "#333333")
|
||||
bubbleView.backgroundColor = .clear
|
||||
|
||||
bubbleView.snp.remakeConstraints { make in
|
||||
make.top.equalToSuperview().offset(6)
|
||||
make.bottom.equalToSuperview().offset(-6)
|
||||
|
|
@ -73,6 +114,10 @@ final class StreamChatBubbleCell: UITableViewCell {
|
|||
make.width.greaterThanOrEqualTo(60)
|
||||
make.leading.equalToSuperview().offset(16)
|
||||
}
|
||||
|
||||
respBgImgView.snp.remakeConstraints { make in
|
||||
make.edges.equalToSuperview()
|
||||
}
|
||||
}
|
||||
|
||||
messageLabel.snp.remakeConstraints { make in
|
||||
|
|
|
|||
|
|
@ -461,6 +461,33 @@ public extension UIImage {
|
|||
return pngData()?.base64EncodedString()
|
||||
}
|
||||
|
||||
/// 根据“焦点”生成四周可拉伸、四角不变的 UIImage
|
||||
/// 返回的图 *本身* 就是 resizable,尺寸由外部 Auto Layout 决定
|
||||
func makeStretchable(from image: UIImage,
|
||||
focus: CGPoint) -> UIImage {
|
||||
|
||||
let scale = image.scale
|
||||
let w = image.size.width * scale
|
||||
let h = image.size.height * scale
|
||||
let fx = focus.x * scale
|
||||
let fy = focus.y * scale
|
||||
|
||||
// 保护四角:以焦点为中心对称留 cap
|
||||
let capLeft = min(fx, w - fx) * 0.5
|
||||
let capRight = w - capLeft
|
||||
let capTop = min(fy, h - fy) * 0.5
|
||||
let capBottom = h - capTop
|
||||
|
||||
let insets = UIEdgeInsets(top: capTop,
|
||||
left: capLeft,
|
||||
bottom: capBottom,
|
||||
right: capRight)
|
||||
|
||||
// 只生成可拉伸图,不立即渲染固定尺寸
|
||||
return image.resizableImage(withCapInsets: insets,
|
||||
resizingMode: .stretch)
|
||||
}
|
||||
|
||||
/// Base 64 encoded JPEG data of the image.
|
||||
///
|
||||
/// - parameter compressionQuality: The quality of the resulting JPEG image, expressed as a value from 0.0 to 1.0. The value 0.0 represents the maximum compression (or lowest quality) while the value 1.0 represents the least compression (or best quality).
|
||||
|
|
|
|||
Loading…
Reference in New Issue