// // KeyboardViewController.swift // AiKeyboard // // Created by Destiny on 2025/4/23. // import UIKit import Lottie import SnapKit import MarqueeLabel enum KeyboardType: Int { case help = 0 // 帮聊 case teach = 1 // 教你说 case prologue = 2 // 开场白 } class KeyboardViewController: UIInputViewController { struct UX { static let keyboardDefaultHeight = 292.0 static let keyboardWithTipsHeight = 318.0 } // 选择的键盘类型 var chooseType: KeyboardType = .help { didSet { UserDefaults.standard.setValue(chooseType.rawValue, forKey: "KeyboardChooseType") self.updateMainViewUI() } } // 键盘列表 var keyboardList: [KeyboardModel]? // 选择的键盘 var chooseKeyboard: KeyboardModel? // 人设列表 var characterList: [CharacterModel]? // 开场白列表 var prologueList: [PrologueModel]? // 开始持续删除 private var deleteTimer: Timer? private var deleteAcceleration: TimeInterval = 0.1 var heightConstriaint: NSLayoutConstraint? lazy var bgImageView: UIImageView = { let imageView = UIImageView() imageView.image = UIImage(named: "keyboard_bg") return imageView }() lazy var menuBtn: UIButton = { let button = UIButton() button.setImage(UIImage(named: "keyboard_menu_btn"), for: .normal) button.addTarget(self, action: #selector(menuBtnClickAction), for: .touchUpInside) return button }() lazy var heartAnimation: LottieAnimationView = { let animate = LottieAnimationView(name: "heart") animate.loopMode = .loop animate.backgroundColor = .clear animate.isUserInteractionEnabled = true let tap = UITapGestureRecognizer(target: self, action: #selector(heartBtnClickAction)) animate.addGestureRecognizer(tap) return animate }() lazy var heartLabel: UILabel = { let label = UILabel() label.text = "30%" label.font = .boldSystemFont(ofSize: 12) label.textColor = .white label.isUserInteractionEnabled = true let tap = UITapGestureRecognizer(target: self, action: #selector(heartBtnClickAction)) label.addGestureRecognizer(tap) return label }() lazy var exchangeBtn: UIButton = { let button = UIButton() button.setImage(UIImage(named: "keyboard_exchange_btn"), for: .normal) button.addTarget(self, action: #selector(exchangeBtnClickAction), for: .touchUpInside) return button }() lazy var chooseView: UIView = { let view = UIView() view.backgroundColor = .white view.layer.cornerRadius = 17 return view }() lazy var functionView: UIView = { let view = UIView() view.backgroundColor = .hexStringColor(hexString: "#DDCFFD") view.layer.cornerRadius = 16 view.isUserInteractionEnabled = true let tap = UITapGestureRecognizer(target: self, action: #selector(functionBtnClickAction)) view.addGestureRecognizer(tap) return view }() lazy var functionLabel: UILabel = { let label = UILabel() label.text = "帮聊" label.font = .boldSystemFont(ofSize: 14) label.textColor = .hexStringColor(hexString: "#000000", alpha: 0.8) return label }() lazy var arrowIcon: UIImageView = { let imageView = UIImageView() imageView.image = UIImage(named: "icon_arrow_down") return imageView }() lazy var userChangeBtn: UIButton = { let btn = UIButton() btn.setTitle("小蕾", for: .normal) btn.titleLabel?.font = .systemFont(ofSize: 14, weight: .medium) btn.setTitleColor(.hexStringColor(hexString: "#000000").withAlphaComponent(0.8), for: .normal) btn.setImage(UIImage(named: "keyboard_user_change_icon"), for: .normal) btn.setImageTitleLayout(.imgRight, spacing: 8) btn.addTarget(self, action: #selector(changeBtnClickAction), for: .touchUpInside) return btn }() lazy var userChangeView: UIView = { let view = UIView() let tap = UITapGestureRecognizer(target: self, action: #selector(changeBtnClickAction)) view.addGestureRecognizer(tap) return view }() lazy var userChangeLabel: MarqueeLabel = { let label = MarqueeLabel(frame: .zero, duration: 3.0, fadeLength: 0) label.type = .leftRight label.text = "通用键盘" label.font = .systemFont(ofSize: 14) label.textColor = .hexStringColor(hexString: "#000000") label.textAlignment = .center return label }() lazy var userChangeIcon: UIImageView = { let icon = UIImageView() icon.image = UIImage(named: "keyboard_user_change_icon") return icon }() lazy var helpView: KeyboardHelpView = { let view = KeyboardHelpView() view.delegate = self view.helpDelegate = self return view }() lazy var teachView: KeyboardTeachView = { let view = KeyboardTeachView() view.delegate = self view.teachDelegate = self view.isHidden = true return view }() lazy var prologueView: KeyboardPrologueView = { let view = KeyboardPrologueView() view.delegate = self view.prologueDelegate = self view.isHidden = true return view }() lazy var exchangeView: KeyboardExchangeView = { let view = KeyboardExchangeView() view.isHidden = true view.delegate = self return view }() lazy var menuView: KeyboardMenuView = { let view = KeyboardMenuView() view.isHidden = true view.delegate = self return view }() lazy var loginView: KeyboardLoginTipView = { let view = KeyboardLoginTipView() view.isHidden = true view.loginBtnClosure = { self.navigateToLogin() } view.backBtnClosure = { self.clearPopView() self.loginView.isHidden = true self.nowShowView?.isHidden = false } return view }() lazy var vipView: KeyboardVipTipView = { let view = KeyboardVipTipView() view.isHidden = true view.unlockBtnClosure = { self.navigateToMembership() } view.backBtnClosure = { self.clearPopView() self.vipView.isHidden = true self.nowShowView?.isHidden = false } return view }() var nowShowView: UIView? // 命令检查定时器 private var guideCheckTimer: Timer? override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) self.prepareHeightConstraint() } override func viewDidLoad() { super.viewDidLoad() setUI() checkFullAccess() KeyboardApi.initParams() let isFullAccess = self.hasFullAccess if isFullAccess { requestKeyboardList() requestPrologueList() } if let defaultType = UserDefaults.standard.value(forKey: "KeyboardChooseType") as? Int, let type = KeyboardType(rawValue: defaultType) { self.chooseType = type } startMonitoringPasteboard() startListenGuide() // self.nextKeyboardButton.leftAnchor.constraint(equalTo: self.view.leftAnchor).isActive = true // self.nextKeyboardButton.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) } override func viewWillLayoutSubviews() { super.viewWillLayoutSubviews() } override func updateViewConstraints() { super.updateViewConstraints() if self.view.frame.size.width == 0 && self.view.frame.size.height == 0 { return } self.prepareHeightConstraint() } override func textWillChange(_ textInput: UITextInput?) { // The app is about to change the document's contents. Perform any preparation here. } override func textDidChange(_ textInput: UITextInput?) { // The app has just changed the document's contents, the document context has been updated. var textColor: UIColor let proxy = self.textDocumentProxy if proxy.keyboardAppearance == UIKeyboardAppearance.dark { textColor = UIColor.white } else { textColor = UIColor.black } } func prepareHeightConstraint() { if self.heightConstriaint == nil { if let view = self.view { self.heightConstriaint = NSLayoutConstraint(item: view, attribute: NSLayoutConstraint.Attribute.height, relatedBy: NSLayoutConstraint.Relation.equal, toItem: nil, attribute: NSLayoutConstraint.Attribute.notAnAttribute, multiplier: 0.0, constant: UX.keyboardDefaultHeight) // self.heightConstriaint?.priority = UILayoutPriority(750) self.view.addConstraint(self.heightConstriaint!) } } else { self.heightConstriaint?.constant = UX.keyboardDefaultHeight } } // 开始监听是否需要打开引导页 func startListenGuide() { let isNotFirstOpen = UserDefaults.standard.bool(forKey: "isNotFirstOpenKey") if !isNotFirstOpen { // 创建定时器定期检查命令 guideCheckTimer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [weak self] _ in self?.popGuideView() } } } func popGuideView() { let hasFullAccess = self.hasFullAccess let showGuide = KeyboardSharedDataManager.shared.getIsShowGuide() if hasFullAccess && (showGuide == true) { let guideView = KeyboardGuideView() self.view.addSubview(guideView) guideView.snp.makeConstraints { make in make.top.left.right.bottom.equalTo(0) } UserDefaults.standard.set(true, forKey: "isNotFirstOpenKey") guideCheckTimer?.invalidate() guideCheckTimer = nil } } } // MARK: - 网络请求 extension KeyboardViewController { // 获取键盘列表 func requestKeyboardList() { KeyboardNetworkManager.request(.keyboard_list(params: [:])) { response in if let keyboardInfos = try? response.mapArray(KeyboardModel.self, atKeyPath: "data.keyboardInfos") { self.keyboardList = keyboardInfos self.updateUserChangeBtnUI() self.requestCharacterList() print("成功解析数组,数量:\(keyboardInfos.count)") } } fail: { code, error in self.view.toast(text: error) print(error) } } // 获取键盘人设列表 func requestCharacterList() { var params: [String: Any] = [String: Any]() if let chooseKeyboard = self.chooseKeyboard { params = ["keyboardId": chooseKeyboard.id ?? ""] } KeyboardNetworkManager.request(.character_list(params: params)) { response in if let characterInfos = try? response.mapArray(CharacterModel.self, atKeyPath: "data.characterInfos") { self.characterList = characterInfos self.updateCharacterUI() print("成功解析数组,数量:\(characterInfos.count)") } } fail: { code, error in self.view.toast(text: error) print(error) } } // 获取键盘开场白列表 func requestPrologueList() { KeyboardNetworkManager.request(.prologue_list(params: [:])) { response in if let prologueList = try? response.mapArray(PrologueModel.self, atKeyPath: "data.prologues") { self.prologueList = prologueList self.updatePrologueUI() } } fail: { code, error in self.view.toast(text: error) print(error) } } // 选择键盘 func requestChooseKeyboard(keyboardId: String, success: @escaping (() -> Void)) { var params: [String: Any] = [String: Any]() params = ["keyboardId": keyboardId] KeyboardNetworkManager.request(.keyboard_choose(params: params)) { response in self.view.toast(text: "保存成功") success() } fail: { code, error in self.view.toast(text: error) print(error) } } // 请求获取超会回 func requestSuperReply(characterId: String, content: String, complete: @escaping ((String) -> ())) { var params: [String: Any] = [String: Any]() params = ["keyboardId": self.chooseKeyboard?.id ?? "", "characterId": characterId, "content": content] KeyboardNetworkManager.request(.chat_super_reply(params: params)) { response in if let contentModel = try? response.mapObject(ReplyModel.self, atKeyPath: "data") { complete(contentModel.content ?? "") } else { complete("") } } fail: { code, error in self.view.toast(text: error) print(error) complete("") if code == 1006 { // 弹出登录页 self.popLoginView() } else if code == 1008 { // 弹出会员页 self.popVipView() } } } // 请求获取超会说 func requestSuperSpeak(characterId: String, content: String, complete: @escaping (([String]) -> ())) { var params: [String: Any] = [String: Any]() params = ["keyboardId": self.chooseKeyboard?.id ?? "", "characterId": characterId, "content": content] KeyboardNetworkManager.request(.chat_super_speak(params: params)) { response in if let contentModel = try? response.mapObject(SpeakModel.self, atKeyPath: "data"), let list = contentModel.list { complete(list) } else { complete([String]()) } } fail: { code, error in self.view.toast(text: error) print(error) complete([String]()) if code == 1006 { // 弹出登录页 self.popLoginView() } else if code == 1008 { // 弹出会员页 self.popVipView() } } } // 请求获取超会说 func requestSuperPrologue(name: String, complete: @escaping (([String]) -> ())) { var params: [String: Any] = [String: Any]() params = ["name": name] KeyboardNetworkManager.request(.chat_super_prologue(params: params)) { response in if let contentModel = try? response.mapObject(SpeakModel.self, atKeyPath: "data"), let list = contentModel.list { complete(list) } else { complete([String]()) } } fail: { code, error in self.view.toast(text: error) print(error) complete([String]()) if code == 1006 { // 弹出登录页 self.popLoginView() } else if code == 1008 { // 弹出会员页 self.popVipView() } } } } // MARK: - 点击事件 extension KeyboardViewController: KeyboardMenuViewDelegate, KeyboardExchangeViewDelegate { // 亲密度按钮点击 @objc func heartBtnClickAction() { let url = URL(string: "com.qihuan.zhuiaijianpan:///intimacy")! openURL(url) } // 切换系统键盘 @objc func exchangeBtnClickAction() { self.advanceToNextInputMode() } // 功能按钮选择点击 @objc func functionBtnClickAction() { KeyboardFunctionPopView.show(view: self.view, selectType: self.chooseType) { type in self.chooseType = type } } // 菜单按钮点击 @objc func menuBtnClickAction() { clearPopView() self.menuView.isHidden = false } // 菜单按钮返回 func menuBackBtnClickAction() { clearPopView() self.nowShowView?.isHidden = false } // 会员按钮点击 func vipBtnClickAction() { navigateToMembership() } // 定制人设 func diyBtnClickAction() { let url = URL(string: "com.qihuan.zhuiaijianpan:///character/custom")! openURL(url) } // 人设市场 func marketBtnClickAction() { let url = URL(string: "com.qihuan.zhuiaijianpan:///character/market")! openURL(url) } // 跳转到主应用的登录页面 @objc func navigateToLogin() { let url = URL(string: "com.qihuan.zhuiaijianpan:///login")! openURL(url) } // 跳转到主应用的会员页面 @objc func navigateToMembership() { let url = URL(string: "com.qihuan.zhuiaijianpan:///member")! openURL(url) } @objc @discardableResult private func openURL(_ url: URL) -> Bool { var responder: UIResponder? = self while responder != nil { if let application = responder as? UIApplication { if #available(iOS 18.0, *) { application.open(url, options: [:], completionHandler: nil) return true } else { return application.perform(#selector(openURL(_:)), with: url) != nil } } responder = responder?.next } return false } // // 通用的打开URL方法 // private func openURL(_ url: URL) { //// var responder = self as UIResponder? //// while (responder != nil && !(responder is UIApplication)) { //// responder = responder?.next //// } //// if responder != nil { //// let selectorOpenURL = sel_registerName("openURL:options:completionHandler:") //// if responder!.responds(to: selectorOpenURL) { //// self.dismissKeyboard() //// responder?.perform(selectorOpenURL, with: [url, nil, nil]) //// } //// } // // var responder: UIResponder? = self // while responder != nil { // if let application = responder as? UIApplication { // if #available(iOS 18.0, *) { // application.open(url, options: [:], completionHandler: nil) // } else { // application.perform(#selector(openURL(_:)), with: url) // } // } // responder = responder?.next // } // // 不知道为什么无法使用 //// self.extensionContext?.open(url, completionHandler: nil) // } // 选择键盘按钮点击 @objc func changeBtnClickAction() { clearPopView() self.exchangeView.keyboardList = self.keyboardList self.exchangeView.isHidden = false } // 选择键盘后返回 func exchangeViewBackClickAction() { clearPopView() self.nowShowView?.isHidden = false } // 点击保存按钮 func exchangeViewSaveClickAction(keyboardList: [KeyboardModel], success: @escaping (() -> ())) { var keyboardId = "" var selectKeyboard: KeyboardModel? for keyboard in keyboardList { if keyboard.isChoose == true { keyboardId = keyboard.id ?? "" selectKeyboard = keyboard break } } if let selectKeyboard = selectKeyboard { // 当为系统键盘时不需要调接口 if selectKeyboard.type == "system" { self.keyboardList = keyboardList self.chooseKeyboard = selectKeyboard self.requestCharacterList() success() self.userChangeLabel.text = self.chooseKeyboard?.name self.clearPopView() self.nowShowView?.isHidden = false } else { requestChooseKeyboard(keyboardId: keyboardId) { self.keyboardList = keyboardList self.chooseKeyboard = selectKeyboard self.requestCharacterList() success() self.userChangeLabel.text = self.chooseKeyboard?.name self.clearPopView() self.nowShowView?.isHidden = false } } } } } extension KeyboardViewController: KeyboardHelpViewDelegate, KeyboardTeachViewDelegate, KeyboardPrologueViewDelegate { // 帮聊点击cell func helpCollectionViewDidSelectItem(characterId: String, content: String, complete: @escaping ((Bool) -> ())) { // 判断是否登录 let isLogin = KeyboardSharedDataManager.shared.isLoggedIn() if !isLogin { popLoginView() complete(false) return } self.requestSuperReply(characterId: characterId, content: content) { text in self.insertText(text) complete(true) } } // 教你说点击cell func teachCollectionViewDidSelectItem(characterId: String, content: String, complete: @escaping (([String], Bool, Bool) -> ())) { // 判断是否登录 let isLogin = KeyboardSharedDataManager.shared.isLoggedIn() if !isLogin { popLoginView() complete([String](), false, false) return } else { complete([String](), true, false) } self.requestSuperSpeak(characterId: characterId, content: content) { list in complete(list, true, true) } } // 教你说点击 TableViewCell func teachTableViewDidSelectItem(content: String) { self.insertText(content) } // 开场白点击cell func prologueCollectionViewDidSelectItem(name: String, complete: @escaping (([String], Bool, Bool) -> ())) { // 判断是否登录 let isLogin = KeyboardSharedDataManager.shared.isLoggedIn() if !isLogin { popLoginView() complete([String](), false, false) return } else { complete([String](), true, false) } self.requestSuperPrologue(name: name) { list in complete(list, true, true) } } // 开场白点击 TableViewCell func prologueTableViewDidSelectItem(content: String) { self.insertText(content) } // 点击添加人设 func addCharacterJump() { self.marketBtnClickAction() } } // MARK: - 处理键盘操作 extension KeyboardViewController: KeyboardBaseViewDelegate { // 插入文字 func insertText(_ text: String) { self.textDocumentProxy.insertText(text) } // 点击粘贴按钮 func pasteBtnClickAction() { detectPasteboardPermissionAlert { isShowing in if isShowing { print("系统正在显示剪贴板权限弹窗") self.view.toast(text: "请允许访问剪贴板") self.openPasteTipView() } if let content = self.getPasteboardContent() { print("获取到剪贴板内容: \(content)") self.view.toast(text: "获取到剪贴板内容") self.helpView.setPasteStr(content: content) self.teachView.setPasteStr(content: content) } else { print("无法获取剪贴板内容") self.view.toast(text: "无法获取剪贴板内容") } } } // 删除按钮 func deleteBtnClickAction() { self.textDocumentProxy.deleteBackward() } // 清除按钮 func clearBtnClickAction() { // 获取当前文本 let proxy = self.textDocumentProxy // 清空所有文本 for _ in 0..<100 { proxy.deleteBackward() } } // 发送按钮 func sendBtnClickAction() { self.textDocumentProxy.insertText("\n") } func deleteBtnLongPressBegin() { // 停止已有的定时器 stopContinuousDelete() // 创建新的定时器,初始间隔为0.5秒 deleteTimer = Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(continuousDeleteAction), userInfo: nil, repeats: false) } func deleteBtnLongPressEnd() { stopContinuousDelete() } // 停止删除 func stopContinuousDelete() { deleteTimer?.invalidate() deleteTimer = nil deleteAcceleration = 0.1 // 重置加速度 } @objc func continuousDeleteAction() { // 执行删除操作 self.textDocumentProxy.deleteBackward() // 停止当前定时器 deleteTimer?.invalidate() // 加速删除(最快0.05秒一次) let newInterval = max(0.05, 0.5 - deleteAcceleration) deleteAcceleration += 0.05 // 每次加速0.05秒 // 创建新的更快的定时器 deleteTimer = Timer.scheduledTimer(timeInterval: newInterval, target: self, selector: #selector(continuousDeleteAction), userInfo: nil, repeats: false) } // 监听剪贴板变化 func startMonitoringPasteboard() { // 记录当前剪贴板变化计数 var initialChangeCount = UIPasteboard.general.changeCount // 记录上一次的剪贴板内容 var lastPasteboardContent: String? = UIPasteboard.general.string // 创建定时器定期检查剪贴板变化 Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { [weak self] timer in guard let self = self else { timer.invalidate() return } let currentChangeCount = UIPasteboard.general.changeCount if currentChangeCount != initialChangeCount { // 记录访问前的时间 let startTime = Date() // 剪贴板计数已变化,检查内容是否真的变化 if let copiedString = UIPasteboard.general.string { // 只有当内容真的不同时才处理 if !copiedString.isEmpty { print("检测到新复制的内容: \(copiedString)") // 更新记录的内容和计数 lastPasteboardContent = copiedString initialChangeCount = currentChangeCount // 处理复制的内容 self.handleCopiedContent(copiedString) // 检查访问后的时间延迟 let timeDelay = Date().timeIntervalSince(startTime) // 如果访问剪贴板的时间超过一定阈值,可能是因为系统弹出了权限弹窗 // 通常正常访问剪贴板的时间应该很短,如果超过100毫秒,可能是弹出了弹窗 if timeDelay > 0.1 { self.openPasteTipView() } else { } } else { // 内容相同或为空,只更新计数 initialChangeCount = currentChangeCount print("剪贴板计数变化但内容未变或为空") self.openPasteTipView() } } else { // 剪贴板内容为nil,更新计数 initialChangeCount = currentChangeCount lastPasteboardContent = nil print("剪贴板内容被清空") } } } } // 处理复制的内容 func handleCopiedContent(_ content: String) { self.helpView.setPasteStr(content: content) self.teachView.setPasteStr(content: content) } // 检查键盘权限 func checkPasteboardPermission() -> Bool { var hasPasteboardPermission = false // iOS 14及以上版本需要检查权限 if #available(iOS 14.0, *) { // 尝试读取剪贴板内容来检查权限 let pasteboard = UIPasteboard.general if let _ = pasteboard.string { hasPasteboardPermission = true print("键盘扩展有剪贴板访问权限") } else { hasPasteboardPermission = false print("键盘扩展没有剪贴板访问权限") } } else { // iOS 14以下版本默认有权限 hasPasteboardPermission = true } return hasPasteboardPermission } // 检测系统是否弹出剪贴板权限弹窗 func detectPasteboardPermissionAlert(completion: @escaping (Bool) -> Void) { // 记录访问前的时间 let startTime = Date() // 尝试访问剪贴板 let _ = UIPasteboard.general.string // 检查访问后的时间延迟 let timeDelay = Date().timeIntervalSince(startTime) // 如果访问剪贴板的时间超过一定阈值,可能是因为系统弹出了权限弹窗 // 通常正常访问剪贴板的时间应该很短,如果超过100毫秒,可能是弹出了弹窗 if timeDelay > 0.1 { completion(true) } else { completion(false) } } // 获取剪贴板内容 func getPasteboardContent() -> String? { let pasteboard = UIPasteboard.general return pasteboard.string } // 允许粘贴跳转至设置页 func jumpToSettings() { if let url = URL(string: UIApplication.openSettingsURLString) { self.openURL(url) } } func tipsCloseBtnAction() { self.helpView.topView.isHidden = true self.helpView.topView.snp.updateConstraints { make in make.height.equalTo(0) } self.teachView.topView.isHidden = true self.teachView.topView.snp.updateConstraints { make in make.height.equalTo(0) } self.prologueView.topView.isHidden = true self.prologueView.topView.snp.updateConstraints { make in make.height.equalTo(0) } self.view.removeConstraint(self.heightConstriaint!) self.heightConstriaint = NSLayoutConstraint(item: self.view, attribute: NSLayoutConstraint.Attribute.height, relatedBy: NSLayoutConstraint.Relation.equal, toItem: nil, attribute: NSLayoutConstraint.Attribute.notAnAttribute, multiplier: 0.0, constant: UX.keyboardDefaultHeight) // newHeightConstriaint.priority = UILayoutPriority(750) self.view.addConstraint(self.heightConstriaint!) } } extension KeyboardViewController { // 打开弹窗 func openPasteTipView() { self.helpView.topView.isHidden = false self.helpView.topView.snp.updateConstraints { make in make.height.equalTo(32) } self.teachView.topView.isHidden = false self.teachView.topView.snp.updateConstraints { make in make.height.equalTo(32) } self.prologueView.topView.isHidden = false self.prologueView.topView.snp.updateConstraints { make in make.height.equalTo(32) } self.view.removeConstraint(self.heightConstriaint!) self.heightConstriaint = NSLayoutConstraint(item: self.view, attribute: NSLayoutConstraint.Attribute.height, relatedBy: NSLayoutConstraint.Relation.equal, toItem: nil, attribute: NSLayoutConstraint.Attribute.notAnAttribute, multiplier: 0.0, constant: UX.keyboardWithTipsHeight) // newHeightConstriaint.priority = UILayoutPriority(750) self.view.addConstraint(self.heightConstriaint!) } // 检查是否有完全访问权限 func checkFullAccess() { let isFullAccess = self.hasFullAccess if !isFullAccess { let tipView = KeyboardTipsPopView() tipView.settingBtnClosure = { if let url = URL(string: UIApplication.openSettingsURLString) { self.openURL(url) } } self.view.addSubview(tipView) tipView.snp.makeConstraints { make in make.left.right.bottom.equalTo(0) make.top.equalTo(56) } } } // 跳转登录页 func popLoginView() { self.clearPopView() self.loginView.isHidden = false } // 弹出vip页面 func popVipView() { self.clearPopView() self.vipView.isHidden = false } // 关闭其他弹出页 func clearPopView() { self.vipView.isHidden = true self.loginView.isHidden = true self.menuView.isHidden = true self.exchangeView.isHidden = true self.helpView.isHidden = true self.teachView.isHidden = true self.prologueView.isHidden = true } // 更新主要界面 func updateMainViewUI() { clearPopView() switch chooseType { case .help: // self.helpView.characterList = self.characterList self.helpView.isHidden = false self.nowShowView = self.helpView self.functionLabel.text = "帮聊" break case .teach: // self.teachView.characterList = self.characterList self.teachView.isHidden = false self.nowShowView = self.teachView self.functionLabel.text = "教你说" break case .prologue: self.prologueView.isHidden = false self.nowShowView = self.prologueView self.functionLabel.text = "开场白" break } } // 更新人设列表 func updateCharacterUI() { self.helpView.characterList = self.characterList self.teachView.characterList = self.characterList } // 更新开场白 func updatePrologueUI() { self.prologueView.prologueList = self.prologueList } // 更新键盘选择按钮 func updateUserChangeBtnUI() { if self.keyboardList?.count == 1 { self.keyboardList?[0].isChoose = true self.chooseKeyboard = self.keyboardList?.first } else { if let keyboardList = self.keyboardList { for keyboard in keyboardList { if keyboard.isChoose == true { self.chooseKeyboard = keyboard } } } } if let chooseKeyboard = self.chooseKeyboard { self.userChangeLabel.text = chooseKeyboard.name self.heartLabel.text = "\(chooseKeyboard.intimacy ?? 0)%" } } func setUI() { self.view.addSubview(bgImageView) bgImageView.snp.makeConstraints { make in make.edges.equalToSuperview() } self.view.addSubview(menuBtn) menuBtn.snp.makeConstraints { make in make.size.equalTo(CGSize(width: 32, height: 32)) make.left.equalTo(13) make.top.equalTo(17) } self.view.addSubview(heartAnimation) heartAnimation.snp.makeConstraints { make in make.size.equalTo(CGSize(width: 35, height: 30)) make.right.equalTo(-10) make.centerY.equalTo(menuBtn.snp.centerY) } heartAnimation.play() self.view.addSubview(heartLabel) heartLabel.snp.makeConstraints { make in make.centerY.equalTo(heartAnimation.snp.centerY).offset(-2) make.centerX.equalTo(heartAnimation.snp.centerX) } self.view.addSubview(exchangeBtn) exchangeBtn.snp.makeConstraints { make in make.size.equalTo(CGSize(width: 34, height: 34)) make.right.equalTo(heartAnimation.snp.left).offset(-10) make.centerY.equalTo(menuBtn.snp.centerY) } self.view.addSubview(teachView) teachView.snp.makeConstraints { make in make.left.right.bottom.equalTo(0) make.top.equalTo(60) } self.view.addSubview(helpView) helpView.snp.makeConstraints { make in make.left.right.bottom.equalTo(0) make.top.equalTo(60) } self.view.addSubview(prologueView) prologueView.snp.makeConstraints { make in make.left.right.bottom.equalTo(0) make.top.equalTo(60) } self.view.addSubview(chooseView) chooseView.snp.makeConstraints { make in make.width.equalTo(185) make.height.equalTo(34) make.left.equalTo(menuBtn.snp.right).offset(9) make.centerY.equalTo(menuBtn.snp.centerY) } self.view.addSubview(exchangeView) exchangeView.snp.makeConstraints { make in make.top.equalTo(menuBtn.snp.bottom) make.left.right.bottom.equalTo(0) } self.view.addSubview(menuView) menuView.snp.makeConstraints { make in make.left.right.bottom.equalTo(0) make.top.equalTo(menuBtn.snp.bottom) } self.view.addSubview(loginView) loginView.snp.makeConstraints { make in make.top.left.right.bottom.equalTo(0) } self.view.addSubview(vipView) vipView.snp.makeConstraints { make in make.top.left.right.bottom.equalTo(0) } chooseView.addSubview(functionView) functionView.snp.makeConstraints { make in make.top.left.equalTo(1) make.bottom.equalTo(-1) make.width.equalTo(85) } functionView.addSubview(functionLabel) functionLabel.snp.makeConstraints { make in make.left.equalTo(12) make.centerY.equalToSuperview() } functionView.addSubview(arrowIcon) arrowIcon.snp.makeConstraints { make in make.size.equalTo(CGSize(width: 18, height: 18)) make.centerY.equalToSuperview() make.right.equalTo(-5) } chooseView.addSubview(userChangeView) userChangeView.snp.makeConstraints { make in make.left.equalTo(functionView.snp.right) make.right.equalToSuperview() make.top.bottom.equalTo(0) } userChangeView.addSubview(userChangeIcon) userChangeIcon.snp.makeConstraints { make in make.size.equalTo(CGSize(width: 12, height: 12)) make.centerY.equalToSuperview() make.right.equalTo(-8) } userChangeView.addSubview(userChangeLabel) userChangeLabel.snp.makeConstraints { make in make.right.equalTo(userChangeIcon.snp.left).offset(-4) make.left.equalTo(4) make.centerY.equalToSuperview() } // chooseView.addSubview(userChangeBtn) // userChangeBtn.snp.makeConstraints { make in // make.left.equalTo(functionView.snp.right) // make.right.equalToSuperview() // make.top.bottom.equalTo(0) // } self.nowShowView = self.helpView } }