jsdw_ios/QuickLocation/Section/PopupWindow/PopupWindow.swift

826 lines
27 KiB
Swift

//
// PopupWindow.swift
// QuickLocation
//
// Created by on 2026/7/2.
//
import UIKit
import RxSwift
import RxCocoa
import Lottie
enum PopupType {
///
case search
///
case register
///
case vip
}
class PopupWindow: UIView {
private static let shared = PopupWindow(frame: CGRect(origin: .zero, size: kScreenSize))
var disposeBag = DisposeBag()
private var popupType: PopupType? {
didSet {
switch popupType {
case .search:
searchPopupView.isHidden = false
earthLottieView.play()
case .register:
if Bool.random() {
registerPopupView.isHidden = true
register2PopupView.isHidden = false
slideInRegister2Popup()
} else {
register2PopupView.isHidden = true
registerPopupView.isHidden = false
slideInRegisterPopup()
}
case .vip:
slideInUnlockVip1Popup()
default:
break
}
}
}
static func show(popupType: PopupType) {
guard let superView = kKeyWindow else {
return
}
if PopupWindow.shared.superview != nil {
PopupWindow.shared.removeFromSuperview()
PopupWindow.shared.bgView.frame = .zero
}
PopupWindow.shared.resetPopupState()
PopupWindow.shared.popupType = popupType
PopupWindow.shared.bgView.alpha = 1
PopupWindow.shared.bgView.frame = CGRect(x: 0, y: 0, width: kScreenWidth, height: kScreenHeight)
superView.addSubview(PopupWindow.shared)
superView.bringSubviewToFront(PopupWindow.shared)
UIView.animate(withDuration: 0.25) {
PopupWindow.shared.bgView.alpha = 1
}
}
private func resetPopupState() {
stopRegisterStarFlash()
stopRegister1LottieAlternate()
stopUnlockVip1Animations()
registerPopupView.transform = .identity
register2PopupView.transform = .identity
unlockVip1View.transform = .identity
registerStar1.transform = .identity
// register2Star1.transform = .identity
searchPopupView.isHidden = true
registerPopupView.isHidden = true
register2PopupView.isHidden = true
unlockVip1View.isHidden = true
bgView.isUserInteractionEnabled = true
}
///
static func dismiss() {
guard PopupWindow.shared.superview != nil else { return }
UIView.animate(withDuration: 0.25, delay: 0, options: [.curveEaseIn]) {
PopupWindow.shared.bgView.alpha = 0
} completion: { _ in
PopupWindow.shared.resetPopupState()
PopupWindow.shared.removeFromSuperview()
}
}
private func setupRx() {
registerCloseBtn.rx.tap
.subscribe(onNext: { [weak self] _ in
self?.activePopupView == 2 ? self?.slideOutRegister2Popup() : self?.slideOutRegisterPopup()
})
.disposed(by: disposeBag)
registerBtn.rx.tap
.subscribe(onNext: { [weak self] _ in
self?.activePopupView == 2 ? self?.slideOutRegister2Popup() : self?.slideOutRegisterPopup()
AppRouter.push(Route.login)
})
.disposed(by: disposeBag)
register2CloseBtn.rx.tap
.subscribe(onNext: { [weak self] _ in
self?.slideOutRegister2Popup()
})
.disposed(by: disposeBag)
register2Btn.rx.tap
.subscribe(onNext: { [weak self] _ in
self?.slideOutRegister2Popup()
AppRouter.push(Route.login)
})
.disposed(by: disposeBag)
vip1CloseBtn.rx.tap
.subscribe(onNext: { [weak self] _ in
self?.slideOutUnlockVip1Popup()
})
.disposed(by: disposeBag)
vip1UnlockBtn.rx.tap
.subscribe(onNext: { [weak self] _ in
self?.slideOutUnlockVip1Popup()
})
.disposed(by: disposeBag)
}
private lazy var bgView: UIView = {
let view = UIView()
view.backgroundColor = .black.withAlphaComponent(0.5)
return view
}()
// MARK: -
lazy var searchPopupView: UIView = {
let view = UIView()
view.backgroundColor = .clear
view.isHidden = true
let bgImgView = UIImageView(image: UIImage(named: "PopupWindow/search_bg"))
bgImgView.contentMode = .scaleAspectFill
view.addSubview(bgImgView)
bgImgView.layoutChain
.edges(excludingEdge: .bottom)
.heightToWidth(828/770)
let btn = UIButton(type: .custom)
btn.backgroundColor = .clear
btn.setBackgroundImage(UIImage(named: "Group/close"), for: .normal)
btn.extendEdgeInsets = UIEdgeInsets(top: 10, left: 100, bottom: 100, right: 100)
btn.rx.tap.subscribe(onNext: { _ in
PopupWindow.dismiss()
}).disposed(by: disposeBag)
view.addSubview(btn)
btn.layoutChain
.topToBottomOfView(bgImgView, offset: 0)
.centerX()
.width(22)
.height(22)
.bottom()
// let peopleIcon = UIImageView(image: UIImage(named: "PopupWindow/search_people"))
// peopleIcon.contentMode = .scaleAspectFill
// view.addSubview(peopleIcon)
// peopleIcon.layoutChain
// .top(20)
// .width(73)
// .height(95)
// .rightToCenterXOfView(view)
// let eartIcon = UIImageView(image: UIImage(named: "PopupWindow/search_earth"))
// eartIcon.contentMode = .scaleAspectFill
// view.addSubview(eartIcon)
// eartIcon.layoutChain
// .topToView(peopleIcon, offset: 12)
// .width(88)
// .height(81)
// .leftToCenterXOfView(view)
view.addSubview(earthLottieView)
earthLottieView.layoutChain
.top()
.edgesHorzontal(50)
.heightToWidth(95/155)
return view
}()
lazy var earthLottieView: LottieAnimationView = {
let view = LottieAnimationView(name: "dialog_phone_search")
view.loopMode = .loop
return view
}()
// MARK: - 1
lazy var unlockVip1View: UIView = {
let view = UIView()
view.backgroundColor = .clear
view.isHidden = true
let bgImg = UIImageView(image: UIImage(named: "PopupWindow/vip_bg"))
bgImg.contentMode = .scaleAspectFill
view.addSubview(bgImg)
bgImg.layoutChain
.top(45)
.edgesHorzontal()
.bottom()
view.addSubview(vip1HeartIcon)
vip1HeartIcon.layoutChain
.top()
.left(21)
.width(116)
.height(99)
let logoImg = UIImageView(image: UIImage(named: "PopupWindow/vip1_logo"))
logoImg.contentMode = .scaleAspectFill
view.addSubview(logoImg)
logoImg.layoutChain
.topToView(bgImg, offset: 40)
.centerX()
.width(125)
.height(42)
view.addSubview(vip1Tips2Img)
vip1Tips2Img.layoutChain
.topToBottomOfView(logoImg, offset: 30)
.centerX()
.width(71)
.height(26)
view.addSubview(vip1Tips1Img)
vip1Tips1Img.layoutChain
.rightToLeftOfView(vip1Tips2Img, offset: -24)
.centerY(vip1Tips2Img)
.width(71)
.height(26)
view.addSubview(vip1Tips3Img)
vip1Tips3Img.layoutChain
.leftToRightOfView(vip1Tips2Img, offset: 24)
.centerY(vip1Tips2Img)
.width(71)
.height(26)
let textLab = UILabel()
textLab.text = "看看TA真实走过哪里"
textLab.font = .systemFont(ofSize: 14, weight: .medium)
textLab.textColor = UIColor(hexStr: "#16B3FF")
view.addSubview(textLab)
textLab.layoutChain
.topToBottomOfView(vip1Tips2Img, offset: 20)
.centerX()
view.addSubview(vip1CloseBtn)
vip1CloseBtn.layoutChain
.topToView(bgImg, offset: 32)
.right(17)
view.addSubview(vip1UnlockBtn)
vip1UnlockBtn.layoutChain
.width(224)
.height(50)
.centerX()
.bottom(kSafeBottomMargin + 15)
return view
}()
lazy var vip1HeartIcon: UIImageView = {
let view = UIImageView()
view.image = UIImage(named: "PopupWindow/vip1_heart")
view.contentMode = .scaleAspectFill
return view
}()
lazy var vip1Tips1Img: UIImageView = {
let view = UIImageView()
view.image = UIImage(named: "PopupWindow/vip1_tips_1")
view.contentMode = .scaleAspectFill
return view
}()
lazy var vip1Tips2Img: UIImageView = {
let view = UIImageView()
view.image = UIImage(named: "PopupWindow/vip1_tips_2")
view.contentMode = .scaleAspectFill
return view
}()
lazy var vip1Tips3Img: UIImageView = {
let view = UIImageView()
view.image = UIImage(named: "PopupWindow/vip1_tips_3")
view.contentMode = .scaleAspectFill
return view
}()
lazy var vip1CloseBtn: UIButton = {
let btn = UIButton(type: .custom)
btn.setImage(UIImage(named: "PopupWindow/close"), for: .normal)
btn.extendEdgeInsets = UIEdgeInsets(top: 30, left: 30, bottom: 30, right: 17)
return btn
}()
lazy var vip1UnlockBtn: UIButton = {
let btn = UIButton(type: .custom)
btn.setTitle("立即解锁", for: .normal)
btn.setTitleColor(.white, for: .normal)
btn.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium)
btn.setBackgroundImage(UIImage(named: "Common/button_bg_2"), for: .normal)
btn.cornerRadius = 25
return btn
}()
private func startUnlockVip1Animations() {
stopUnlockVip1Animations()
let heartAnimation = CABasicAnimation(keyPath: "transform.scale")
heartAnimation.fromValue = 1.0
heartAnimation.toValue = 1.2
heartAnimation.duration = 0.55
heartAnimation.autoreverses = true
heartAnimation.repeatCount = .infinity
heartAnimation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
vip1HeartIcon.layer.add(heartAnimation, forKey: "vip1HeartBeat")
addVip1TipSwingAnimation(to: vip1Tips1Img, from: -0.12, to: 0.12, duration: 0.55)
addVip1TipSwingAnimation(to: vip1Tips2Img, from: -0.12, to: 0.12, duration: 0.55)
addVip1TipSwingAnimation(to: vip1Tips3Img, from: -0.12, to: 0.12, duration: 0.55)
}
private func addVip1TipSwingAnimation(to imageView: UIImageView, from: CGFloat, to: CGFloat, duration: CFTimeInterval) {
let animation = CABasicAnimation(keyPath: "transform.rotation.z")
animation.fromValue = from
animation.toValue = to
animation.duration = duration
animation.autoreverses = true
animation.repeatCount = .infinity
animation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
imageView.layer.add(animation, forKey: "vip1TipSwing")
}
private func stopUnlockVip1Animations() {
vip1HeartIcon.layer.removeAnimation(forKey: "vip1HeartBeat")
vip1Tips1Img.layer.removeAnimation(forKey: "vip1TipSwing")
vip1Tips2Img.layer.removeAnimation(forKey: "vip1TipSwing")
vip1Tips3Img.layer.removeAnimation(forKey: "vip1TipSwing")
}
private let unlockVip1PopupHeight: CGFloat = 339
private func slideInUnlockVip1Popup() {
stopUnlockVip1Animations()
bgView.isUserInteractionEnabled = false
unlockVip1View.isHidden = false
unlockVip1View.layoutIfNeeded()
unlockVip1View.transform = CGAffineTransform(translationX: 0, y: unlockVip1PopupHeight)
UIView.animate(withDuration: 0.45, delay: 0,
usingSpringWithDamping: 0.8,
initialSpringVelocity: 0.5,
options: .curveEaseOut) {
self.unlockVip1View.transform = .identity
} completion: { _ in
self.bgView.isUserInteractionEnabled = true
self.startUnlockVip1Animations()
}
}
private func slideOutUnlockVip1Popup() {
stopUnlockVip1Animations()
bgView.isUserInteractionEnabled = false
UIView.animate(withDuration: 0.3, delay: 0, options: .curveEaseIn) {
self.unlockVip1View.transform = CGAffineTransform(translationX: 0, y: self.unlockVip1PopupHeight)
} completion: { _ in
Self.dismiss()
}
}
// MARK: - 1
lazy var registerPopupView: UIView = {
let view = UIView()
view.backgroundColor = .clear
view.isHidden = true
let bgImg = UIImageView(image: UIImage(named: "PopupWindow/register_bg"))
bgImg.contentMode = .scaleAspectFill
view.addSubview(bgImg)
bgImg.layoutChain
.top(51)
.edgesHorzontal()
.bottom()
let logoImg = UIImageView(image: UIImage(named: "PopupWindow/register_logo"))
logoImg.contentMode = .scaleAspectFill
view.addSubview(logoImg)
logoImg.layoutChain
.top()
.centerX()
.width(250)
.height(123)
let textImg = UIImageView(image: UIImage(named: "PopupWindow/register_text"))
textImg.contentMode = .scaleAspectFill
view.addSubview(textImg)
textImg.layoutChain
.topToBottomOfView(logoImg, offset: 20)
.width(272)
.height(50)
.centerX()
view.addSubview(register1UpLottieView)
register1UpLottieView.layoutChain
.bottomToTopOfView(logoImg, offset: 120)
.edgesHorzontal()
.height(200)
view.addSubview(register1DownLottieView)
register1DownLottieView.layoutChain
.topToBottomOfView(logoImg, offset: -140)
.edgesHorzontal()
.height(200)
// view.addSubview(registerStar1)
// registerStar1.layoutChain
// .top(19)
// .leftToView(logoImg, offset: -31)
// .width(68)
// .heightToWidth(1.0)
view.addSubview(registerStar3)
registerStar3.layoutChain
.top(23)
.rightToView(logoImg, offset: -9)
.width(26)
.height(20)
view.addSubview(registerStar2)
registerStar2.layoutChain
.top(31)
.rightToView(logoImg, offset: 20)
.width(48)
.height(44)
view.addSubview(registerCloseBtn)
registerCloseBtn.layoutChain
.topToBottomOfView(textImg, offset: 30)
.left(30)
.height(50)
view.addSubview(registerBtn)
registerBtn.layoutChain
.topToBottomOfView(textImg, offset: 30)
.right(30)
.height(50)
.widthToView(registerCloseBtn)
registerCloseBtn.layoutChain.rightToLeftOfView(registerBtn, offset: -10)
return view
}()
lazy var register1UpLottieView: LottieAnimationView = {
let view = LottieAnimationView(name: "dialog_register_tip1_1")
return view
}()
lazy var register1DownLottieView: LottieAnimationView = {
let view = LottieAnimationView(name: "dialog_register_tip1_2")
return view
}()
lazy var registerStar1: UIImageView = {
let view = UIImageView()
view.image = UIImage(named: "PopupWindow/star_1")
return view
}()
lazy var registerStar2: UIImageView = {
let view = UIImageView()
view.image = UIImage(named: "PopupWindow/star_2")
return view
}()
lazy var registerStar3: UIImageView = {
let view = UIImageView()
view.image = UIImage(named: "PopupWindow/star_3")
return view
}()
lazy var registerCloseBtn: UIButton = {
let btn = UIButton(type: .custom)
btn.setTitle("稍后再说", for: .normal)
btn.setTitleColor(UIColor(hexStr: "#16B3FF"), for: .normal)
btn.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium)
btn.backgroundColor = .white
btn.cornerRadius = 25
btn.borderWidth = 0.5
btn.borderColor = UIColor(hexStr: "#16B3FF")
return btn
}()
lazy var registerBtn: UIButton = {
let btn = UIButton(type: .custom)
btn.setTitle("免费注册", for: .normal)
btn.setTitleColor(.white, for: .normal)
btn.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium)
btn.setBackgroundImage(UIImage(named: "Common/button_bg_2"), for: .normal)
btn.cornerRadius = 25
return btn
}()
private var register1LottieAlternating = false
private func startRegister1LottieAlternate() {
stopRegister1LottieAlternate()
register1LottieAlternating = true
playRegister1Up()
}
private func playRegister1Up() {
guard register1LottieAlternating else { return }
register1UpLottieView.isHidden = false
register1DownLottieView.isHidden = true
register1UpLottieView.play { [weak self] _ in
self?.playRegister1Down()
}
}
private func playRegister1Down() {
guard register1LottieAlternating else { return }
register1UpLottieView.isHidden = true
register1DownLottieView.isHidden = false
register1DownLottieView.play { [weak self] _ in
self?.playRegister1Up()
}
}
private func stopRegister1LottieAlternate() {
register1LottieAlternating = false
register1UpLottieView.stop()
register1DownLottieView.stop()
register1UpLottieView.isHidden = true
register1DownLottieView.isHidden = true
}
private func startRegisterStarFlash() {
stopRegisterStarFlash()
let (star2, star3) = activePopupView == 2 ? (register2Star2, register2Star3) : (registerStar2, registerStar3)
let animation2 = CABasicAnimation(keyPath: "opacity")
animation2.fromValue = 1.0
animation2.toValue = 0.0
animation2.duration = 0.4
animation2.autoreverses = true
animation2.repeatCount = .infinity
star2.layer.add(animation2, forKey: "starFlash")
let animation3 = CABasicAnimation(keyPath: "opacity")
animation3.fromValue = 0.0
animation3.toValue = 1.0
animation3.duration = 0.4
animation3.autoreverses = true
animation3.repeatCount = .infinity
star3.layer.add(animation3, forKey: "starFlash")
}
private func stopRegisterStarFlash() {
registerStar2.layer.removeAnimation(forKey: "starFlash")
registerStar3.layer.removeAnimation(forKey: "starFlash")
register2Star2.layer.removeAnimation(forKey: "starFlash")
register2Star3.layer.removeAnimation(forKey: "starFlash")
}
private func animateRegisterStarSlideIn() {
UIView.animate(withDuration: 0.5, delay: 0,
usingSpringWithDamping: 0.7,
initialSpringVelocity: 0.6,
options: .curveEaseOut) {
self.registerStar1.transform = .identity
}
}
private let registerPopupHeight: CGFloat = 308
private var activePopupView = 1
private func slideInRegisterPopup() {
activePopupView = 1
stopRegisterStarFlash()
bgView.isUserInteractionEnabled = false
registerPopupView.isHidden = false
registerPopupView.layoutIfNeeded()
// registerStar1.transform = CGAffineTransform(translationX: -(registerStar1.frame.maxX + 30), y: 0)
registerPopupView.transform = CGAffineTransform(translationX: 0, y: registerPopupHeight)
UIView.animate(withDuration: 0.45, delay: 0,
usingSpringWithDamping: 0.8,
initialSpringVelocity: 0.5,
options: .curveEaseOut) {
self.registerPopupView.transform = .identity
} completion: { _ in
self.bgView.isUserInteractionEnabled = true
self.startRegisterStarFlash()
self.startRegister1LottieAlternate()
// self.animateRegisterStarSlideIn()
}
}
private func slideOutRegisterPopup() {
stopRegisterStarFlash()
stopRegister1LottieAlternate()
bgView.isUserInteractionEnabled = false
UIView.animate(withDuration: 0.3, delay: 0, options: .curveEaseIn) {
self.registerPopupView.transform = CGAffineTransform(translationX: 0, y: self.registerPopupHeight)
} completion: { _ in
Self.dismiss()
}
}
private func slideInRegister2Popup() {
activePopupView = 2
stopRegisterStarFlash()
bgView.isUserInteractionEnabled = false
register2PopupView.isHidden = false
register2PopupView.layoutIfNeeded()
// register2Star1.transform = CGAffineTransform(translationX: -(register2Star1.frame.maxX + 30), y: 0)
register2PopupView.transform = CGAffineTransform(translationX: 0, y: register2PopupView.bounds.height)
UIView.animate(withDuration: 0.45, delay: 0,
usingSpringWithDamping: 0.8,
initialSpringVelocity: 0.5,
options: .curveEaseOut) {
self.register2PopupView.transform = .identity
} completion: { _ in
self.bgView.isUserInteractionEnabled = true
self.startRegisterStarFlash()
self.register2LottieView.play()
// self.animateRegister2StarSlideIn()
}
}
private func slideOutRegister2Popup() {
stopRegisterStarFlash()
bgView.isUserInteractionEnabled = false
UIView.animate(withDuration: 0.3, delay: 0, options: .curveEaseIn) {
self.register2PopupView.transform = CGAffineTransform(translationX: 0, y: self.register2PopupView.bounds.height)
} completion: { _ in
Self.dismiss()
}
}
private func animateRegister2StarSlideIn() {
UIView.animate(withDuration: 0.55, delay: 0.1,
usingSpringWithDamping: 0.65,
initialSpringVelocity: 0.4,
options: .curveEaseOut) {
self.register2Star1.transform = .identity
}
}
// MARK: - 2
lazy var register2PopupView: UIView = {
let view = UIView()
view.backgroundColor = .clear
view.isHidden = true
let bgImg = UIImageView(image: UIImage(named: "PopupWindow/register_bg"))
bgImg.contentMode = .scaleAspectFill
view.addSubview(bgImg)
bgImg.layoutChain
.top(58)
.edgesHorzontal()
.bottom()
let logoImg = UIImageView(image: UIImage(named: "PopupWindow/register2_logo"))
logoImg.contentMode = .scaleAspectFill
view.addSubview(register2LottieView)
view.addSubview(logoImg)
logoImg.layoutChain
.top()
.centerX()
.width(243)
.height(97)
let textLab = UILabel()
textLab.text = "注册后即可保存历史轨迹、多人 共享地图、跨设备同步。"
textLab.font = .systemFont(ofSize: 16, weight: .medium)
textLab.textColor = UIColor(hexStr: "#16B3FF")
textLab.numberOfLines = 0
view.addSubview(textLab)
textLab.layoutChain
.topToBottomOfView(logoImg, offset: 33)
.edgesHorzontal(75)
register2LottieView.layoutChain
.top()
.rightToLeftOfView(logoImg, offset: 45)
.width(100)
.heightToWidth(1.0)
view.addSubview(register2Star3)
register2Star3.layoutChain
.top(25)
.rightToView(logoImg, offset: -6)
.width(26)
.height(20)
view.addSubview(register2Star2)
register2Star2.layoutChain
.top(32)
.rightToView(logoImg, offset: 25)
.width(48)
.height(44)
view.addSubview(register2Btn)
register2Btn.layoutChain
.topToBottomOfView(textLab, offset: 30)
.width(224)
.height(50)
.centerX()
view.addSubview(register2CloseBtn)
register2CloseBtn.layoutChain
.topToView(bgImg, offset: 32)
.right(15)
return view
}()
lazy var register2LottieView: LottieAnimationView = {
let view = LottieAnimationView(name: "dialog_register_tip2")
view.loopMode = .loop
return view
}()
lazy var register2Star1: UIImageView = {
let view = UIImageView()
view.image = UIImage(named: "PopupWindow/register_heart")
return view
}()
lazy var register2Star2: UIImageView = {
let view = UIImageView()
view.image = UIImage(named: "PopupWindow/star_2")
return view
}()
lazy var register2Star3: UIImageView = {
let view = UIImageView()
view.image = UIImage(named: "PopupWindow/star_3")
return view
}()
lazy var register2CloseBtn: UIButton = {
let btn = UIButton(type: .custom)
btn.setImage(UIImage(named: "PopupWindow/close"), for: .normal)
btn.extendEdgeInsets = UIEdgeInsets(top: 30, left: 30, bottom: 30, right: 15)
return btn
}()
lazy var register2Btn: UIButton = {
let btn = UIButton(type: .custom)
btn.setTitle("免费注册", for: .normal)
btn.setTitleColor(.white, for: .normal)
btn.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium)
btn.setBackgroundImage(UIImage(named: "Common/button_bg_2"), for: .normal)
btn.cornerRadius = 25
return btn
}()
// MARK: - Init
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .clear
addSubview(bgView)
bgView.addSubview(searchPopupView)
bgView.addSubview(unlockVip1View)
bgView.addSubview(registerPopupView)
bgView.addSubview(register2PopupView)
searchPopupView.layoutChain
.centerY()
.centerX()
registerPopupView.layoutChain
.edgesHorzontal()
.bottom()
.height(308)
register2PopupView.layoutChain
.edgesHorzontal()
.bottom()
.height(295)
unlockVip1View.layoutChain
.edgesHorzontal()
.bottom()
.height(unlockVip1PopupHeight)
setupRx()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
}
}