TRTCRegisterRootView.swift 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. //
  2. // TRTCRegisterRootView.swift
  3. // TXLiteAVDemo
  4. //
  5. // Created by gg on 2021/4/8.
  6. // Copyright © 2021 Tencent. All rights reserved.
  7. //
  8. import UIKit
  9. class TRTCRegisterRootView: UIView {
  10. lazy var headImageView: UIImageView = {
  11. let imageView = UIImageView(frame: .zero)
  12. imageView.contentMode = .scaleAspectFill
  13. imageView.layer.cornerRadius = 50
  14. imageView.clipsToBounds = true
  15. return imageView
  16. }()
  17. lazy var textLable: UILabel = {
  18. let label = UILabel()
  19. label.text = .nicknameText
  20. label.font = UIFont(name: "PingFangSC-Regular", size: 16)
  21. label.adjustsFontSizeToFitWidth = true
  22. return label
  23. }()
  24. lazy var textField: UITextField = {
  25. let textField = createTextField(.nicknamePlaceholderText)
  26. return textField
  27. }()
  28. lazy var textFieldSpacingLine: UIView = {
  29. let view = createSpacingLine()
  30. return view
  31. }()
  32. lazy var descLabel: UILabel = {
  33. let label = UILabel(frame: .zero)
  34. label.font = UIFont(name: "PingFangSC-Regular", size: 16)
  35. label.textColor = .darkGray
  36. label.text = .descText
  37. label.adjustsFontSizeToFitWidth = true
  38. return label
  39. }()
  40. lazy var registBtn: UIButton = {
  41. let btn = UIButton(type: .custom)
  42. btn.setTitleColor(.white, for: .normal)
  43. btn.setTitle(.registText, for: .normal)
  44. btn.adjustsImageWhenHighlighted = false
  45. btn.setBackgroundImage(UIColor.tui_color(withHex: "006EFF").trans2Image(), for: .normal)
  46. btn.titleLabel?.font = UIFont(name: "PingFangSC-Medium", size: 18)
  47. btn.layer.shadowColor = UIColor.tui_color(withHex: "006EFF").cgColor
  48. btn.layer.shadowOffset = CGSize(width: 0, height: 6)
  49. btn.layer.shadowRadius = 16
  50. btn.layer.shadowOpacity = 0.4
  51. btn.layer.masksToBounds = true
  52. btn.isEnabled = false
  53. return btn
  54. }()
  55. private func createTextField(_ placeholder: String) -> UITextField {
  56. let textField = UITextField(frame: .zero)
  57. textField.backgroundColor = .white
  58. textField.font = UIFont(name: "PingFangSC-Regular", size: 16)
  59. textField.textColor = UIColor.tui_color(withHex: "333333")
  60. textField.attributedPlaceholder = NSAttributedString(string: placeholder,
  61. attributes: [NSAttributedString.Key.font:
  62. UIFont(name: "PingFangSC-Regular", size: 16) ??
  63. UIFont.systemFont(ofSize: 16),
  64. NSAttributedString.Key.foregroundColor :
  65. UIColor.tui_color(withHex: "BBBBBB"),])
  66. textField.delegate = self
  67. return textField
  68. }
  69. private func createSpacingLine() -> UIView {
  70. let view = UIView(frame: .zero)
  71. view.backgroundColor = UIColor.tui_color(withHex: "EEEEEE")
  72. return view
  73. }
  74. override func draw(_ rect: CGRect) {
  75. super.draw(rect)
  76. registBtn.layer.cornerRadius = registBtn.frame.height * 0.5
  77. }
  78. override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
  79. super.touchesBegan(touches, with: event)
  80. textField.resignFirstResponder()
  81. UIView.animate(withDuration: 0.3) {
  82. self.transform = .identity
  83. }
  84. checkRegistBtnState()
  85. }
  86. weak var rootVC: TRTCRegisterViewController?
  87. override init(frame: CGRect) {
  88. super.init(frame: frame)
  89. NotificationCenter.default.addObserver(self, selector: #selector(keyboardFrameChange(noti:)), name:
  90. UIResponder.keyboardWillChangeFrameNotification, object: nil)
  91. }
  92. deinit {
  93. NotificationCenter.default.removeObserver(self)
  94. }
  95. @objc func keyboardFrameChange(noti : Notification) {
  96. guard let info = noti.userInfo else {
  97. return
  98. }
  99. guard let value = info[UIResponder.keyboardFrameEndUserInfoKey], value is CGRect else {
  100. return
  101. }
  102. guard let superview = textField.superview else {
  103. return
  104. }
  105. let rect = value as! CGRect
  106. let converted = superview.convert(textField.frame, to: self)
  107. if rect.intersects(converted) {
  108. transform = CGAffineTransform(translationX: 0, y: -converted.maxY+rect.minY)
  109. }
  110. }
  111. required init?(coder: NSCoder) {
  112. fatalError("init(coder:) has not been implemented")
  113. }
  114. var isViewReady = false
  115. override func didMoveToWindow() {
  116. super.didMoveToWindow()
  117. guard !isViewReady else {
  118. return
  119. }
  120. isViewReady = true
  121. constructViewHierarchy()
  122. activateConstraints()
  123. bindInteraction()
  124. if let url = ProfileManager.shared.curUserModel?.avatar, url.count > 0 {
  125. headImageView.sd_setImage(with: URL(string: url))
  126. } else {
  127. let url = "https://liteav.sdk.qcloud.com/app/res/picture/voiceroom/avatar/user_avatar1.png"
  128. ProfileManager.shared.curUserModel?.avatar = url
  129. headImageView.sd_setImage(with: URL(string: url))
  130. }
  131. }
  132. func constructViewHierarchy() {
  133. addSubview(headImageView)
  134. addSubview(textLable)
  135. addSubview(textField)
  136. addSubview(textFieldSpacingLine)
  137. addSubview(descLabel)
  138. addSubview(registBtn)
  139. }
  140. func activateConstraints() {
  141. headImageView.snp.makeConstraints { (make) in
  142. make.centerX.equalToSuperview()
  143. make.top.equalToSuperview().offset(kDeviceSafeTopHeight + 70)
  144. make.size.equalTo(CGSize(width: 100, height: 100))
  145. }
  146. textLable.snp.makeConstraints { (make) in
  147. make.top.equalTo(headImageView.snp.bottom).offset(convertPixel(h: 40))
  148. make.leading.equalToSuperview().offset(convertPixel(w: 40))
  149. make.height.equalTo(convertPixel(h: 57))
  150. make.width.equalTo(convertPixel(w: 60))
  151. }
  152. textField.snp.makeConstraints { (make) in
  153. make.top.equalTo(textLable)
  154. make.leading.equalTo(textLable.snp.trailing).offset(convertPixel(w: 5))
  155. make.trailing.equalToSuperview().offset(-convertPixel(w: 40))
  156. make.height.equalTo(convertPixel(h: 57))
  157. }
  158. textFieldSpacingLine.snp.makeConstraints { (make) in
  159. make.bottom.trailing.equalTo(textField)
  160. make.leading.equalTo(textLable)
  161. make.height.equalTo(1)
  162. }
  163. descLabel.snp.makeConstraints { (make) in
  164. make.top.equalTo(textField.snp_bottom).offset(10)
  165. make.leading.equalToSuperview().offset(convertPixel(w: 40))
  166. make.trailing.lessThanOrEqualToSuperview().offset(convertPixel(w: -40))
  167. }
  168. registBtn.snp.makeConstraints { (make) in
  169. make.top.equalTo(descLabel.snp_bottom).offset(convertPixel(h: 40))
  170. make.leading.equalToSuperview().offset(convertPixel(w: 20))
  171. make.trailing.equalToSuperview().offset(-convertPixel(w: 20))
  172. make.height.equalTo(convertPixel(h: 52))
  173. }
  174. }
  175. func bindInteraction() {
  176. registBtn.addTarget(self, action: #selector(registBtnClick), for: .touchUpInside)
  177. let tap = UITapGestureRecognizer(target: self, action: #selector(headBtnClick))
  178. headImageView.addGestureRecognizer(tap)
  179. }
  180. override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
  181. guard let superview = headImageView.superview else {
  182. return super.hitTest(point, with: event)
  183. }
  184. let rect = superview.convert(headImageView.frame, to: self)
  185. if rect.contains(point) {
  186. return headImageView
  187. }
  188. return super.hitTest(point, with: event)
  189. }
  190. @objc func headBtnClick() {
  191. }
  192. @objc func registBtnClick() {
  193. textField.resignFirstResponder()
  194. guard let name = textField.text else {
  195. return
  196. }
  197. if name.utf8.count > 30 {
  198. makeToast(.nameTooLongText, duration: 1)
  199. } else {
  200. ProfileManager.shared.curUserModel?.name = name
  201. rootVC?.regist(name)
  202. }
  203. }
  204. func checkRegistBtnState(_ count: Int = -1) {
  205. registBtn.isEnabled = count > 1
  206. }
  207. }
  208. extension TRTCRegisterRootView : UITextFieldDelegate {
  209. func textFieldDidBeginEditing(_ textField: UITextField) {
  210. textField.becomeFirstResponder()
  211. }
  212. func textFieldDidEndEditing(_ textField: UITextField) {
  213. textField.resignFirstResponder()
  214. UIView.animate(withDuration: 0.3) {
  215. self.transform = .identity
  216. }
  217. checkRegistBtnState()
  218. }
  219. func textFieldShouldReturn(_ textField: UITextField) -> Bool {
  220. textField.resignFirstResponder()
  221. return true
  222. }
  223. func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
  224. let maxCount = 20
  225. guard let textFieldText = textField.text,
  226. let rangeOfTextToReplace = Range(range, in: textFieldText) else {
  227. return false
  228. }
  229. let substringToReplace = textFieldText[rangeOfTextToReplace]
  230. let count = textFieldText.count - substringToReplace.count + string.count
  231. let res = count <= maxCount
  232. if res {
  233. checkRegistBtnState(count)
  234. if string.isEmpty {
  235. return true
  236. }else if string.count > 1 {
  237. for char in string {
  238. let str = String(char)
  239. if !validateString(str) {
  240. return false
  241. }
  242. }
  243. return true
  244. }else{
  245. return validateString(string)
  246. }
  247. }
  248. return res
  249. }
  250. }
  251. func validateString(_ string: String) -> Bool {
  252. let regex = try! NSRegularExpression(pattern: "^[a-zA-Z0-9_\u{4e00}-\u{9fa5}]{0,20}$")
  253. let range = NSRange(location: 0, length: string.utf16.count)
  254. return regex.firstMatch(in: string, options: [], range: range) != nil
  255. }
  256. /// MARK: - internationalization string
  257. fileprivate extension String {
  258. static let nicknamePlaceholderText = LoginLocalize(key:"Please enter a nickname")
  259. static let descText = LoginLocalize(key:"Letters, numbers and underscores")
  260. static let registText = LoginLocalize(key:"Sign Up")
  261. static let nameTooLongText = LoginLocalize(key:"Your Nickname is too long")
  262. static let nicknameText = LoginLocalize(key:"Nickname")
  263. }