MenuView, unable to find attribute android:preserveIconSpacing

当使用Eclipse SDK从较低版本切换到较高版本时,可能会遇到与v7包中MenuView相关的错误提示。解决此问题的方法是在V7包的values文件夹中找到attrs.xml文件,然后删除或注释掉无法找到的属性“preserveIconSpacing”,最后清理项目即可。

eclipse  sdk从低版本切换到高版本sdk的时候   v7包会包这个错ERROR: In <declare-styleable> MenuView, unable to find attribute android:preserveIconSpacing

   问题解决:

     点击V7包找到values文件夹   打开attrs.xml      ctrl+f   查找 MenuView     将preserveIconSpacing注释掉或者删掉    clean项目

ok 完成。

这是代码import UIKit protocol CustomMenuItem { } protocol CustomMenuView: UIView { associatedtype MenuItemView: CustomMenuItemView var items: [MenuItemView.MenuItem] { get } func itemClickCallback(index: Int) } protocol CustomMenuItemView: UIView { associatedtype MenuItem: CustomMenuItem init(item: MenuItem) var action: (() -> Void)? { get set } } extension CustomMenuView { func setup() { backgroundColor = .tpbCard let count = items.count let container = UIView() addSubview(container) container.frame = bounds.inset(by: UIEdgeInsets(top: 8, left: 0, bottom: 8, right: 0)) container.autoresizingMask = [.flexibleWidth, .flexibleHeight] var previousView: UIView? = nil var height: CGFloat = 0 for i in 0..<count { let menuView = MenuItemView(item: items[i]) menuView.translatesAutoresizingMaskIntoConstraints = false container.addSubview(menuView) let cons1 = NSLayoutConstraint(item: menuView, attribute: .leading, relatedBy: .equal, toItem: container, attribute: .leading, multiplier: 1, constant: 0) let cons2 = NSLayoutConstraint(item: menuView, attribute: .trailing, relatedBy: .equal, toItem: container, attribute: .trailing, multiplier: 1, constant: 0) let cons3: NSLayoutConstraint if let prev = previousView { cons3 = NSLayoutConstraint(item: menuView, attribute: .top, relatedBy: .equal, toItem: prev, attribute: .bottom, multiplier: 1, constant: 0) } else { cons3 = NSLayoutConstraint(item: menuView, attribute: .top, relatedBy: .equal, toItem: container, attribute: .top, multiplier: 1, constant: 0) } menuView.action = { [weak self] in self?.itemClickCallback(index: i) } NSLayoutConstraint.activate([cons1, cons2, cons3]) menuView.layoutIfNeeded() height += menuView.frame.size.height previousView = menuView } frame.size.height = 8 + height + 8 } } class AnyMenuItemView<MenuItem: CustomMenuItem>: TapGestureSwallowingControl, CustomMenuItemView { var action: (() -> Void)? let item: MenuItem required init(item: MenuItem) { self.item = item super.init(frame: .zero) } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool { backgroundColor = .tpbBackgroundInCard return true } override func endTracking(_ touch: UITouch?, with event: UIEvent?) { stopTracking(with: event) } override func cancelTracking(with event: UIEvent?) { stopTracking(with: event) } private func stopTracking(with event: UIEvent?) { backgroundColor = .tpbCard if let loc = event?.touches(for: self)?.first?.location(in: self), bounds.contains(loc) { action?() } } } class DeviceGroupMenuView: UIView, CustomMenuView { typealias MenuItemView = DeviceGroupMenuItemView enum Item: Int { //Fix: 隐藏Home/Away Mode // case alarmMode = 0 case viewMode = 0 case reorder case search } //Fix: 隐藏Home/Away Mode // let items: [DeviceGroupMenuItem] = [.alarmMode, .viewMode, .reorder, .search] var items: [DeviceGroupMenuItem] = [.viewMode, .reorder, .search] { didSet { setup() } } var action: ((Item) -> Void)? override init(frame: CGRect) { super.init(frame: frame) } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } func itemClickCallback(index: Int) { if items[index] == .viewMode { action?(.viewMode) } else if items[index] == .reorder { action?(.reorder) } else if items[index] == .search { action?(.search) } } } class DeviceGroupMenuItem: NSObject, CustomMenuItem { @objc dynamic var image: UIImage @objc dynamic var title: String @objc dynamic var subtitle: String? @objc dynamic var enabled: Bool init(image: UIImage, title: String, subtitle: String? = nil, enabled: Bool = true) { self.image = image self.title = title self.subtitle = subtitle self.enabled = enabled super.init() } //Fix: 隐藏Home/Away Mode // static let alarmMode: DeviceGroupMenuItem = DeviceGroupMenuItem(image: TPImageLiteral("devicelist_home_active").withRenderingMode(.alwaysOriginal), title: LocalizedString(key: deviceListModeHome), subtitle: LocalizedString(key: deviceListSwitchModeToOut)) static let viewMode: DeviceGroupMenuItem = DeviceGroupMenuItem(image: TPImageLiteral("deviceList_display_bigPic").withRenderingMode(.alwaysOriginal), title: LocalizedString(key: deviceListSwitchView), subtitle: "") static let reorder: DeviceGroupMenuItem = DeviceGroupMenuItem(image: TPImageLiteral("devicelist_nvr_channel_reorder"), title: LocalizedString(key: deviceListReorder)) static let search: DeviceGroupMenuItem = DeviceGroupMenuItem(image: TPImageLiteral("devicelist_search"), title: LocalizedString(key: deviceListSearch)) } class DeviceGroupMenuItemView: AnyMenuItemView<DeviceGroupMenuItem> { var observers = [NSKeyValueObservation]() required init(item: DeviceGroupMenuItem) { super.init(item: item) setup() } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } override var intrinsicContentSize: CGSize { return CGSize(width: super.intrinsicContentSize.width, height: 44) } override func didMoveToSuperview() { super.didMoveToSuperview() if superview == nil { observers = [] } else { observers = [ item.observe(\.image, options: .initial) { [weak self] (object, _) in self?.imageView.image = object.image }, item.observe(\.title, options: .initial) { [weak self] (object, _) in self?.titleLabel.text = object.title }, item.observe(\.enabled, options: .initial) { [weak self] (object, _) in self?.isEnabled = object.enabled }, item.observe(\.subtitle, options: .initial) { [weak self] (object, _) in self?.informationLabel.text = object.subtitle } ] } } private lazy var imageView: UIImageView = { let imageView = UIImageView() imageView.contentMode = .scaleAspectFit return imageView }() private lazy var titleLabel: UILabel = { let titleLabel = UILabel() titleLabel.textColor = UIColor.tpbTextPrimary titleLabel.font = UIFont.projectFont(ofSize: 16) titleLabel.textAlignment = .left titleLabel.numberOfLines = 1 // titleLabel.lineBreakMode = .byWordWrapping return titleLabel }() private lazy var informationLabel: UILabel = { let label = UILabel(frame: .zero) label.textColor = UIColor.tpbTextThirdContent label.font = UIFont.projectFont(ofSize: 13) label.textAlignment = .right label.numberOfLines = 0 label.lineBreakMode = .byWordWrapping return label }() private func setup() { backgroundColor = .tpbCard let container = UIView() container.translatesAutoresizingMaskIntoConstraints = false addSubview(container) let cons1 = NSLayoutConstraint(item: container, attribute: .leading, relatedBy: .equal, toItem: self, attribute: .leading, multiplier: 1, constant: 16) let cons2 = NSLayoutConstraint(item: container, attribute: .top, relatedBy: .equal, toItem: self, attribute: .top, multiplier: 1, constant: 0) let cons3 = NSLayoutConstraint(item: container, attribute: .trailing, relatedBy: .equal, toItem: self, attribute: .trailing, multiplier: 1, constant: -16) let cons4 = NSLayoutConstraint(item: container, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1, constant: 0) NSLayoutConstraint.activate([cons1, cons2, cons3, cons4]) imageView.translatesAutoresizingMaskIntoConstraints = false container.addSubview(imageView) let imageViewCons1 = NSLayoutConstraint(item: imageView, attribute: .leading, relatedBy: .equal, toItem: container, attribute: .leading, multiplier: 1, constant: 4) let imageViewCons2 = NSLayoutConstraint(item: imageView, attribute: .centerY, relatedBy: .equal, toItem: container, attribute: .centerY, multiplier: 1, constant: 0) let imageViewCons3 = NSLayoutConstraint(item: imageView, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .width, multiplier: 1, constant: 24) let imageViewCons4 = NSLayoutConstraint(item: imageView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 1, constant: 24) NSLayoutConstraint.activate([imageViewCons1, imageViewCons2, imageViewCons3, imageViewCons4]) titleLabel.translatesAutoresizingMaskIntoConstraints = false container.addSubview(titleLabel) let titleLabelCons1 = NSLayoutConstraint(item: titleLabel, attribute: .leading, relatedBy: .equal, toItem: imageView, attribute: .trailing, multiplier: 1, constant: 4) let titleLabelCons2 = NSLayoutConstraint(item: titleLabel, attribute: .top, relatedBy: .equal, toItem: container, attribute: .top, multiplier: 1, constant: 0) let titleLabelCons3 = NSLayoutConstraint(item: titleLabel, attribute: .bottom, relatedBy: .equal, toItem: container, attribute: .bottom, multiplier: 1, constant: 0) NSLayoutConstraint.activate([titleLabelCons1, titleLabelCons2, titleLabelCons3]) informationLabel.translatesAutoresizingMaskIntoConstraints = false container.addSubview(informationLabel) let informationLabelCons1 = NSLayoutConstraint(item: informationLabel, attribute: .leading, relatedBy: .equal, toItem: titleLabel, attribute: .trailing, multiplier: 1, constant: 5) let informationLabelCons2 = NSLayoutConstraint(item: informationLabel, attribute: .top, relatedBy: .equal, toItem: container, attribute: .top, multiplier: 1, constant: 0) let informationLabelCons3 = NSLayoutConstraint(item: informationLabel, attribute: .trailing, relatedBy: .equal, toItem: container, attribute: .trailing, multiplier: 1, constant: 0) let informationLabelCons4 = NSLayoutConstraint(item: informationLabel, attribute: .bottom, relatedBy: .equal, toItem: container, attribute: .bottom, multiplier: 1, constant: 0) NSLayoutConstraint.activate([informationLabelCons1, informationLabelCons2, informationLabelCons3, informationLabelCons4]) titleLabel.setContentCompressionResistancePriority(.required, for: .horizontal) container.isUserInteractionEnabled = false } } // MARK: GeneralMenuView class GeneralMenuView: UIView, CustomMenuView { typealias MenuItemView = GeneralMenuItemView var items: [GeneralMenuItem] = [] { didSet { setup() } } /// 点击后的动作 /// index: 第几个menuItem var action: ((_ itemId: String) -> Void)? override init(frame: CGRect) { super.init(frame: frame) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } func itemClickCallback(index: Int) { action?(items[safe: index]?.itemId ?? "") } } class GeneralMenuItem: NSObject, CustomMenuItem { var itemId: String @objc dynamic var image: UIImage @objc dynamic var title: String @objc dynamic var subtitle: String? @objc dynamic var enabled: Bool init(itemId: String, image: UIImage, title: String, subtitle: String? = nil, enabled: Bool = true) { self.itemId = itemId self.image = image self.title = title self.subtitle = subtitle self.enabled = enabled super.init() } } class GeneralMenuItemView: AnyMenuItemView<GeneralMenuItem> { var observers = [NSKeyValueObservation]() var informationLabelWidthConstraint: NSLayoutConstraint? required init(item: GeneralMenuItem) { super.init(item: item) setup() } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } override var intrinsicContentSize: CGSize { return CGSize(width: super.intrinsicContentSize.width, height: 44) } override func didMoveToSuperview() { super.didMoveToSuperview() if superview == nil { observers = [] } else { observers = [ item.observe(\.image, options: .initial) { [weak self] (object, _) in self?.imageView.image = object.image }, item.observe(\.title, options: .initial) { [weak self] (object, _) in self?.titleLabel.text = object.title }, item.observe(\.enabled, options: .initial) { [weak self] (object, _) in self?.isEnabled = object.enabled }, item.observe(\.subtitle, options: .initial) { [weak self] (object, _) in if object.subtitle == nil || object.subtitle == "" { self?.informationLabelWidthConstraint?.isActive = true } else { self?.informationLabelWidthConstraint?.isActive = false self?.informationLabel.text = object.subtitle } } ] } } private lazy var imageView: UIImageView = { let imageView = UIImageView() imageView.contentMode = .scaleAspectFit return imageView }() private lazy var titleLabel: UILabel = { let titleLabel = UILabel() titleLabel.textColor = UIColor.tpbTextPrimary titleLabel.font = UIFont.projectFont(ofSize: 16) titleLabel.textAlignment = .left titleLabel.numberOfLines = 0 titleLabel.lineBreakMode = .byWordWrapping return titleLabel }() private lazy var informationLabel: UILabel = { let label = UILabel(frame: .zero) label.textColor = UIColor.tpbTextThirdContent label.font = UIFont.projectFont(ofSize: 13) label.textAlignment = .right label.numberOfLines = 0 label.lineBreakMode = .byWordWrapping return label }() private func setup() { backgroundColor = .tpbCard let container = UIView() container.translatesAutoresizingMaskIntoConstraints = false addSubview(container) let cons1 = NSLayoutConstraint(item: container, attribute: .leading, relatedBy: .equal, toItem: self, attribute: .leading, multiplier: 1, constant: 16) let cons2 = NSLayoutConstraint(item: container, attribute: .top, relatedBy: .equal, toItem: self, attribute: .top, multiplier: 1, constant: 0) let cons3 = NSLayoutConstraint(item: container, attribute: .trailing, relatedBy: .equal, toItem: self, attribute: .trailing, multiplier: 1, constant: -16) let cons4 = NSLayoutConstraint(item: container, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1, constant: 0) NSLayoutConstraint.activate([cons1, cons2, cons3, cons4]) imageView.translatesAutoresizingMaskIntoConstraints = false container.addSubview(imageView) let imageViewCons1 = NSLayoutConstraint(item: imageView, attribute: .leading, relatedBy: .equal, toItem: container, attribute: .leading, multiplier: 1, constant: 4) let imageViewCons2 = NSLayoutConstraint(item: imageView, attribute: .centerY, relatedBy: .equal, toItem: container, attribute: .centerY, multiplier: 1, constant: 0) let imageViewCons3 = NSLayoutConstraint(item: imageView, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .width, multiplier: 1, constant: 24) let imageViewCons4 = NSLayoutConstraint(item: imageView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 1, constant: 24) NSLayoutConstraint.activate([imageViewCons1, imageViewCons2, imageViewCons3, imageViewCons4]) titleLabel.translatesAutoresizingMaskIntoConstraints = false container.addSubview(titleLabel) let titleLabelCons1 = NSLayoutConstraint(item: titleLabel, attribute: .leading, relatedBy: .equal, toItem: imageView, attribute: .trailing, multiplier: 1, constant: 12) let titleLabelCons2 = NSLayoutConstraint(item: titleLabel, attribute: .top, relatedBy: .equal, toItem: container, attribute: .top, multiplier: 1, constant: 0) let titleLabelCons3 = NSLayoutConstraint(item: titleLabel, attribute: .bottom, relatedBy: .equal, toItem: container, attribute: .bottom, multiplier: 1, constant: 0) NSLayoutConstraint.activate([titleLabelCons1, titleLabelCons2, titleLabelCons3]) informationLabel.translatesAutoresizingMaskIntoConstraints = false container.addSubview(informationLabel) let informationLabelCons1 = NSLayoutConstraint(item: informationLabel, attribute: .leading, relatedBy: .equal, toItem: titleLabel, attribute: .trailing, multiplier: 1, constant: 5) let informationLabelCons2 = NSLayoutConstraint(item: informationLabel, attribute: .top, relatedBy: .equal, toItem: container, attribute: .top, multiplier: 1, constant: 0) let informationLabelCons3 = NSLayoutConstraint(item: informationLabel, attribute: .trailing, relatedBy: .equal, toItem: container, attribute: .trailing, multiplier: 1, constant: 0) let informationLabelCons4 = NSLayoutConstraint(item: informationLabel, attribute: .bottom, relatedBy: .equal, toItem: container, attribute: .bottom, multiplier: 1, constant: 0) informationLabelWidthConstraint = NSLayoutConstraint(item: informationLabel, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 0) NSLayoutConstraint.activate([informationLabelCons1, informationLabelCons2, informationLabelCons3, informationLabelCons4]) titleLabel.setContentCompressionResistancePriority(.required, for: .horizontal) container.isUserInteractionEnabled = false } } class DeviceListMenuView: UIView, CustomMenuView { enum Item: Int { case alarmMode = 0 //Fix: 隐藏云存储 // case cloudStorage //Fix: 隐藏设备分享 // case share case upgrade // case reonboard case unbind case setting case collect } typealias MenuItemView = DeviceListMenuItemView let items: [DeviceListMenuItem] = DeviceListMenuItem.allItems static var deviceChannel: (device: TPSSDeviceForDeviceList, channel: TPSSChannelInfo?)? var action: ((Item, TPSSDeviceForDeviceList, TPSSChannelInfo?) -> Void)? = nil override init(frame: CGRect) { super.init(frame: frame) setup() } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } func itemClickCallback(index: Int) { action?(Item(rawValue: index)!, DeviceListMenuView.deviceChannel!.device, DeviceListMenuView.deviceChannel!.channel) } } class DeviceListMenuItem: NSObject, CustomMenuItem { @objc dynamic var image: UIImage @objc dynamic var title: String @objc dynamic var subtitle: String? @objc dynamic var enabled: Bool @objc dynamic var hidden: Bool @objc dynamic var subtitleTextColor: UIColor @objc dynamic var subtitleBackgroundColor: UIColor @objc dynamic var alpha: Float init(image: UIImage, title: String, subtitle: String? = nil, enabled: Bool = true, hidden: Bool = false, subtitleTextColor: UIColor = .tpbTextPrimary, subtitleBackgroundColor: UIColor = .tpbCard, alpha: Float = 1) { self.image = image self.title = title self.subtitle = subtitle self.enabled = enabled self.hidden = hidden self.subtitleTextColor = subtitleTextColor self.subtitleBackgroundColor = subtitleBackgroundColor self.alpha = alpha super.init() } static let alarmMode: DeviceListMenuItem = DeviceListMenuItem(image: TPImageLiteral("devicelist_alarm_on").withRenderingMode(.alwaysOriginal), title: LocalizedString(key: deviceListEventAlarmOn)) //Fix: 隐藏云存储 // static let cloudStorage: DeviceListMenuItem = DeviceListMenuItem(image: TPImageLiteral("cloud_service"), title: LocalizedString(key: deviceListCloudStorage), subtitle: LocalizedString(key: deviceListSwitchViewToList)) //Fix: 隐藏设备分享 // static let share: DeviceListMenuItem = DeviceListMenuItem(image: TPImageLiteral("devicelist_share_nor"), title: LocalizedString(key: deviceListShare)) static let upgrade: DeviceListMenuItem = DeviceListMenuItem(image: TPImageLiteral("devicelist_update_reddot_nor"), title: LocalizedString(key: deviceListUpgrade)) // static let reonboard: DeviceListMenuItem = DeviceListMenuItem(image: TPImageLiteral("common_reonboarding_wifi"), title: LocalizedString(key: deviceListReonboarding)) static let setting: DeviceListMenuItem = DeviceListMenuItem(image: TPImageLiteral("common_setting_nor"), title: LocalizedString(key: deviceListMoreSetting)) static let unbind: DeviceListMenuItem = DeviceListMenuItem(image: TPImageLiteral("devicelist_unbind"), title: LocalizedString(key: deviceUnbindButtonTitle)) static let collect: DeviceListMenuItem = DeviceListMenuItem(image: TPImageLiteral("device_not_collect_list"), title: LocalizedString(key: deviceCollectFavorite)) //Fix: 隐藏云存储 //Fix: 隐藏设备分享 // static let allItems: [DeviceListMenuItem] = [.alarmMode, .cloudStorage, .share, .upgrade, .reonboard, .setting] static let allItems: [DeviceListMenuItem] = [.alarmMode, .upgrade, unbind, .setting, .collect] } extension Array where Element == DeviceListMenuItem { var preferredheight: CGFloat { return CGFloat(filter {!$0.hidden}.count) * 44 + 16 } } class DeviceListMenuItemView: AnyMenuItemView<DeviceListMenuItem> { var observers = [NSKeyValueObservation]() required init(item: DeviceListMenuItem) { super.init(item: item) setup() } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } override var intrinsicContentSize: CGSize { return CGSize(width: super.intrinsicContentSize.width, height: item.hidden ? 0 : 44) } override func didMoveToSuperview() { super.didMoveToSuperview() if superview == nil { observers = [] } else { observers = [ item.observe(\.image, options: .initial) { [weak self] (object, _) in self?.imageView.image = object.image }, item.observe(\.title, options: .initial) { [weak self] (object, _) in self?.titleLabel.text = object.title }, item.observe(\.enabled, options: .initial) { [weak self] (object, _) in self?.isEnabled = object.enabled }, item.observe(\.subtitle, options: .initial) { [weak self] (object, _) in if let subtitle = object.subtitle { self?.informationButton.isHidden = false self?.informationLabel.text = subtitle } else { self?.informationButton.isHidden = true self?.hasInformationLayout(false) } }, item.observe(\.subtitleTextColor, options: .initial) { [weak self] (object, _) in self?.informationLabel.textColor = object.subtitleTextColor }, item.observe(\.subtitleBackgroundColor, options: .initial) { [weak self] (object, _) in self?.informationButton.backgroundColor = object.subtitleBackgroundColor }, item.observe(\.hidden, options: .initial) { [weak self] (object, _) in self?.isHidden = object.hidden self?.invalidateIntrinsicContentSize() }, item.observe(\.alpha, options: .initial) { [weak self] (object, _) in self?.alpha = CGFloat(object.alpha) } ] } } private lazy var imageView: UIImageView = { let imageView = UIImageView() imageView.contentMode = .scaleAspectFit return imageView }() private lazy var titleLabel: UILabel = { let titleLabel = UILabel() titleLabel.textColor = UIColor.tpbTextPrimary titleLabel.font = UIFont.projectFont(ofSize: 16) titleLabel.textAlignment = .left titleLabel.numberOfLines = 0 titleLabel.lineBreakMode = .byWordWrapping titleLabel.setContentCompressionResistancePriority(.defaultLow, for: .vertical) titleLabel.setContentCompressionResistancePriority(.required, for: .horizontal) return titleLabel }() private lazy var informationButton: UIButton = { let btn = UIButton(type: .system) btn.tintColor = .tpbTextPrimary btn.backgroundColor = .tpbCard btn.titleLabel?.font = UIFont.projectFont(ofSize: 13) btn.layer.cornerRadius = 12 // btn.contentEdgeInsets = UIEdgeInsets(top: 0, left: 12, bottom: 0, right: 12) NSLayoutConstraint(item: btn, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 0, constant: 24).isActive = true return btn }() private lazy var informationLabel: UILabel = { let informationLabel = UILabel() informationLabel.textColor = UIColor.tpbTextPrimary informationLabel.font = UIFont.projectFont(ofSize: 13) informationLabel.textAlignment = .left informationLabel.numberOfLines = 1 // informationLabel.setContentCompressionResistancePriority(.required, for: .horizontal) return informationLabel }() private func hasInformationLayout(_ hasInfo: Bool) { let titleLabelCons4 = NSLayoutConstraint(item: titleLabel, attribute: .trailing, relatedBy: .equal, toItem: self, attribute: .trailing, multiplier: 1, constant: 0) titleLabelCons4.isActive = !hasInfo } private func setup() { backgroundColor = .tpbCard let container = UIView() container.translatesAutoresizingMaskIntoConstraints = false addSubview(container) let cons1 = NSLayoutConstraint(item: container, attribute: .leading, relatedBy: .equal, toItem: self, attribute: .leading, multiplier: 1, constant: 16) let cons2 = NSLayoutConstraint(item: container, attribute: .top, relatedBy: .equal, toItem: self, attribute: .top, multiplier: 1, constant: 0) let cons3 = NSLayoutConstraint(item: container, attribute: .trailing, relatedBy: .equal, toItem: self, attribute: .trailing, multiplier: 1, constant: -22) let cons4 = NSLayoutConstraint(item: container, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1, constant: 0) NSLayoutConstraint.activate([cons1, cons2, cons3, cons4]) imageView.translatesAutoresizingMaskIntoConstraints = false container.addSubview(imageView) let imageViewCons1 = NSLayoutConstraint(item: imageView, attribute: .leading, relatedBy: .equal, toItem: container, attribute: .leading, multiplier: 1, constant: 4) let imageViewCons2 = NSLayoutConstraint(item: imageView, attribute: .centerY, relatedBy: .equal, toItem: container, attribute: .centerY, multiplier: 1, constant: 0) let imageViewCons3 = NSLayoutConstraint(item: imageView, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .width, multiplier: 1, constant: 24) let imageViewCons4 = NSLayoutConstraint(item: imageView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 1, constant: 24) NSLayoutConstraint.activate([imageViewCons1, imageViewCons2, imageViewCons3, imageViewCons4]) titleLabel.translatesAutoresizingMaskIntoConstraints = false container.addSubview(titleLabel) let titleLabelCons1 = NSLayoutConstraint(item: titleLabel, attribute: .leading, relatedBy: .equal, toItem: imageView, attribute: .trailing, multiplier: 1, constant: 4) let titleLabelCons2 = NSLayoutConstraint(item: titleLabel, attribute: .top, relatedBy: .equal, toItem: container, attribute: .top, multiplier: 1, constant: 0) let titleLabelCons3 = NSLayoutConstraint(item: titleLabel, attribute: .bottom, relatedBy: .equal, toItem: container, attribute: .bottom, multiplier: 1, constant: 0) NSLayoutConstraint.activate([titleLabelCons1, titleLabelCons2, titleLabelCons3]) informationButton.translatesAutoresizingMaskIntoConstraints = false container.addSubview(informationButton) informationLabel.translatesAutoresizingMaskIntoConstraints = false informationButton.addSubview(informationLabel) let informationLabelCons1 = NSLayoutConstraint(item: informationLabel, attribute: .leading, relatedBy: .equal, toItem: titleLabel, attribute: .trailing, multiplier: 1, constant: 12) let informationLabelCons2 = NSLayoutConstraint(item: informationLabel, attribute: .trailing, relatedBy: .equal, toItem: informationButton, attribute: .trailing, multiplier: 1, constant: -12) let informationLabelCons3 = NSLayoutConstraint(item: informationLabel, attribute: .top, relatedBy: .equal, toItem: informationButton, attribute: .top, multiplier: 1, constant: 0) let informationLabelCons4 = NSLayoutConstraint(item: informationLabel, attribute: .bottom, relatedBy: .equal, toItem: informationButton, attribute: .bottom, multiplier: 1, constant: 0) let informationLabelCons5 = NSLayoutConstraint(item: informationLabel, attribute: .width, relatedBy: .greaterThanOrEqual, toItem: nil, attribute: .width, multiplier: 1, constant: 40) NSLayoutConstraint.activate([informationLabelCons1, informationLabelCons2, informationLabelCons3, informationLabelCons4, informationLabelCons5]) let informationButtonCons1 = NSLayoutConstraint(item: informationButton, attribute: .leading, relatedBy: .equal, toItem: informationLabel, attribute: .leading, multiplier: 1, constant: -12) let informationButtonCons2 = NSLayoutConstraint(item: informationButton, attribute: .trailing, relatedBy: .equal, toItem: container, attribute: .trailing, multiplier: 1, constant: 0) let informationButtonCons3 = NSLayoutConstraint(item: informationButton, attribute: .centerY, relatedBy: .equal, toItem: container, attribute: .centerY, multiplier: 1, constant: 0) NSLayoutConstraint.activate([informationButtonCons1, informationButtonCons2, informationButtonCons3]) container.isUserInteractionEnabled = false } } extension DeviceListMenuView { private class func setDeviceListMenuItemAlpha(_ alpha: Float, for itemList: [DeviceListMenuItem]) { if alpha >= 0 && alpha <= 1 { itemList.forEach({$0.alpha = alpha}) } } class func configure(device: TPSSDeviceForDeviceList, channel: TPSSChannelInfo?, displayMode: TPSSDeviceGroupDisplayMode = .card) { deviceChannel = (device, channel) //OnlineDeviceListViewController调用configure函数是配置两个item title以满足多语言切换刷新文案 DeviceListMenuItem.upgrade.title = LocalizedString(key: deviceListUpgrade) DeviceListMenuItem.setting.title = LocalizedString(key: deviceListMoreSetting) DeviceListMenuItem.collect.title = LocalizedString(key: deviceCollectFavorite) DeviceListMenuItem.unbind.title = LocalizedString(key: deviceUnbindButtonTitle) //太阳能\NVR\local;card模式此处不显示收藏,老版本vms也不支持 let isVms = TPAppContextFactory.shared().isVmsLogin DeviceListMenuItem.collect.hidden = (device.deviceType == .solar || device.listType == .local || displayMode == .card || (TPSSAppContext.shared.loginType == .personal ? false : TPSSAppContext.shared.isVmsDeviceListFavoriteOldVersion) || ( device.deviceType == .NVR && channel == nil) ) ? true : false //根据设备收否被收藏来设置收藏按钮状态 var isCollected = false if device.deviceType == .IPC { isCollected = isVms ? device.isVMSFavorited : device.isCollected } else { if channel != nil { isCollected = isVms ? channel!.isVMSFavorited : device.isCollected && device.collectChannels.contains(channel!.channelId as NSNumber) } else { isCollected = isVms ? device.isVMSFavorited : device.isCollected } } DeviceListMenuItem.collect.image = isCollected ? TPImageLiteral("device_have_collect_list") : TPImageLiteral("device_not_collect_list") //太阳能设备适配 if device.deviceType == .IPC || device.deviceType == .solar { // 消息报警 var showMessage = device.listType == .remote && device.supportMessage && device.displayOnline && !device.isSharedDevice if let cn = channel { showMessage = cn.supportsMessagePush && cn.online && device.displayOnline && !device.isSharedDevice } //太阳能设备适配 if device.deviceType == .solar { //太阳能设备不支持通知开关 showMessage = false // showMessage = device.listType == .remote && device.displayOnline } if !showMessage { DeviceListMenuItem.alarmMode.hidden = true } else { DeviceListMenuItem.alarmMode.hidden = false let messageEnable = channel?.messageEnable ?? device.messageEnable DeviceListMenuItem.alarmMode.image = messageEnable ? TPImageLiteral("devicelist_alarm_on").withRenderingMode(.alwaysOriginal) : TPImageLiteral("devicelist_alarm_off") DeviceListMenuItem.alarmMode.title = messageEnable ? LocalizedString(key: deviceListEventAlarmOn) : LocalizedString(key: deviceListEventAlarmOff) } if device.deviceSubType == .doorBellCamera { DeviceListMenuItem.alarmMode.hidden = true } // 如果是分享的设备且没有管理权限, cell设为透明, 不许设置 if device.isSharedFromOthers && device.shareDevicePermissionInfo.deviceSettingWrite == false { setDeviceListMenuItemAlpha(0.5, for: [.alarmMode, .upgrade, .unbind]) } else { setDeviceListMenuItemAlpha(1, for: [.alarmMode, .upgrade, .unbind]) } // 云存储 //Fix: 隐藏云存储 // if !device.supportCloudStorage || device.isSharedDevice { // DeviceListMenuItem.cloudStorage.hidden = true // } else { // let cloudStorageService = appContext.currentServiceInfo(forDevice: device.cloudDeviceId, // channel: max(0, channelID), // serviceType: .cloudStorage) // // DeviceListMenuItem.cloudStorage.hidden = false // // if cloudStorageService.isVaild { // DeviceListMenuItem.cloudStorage.subtitle = cloudStorageService.cloudStorageStateText // DeviceListMenuItem.cloudStorage.subtitleTextColor = cloudStorageService.stateColor // DeviceListMenuItem.cloudStorage.subtitleBackgroundColor = cloudStorageService.stateBackgroundColor // } else { // DeviceListMenuItem.cloudStorage.subtitle = nil // } // } // 分享 //Fix: 隐藏设备分享 // let appContext = TPSSAppContext.shared // // let channelID = channel?.channelId.intValue ?? -1 // if device.isSharedDevice || !device.supportsShare { // DeviceListMenuItem.share.hidden = true // } else { // DeviceListMenuItem.share.hidden = false // let isEnterpriseShare = appContext.isValidEnterpriseShareDevice(device.cloudDeviceId, channelD: max(0, channelID)) // let shareService: TPSSCloudStorageService // if isEnterpriseShare { // shareService = appContext.enterpriseShareService // } else { // shareService = appContext.currentServiceInfo(forDevice: device.cloudDeviceId, // channel: max(0, channelID), // serviceType: .paidShare) // } // let stateText = shareService.shareStateText(isEnterpriseShare: isEnterpriseShare) // if shareService.isVaild && !stateText.isEmpty && (shareService.serviceState != .expired || UserDefaults.standard.needShowRenewalHint(for: device.cloudDeviceId, channelID: max(0, channelID), isEnterpriseShare: isEnterpriseShare)) { // DeviceListMenuItem.share.subtitle = stateText // DeviceListMenuItem.share.subtitleTextColor = shareService.stateColor // DeviceListMenuItem.share.subtitleBackgroundColor = shareService.stateBackgroundColor // } else { // DeviceListMenuItem.share.subtitle = nil // } // } // // // 重新配置WiFi // if (device.displayOnline || !device.supportsReonboarding) || channel != nil { // DeviceListMenuItem.reonboard.hidden = true // } else { // DeviceListMenuItem.reonboard.hidden = false // } // 固件升级 if device.listType != .remote { DeviceListMenuItem.upgrade.hidden = true } else { if let cn = channel { if let version = cn.shortReleaseFirmwareVersion, cn.hasNewFirmware && !device.isSharedDevice { DeviceListMenuItem.upgrade.hidden = false DeviceListMenuItem.upgrade.image = device.showUpdateForChannel(channel: channel) ? TPImageLiteral("devicelist_update_reddot_nor") : TPImageLiteral("devicelist_update_nor") DeviceListMenuItem.upgrade.subtitle = version DeviceListMenuItem.upgrade.subtitleTextColor = .tpbRed DeviceListMenuItem.upgrade.subtitleBackgroundColor = .tpbRedLight } else { DeviceListMenuItem.upgrade.hidden = true } } else { if let version = device.shortReleaseFirmwareVersion, device.online && device.needUpgrade && !device.isSharedDevice { DeviceListMenuItem.upgrade.hidden = false DeviceListMenuItem.upgrade.image = device.showUpdateForChannel(channel: nil) ? TPImageLiteral("devicelist_update_reddot_nor") : TPImageLiteral("devicelist_update_nor") DeviceListMenuItem.upgrade.subtitle = version DeviceListMenuItem.upgrade.subtitleTextColor = .tpbRed DeviceListMenuItem.upgrade.subtitleBackgroundColor = .tpbRedLight } else { DeviceListMenuItem.upgrade.hidden = true } } } //未初始化设备只有非本地设备首页可显示解绑按钮 if device.listType == .local || device.factoryStatus != .yes || !device.online { DeviceListMenuItem.unbind.hidden = true } else { DeviceListMenuItem.unbind.hidden = false } } else if device.deviceType == .NVR { // DeviceListMenuItem.alarmMode.hidden = true // DeviceListMenuItem.upgrade.hidden = true guard let channelInfo = channel else { DeviceListMenuItem.alarmMode.hidden = true DeviceListMenuItem.upgrade.hidden = true if device.listType == .local || device.factoryStatus != .yes || !device.online { DeviceListMenuItem.unbind.hidden = true } else { DeviceListMenuItem.unbind.hidden = false } return } // 如果是分享的通道且没有管理权限, cell设为透明, 不许设置 if channelInfo.isSharedFromOthers && channelInfo.shareDevicePermissionInfo.deviceSettingWrite == false { setDeviceListMenuItemAlpha(0.5, for: [.alarmMode, .upgrade, .unbind]) } else { setDeviceListMenuItemAlpha(1, for: [.alarmMode, .upgrade, .unbind]) } // 消息报警 let showMessage = (device.listType == .remote) && channelInfo.supportsMessagePush && channelInfo.online && device.displayOnline && !device.isSharedDevice && channelInfo.active if !showMessage { DeviceListMenuItem.alarmMode.hidden = true } else { DeviceListMenuItem.alarmMode.hidden = false let messageEnable = channelInfo.messageEnable DeviceListMenuItem.alarmMode.image = messageEnable ? TPImageLiteral("devicelist_alarm_on").withRenderingMode(.alwaysOriginal) : TPImageLiteral("devicelist_alarm_off") DeviceListMenuItem.alarmMode.title = messageEnable ? LocalizedString(key: deviceListEventAlarmOn) : LocalizedString(key: deviceListEventAlarmOff) } if device.deviceSubType == .doorBellCamera { DeviceListMenuItem.alarmMode.hidden = true } // 固件升级 if device.listType != .remote { DeviceListMenuItem.upgrade.hidden = true } else { if let version = channelInfo.shortReleaseFirmwareVersion, channelInfo.hasNewFirmware && !device.isSharedDevice && channelInfo.active { DeviceListMenuItem.upgrade.hidden = false DeviceListMenuItem.upgrade.image = device.showUpdateForChannel(channel: channelInfo) ? TPImageLiteral("devicelist_update_reddot_nor") : TPImageLiteral("devicelist_update_nor") DeviceListMenuItem.upgrade.subtitle = version DeviceListMenuItem.upgrade.subtitleTextColor = .tpbRed DeviceListMenuItem.upgrade.subtitleBackgroundColor = .tpbRedLight } else { DeviceListMenuItem.upgrade.hidden = true } } //未初始化设备只有非本地设备首页可显示解绑按钮;!channelInfo.active仅针对初始化状态,channel都没设备,不显示解绑(非初始化状态device.factoryStatus != .yes直接隐藏unbind) if device.listType == .local || device.factoryStatus != .yes || !device.online || !channelInfo.active { DeviceListMenuItem.unbind.hidden = true } else { DeviceListMenuItem.unbind.hidden = false } } } }
最新发布
12-06
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值