leftbarbuttonitem

本文介绍如何在iOS应用中使用Objective-C为UINavigationController的左侧和右侧添加自定义按钮,并展示了如何针对不同状态调整按钮样式。

//

        UIBarButtonItem *leftButton = [[UIBarButtonItem alloc] initWithTitle:@"+"

                                                                       style:UIBarButtonItemStyleDone

                                                                      target:self

                                                                      action:@selector(CreateNewFolder_Func)];

        if (IsIos7_Func()) {

            [leftButton setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:

                                                RGB(0, 122, 255), UITextAttributeTextColor,

                                                [UIFont systemFontOfSize:26.0], UITextAttributeFont,

                                                nil] forState:UIControlStateNormal];

        }

        

        //

        UIBarButtonItem *rightButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:self action:@selector(Edit_Func)];

        

        [self.navigationItem setLeftBarButtonItem:leftButton];

        [self.navigationItem setRightBarButtonItem:rightButton];




import UIKit import SnapKit class DeviceListNewViewController: SurveillanceCommonTableController { // MARK: - 属性 private lazy var titleView: UILabel = { let label = UILabel() label.text = "设备列表" label.font = .tpm20Medium() label.textColor = .tpbTextPrimary label.textAlignment = .center return label }() private lazy var searchBar: TPBSearchBar = { let bar = TPBSearchBar() bar.placeholder = "搜索" bar.backgroundColor = .clear bar.delegate = self return bar }() private lazy var searchContainerView: UIView = { let view = UIView() view.backgroundColor = UIColor(white: 0.96, alpha: 1.0) view.layer.cornerRadius = 22 view.clipsToBounds = true view.addSubview(searchBar) return view }() private lazy var tabScrollView: UIScrollView = { let scrollView = UIScrollView() scrollView.showsHorizontalScrollIndicator = false scrollView.backgroundColor = .clear scrollView.translatesAutoresizingMaskIntoConstraints = false return scrollView }() private lazy var tabButtons: [UIButton] = { return tabButtonTitles.enumerated().map { index, title in let btn = UIButton(type: .custom) btn.tag = index btn.setTitle(title, for: .normal) btn.titleLabel?.font = UIFont.tpr14Regular() btn.setTitleColor(.black, for: .normal) btn.setTitleColor(.tpbPrimary, for: .selected) btn.layer.borderWidth = 1 btn.layer.borderColor = UIColor(white: 0.85, alpha: 1.0).cgColor btn.layer.cornerRadius = 20 btn.contentEdgeInsets = UIEdgeInsets(top: 8, left: 16, bottom: 8, right: 16) btn.addTarget(self, action: #selector(onTabTapped(_:)), for: .touchUpInside) return btn } }() private let tabButtonTitles = ["所有设备", "收藏页面", "站点选择"] private var selectedTabIndex = 0 // MARK: - View Setup override func tpbSetupSubviews() { super.tpbSetupSubviews() setupNav() view.addSubview(titleView) view.addSubview(searchContainerView) view.addSubview(tabScrollView) // 初始化按钮选中状态 updateTabSelection(index: selectedTabIndex) // 👇 直接在这里布局 tab 按钮(内联实现,避免找不到方法) layoutTabButtonsInScrollView() } private func setupNav() { navigationItem.leftBarButtonItem = tpbCreateLeftBarButtonItem( with: TPImageLiteral("icon_back"), andTarget: self, andAction: #selector(onBack) ) navigationItem.rightBarButtonItem = tpbCreateRightBarButtonItem( with: TPImageLiteral("icon_settings"), andTarget: self, andAction: #selector(onSettings) ) navigationItem.title = "" } override func tpbMakeConstraint() { super.tpbMakeConstraint() titleView.snp.makeConstraints { make in make.top.equalTo(view.safeAreaLayoutGuide).offset(8) make.centerX.equalToSuperview() } searchContainerView.snp.makeConstraints { make in make.top.equalTo(titleView.snp.bottom).offset(16) make.leading.trailing.equalToSuperview().inset(16) make.height.equalTo(44) // 固定高度适配 TPBSearchBar 常见大小 } searchBar.snp.makeConstraints { make in make.edges.equalTo(searchContainerView).inset(UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 16)) } tabScrollView.snp.makeConstraints { make in make.top.equalTo(searchContainerView.snp.bottom).offset(16) make.leading.trailing.equalToSuperview().inset(0) make.height.equalTo(40) } } // MARK: - 内联布局 Tab 按钮(防止 “Cannot find” 错误) private func layoutTabButtonsInScrollView() { // 清空之前的内容 tabScrollView.subviews.forEach { $0.removeFromSuperview() } var previousButton: UIButton? var currentX: CGFloat = 16 for button in tabButtons { tabScrollView.addSubview(button) // 使用固定 frame 或 SnapKit 设置位置 button.snp.makeConstraints { make in make.centerY.equalToSuperview() make.height.equalTo(36) if let prev = previousButton { make.leading.equalTo(prev.snp.trailing).offset(8) } else { make.leading.equalTo(tabScrollView.contentLayoutGuide).offset(16) } make.width.greaterThanOrEqualTo(80) } previousButton = button currentX += button.intrinsicContentSize.width + 8 } // 手动设置 contentSize(更稳定) DispatchQueue.main.async { var totalWidth: CGFloat = 16 for (i, btn) in self.tabButtons.enumerated() { totalWidth += btn.intrinsicContentSize.width + (i > 0 ? 8 : 0) } totalWidth += 16 self.tabScrollView.contentSize = CGSize(width: totalWidth, height: 40) } } // MARK: - 数据模型构建(仅搭建结构,不填充真实数据) private func reloadData() { var tempSectionArray = [TPBTableSectionModel]() let section0 = TPBTableSectionModel() var cellModels = [TPBBaseTableCellModel]() // Cell 1: Tab ScrollView let tabCellModel = TPBBaseTableCellModel.customContent(with: tabScrollView) cellModels.append(tabCellModel) // Cell 2: 占位用的 CollectionView 区域(仅视觉框架) let collectionViewPlaceholder = UIView() collectionViewPlaceholder.backgroundColor = .tpbBackground collectionViewPlaceholder.layer.cornerRadius = 12 collectionViewPlaceholder.clipsToBounds = true // 添加一个简单的提示标签表示“这里是列表” let placeholderLabel = UILabel() placeholderLabel.text = "设备内容区域" placeholderLabel.textColor = .tpbTextSecondaryContent placeholderLabel.font = .tpr14Regular() placeholderLabel.textAlignment = .center placeholderLabel.sizeToFit() collectionViewPlaceholder.addSubview(placeholderLabel) placeholderLabel.snp.makeConstraints { make in make.center.equalToSuperview() } let collectionCellModel = TPBBaseTableCellModel.customContent(with: collectionViewPlaceholder) collectionCellModel.height = TPBTableElementHeight.customHeight(240) cellModels.append(collectionCellModel) section0.cellModelArray = cellModels tempSectionArray.append(section0) sectionArray = tempSectionArray tableView.reloadData() } // MARK: - 生命周期 override func viewDidLoad() { super.viewDidLoad() reloadData() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) // 后续绑定 collectionView delegate } // MARK: - 点击事件 @objc private func onBack() { navigationController?.popViewController(animated: true) } @objc private func onSettings() { print("Settings tapped") } @objc private func onTabTapped(_ sender: UIButton) { guard sender.tag != selectedTabIndex else { return } tabButtons[selectedTabIndex].isSelected = false selectedTabIndex = sender.tag sender.isSelected = true // 后续刷新数据 print("Switched to tab: \(selectedTabIndex)") } private func updateTabSelection(index: Int) { for (i, btn) in tabButtons.enumerated() { btn.isSelected = (i == index) } } } // MARK: - TPBSearchBarDelegate(空实现,仅满足协议要求) extension DeviceListNewViewController: TPBSearchBarDelegate { func searchBar(_ searchBar: TPBSearchBar, textDidChange searchText: String) { // TODO: 搜索关键词变化时处理(后续接入 ViewModel) } func searchBarTextDidBeginEditing(_ searchBar: TPBSearchBar) { addTapToDismissKeyboard() } func searchBarTextDidEndEditing(_ searchBar: TPBSearchBar) { removeTapToDismissKeyboard() } func searchBarSearchButtonClicked(_ searchBar: TPBSearchBar) { searchBar.resignFirstResponder() } } // MARK: - Keyboard Dismiss Gesture private extension DeviceListNewViewController { func addTapToDismissKeyboard() { let tap = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard)) tap.cancelsTouchesInView = false view.addGestureRecognizer(tap) objc_setAssociatedObject( self, &AssociatedKeys.searchBarTapGestureKey, tap, .OBJC_ASSOCIATION_RETAIN_NONATOMIC ) } func removeTapToDismissKeyboard() { guard let tap = objc_getAssociatedObject(self, &AssociatedKeys.searchBarTapGestureKey) as? UITapGestureRecognizer else { return } view.removeGestureRecognizer(tap) objc_setAssociatedObject(self, &AssociatedKeys.searchBarTapGestureKey, nil, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) } @objc func dismissKeyboard() { searchBar.resignFirstResponder() } } // MARK: - Associated Object Keys private struct AssociatedKeys { static var searchBarTapGestureKey: UInt8 = 0 } 现在这个,给我实现成这样的效果: 屏幕靠上部分显示titleview,然后下面显示searchbar,然后下面显示收藏按钮、所有设备那个scrollview,然后在下面显示一个UIcollectionView,滚动范围就在这个UICollectionView区域,明白我想要的结构了吗?修改代码 import UIKit import SnapKit class DeviceListNewViewController: SurveillanceCommonTableController { // MARK: - 属性 private lazy var titleView: UILabel = { let label = UILabel() label.text = "设备列表" label.font = .tpm20Medium() label.textColor = .tpbTextPrimary label.textAlignment = .center return label }() private lazy var searchBar: TPBSearchBar = { let bar = TPBSearchBar() bar.placeholder = "搜索" bar.backgroundColor = .clear bar.delegate = self return bar }() private lazy var searchContainerView: UIView = { let view = UIView() view.backgroundColor = UIColor(white: 0.96, alpha: 1.0) view.layer.cornerRadius = 22 view.clipsToBounds = true view.addSubview(searchBar) return view }() private lazy var tabScrollView: UIScrollView = { let scrollView = UIScrollView() scrollView.showsHorizontalScrollIndicator = false scrollView.backgroundColor = .clear scrollView.translatesAutoresizingMaskIntoConstraints = false return scrollView }() private lazy var tabButtons: [UIButton] = { return tabButtonTitles.enumerated().map { index, title in let btn = UIButton(type: .custom) btn.tag = index btn.setTitle(title, for: .normal) btn.titleLabel?.font = UIFont.tpr14Regular() btn.setTitleColor(.black, for: .normal) btn.setTitleColor(.tpbPrimary, for: .selected) btn.layer.borderWidth = 1 btn.layer.borderColor = UIColor(white: 0.85, alpha: 1.0).cgColor btn.layer.cornerRadius = 20 btn.contentEdgeInsets = UIEdgeInsets(top: 8, left: 16, bottom: 8, right: 16) btn.addTarget(self, action: #selector(onTabTapped(_:)), for: .touchUpInside) return btn } }() private let tabButtonTitles = ["所有设备", "收藏页面", "站点选择"] private var selectedTabIndex = 0 // MARK: - View Setup override func tpbSetupSubviews() { super.tpbSetupSubviews() setupNav() view.addSubview(titleView) view.addSubview(searchContainerView) view.addSubview(tabScrollView) // 初始化按钮选中状态 updateTabSelection(index: selectedTabIndex) // 👇 直接在这里布局 tab 按钮(内联实现,避免找不到方法) layoutTabButtonsInScrollView() } private func setupNav() { navigationItem.leftBarButtonItem = tpbCreateLeftBarButtonItem( with: TPImageLiteral("icon_back"), andTarget: self, andAction: #selector(onBack) ) navigationItem.rightBarButtonItem = tpbCreateRightBarButtonItem( with: TPImageLiteral("icon_settings"), andTarget: self, andAction: #selector(onSettings) ) navigationItem.title = "" } override func tpbMakeConstraint() { super.tpbMakeConstraint() titleView.snp.makeConstraints { make in make.top.equalTo(view.safeAreaLayoutGuide).offset(8) make.centerX.equalToSuperview() } searchContainerView.snp.makeConstraints { make in make.top.equalTo(titleView.snp.bottom).offset(16) make.leading.trailing.equalToSuperview().inset(16) make.height.equalTo(44) // 固定高度适配 TPBSearchBar 常见大小 } searchBar.snp.makeConstraints { make in make.edges.equalTo(searchContainerView).inset(UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 16)) } tabScrollView.snp.makeConstraints { make in make.top.equalTo(searchContainerView.snp.bottom).offset(16) make.leading.trailing.equalToSuperview().inset(0) make.height.equalTo(40) } } // MARK: - 内联布局 Tab 按钮(防止 “Cannot find” 错误) private func layoutTabButtonsInScrollView() { // 清空之前的内容 tabScrollView.subviews.forEach { $0.removeFromSuperview() } var previousButton: UIButton? var currentX: CGFloat = 16 for button in tabButtons { tabScrollView.addSubview(button) // 使用固定 frame 或 SnapKit 设置位置 button.snp.makeConstraints { make in make.centerY.equalToSuperview() make.height.equalTo(36) if let prev = previousButton { make.leading.equalTo(prev.snp.trailing).offset(8) } else { make.leading.equalTo(tabScrollView.contentLayoutGuide).offset(16) } make.width.greaterThanOrEqualTo(80) } previousButton = button currentX += button.intrinsicContentSize.width + 8 } // 手动设置 contentSize(更稳定) DispatchQueue.main.async { var totalWidth: CGFloat = 16 for (i, btn) in self.tabButtons.enumerated() { totalWidth += btn.intrinsicContentSize.width + (i > 0 ? 8 : 0) } totalWidth += 16 self.tabScrollView.contentSize = CGSize(width: totalWidth, height: 40) } } // MARK: - 数据模型构建(仅搭建结构,不填充真实数据) private func reloadData() { var tempSectionArray = [TPBTableSectionModel]() let section0 = TPBTableSectionModel() var cellModels = [TPBBaseTableCellModel]() // Cell 1: Tab ScrollView let tabCellModel = TPBBaseTableCellModel.customContent(with: tabScrollView) cellModels.append(tabCellModel) // Cell 2: 占位用的 CollectionView 区域(仅视觉框架) let collectionViewPlaceholder = UIView() collectionViewPlaceholder.backgroundColor = .tpbBackground collectionViewPlaceholder.layer.cornerRadius = 12 collectionViewPlaceholder.clipsToBounds = true // 添加一个简单的提示标签表示“这里是列表” let placeholderLabel = UILabel() placeholderLabel.text = "设备内容区域" placeholderLabel.textColor = .tpbTextSecondaryContent placeholderLabel.font = .tpr14Regular() placeholderLabel.textAlignment = .center placeholderLabel.sizeToFit() collectionViewPlaceholder.addSubview(placeholderLabel) placeholderLabel.snp.makeConstraints { make in make.center.equalToSuperview() } let collectionCellModel = TPBBaseTableCellModel.customContent(with: collectionViewPlaceholder) collectionCellModel.height = TPBTableElementHeight.customHeight(240) cellModels.append(collectionCellModel) section0.cellModelArray = cellModels tempSectionArray.append(section0) sectionArray = tempSectionArray tableView.reloadData() } // MARK: - 生命周期 override func viewDidLoad() { super.viewDidLoad() reloadData() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) // 后续绑定 collectionView delegate } // MARK: - 点击事件 @objc private func onBack() { navigationController?.popViewController(animated: true) } @objc private func onSettings() { print("Settings tapped") } @objc private func onTabTapped(_ sender: UIButton) { guard sender.tag != selectedTabIndex else { return } tabButtons[selectedTabIndex].isSelected = false selectedTabIndex = sender.tag sender.isSelected = true // 后续刷新数据 print("Switched to tab: \(selectedTabIndex)") } private func updateTabSelection(index: Int) { for (i, btn) in tabButtons.enumerated() { btn.isSelected = (i == index) } } } // MARK: - TPBSearchBarDelegate(空实现,仅满足协议要求) extension DeviceListNewViewController: TPBSearchBarDelegate { func searchBar(_ searchBar: TPBSearchBar, textDidChange searchText: String) { // TODO: 搜索关键词变化时处理(后续接入 ViewModel) } func searchBarTextDidBeginEditing(_ searchBar: TPBSearchBar) { addTapToDismissKeyboard() } func searchBarTextDidEndEditing(_ searchBar: TPBSearchBar) { removeTapToDismissKeyboard() } func searchBarSearchButtonClicked(_ searchBar: TPBSearchBar) { searchBar.resignFirstResponder() } } // MARK: - Keyboard Dismiss Gesture private extension DeviceListNewViewController { func addTapToDismissKeyboard() { let tap = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard)) tap.cancelsTouchesInView = false view.addGestureRecognizer(tap) objc_setAssociatedObject( self, &AssociatedKeys.searchBarTapGestureKey, tap, .OBJC_ASSOCIATION_RETAIN_NONATOMIC ) } func removeTapToDismissKeyboard() { guard let tap = objc_getAssociatedObject(self, &AssociatedKeys.searchBarTapGestureKey) as? UITapGestureRecognizer else { return } view.removeGestureRecognizer(tap) objc_setAssociatedObject(self, &AssociatedKeys.searchBarTapGestureKey, nil, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) } @objc func dismissKeyboard() { searchBar.resignFirstResponder() } } // MARK: - Associated Object Keys private struct AssociatedKeys { static var searchBarTapGestureKey: UInt8 = 0 }
最新发布
12-02
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值