私聊界面的UI完善

This commit is contained in:
fengshuo
2024-03-01 01:27:25 +08:00
parent 26d586290c
commit 678297f771
35 changed files with 4891 additions and 3651 deletions

View File

@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "chat_back@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "chat_back@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 573 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "chat_input_text@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "chat_input_text@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "chat_more@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "chat_more@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "chat_opt@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "chat_opt@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 484 B

View File

@@ -159,3 +159,56 @@ extension UIView {
}
}
extension UIView {
//4
func addCorner(cornerRadii:CornerRadii, frame:CGRect){
let path = createPathWithRoundedRect(bounds: frame, cornerRadii:cornerRadii)
let shapLayer = CAShapeLayer()
shapLayer.frame = self.bounds
shapLayer.path = path
self.layer.mask = shapLayer
}
//
struct CornerRadii {
var topLeft :CGFloat = 0
var topRight :CGFloat = 0
var bottomLeft :CGFloat = 0
var bottomRight :CGFloat = 0
}
//线
func createPathWithRoundedRect( bounds:CGRect,cornerRadii:CornerRadii) -> CGPath
{
let minX = bounds.minX
let minY = bounds.minY
let maxX = bounds.maxX
let maxY = bounds.maxY
//
let topLeftCenterX = minX + cornerRadii.topLeft
let topLeftCenterY = minY + cornerRadii.topLeft
let topRightCenterX = maxX - cornerRadii.topRight
let topRightCenterY = minY + cornerRadii.topRight
let bottomLeftCenterX = minX + cornerRadii.bottomLeft
let bottomLeftCenterY = maxY - cornerRadii.bottomLeft
let bottomRightCenterX = maxX - cornerRadii.bottomRight
let bottomRightCenterY = maxY - cornerRadii.bottomRight
//YESiOSUIView
let path :CGMutablePath = CGMutablePath();
//
path.addArc(center: CGPoint(x: topLeftCenterX, y: topLeftCenterY), radius: cornerRadii.topLeft, startAngle: CGFloat.pi, endAngle: CGFloat.pi * 3 / 2, clockwise: false)
//
path.addArc(center: CGPoint(x: topRightCenterX, y: topRightCenterY), radius: cornerRadii.topRight, startAngle: CGFloat.pi * 3 / 2, endAngle: 0, clockwise: false)
//
path.addArc(center: CGPoint(x: bottomRightCenterX, y: bottomRightCenterY), radius: cornerRadii.bottomRight, startAngle: 0, endAngle: CGFloat.pi / 2, clockwise: false)
//
path.addArc(center: CGPoint(x: bottomLeftCenterX, y: bottomLeftCenterY), radius: cornerRadii.bottomLeft, startAngle: CGFloat.pi / 2, endAngle: CGFloat.pi, clockwise: false)
path.closeSubpath();
return path;
}
}

View File

@@ -7,7 +7,7 @@
import UIKit
import NIMSDK
class ChatListVC: BaseViewController {
class ChatListVC: BaseViewController, HiddenNavigationBarProtocol {
var list:NSMutableArray?
@@ -21,6 +21,30 @@ class ChatListVC: BaseViewController {
NIMSDK.shared().conversationManager.add(self)
NIMSDK.shared().loginManager.add(self)
getList()
view.addSubview(backImgView)
view.addSubview(tableView)
view.addSubview(clearBtn)
view.addSubview(titleLb)
backImgView.snp.makeConstraints { make in
make.edges.equalTo(view)
}
tableView.snp.makeConstraints { make in
make.left.right.bottom.equalToSuperview()
make.top.equalToSuperview().offset(NavHeight)
}
clearBtn.snp.makeConstraints { make in
make.size.equalTo(CGSize(width: 28, height: 28))
make.right.equalToSuperview().offset(-16)
make.top.equalToSuperview().offset(StatusBarHeight + 8)
}
titleLb.snp.makeConstraints { make in
make.centerY.equalTo(clearBtn)
make.left.equalToSuperview().offset(16)
}
}
private lazy var tableView: UITableView = {
@@ -37,11 +61,45 @@ class ChatListVC: BaseViewController {
return tableView
}()
private lazy var backImgView: UIImageView = {
let imageView = UIImageView()
imageView.image = UIImage(named: "auth_login_bg")
imageView.isUserInteractionEnabled = true
imageView.layer.masksToBounds = true
imageView.contentMode = .scaleAspectFill
return imageView
}()
private lazy var clearBtn: UIButton = {
let button = UIButton(type: .custom)
button.setImage(UIImage(named: "chat_clear"), for: .normal)
button.setImage(UIImage(named: "chat_clear"), for: .selected)
button.addTarget(self, action: #selector(clearClick), for: .touchUpInside)
return button
}()
private lazy var titleLb: UILabel = {
let label = UILabel()
label.textColor = .white
label.text = "消息中心"
label.font = UIFont.systemFont(ofSize: 18, weight: .medium)
return label
}()
@objc func clearClick() {
NIMSDK.shared().conversationManager.markAllMessagesRead()
}
}
extension ChatListVC: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(for: indexPath, cellType: ChatListCell.self)
if indexPath.row < list?.count ?? 0 {
let res = list?.object(at: indexPath.row) as? NIMRecentSession
cell.rescent = res
}
return cell
}
@@ -50,7 +108,18 @@ extension ChatListVC: UITableViewDelegate, UITableViewDataSource {
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 64
return 82
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
if indexPath.row < list?.count ?? 0 {
let res = list?.object(at: indexPath.row) as? NIMRecentSession
if let session = res?.session {
let chat = ChatVC(session: session)
self.navigationController?.pushViewController(chat, animated: true)
}
}
}
}

View File

@@ -7,14 +7,14 @@
import UIKit
import NIMSDK
class ChatVC: BaseViewController {
class ChatVC: BaseViewController, HiddenNavigationBarProtocol {
// /
private var isBecome: Bool = false
///
private var isSended: Bool = true
///
private let ToolBarLastH: CGFloat = 52
private let ToolBarLastH: CGFloat = (52 + SafeAraeBottomHeight)
public init(session: NIMSession) {
vm = ChatViewModel(session: session)
@@ -29,13 +29,19 @@ class ChatVC: BaseViewController {
var vm:ChatViewModel
override var preferredStatusBarStyle: UIStatusBarStyle {
.darkContent
}
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = ThemeColor(hexStr: "#F6F6F6")
let height = ScreenHeight - (ToolBarLastH + SafeAraeBottomHeight + NavHeight)
chatTableView.frame = CGRect(x: 0, y: 0, width: ScreenWidth, height: height)
let height = ScreenHeight - (ToolBarLastH + NavHeight)
chatTableView.frame = CGRect(x: 0, y: NavHeight, width: ScreenWidth, height: height)
navView.frame = CGRect(x: 0, y: 0, width: ScreenWidth, height: NavHeight)
view.addSubview(chatTableView)
view.addSubview(keyboardView)
view.addSubview(navView)
}
///cell
@@ -43,13 +49,15 @@ class ChatVC: BaseViewController {
chatTableView.register(cellType: ChatTextCell.self)
}
private lazy var chatTableView: UITableView = {
let tableView = UITableView(frame: .zero, style: .plain)
tableView.delegate = self
tableView.dataSource = self
tableView.tableFooterView = UIView()
tableView.separatorStyle = .none
tableView.backgroundColor = .clear
tableView.backgroundColor = ThemeColor(hexStr: "#F8F8FB")
if #available(iOS 11.0, *) {
tableView.contentInsetAdjustmentBehavior = .never
}
@@ -57,12 +65,20 @@ class ChatVC: BaseViewController {
}()
private lazy var keyboardView: ChatKeyboardView = {
let toolBarY = ScreenHeight - NavHeight - ToolBarLastH - SafeAraeBottomHeight
let toolBarY = ScreenHeight - ToolBarLastH
let view = ChatKeyboardView(frame: CGRect(x: 0, y: toolBarY, width: ScreenWidth, height: ToolBarLastH))
view.backgroundColor = .white
view.delegate = self
return view
}()
private lazy var navView: ChatNavView = {
let view = ChatNavView(frame: .zero)
view.backgroundColor = .white
return view
}()
}
// MARK: - ChatKeyboardViewDelegate

View File

@@ -48,7 +48,7 @@ class ChatGrowingTextView: UITextView {
let label = UILabel(frame: frame)
label.numberOfLines = 1
label.text = "请输入你要发送的消息"
label.textColor = ThemeColor(hexStr: "#F6F6F6")
label.textColor = ThemeColor(hexStr: "#8E92A2")
label.font = UIFont.systemFont(ofSize: self.kDefultSize)
return label
}()

View File

@@ -28,8 +28,9 @@ extension ChatKeyboardViewDelegate {
class ChatKeyboardView: UIView {
private let kSpace: CGFloat = 8.0
private let kViewWH: CGFloat = 36.0
private let kLeft: CGFloat = 12.0
private let kSpace: CGFloat = 12.0
private let kViewWH: CGFloat = 25.0
private let kLineHeight: CGFloat = 0.75
// MARK: - var lazy
@@ -47,6 +48,17 @@ class ChatKeyboardView: UIView {
///
fileprivate var isShowKeyboard = false
///
fileprivate lazy var changeButton : UIButton = {
let button = UIButton(type: .custom)
let x: CGFloat = self.kLeft
button.frame = CGRect(x: x, y: self.kSpace, width: self.kViewWH, height: self.kViewWH)
button.setImage(UIImage(named: "chat_more"), for: .normal)
button.setImage(UIImage(named: "chat_more"), for: .highlighted)
button.addTarget(self, action: #selector(moreDidAction(_:)), for: .touchUpInside)
return button
}()
///
fileprivate lazy var moreButton : UIButton = {
let button = UIButton(type: .custom)
@@ -61,32 +73,23 @@ class ChatKeyboardView: UIView {
///
fileprivate lazy var chatTextView: ChatGrowingTextView = {
let w: CGFloat = ScreenWidth - self.kViewWH * 2 - self.kSpace * 3 - self.kSpace
let textView = ChatGrowingTextView(frame: CGRect(x: self.kSpace, y: self.kSpace, width: w, height: self.kViewWH))
let textView = ChatGrowingTextView(frame: CGRect(x: self.kSpace + self.kLeft + self.kViewWH, y: self.kSpace, width: w, height: 36))
textView.placeholder = "请输入..."
textView.textColor = ThemeColor(hexStr: "#000000")
textView.maxNumberOfLines = 5
textView.delegate = self
textView.backgroundColor = ThemeColor(hexStr: "#F1F1FA")
textView.layer.cornerRadius = 4
textView.layer.masksToBounds = true
textView.didTextChangedHeightClosure = { [weak self] height in
self?.changeKeyboardHeight(height: height)
}
return textView
}()
fileprivate lazy var topLineView: UIView = {
let lineView1 = UIView(frame: CGRect(x: 0, y: 0, width: ScreenWidth, height: kLineHeight))
lineView1.backgroundColor = ThemeColor(hexStr: "#E5E5E5")
return lineView1
}()
fileprivate lazy var bottomLineView: UIView = {
let lineView2 = UIView(frame: CGRect(x: 0, y: self.toolBarHeight - kLineHeight, width: ScreenWidth, height: kLineHeight))
lineView2.backgroundColor = ThemeColor(hexStr: "#E5E5E5")
return lineView2
}()
fileprivate lazy var toolBarView: UIView = {
let view = UIView(frame: CGRect(x: 0, y: 0, width: ScreenWidth, height: self.toolBarHeight))
view.backgroundColor = ThemeColor(hexStr: "#F7F7F7")
view.backgroundColor = .clear
return view
}()
@@ -94,7 +97,7 @@ class ChatKeyboardView: UIView {
fileprivate lazy var contentView: UIView = {
let y = self.toolBarView.maxY
let view = UIView(frame: CGRect(x: 0, y: y, width: ScreenWidth, height: self.contentHeight))
view.backgroundColor = ThemeColor(hexStr: "#F8F8F8")
view.backgroundColor = .white
return view
}()
@@ -123,14 +126,13 @@ class ChatKeyboardView: UIView {
}
func setupKeyboardView() {
self.backgroundColor = ThemeColor(hexStr: "#F7F7F7")
self.backgroundColor = .clear
self.isUserInteractionEnabled = true
addSubview(toolBarView)
toolBarView.addSubview(moreButton)
toolBarView.addSubview(changeButton)
toolBarView.addSubview(chatTextView)
toolBarView.addSubview(topLineView)
toolBarView.addSubview(bottomLineView)
addSubview(contentView)
contentView.addSubview(moreMenuView)
@@ -347,9 +349,6 @@ extension ChatKeyboardView {
moreButton.frame = CGRect(x: moreButton.x, y: spaceY, width: moreButton.width, height: moreButton.height)
contentView.frame = CGRect(x: contentView.x, y: toolBarView.maxY, width: contentView.width, height: contentHeight)
topLineView.frame = CGRect(x: 0, y: 0, width: ScreenWidth, height: kLineHeight)
bottomLineView.frame = CGRect(x: 0, y: toolBarView.height - kLineHeight, width: ScreenWidth, height: kLineHeight)
if (isShowKeyboard) {
if (isShowMore) {

View File

@@ -7,21 +7,173 @@
import UIKit
import Reusable
import NIMSDK
import Kingfisher
func showTime(msglastTime: TimeInterval, showDetail: Bool) -> String {
//
let nowDate = Date()
let msgDate = Date(timeIntervalSince1970: msglastTime)
var result: String?
let components: Set<Calendar.Component> = [.year, .month, .day, .weekday, .hour, .minute]
let calendar = Calendar.current
let nowDateComponents = calendar.dateComponents(components, from: nowDate)
let msgDateComponents = calendar.dateComponents(components, from: msgDate)
var hour = msgDateComponents.hour ?? 0
let oneDayTimeIntervalValue: TimeInterval = 24 * 60 * 60 //
result = getPeriodOfTime(hour: hour, minute: msgDateComponents.minute ?? 0)
if hour > 12 {
hour -= 12
}
let isSameMonth = (nowDateComponents.year == msgDateComponents.year) && (nowDateComponents.month == msgDateComponents.month)
if isSameMonth && (nowDateComponents.day == msgDateComponents.day) { //
result = "\(result ?? "") \(hour):\(String(format: "%02d", msgDateComponents.minute ?? 0))"
} else if isSameMonth && (nowDateComponents.day == (msgDateComponents.day! + 1)) { //
result = showDetail ? "昨天\(result ?? "") \(hour):\(String(format: "%02d", msgDateComponents.minute ?? 0))" : "昨天"
} else if isSameMonth && (nowDateComponents.day == (msgDateComponents.day! + 2)) { //
result = showDetail ? "前天\(result ?? "") \(hour):\(String(format: "%02d", msgDateComponents.minute ?? 0))" : "前天"
} else if nowDate.timeIntervalSince(msgDate) < 7 * oneDayTimeIntervalValue { //
let weekDay = weekdayStr(msgDateComponents.weekday ?? 1)
result = showDetail ? "\(weekDay)\(result ?? "") \(hour):\(String(format: "%02d", msgDateComponents.minute ?? 0))" : weekDay
} else { //
let day = "\(msgDateComponents.year ?? 0)-\(msgDateComponents.month ?? 0)-\(msgDateComponents.day ?? 0)"
result = showDetail ? "\(day)\(result ?? "") \(hour):\(String(format: "%02d", msgDateComponents.minute ?? 0))" : day
}
return result ?? ""
}
func getPeriodOfTime(hour: Int, minute: Int) -> String {
var periodOfTime = ""
if hour >= 0 && hour < 6 {
periodOfTime = "凌晨"
} else if hour >= 6 && hour < 12 {
periodOfTime = "上午"
} else if hour == 12 {
periodOfTime = "中午"
} else if hour > 12 && hour < 18 {
periodOfTime = "下午"
} else if hour >= 18 && hour <= 23 {
periodOfTime = "晚上"
}
return periodOfTime
}
func weekdayStr(_ weekday: Int) -> String {
switch weekday {
case 1:
return "星期日"
case 2:
return "星期一"
case 3:
return "星期二"
case 4:
return "星期三"
case 5:
return "星期四"
case 6:
return "星期五"
case 7:
return "星期六"
default:
return ""
}
}
class ChatListCell: UITableViewCell, Reusable {
var rescent:NIMRecentSession? {
didSet {
if let sessionId = rescent?.session?.sessionId {
NIMSDK.shared().userManager.fetchUserInfos([sessionId]) { users, error in
if error == nil {
let user = users?[safe:0]
if let url = user?.userInfo?.avatarUrl {
self.avatarImgView.kf.setImage(with: URL(string: url),
placeholder: nil)
}
self.nameLb.text = user?.userInfo?.nickName
}
}
textLb.text = rescent?.lastMessage?.text ?? "消息"
if let count = rescent?.unreadCount, count > 0 {
badgeLb.text = "\(count)"
badgeLb.isHidden = false
} else {
badgeLb.isHidden = true
}
if let message = rescent?.lastMessage {
self.dateLb.isHidden = false
self.dateLb.text = showTime(msglastTime: rescent?.lastMessage?.timestamp ?? 0, showDetail: false)
} else {
self.dateLb.isHidden = true
}
}
}
}
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
selectionStyle = .none
backgroundColor = .clear
contentView.addSubview(backView)
backView.addSubview(avatarImgView)
backView.addSubview(textLb)
backView.addSubview(nameLb)
backView.addSubview(dateLb)
backView.addSubview(badgeLb)
backView.snp.makeConstraints { make in
make.left.right.equalToSuperview().inset(16)
make.top.equalToSuperview().offset(10)
make.bottom.equalToSuperview()
}
avatarImgView.snp.makeConstraints { make in
make.size.equalTo(CGSize(width: 60, height: 60))
make.centerY.equalToSuperview()
make.left.equalToSuperview().offset(8)
}
nameLb.snp.makeConstraints { make in
make.left.equalTo(avatarImgView.snp.right).offset(12)
make.bottom.equalTo(avatarImgView.snp.centerY).offset(-4)
make.right.lessThanOrEqualTo(backView).offset(-20)
}
textLb.snp.makeConstraints { make in
make.left.equalTo(nameLb)
make.top.equalTo(avatarImgView.snp.centerY).offset(4)
make.right.lessThanOrEqualTo(backView).offset(-20)
}
dateLb.snp.makeConstraints { make in
make.centerY.equalTo(nameLb)
make.right.equalToSuperview().offset(-8)
}
badgeLb.snp.makeConstraints { make in
make.right.equalTo(dateLb)
make.centerY.equalTo(textLb)
make.size.equalTo(CGSize(width: 18, height: 18))
}
}
private lazy var backView: UIView = {
let view = UIView()
view.backgroundColor = ThemeColor(hexStr: "#525566")
view.layer.masksToBounds = true
view.addCorner(cornerRadii: UIView.CornerRadii.init(topLeft: 36, topRight: 10, bottomLeft: 36, bottomRight: 10), frame: CGRectMake(0, 0, ScreenWidth - 32, 72))
return view
}()
@@ -50,7 +202,7 @@ class ChatListCell: UITableViewCell, Reusable {
private lazy var dateLb: UILabel = {
let label = UILabel()
label.textColor = .red
label.textColor = ThemeColor(hexStr: "#7D8499")
label.font = UIFont.systemFont(ofSize: 12, weight: .light)
return label
}()
@@ -61,11 +213,13 @@ class ChatListCell: UITableViewCell, Reusable {
label.backgroundColor = .red
label.textAlignment = .center
label.font = UIFont.systemFont(ofSize: 11)
label.layer.cornerRadius = 9
label.layer.masksToBounds = true
return label
}()
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

View File

@@ -0,0 +1,78 @@
//
// ChatNavView.swift
// yinmeng-ios
//
// Created by MaiMang on 2024/3/1.
//
import UIKit
class ChatNavView: BaseView {
override func loadSubViews() {
addSubview(backBtn)
addSubview(titleLb)
addSubview(likeBtn)
addSubview(optBtn)
backBtn.snp.makeConstraints { make in
make.size.equalTo(CGSize(width: 18, height: 18))
make.left.equalToSuperview().offset(16)
make.bottom.equalTo(self).offset(-13)
}
titleLb.snp.makeConstraints { make in
make.centerX.equalTo(self)
make.centerY.equalTo(backBtn)
}
likeBtn.snp.makeConstraints { make in
make.size.equalTo(CGSize(width: 48, height: 21))
make.centerY.equalTo(backBtn)
make.right.equalTo(optBtn.snp.left).offset(-10)
}
optBtn.snp.makeConstraints { make in
make.size.equalTo(CGSize(width: 18, height: 18))
make.right.equalTo(self).offset(-16)
make.centerY.equalTo(backBtn)
}
}
private lazy var backBtn: UIButton = {
let button = UIButton(type: .custom)
button.setImage(UIImage(named: "chat_back"), for: .normal)
button.setImage(UIImage(named: "chat_back"), for: .selected)
return button
}()
private lazy var titleLb: UILabel = {
let label = UILabel()
label.textColor = ThemeColor(hexStr: "#2B2D33")
label.font = UIFont.systemFont(ofSize: 16, weight: .medium)
label.textAlignment = .center
return label
}()
private lazy var likeBtn: UIButton = {
let button = UIButton(type: .custom)
button.setTitle("关注", for: .normal)
button.setTitleColor(ThemeColor(hexStr: "#FFDA24"), for: .normal)
button.titleLabel?.font = UIFont.systemFont(ofSize: 16, weight: .medium)
button.layer.masksToBounds = true
button.layer.cornerRadius = 26
button.isEnabled = false
button.addTarget(self, action: #selector(likeClick), for: .touchUpInside)
return button
}()
private lazy var optBtn: UIButton = {
let button = UIButton(type: .custom)
button.setImage(UIImage(named: "chat_opt"), for: .normal)
button.setImage(UIImage(named: "chat_opt"), for: .selected)
return button
}()
@objc func likeClick() {
//TODO:
}
}