UIFont

UIFont使用方法详解
本文介绍了UIFont类中的三种常用方法:systemFontOfSize、boldSystemFontOfSize及italicSystemFontOfSize,分别用于设置普通字体、加粗字体和斜体字体。这三种方法能够帮助开发者快速地在iOS应用中实现不同样式的字体显示。

使用 UIFont 的下列方法之一:

1  + systemFontOfSize:
2  + boldSystemFontOfSize:
3  + italicSystemFontOfSize:


1 中是系统的默认方法;

2 是字体  bold:醒目的;雄浑的;突出的,使用后会加粗字体; 

3字体为斜体 italic [i'tælik] n. 斜体,斜体字

转自:http://blog.sina.com.cn/s/blog_a263f0c601010tbg.html

内容概要:本文介绍了一个基于冠豪猪优化算法(CPO)的无人机三维路径规划项目,利用Python实现了在复杂三维环境中为无人机规划安全、高效、低能耗飞行路径的完整解决方案。项目涵盖空间环境建模、无人机动力学约束、路径编码、多目标代价函数设计以及CPO算法的核心实现。通过体素网格建模、动态障碍物处理、路径平滑技术和多约束融合机制,系统能够在高维、密集障碍环境下快速搜索出满足飞行可行性、安全性与能效最优的路径,并支持在线重规划以适应动态环境变化。文中还提供了关键模块的代码示例,包括环境建模、路径评估和CPO优化流程。; 适合人群:具备一定Python编程基础和优化算法基础知识,从事无人机、智能机器人、路径规划或智能优化算法研究的相关科研人员与工程技术人员,尤其适合研究生及有一定工作经验的研发工程师。; 使用场景及目标:①应用于复杂三维环境下的无人机自主导航与避障;②研究智能优化算法(如CPO)在路径规划中的实际部署与性能优化;③实现多目标(路径最短、能耗最低、安全性最高)耦合条件下的工程化路径求解;④构建可扩展的智能无人系统决策框架。; 阅读建议:建议结合文中模型架构与代码示例进行实践运行,重点关注目标函数设计、CPO算法改进策略与约束处理机制,宜在仿真环境中测试不同场景以深入理解算法行为与系统鲁棒性。
完整的修改我这两个新建的文件: // NewCoverImageContainerView.swift // SurveillanceHome // // Created by MaCong on 2025/12/8. // Copyright © 2025 tplink. All rights reserved. // import UIKit import SnapKit class NewCoverImageContainerView: UIView { // MARK: - Subviews var coverImageView: UIImageView! var maskImageView: UIImageView! var maskLabel: UILabel! var helpButton: UIButton? var helpLabel: UILabel! var collectButton: UIButton! var maskLabelCenterYConstraint: NSLayoutConstraint? // Constraints private var maskLabelCenterYConstraint: Constraint? // Data & Actions private var isCollected: Bool = false { didSet { let image = isCollected ? TPImageLiteral("device_have_collect_card") : TPImageLiteral("device_not_collect_card") collectButton.setImage(image, for: .normal) } } var collectAction: ((Bool) -> Void)? var helpAction: (() -> Void)? // Status Icons (for future extension if needed) private var statusImageViews = [UIImageView]() private let numberOfStatusImages = 0 private let needHideMask = 1 // MARK: - Initializers override init(frame: CGRect) { super.init(frame: frame) commonInit() } required init?(coder: NSCoder) { super.init(coder: coder) commonInit() } private func commonInit() { setupViews() setupConstraints() } // MARK: - Setup Views private func setupViews() { backgroundColor = .clear layer.cornerRadius = 2 layer.masksToBounds = true // === Cover Image View === coverImageView = UIImageView() coverImageView.contentMode = .scaleToFill coverImageView.clipsToBounds = true coverImageView.isUserInteractionEnabled = false // === Mask Image View === maskImageView = UIImageView() maskImageView.contentMode = .scaleToFill maskImageView.clipsToBounds = true maskImageView.isUserInteractionEnabled = false maskImageView.tag = 3 // === Mask Label === maskLabel = UILabel() maskLabel.tag = 4 maskLabel.text = LocalizedString(key: deviceListNoSuchDevice) maskLabel.font = UIFont(name: "PingFangSC-Regular", size: 12) maskLabel.textColor = UIColor(white: 1.0, alpha: 1.0) maskLabel.textAlignment = .center maskLabel.backgroundColor = .clear maskLabel.numberOfLines = 1 maskLabel.adjustsFontSizeToFitWidth = false maskLabel.baselineAdjustment = .alignBaselines // === Help Button (transparent clickable area) === helpButton = UIButton(type: .custom) helpButton?.backgroundColor = .clear helpButton?.layer.cornerRadius = 14 helpButton?.clipsToBounds = true helpButton?.layer.borderWidth = 1 helpButton?.layer.borderColor = UIColor.tpbTextDisabled.cgColor helpButton?.addTarget(self, action: #selector(helpButtonClicked), for: .touchUpInside) // === Help Label (inside helpButton) === helpLabel = UILabel() helpLabel.text = LocalizedString(key: deviceListOfflineNeedHelp) helpLabel.font = UIFont(name: "PingFangSC-Regular", size: 12) helpLabel.textColor = UIColor(white: 1.0, alpha: 1.0) helpLabel.textAlignment = .center helpLabel.backgroundColor = .clear helpButton?.addSubview(helpLabel) // === Collect Button === collectButton = UIButton(type: .custom) collectButton.setImage(TPImageLiteral("device_not_collect_card"), for: .normal) collectButton.addTarget(self, action: #selector(collectButtonClicked), for: .touchUpInside) collectButton.isHidden = true // Add to hierarchy addSubview(coverImageView) addSubview(maskImageView) addSubview(maskLabel) addSubview(collectButton) addSubview(helpButton!) } // MARK: - Setup Constraints with SnapKit private func setupConstraints() { coverImageView.snp.makeConstraints { make in make.edges.equalToSuperview() } maskImageView.snp.makeConstraints { make in make.edges.equalToSuperview() } maskLabel.snp.makeConstraints { make in make.centerX.equalToSuperview() make.leading.greaterThanOrEqualToSuperview().offset(16) make.trailing.lessThanOrEqualToSuperview().offset(-16) let centerY = make.centerY.equalToSuperview().offset(0).priority(.defaultLow).constraint maskLabelCenterYConstraint = centerY } collectButton.snp.makeConstraints { make in make.top.equalToSuperview().offset(8) make.trailing.equalToSuperview().offset(-8) make.width.height.equalTo(26) } helpButton?.snp.makeConstraints { make in make.centerY.equalToSuperview().offset(20) make.trailing.equalToSuperview().offset(-8) make.width.greaterThanOrEqualTo(30) } helpLabel.snp.makeConstraints { make in make.edges.equalToSuperview().inset(UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 10)) } // Setup status image views (if enabled later) for i in 0..<numberOfStatusImages { let imageView = UIImageView() imageView.isHidden = true imageView.isUserInteractionEnabled = false statusImageViews.append(imageView) addSubview(imageView) } } // MARK: - Actions @objc private func collectButtonClicked() { isCollected.toggle() collectAction?(isCollected) } @objc private func helpButtonClicked() { helpAction?() } // MARK: - Public Configuration Methods func shouldShowCollectButton(device: TPSSDeviceForDeviceList, channel: TPSSChannelInfo? = nil, isCard: Bool) { let isVms = TPAppContextFactory.shared().isVmsLogin collectButton.isHidden = (device.displayType == .solar || device.listType == .local || !isCard || (TPSSAppContext.shared.loginType == .personal ? false : TPSSAppContext.shared.isVmsDeviceListFavoriteOldVersion)) if device.deviceType == .IPC { isCollected = isVms ? device.isVMSFavorited : device.isCollected } else if device.deviceType == .NVR { if let channel = channel { isCollected = isVms ? channel.isVMSFavorited : device.isCollected && device.collectChannels.contains(channel.channelId as NSNumber) } else { isCollected = isVms ? device.isVMSFavorited : device.isCollected } } } func configureCoverWith(size: TPSSDeviceForDeviceList.CoverImageSize, device: TPSSDeviceForDeviceList, channel: TPSSChannelInfo? = nil, hideMaskIfNeeded: Bool = false, isCard: Bool = false, folded: Bool = false, leadingConst: NSLayoutConstraint? = nil, trailConst: NSLayoutConstraint? = nil, isSmall: Bool = false, isModelCover: Bool = false, noDevice: Bool = false, isHideLogo: Bool = false) { var hasNoChannels = true if let channel = channel { hasNoChannels = !device.activeChannelsInfo.contains(channel) } shouldShowCollectButton(device: device, channel: channel, isCard: isCard) var coverImage: UIImage? = device.displayType == .solar ? TPSSDeviceForDeviceList.defaultSolarCoverImage(of: size) : TPSSDeviceForDeviceList.defaultCoverImage(of: size) if isModelCover { coverImage = TPSSDeviceForDeviceList.getDeviceModelImage(type: .IPC, model: noDevice ? "" : channel?.deviceModel ?? "") } if !hasNoChannels { coverImage = device.coverImage(of: size, channelID: channel?.channelId.intValue ?? -1, listType: device.listType) } if hideMaskIfNeeded && !maskImageView.isHidden { maskImageView.isHidden = maskImageView.tag == needHideMask && coverImage != nil } coverImageView.image = coverImage ?? (device.displayType == .solar ? TPSSDeviceForDeviceList.defaultSolarCoverImage(of: size) : (isModelCover ? TPSSDeviceForDeviceList.getDeviceModelImage(type: .IPC, model: noDevice ? "" : channel?.deviceModel ?? "") : TPSSDeviceForDeviceList.defaultCoverImage(of: size))) // Handle fisheye / pano logic var isFisheye = false if TPSSAppContext.shared.isVmsLogin && device.listType == .remote { isFisheye = coverImage != nil && device.coverImageIsFisheye(of: size, channelID: channel?.channelId.intValue ?? -1, listType: device.listType) } else if let channelInfo = channel, device.displayType == .NVR { isFisheye = coverImage != nil && channelInfo.supportsFisheye } else { isFisheye = coverImage != nil && device.supportFishEye } var isPano = false if let channelInfo = channel, device.displayType == .NVR { isPano = coverImage != nil && channelInfo.isSupportSplicingSetting } else { isPano = coverImage != nil && device.supportPano } let imgSize = coverImage?.size ?? CGSize(width: 1, height: 1) if (!isFisheye && imgSize.width > 1.1 && abs(imgSize.width - imgSize.height) < 1) { isFisheye = true } coverImageView.contentMode = isFisheye ? (isCard ? .scaleAspectFit : .scaleAspectFill) : .scaleToFill isPano = isPano || (imgSize.width / imgSize.height >= 3) backgroundColor = isFisheye ? .tpbFisheyeBackground : .clear if device.displayType != .solar { if let oldImg = coverImageView.image, let newImg = cropFishScaleImg(img: oldImg, isFishEye: isFisheye), oldImg != newImg { coverImageView.image = newImg coverImageView.contentMode = isCard ? .scaleAspectFit : .scaleAspectFill backgroundColor = .tpbFisheyeBackground } if isPano { coverImageView.contentMode = .scaleAspectFill backgroundColor = .clear } if let oldImg = coverImageView.image, let newImg = cropFishScaleImg(img: oldImg, isFishEye: isFisheye), isCard && (isFisheye || oldImg != newImg) && (!folded || device.deviceType == .IPC) { coverImageView.contentMode = .scaleAspectFit } } if device.displayType == .solar || (isModelCover && (noDevice || coverImage == nil)) { coverImageView.contentMode = .scaleAspectFit coverImageView.backgroundColor = .tpbBackground } else { coverImageView.backgroundColor = .clear } if isHideLogo && coverImage == nil { coverImageView.isHidden = true } else { coverImageView.isHidden = false } guard let finalImage = coverImageView.image, !isFisheye, finalImage.size.height > finalImage.size.width else { return } backgroundColor = .tpbFisheyeBackground coverImageView.contentMode = .scaleAspectFill } func configureWith(cloudStorageEnabled: Bool = false, supportsAlarm: Bool = false, alarm: Bool = true, noDevice: Bool = false, channelOffline: Bool = false, channelHidden: Bool = false, channelUnAuth: Bool = false, channelUninitialized: Bool = false, offline: Bool = false, nvrOffline: Bool = false, ipcOffline: Bool = false, offlineTime: String = "", notInSharePeriod: Bool = false, notShareEnable: Bool = false, notConnected: Bool = false, supportConnectionInfo: Bool = false, connectedViaWifi: Bool = false, wifiRssi: Int = 0, showHelp: Bool = false, playButtonHidden: Bool = false, size: TPSSDeviceForDeviceList.CoverImageSize, showText: Bool = true, showIcons: Bool = true, hasNoVmsLicense: Bool = false, isChannel: Bool = false) { let showAlarm = supportsAlarm && !noDevice let showWifiStatus = supportConnectionInfo && connectedViaWifi && !(offline || nvrOffline || ipcOffline) let showCloudStorage = cloudStorageEnabled let images: [UIImage] = [ showAlarm ? (alarm ? TPImageLiteral("devicelist_indicator_alarm_on") : TPImageLiteral("devicelist_indicator_alarm_off")) : nil, showWifiStatus ? UIImage(named: "common_wifi_indicator\(wifiRssi)") : nil, showCloudStorage ? TPImageLiteral("cloud_label") : nil ].compactMap { $0 } for i in 0..<min(statusImageViews.count, images.count) { statusImageViews[i].image = images[i] statusImageViews[i].isHidden = !showIcons } for i in images.count..<statusImageViews.count { statusImageViews[i].isHidden = true } let deviceOffline = offline || nvrOffline || ipcOffline || channelOffline let basicMaskVisible = noDevice || deviceOffline || notInSharePeriod || notShareEnable || notConnected || channelHidden || hasNoVmsLicense maskImageView.isHidden = !basicMaskVisible maskLabel.isHidden = !basicMaskVisible && !playButtonHidden maskImageView.image = nil maskImageView.backgroundColor = basicMaskVisible ? .tpbDeviceMask : .clear maskImageView.contentMode = .scaleAspectFit maskImageView.tag = basicMaskVisible ? 0 : needHideMask maskLabel.numberOfLines = basicMaskVisible ? (offlineTime.isEmpty ? 1 : 0) : 1 if deviceOffline { if isChannel && noDevice { maskLabel.text = LocalizedString(key: deviceListNoSuchDevice) } else if isChannel && channelUnAuth { maskLabel.text = LocalizedString(key: NVRAddIPCDeviceNotCertified) } else if isChannel && channelUninitialized { maskLabel.text = LocalizedString(key: multiWindowPlayerUninitialized) } else { let firstLine = notInSharePeriod ? LocalizedString(key: deviceListNotInSharePeriod) : LocalizedString(key: deviceListDeviceNotOnline) if !offlineTime.isEmpty { let secondLine = String(format: LocalizedString(key: deviceListOfflineTimeFormat), offlineTime) let attributedText = NSMutableAttributedString(string: "\(firstLine)\n\(secondLine)") let style = NSMutableParagraphStyle() style.lineSpacing = 8 style.alignment = .center attributedText.addAttributes([ .font: UIFont.projectFont(ofSize: 12), .paragraphStyle: style ], range: NSMakeRange(0, firstLine.count)) attributedText.addAttributes([ .font: UIFont.projectFont(ofSize: 10) ], range: NSMakeRange(firstLine.count + 1, secondLine.count)) maskLabel.attributedText = attributedText } else { maskLabel.text = firstLine } } } else if noDevice { maskLabel.text = LocalizedString(key: deviceListNoSuchDevice) } else if notShareEnable { maskLabel.text = LocalizedString(key: deviceListNotShareEnable) } else if notInSharePeriod && !deviceOffline { maskLabel.text = LocalizedString(key: deviceListNotInSharePeriod) } else if channelUnAuth { maskLabel.text = LocalizedString(key: NVRAddIPCDeviceNotCertified) } else if channelHidden { maskLabel.text = LocalizedString(key: deviceListChannelHidden) } else if notConnected { maskLabel.text = LocalizedString(key: wirelessDirectNotConnected) } else if hasNoVmsLicense { maskLabel.text = LocalizedString(key: deviceListCloudVmsWithoutLicenseMaskLabel) } else { maskImageView.isHidden = playButtonHidden maskLabel.isHidden = true switch size { case .small: maskImageView.image = TPImageLiteral("devicelist_preview_small") maskImageView.contentMode = .scaleAspectFit case .medium: maskImageView.image = TPImageLiteral("devicelist_preview_medium") maskImageView.contentMode = .center default: maskImageView.image = TPImageLiteral("devicelist_preview_large") maskImageView.contentMode = .center } maskImageView.backgroundColor = .clear maskImageView.tag = needHideMask } if !showText { maskLabel.text = "" } // Update help button visibility and label position helpButton?.isHidden = !showHelp helpLabel.isHidden = !showHelp maskLabelCenterYConstraint?.update(offset: showHelp ? -22 : 0) } // Helper method (assumed to exist) private func cropFishScaleImg(img: UIImage?, isFishEye: Bool) -> UIImage? { // Implement or keep existing version return img } } // MARK: - Extension: Configure Overloads extension NewCoverImageContainerView { enum CoverType { case play case selection } func configure(ipc: TPSSDeviceForDeviceList, size: TPSSDeviceForDeviceList.CoverImageSize = .medium, type: CoverType = .play, isCard: Bool = false, folded: Bool = false) { shouldShowCollectButton(device: ipc, isCard: isCard) let showAccessory = size != .small let showDetailText = showAccessory && size != .medium let showPlayButton = (ipc.displayType != .solar && type == .play) if ipc.listType == .remote { configureWith( cloudStorageEnabled: ipc.cloudStorageService()?.serviceState.isValid ?? false, supportsAlarm: ipc.supportMessage && ipc.displayOnline && !ipc.isSharedDevice, alarm: ipc.messageEnable, ipcOffline: !ipc.displayOnline, offlineTime: showDetailText ? ipc.offlineTime : "", notInSharePeriod: (ipc.isSharedDevice && !ipc.isInSharePeriod), notShareEnable: (ipc.isSharedDevice && !ipc.isShareEnable), supportConnectionInfo: ipc.supportConnectInfo, connectedViaWifi: ipc.linkType == .wifi, wifiRssi: ipc.linkRssi, showHelp: showAccessory && !ipc.displayOnline && !ipc.isSharedDevice, playButtonHidden: !showPlayButton, size: size, showText: showAccessory, showIcons: showAccessory, hasNoVmsLicense: ipc.isLicenseNotActive ) } else { configureWith( ipcOffline: !ipc.displayOnline, offlineTime: showDetailText ? ipc.offlineTime : "", supportConnectionInfo: ipc.supportConnectInfo, connectedViaWifi: ipc.linkType == .wifi, wifiRssi: ipc.linkRssi, showHelp: showAccessory && !ipc.displayOnline && !ipc.isSharedDevice, playButtonHidden: !showPlayButton, size: size, showText: showAccessory, showIcons: showAccessory ) } configureCoverWith(size: size, device: ipc, channel: ipc.channelsInfo.first, hideMaskIfNeeded: true, isCard: isCard, folded: folded) statusImageViews.forEach { $0.isHidden = true } } func configure(channel: TPSSChannelInfo, nvr: TPSSDeviceForDeviceList, size: TPSSDeviceForDeviceList.CoverImageSize = .medium, type: CoverType = .play, isCard: Bool = false, folded: Bool = false, leadingConst: NSLayoutConstraint? = nil, trialConst: NSLayoutConstraint? = nil, isSmall: Bool = false, isSigleChannel: Bool = false, isHideLogo: Bool = false) { let showAccessory = size != .small let showPlayButton = type == .play && !isSigleChannel shouldShowCollectButton(device: nvr, channel: channel, isCard: isCard) if nvr.listType == .remote { configureWith( cloudStorageEnabled: nvr.cloudStorageService(channel: channel)?.serviceState.isValid ?? false, supportsAlarm: channel.supportsMessagePush && channel.online && !nvr.isSharedDevice, alarm: channel.messageEnable, noDevice: !nvr.activeChannelsInfo.contains(channel), channelOffline: !channel.online, channelUnAuth: channel.authResult == 1, channelUninitialized: channel.authResult == 3, notInSharePeriod: (nvr.isSharedDevice && !channel.isInSharePeriod), notShareEnable: (nvr.isSharedDevice && !channel.isShareEnable), showHelp: !channel.online && channel.authResult == 0 && channel.active, playButtonHidden: !showPlayButton, size: size, showText: showAccessory, showIcons: showAccessory, hasNoVmsLicense: channel.isLicenseNotActive, isChannel: true ) } else { configureWith( noDevice: !nvr.activeChannelsInfo.contains(channel), channelOffline: !channel.online, channelUnAuth: channel.authResult == 1, channelUninitialized: channel.authResult == 3, showHelp: !channel.online && channel.authResult == 0, playButtonHidden: !showPlayButton, size: size, showText: showAccessory, showIcons: showAccessory, isChannel: true ) } configureCoverWith(size: size, device: nvr, channel: channel, hideMaskIfNeeded: true, isCard: isCard, folded: folded, leadingConst: leadingConst, trailConst: trialConst, isSmall: isSmall, isHideLogo: !isCard && isHideLogo) statusImageViews.forEach { $0.isHidden = true } } func configure(nvr: TPSSDeviceForDeviceList, size: TPSSDeviceForDeviceList.CoverImageSize = .medium, type: CoverType = .play) { let showAccessory = size != .small let showPlayButton = type == .play let showDetailText = showAccessory && size != .medium let channelHidden = nvr.channelsInfo.count == 0 && nvr.allChannelsInfo.count != 0 var noDevice = nvr.activeChannelsInfo.count == 0 && !channelHidden if nvr.isSharedFromOthers { for channel in nvr.activeChannelsInfo { if !channel.isSharedFromOthers { noDevice = true } else { noDevice = false break } } } if nvr.listType == .remote { configureWith( noDevice: noDevice, channelHidden: channelHidden, nvrOffline: !nvr.displayOnline, offlineTime: showDetailText ? nvr.offlineTime : "", showHelp: showAccessory && !nvr.displayOnline && !nvr.isSharedDevice, playButtonHidden: !showPlayButton, size: size, showText: showAccessory, showIcons: showAccessory, ) } else { configureWith( noDevice: noDevice, channelHidden: channelHidden, nvrOffline: !nvr.displayOnline, offlineTime: showDetailText ? nvr.offlineTime : "", showHelp: showAccessory && !nvr.displayOnline && !nvr.isSharedDevice, playButtonHidden: !showPlayButton, size: size, showText: showAccessory, showIcons: showAccessory, ) } configureCoverWith(size: size, device: nvr, channel: nil, hideMaskIfNeeded: true) } func showEmpty(size: TPSSDeviceForDeviceList.CoverImageSize = .medium) { configureWith(playButtonHidden: true, size: size, showText: false, showIcons: false) coverImageView.image = TPSSDeviceForDeviceList.defaultCoverImage(of: size) } } // MARK: - Device Setting Extension extension NewCoverImageContainerView { func configure(device: TPSSDeviceForSetting, channel: TPSSChannelInfo?, size: TPSSDeviceForDeviceList.CoverImageSize = .medium, model: String = "") { configureWith(playButtonHidden: true, size: size, showText: false, showIcons: false) let channelID = channel?.channelId.intValue ?? -1 let coverImage = device.coverImage(at: channelID, listType: device.deviceListType) coverImageView.image = coverImage ?? device.defaultCoverImage(at: channelID, size: size, model: model) var isFisheye = false if TPSSAppContext.shared.isVmsLogin && device.deviceListType == .remote { isFisheye = coverImage != nil && device.coverImageIsFisheye(at: channelID, listType: device.deviceListType) } else { isFisheye = coverImage != nil && (channel?.supportsFisheye ?? device.isFishEye) } if isFisheye { coverImageView.contentMode = .scaleAspectFill } else if device.deviceType == .solar || coverImage == nil { coverImageView.contentMode = .scaleAspectFit coverImageView.backgroundColor = .tpbProgressBackground coverImageView.layer.cornerRadius = 8 } else { let mode = (coverImage?.size.height ?? 0) > (coverImage?.size.width ?? 0) ? UIView.ContentMode.scaleAspectFit : .scaleAspectFill if let ch = channel, ch.supportCorridor { coverImageView.contentMode = mode coverImageView.backgroundColor = .tpbProgressBackground } else if device.supportCorridor { coverImageView.contentMode = mode coverImageView.backgroundColor = .tpbProgressBackground } else if let ch = channel, ch.isSupportSplicingSetting { coverImageView.contentMode = .scaleAspectFill } else if device.isSupportSplicingSetting { coverImageView.contentMode = .scaleAspectFill } else { coverImageView.contentMode = .scaleToFill } } backgroundColor = isFisheye ? .tpbFisheyeBackground : .clear } } // // NewCoverImageBigContainerView.swift // SurveillanceHome // // Created by MaCong on 2025/12/8. // Copyright © 2025 tplink. All rights reserved. // import UIKit import SnapKit class NewCoverImageBigContainerView: NewCoverImageContainerView { // MARK: - Only Add NEW Subviews (not existed in parent) let nvrChannelNameContainer = UIView() let nvrChannelNameLabel = UILabel() private let gradientView = GradientView() // MARK: - Initializers override init(frame: CGRect) { super.init(frame: frame) setupSubviews() setupConstraints() setupAppearance() } required init?(coder: NSCoder) { super.init(coder: coder) setupSubviews() setupConstraints() setupAppearance() } // MARK: - Private Setup Methods private func setupSubviews() { // Configure gradient background gradientView.startColor = UIColor(white: 0, alpha: 0) gradientView.endColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.7) gradientView.horizontalMode = false gradientView.startLocation = 0.0 gradientView.endLocation = 1.0 nvrChannelNameContainer.addSubview(gradientView) nvrChannelNameContainer.addSubview(nvrChannelNameLabel) addSubview(nvrChannelNameContainer) // ✅ 使用父类已有的 helpButton 和 helpLabel // 不需要 addSubview(helpButton),它已经在父类中被添加了! // 但我们需要调整它的约束(如果之前是基于 maskLabel 的话) } private func setupConstraints() { // Layout nvr channel name container at bottom nvrChannelNameContainer.snp.makeConstraints { make in make.leading.trailing.bottom.equalToSuperview() make.height.equalTo(24) } gradientView.snp.makeConstraints { make in make.edges.equalToSuperview() } nvrChannelNameLabel.snp.makeConstraints { make in make.leading.equalToSuperview().offset(10) make.trailing.equalToSuperview().offset(-6) make.centerY.equalToSuperview().offset(2) } // ✅ 修正 helpButton 和 helpLabel 的约束(脱离对 maskLabel 的依赖) helpButton?.snp.removeConstraints() // 移除父类可能设置的老约束 helpButton?.snp.makeConstraints { make in make.centerX.equalToSuperview() make.centerY.equalToSuperview().offset(20) make.size.equalTo(CGSize(width: 68, height: 29)) } helpLabel.snp.removeConstraints() // 同样移除旧约束 helpLabel.snp.makeConstraints { make in make.centerX.equalToSuperview() make.centerY.equalToSuperview().offset(20) make.leading.greaterThanOrEqualToSuperview().offset(20) make.trailing.lessThanOrEqualToSuperview().offset(-20) } } private func setupAppearance() { layer.cornerRadius = 2 clipsToBounds = true nvrChannelNameContainer.layer.cornerRadius = 2 nvrChannelNameContainer.clipsToBounds = true nvrChannelNameLabel.font = UIFont(name: "PingFangSC-Regular", size: 13) nvrChannelNameLabel.textColor = .white nvrChannelNameLabel.textAlignment = .left nvrChannelNameLabel.text = "Label" helpButton?.layer.cornerRadius = 14 helpButton?.clipsToBounds = true helpButton?.backgroundColor = .clear // 保持透明背景 helpLabel.font = UIFont(name: "PingFangSC-Regular", size: 12) helpLabel.textColor = .white helpLabel.textAlignment = .center helpLabel.text = LocalizedString(key: "deviceListOfflineNeedHelp") helpLabel.isUserInteractionEnabled = false } // MARK: - Public APIs func showHelpSection(visible: Bool) { helpButton?.isHidden = !visible helpLabel.isHidden = !visible // 可选:触发 maskLabel 位置更新 if let constraint = self.labelToCenterConstraint { constraint.constant = visible ? -22 : 0 UIView.animate(withDuration: 0.25) { self.layoutIfNeeded() } } } func setChannelName(_ name: String?) { guard let name = name, !name.isEmpty else { nvrChannelNameContainer.isHidden = true return } nvrChannelNameLabel.text = name nvrChannelNameContainer.isHidden = false } }
12-09
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值