增加换肤功能

This commit is contained in:
启星
2025-08-14 10:07:49 +08:00
parent f6964c1e89
commit 4f9318d98e
8789 changed files with 978530 additions and 2 deletions

View File

@@ -0,0 +1,145 @@
//
// BottomItemView.swift
// Alamofire
//
// Created by aby on 2022/12/23.
// Copyright © 2023 Tencent. All rights reserved.
//
import UIKit
class BottomItemView: UIView {
var itemData: ButtonItemData
var engineManager: EngineManager {
EngineManager.shared
}
let button: UIButton = {
let button = UIButton(type: .custom)
return button
}()
let label: UILabel = {
let label = UILabel()
label.font = UIFont.systemFont(ofSize: 10.0)
label.textColor = UIColor(0xD1D9EC)
label.textAlignment = .center
label.adjustsFontSizeToFitWidth = true
return label
}()
let imageView: UIImageView = {
let view = UIImageView()
return view
}()
let noticeView: UIView = {
let view = UIView()
view.backgroundColor = UIColor(0xED414D)
view.layer.borderWidth = 3
view.layer.borderColor = UIColor(0x2A2D38).cgColor
view.layer.cornerRadius = 12
view.clipsToBounds = true
return view
}()
let noticeLabel: UILabel = {
let label = UILabel()
label.textColor = UIColor(0xFFFFFF)
label.textAlignment = .center
label.font = UIFont.systemFont(ofSize: 12, weight: .semibold)
label.backgroundColor = .clear
return label
}()
// MARK: - initialized function
init(itemData: ButtonItemData) {
self.itemData = itemData
super.init(frame: .zero)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - view layout
private var isViewReady: Bool = false
override func didMoveToWindow() {
super.didMoveToWindow()
guard !isViewReady else { return }
self.layer.cornerRadius = 10
constructViewHierarchy()
activateConstraints()
bindInteraction()
isViewReady = true
}
func constructViewHierarchy() {
addSubview(button)
button.addSubview(imageView)
button.addSubview(label)
button.addSubview(noticeView)
noticeView.addSubview(noticeLabel)
}
func activateConstraints() {
button.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
imageView.snp.makeConstraints { make in
if itemData.normalTitle.isEmpty, itemData.selectedTitle.isEmpty {
make.centerY.equalToSuperview()
} else {
make.top.equalToSuperview().offset(7)
}
make.width.height.equalTo(24)
make.centerX.equalToSuperview()
}
label.snp.makeConstraints { make in
if itemData.normalIcon.isEmpty, itemData.selectedIcon.isEmpty {
make.centerY.equalToSuperview()
} else {
make.top.equalTo(imageView.snp.bottom).offset(2)
}
make.width.equalToSuperview()
make.height.equalTo(14)
}
noticeLabel.snp.makeConstraints { make in
make.trailing.equalTo(button).offset(-7)
make.top.equalToSuperview().offset(4)
make.width.height.greaterThanOrEqualTo(16)
}
noticeView.snp.makeConstraints { make in
make.leading.top.equalTo(noticeLabel).offset(-4)
make.trailing.bottom.equalTo(noticeLabel).offset(4)
make.width.lessThanOrEqualTo(button)
}
}
func bindInteraction() {
setupViewState(item: itemData)
button.addTarget(self, action: #selector(clickMenuButton(sender:)), for: .touchUpInside)
}
func setupViewState(item: ButtonItemData) {
itemData = item
button.isSelected = item.isSelect
button.isEnabled = item.isEnabled
imageView.image = item.isSelect ? itemData.selectedImage : itemData.normalImage
label.text = item.isSelect ? itemData.selectedTitle : itemData.normalTitle
button.alpha = item.alpha
noticeView.isHidden = !item.hasNotice
noticeLabel.text = item.noticeText
}
@objc
func clickMenuButton(sender: UIView) {
itemData.action?(sender)
}
deinit {
debugPrint("deinit \(self)")
}
}

View File

@@ -0,0 +1,245 @@
//
// BottomView.swift
// TUIRoomKit
//
// Created by aby on 2022/12/21.
// Copyright © 2022 Tencent. All rights reserved.
//
import UIKit
class BottomView: UIView {
// MARK: - store property
let viewModel: BottomViewModel
private var viewArray: [BottomItemView] = []
var isUnfold: Bool = false
let unfoldHeight = Float(130.scale375Height())
let packUpHeight = Float(68.scale375Height())
let baseButtonMenuView: UIStackView = {
let view = UIStackView()
view.axis = .horizontal
view.alignment = .center
view.distribution = .equalSpacing
view.spacing = 10
return view
}()
let moreButtonMenuView: UIStackView = {
let view = UIStackView()
view.axis = .horizontal
view.alignment = .center
view.distribution = .equalSpacing
view.spacing = 10
return view
}()
let buttonMenuView: UIView = {
let view = UIView()
view.backgroundColor = UIColor(0x0F1014)
view.layer.cornerRadius = 12
return view
}()
let backgroundView: UIView = {
let view = UIView()
view.backgroundColor = UIColor(0x0F1014)
return view
}()
// MARK: - initialized function
init(viewModel: BottomViewModel) {
self.viewModel = viewModel
super.init(frame: .zero)
backgroundColor = .clear
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - view layout
private var isViewReady: Bool = false
override func didMoveToWindow() {
super.didMoveToWindow()
guard !isViewReady else { return }
constructViewHierarchy()
activateConstraints()
bindInteraction()
isViewReady = true
}
func constructViewHierarchy() {
addSubview(backgroundView)
addSubview(buttonMenuView)
buttonMenuView.addSubview(moreButtonMenuView)
buttonMenuView.addSubview(baseButtonMenuView)
moreButtonMenuView.isHidden = true
setupMenuStackView(items: viewModel.viewItems)
layoutMoreButtonMenu()
}
func setupMenuStackView(items: [ButtonItemData]) {
for i in 0...(items.count - 1) {
guard let item = viewModel.viewItems[safe: i] else { continue }
let view = BottomItemView(itemData: item)
let size = item.size ?? CGSize(width: 52.scale375(), height: 52.scale375())
view.snp.makeConstraints { make in
make.height.equalTo(size.height)
make.width.equalTo(size.width)
}
view.backgroundColor = item.backgroundColor ?? UIColor(0x2A2D38)
viewArray.append(view)
if i < 6 {
baseButtonMenuView.addArrangedSubview(view)
} else {
moreButtonMenuView.addArrangedSubview(view)
}
}
}
func layoutMoreButtonMenu() {
let emptyViewCount = baseButtonMenuView.subviews.count - moreButtonMenuView.subviews.count
if emptyViewCount <= 0 {return}
for _ in 1...emptyViewCount {
let emptyView = BottomItemView(itemData: ButtonItemData())
emptyView.snp.makeConstraints { make in
make.height.equalTo(52.scale375())
make.width.equalTo(52.scale375())
moreButtonMenuView.addArrangedSubview(emptyView)
}
viewArray.append(emptyView)
}
}
func activateConstraints() {
backgroundView.snp.makeConstraints { make in
make.bottom.leading.trailing.equalToSuperview()
make.height.equalTo(packUpHeight)
}
let width = min(kScreenWidth, kScreenHeight)
buttonMenuView.snp.makeConstraints { make in
make.width.equalTo(width)
make.bottom.centerX.height.equalToSuperview()
}
baseButtonMenuView.snp.makeConstraints { make in
make.top.equalToSuperview().offset(8.scale375())
make.height.equalTo(52.scale375())
make.leading.equalToSuperview().offset(16.scale375())
make.trailing.equalToSuperview().offset(-16.scale375())
}
moreButtonMenuView.snp.makeConstraints { make in
make.bottom.equalToSuperview()
make.height.equalTo(52.scale375())
make.leading.trailing.equalTo(baseButtonMenuView)
}
}
func bindInteraction() {
viewModel.viewResponder = self
}
deinit {
debugPrint("deinit \(self)")
}
}
extension BottomView: BottomViewModelResponder {
func updateButtonView(item: ButtonItemData) {
guard let view = viewArray.first(where: { $0.itemData.buttonType == item.buttonType }) else { return }
view.setupViewState(item: item)
}
func showAlert(title: String?, message: String?, sureTitle: String?, declineTitle: String?, sureBlock: (() -> ())?, declineBlock: (() -> ())?) {
RoomRouter.presentAlert(title: title, message: message, sureTitle: sureTitle, declineTitle: declineTitle, sureBlock: sureBlock, declineBlock: declineBlock)
}
func updateStackView(items: [ButtonItemData]) {
viewArray.forEach { view in
view.removeFromSuperview()
}
viewArray = []
setupMenuStackView(items: items)
layoutMoreButtonMenu()
}
func makeToast(text: String) {
RoomRouter.makeToastInCenter(toast: text, duration: 1)
}
private func updateBottomViewConstraints(isUnfold: Bool, completion: @escaping () -> Void) {
UIView.animate(withDuration: 0.3) { [weak self] () in
guard let self = self else { return }
self.snp.updateConstraints { make in
make.height.equalTo(isUnfold ? self.unfoldHeight : self.packUpHeight)
}
self.superview?.layoutIfNeeded()
} completion: { _ in
completion()
}
}
func updataBottomView(isUp: Bool) {
buttonMenuView.backgroundColor = isUp ? UIColor(0x2A2D38) : UIColor(0x0F1014)
self.isUnfold = isUp
if isUp {
updateBottomViewConstraints(isUnfold: true) { [weak self] in
guard let self = self else { return }
self.moreButtonMenuView.isHidden = false
}
} else {
moreButtonMenuView.isHidden = true
updateBottomViewConstraints(isUnfold: false) {}
}
}
}
private extension String {
static var leaveRoomTitle: String {
localized("Are you sure you want to leave the conference?")
}
static var destroyRoomTitle: String {
localized("Are you sure you want to end the conference?")
}
static var destroyRoomCancelTitle: String {
localized("Wait")
}
static var logoutOkText: String {
localized("OK")
}
static var dismissMeetingTitle: String {
localized("If you don't want to end the conference")
}
static var appointNewHostText: String {
localized("Please appoint a new host before leaving the conference")
}
static var leaveMeetingText: String {
localized("Leave conference")
}
static var dismissMeetingText: String {
localized("End conference")
}
static var cancelText: String {
localized("Cancel")
}
static var toastTitleText: String {
localized("Share Screen")
}
static var toastMessageText: String {
localized("Stop TUIRoom screen sharing screen live?")
}
static var toastStopText: String {
localized("Stop")
}
}