析edgesForExtendedLayout、automaticallyAdjustsScrollViewInsets

本文详细解析了iOS7中ViewController的全屏布局特性,包括edgesForExtendedLayout、automaticallyAdjustsScrollViewInsets及extendedLayoutIncludesOpaqueBars三个关键属性的作用与区别。

在IOS7以后 ViewController 开始使用全屏布局的,而且是默认的行为通常涉及到布局

就离不开这个属性 edgesForExtendedLayout,它是一个类型为UIExtendedEdge的属性,

指定边缘要延伸的方向,它的默认值很自然地是UIRectEdgeAll,四周边缘均延伸,就是说,

如果即使视图中上有navigationBar,下有tabBar,那么视图仍会延伸覆盖到四周的区域。

因为一般为了不让tableView 不延伸到 navigationBar 下面, 属性设置为 UIRectEdgeNone

UIRectEdgeAll -- default

\

UIRectEdgeNone 

\

这时会发现导航栏变灰了,处理如下就OK了

 

 self.navigationController.navigationBar.translucent = NO;

 

那 automaticallyAdjustsScrollViewInsets 呢?

当 automaticallyAdjustsScrollViewInsets 为 NO 时,tableview 是从屏幕的最上边开始,也就是被

导航栏 & 状态栏覆盖

\

 

当 automaticallyAdjustsScrollViewInsets 为 YES 时,也是默认行为,表现就比较正常了,和

edgesForExtendedLayout = UIRectEdgeNone 有啥区别? 不注意可能很难觉察

设计师可能一眼就看穿。。。 automaticallyAdjustsScrollViewInsets 为YES 时,

tableView 上下滑动时,是可以穿过导航栏&状态栏的,在他们下面有淡淡的浅浅红色

\

extendedLayoutIncludesOpaqueBars 

首先看下官方解释,默认 NO, 但是Bar 的默认属性是 透明的。。。也就是说只有在不透明下才有用

但是,测试结果很软肋,基本区别不大。。。但是对于解决一些Bug 是还是起作用的,比如说SearchBar的

跳动问题,详情见:http://www.cnblogs.com/skyming/p/4059128.html, 其他UITableView,UIScrollView 位置的

问题多数和这3属性相关。。

\

看看这个代码 我跟他一样继承的同样的组件库 为什么他这个页面的顶部可以贴着屏幕,但我的会在页面层级中多一个UINavigationBar import UIKit class EditOrganizationMainViewController: SurveillanceCommonTableController { // MARK: - 属性 private lazy var orgHeaderView: EditOrganizationOrgHeaderView = { let view = EditOrganizationOrgHeaderView() return view }() private lazy var appContext = { TPAppContextFactory.shared() }() // 组织信息 private var orgInfo = TPSSVMSOrganizationInfo() private var userManagementPermission: Bool{ get{ #if APP_VIGI if !appContext.currentRolePermission.userManagement { return false } return true #else if orgInfo.vmsOrgType == .omadaSurOnlyCloud{ if !appContext.currentRolePermission.userManagement { return false } } else { if appContext.accountInfo.centralPermission.centralUsers == .block { return false } } return true #endif } } // 必须使用该初始化方式 convenience init(orgInfo: TPSSVMSOrganizationInfo) { self.init() self.orgInfo = orgInfo } deinit { print("EditOrganizationMainViewController deinit") } // MARK: - View override func tpbSetupSubviews() { super.tpbSetupSubviews() view.addSubview(orgHeaderView) } override func tpbMakeConstraint() { // 暂不执行super不然会显示不了title // super.tpbMakeConstraint() orgHeaderView.snp.makeConstraints { make in make.top.leading.trailing.equalTo(view.safeAreaLayoutGuide) } tableView.snp.remakeConstraints { make in make.top.equalTo(orgHeaderView.snp.bottom) make.leading.trailing.equalTo(view.safeAreaLayoutGuide) make.bottom.equalTo(view) } } override func viewDidLoad() { super.viewDidLoad() requestRolePermission() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) // TODO: 接入Omada Central之后需要判定是否隐藏 navigationController?.setNavigationBarHidden(true, animated: false) // 获取基本信息 getOrgDetailInfo() reloadView() } private func reloadView() { orgHeaderView.updateWith(orgName: orgInfo.vmsName, orgCategory: orgInfo.vmsOrgCategory) { [weak self] in if let org = self?.orgInfo { let vc = EditOrganizationSettingsViewController(orgInfo: org) self?.navigationController?.pushViewController(vc, animated: true) } } reloadData() } // MARK: - dateModel private func reloadData() { var tempSectionArray = [TPBTableSectionModel]() // section0 // let section0 = TPBTableSectionModel() // var section0CellModelArray = [TPBBaseTableCellModel]() // // // // section0.cellModelArray = section0CellModelArray // tempSectionArray.append(section0) #if APP_OMADA // section1 let section1 = TPBTableSectionModel() var section1CellModelArray = [TPBBaseTableCellModel]() if orgInfo.networkSelect { let omadaNetworkCellModel = TPBBaseTableCellModel.titleSubtitle(withIcon: TPImageLiteral("central_network"), title: LocalizedString(key: addOrganizationOmadaNetwork), subtitle: nil, value: orgInfo.networkVersion, infoItemArray: nil, action: nil, showIndicator: false) section1CellModelArray.append(omadaNetworkCellModel) } if orgInfo.surveillanceSelect { let omadaGuardCellModel = TPBBaseTableCellModel.titleSubtitle(withIcon: TPImageLiteral("central_surveillance"), title: LocalizedString(key: shareSocialPlatformWebDetail), subtitle: nil, value: orgInfo.surveillanceVersion, infoItemArray: nil, action: nil, showIndicator: false) section1CellModelArray.append(omadaGuardCellModel) } section1.cellModelArray = section1CellModelArray section1.headerTitle = LocalizedString(key: editOrganizationApplication) tempSectionArray.append(section1) #endif // section2 let section2 = TPBTableSectionModel() var section2CellModelArray = [TPBBaseTableCellModel]() if currentOrgIsGuardOnly || TPSSAppContext.shared.accountInfo.centralPermission.centralGlobalSetting != .block { let generalSettingCellModel = TPBBaseTableCellModel.titleSubtitle(withIcon: nil, title: LocalizedString(key: configTitle), subtitle: nil, value: nil, infoItemArray: nil, action: { [weak self] _, _ in if let org = self?.orgInfo { let vc = EditOrganizationSettingsViewController(orgInfo: org) self?.navigationController?.pushViewController(vc, animated: true) } }, showIndicator: true) section2CellModelArray.append(generalSettingCellModel) } let siteManagementCellModel = TPBBaseTableCellModel.titleSubtitle(withIcon: nil, title: LocalizedString(key: editOrganizationSiteManagement), subtitle: nil, value: nil, infoItemArray: nil, action: { [weak self] _, _ in let vc = OmadaSiteManagementListViewController() self?.navigationController?.pushViewController(vc, animated: true) }, showIndicator: true) section2CellModelArray.append(siteManagementCellModel) let userManagementCellModel = TPBBaseTableCellModel.titleSubtitle(withIcon: nil, title: LocalizedString(key: editOrganizationUserManagement), subtitle: nil, value: nil, infoItemArray: nil, action: { [weak self] _, _ in self?.clickUserManagement() }, showIndicator: true) section2CellModelArray.append(userManagementCellModel) section2.cellModelArray = section2CellModelArray tempSectionArray.append(section2) // section3 let section3 = TPBTableSectionModel() var section3CellModelArray = [TPBBaseTableCellModel]() #if APP_VIGI if let hasCloudVMSOrganization = UserDefaults.standard.object(forKey: kHasCloudVMSOrganization) as? Bool { if TPSSAppContext.shared.isSupportCreateOrg || hasCloudVMSOrganization { let createOrgCellModel = TPBBaseTableCellModel.action(withIcon: nil, title: LocalizedString(key: createNewOrganization), action: { _, _ in let vc = AddOrganizationCreateOrgViewController() if let rootVC = UIApplication.shared.keyWindow?.rootViewController as? MainModuleTabBarController { rootVC.presentFullScreenViewController(vc) } }, actionEnabled: true, titleColor: .tpbPrimary) section3CellModelArray.append(createOrgCellModel) } } #else if appContext.accountInfo.createCuardServiceDisable != 1 { } #endif #if APP_VIGI let title = appContext.accountInfo.roleName == DefaultRoleName.owner.rawValue ? LocalizedString(key: editOrganizationDeleteOrganization) : LocalizedString(key: editOrganizationLeaveOrganization) #else let title = orgInfo.role == .owner ? LocalizedString(key: editOrganizationDeleteOrganization) : LocalizedString(key: editOrganizationLeaveOrganization) #endif let deleteCellModel = TPBBaseTableCellModel.action(withIcon: nil, title: title, action: { [weak self] _, _ in self?.showDeleteAlert() }, actionEnabled: true, titleColor: .tpbRed) section3CellModelArray.append(deleteCellModel) section3.cellModelArray = section3CellModelArray tempSectionArray.append(section3) sectionArray = tempSectionArray } // MARK: - 点击事件 @objc private func clickBack() { dismiss(animated: true) } private func showDeleteAlert() { #if APP_VIGI // 如果是owner则需要获取VmsStatistics,根据返回结果决定弹窗表现;如果是user则直接弹窗 if appContext.accountInfo.roleName == DefaultRoleName.owner.rawValue { RequestAsyncHandler.default.perform({ () -> TPSSCode in ToastView.showLoadingToast(cirleWithMessage: nil) return appContext.requestGetVmsStatistics() }, callback: { [weak self] result in guard let self = self else { return } ToastView.dismissLoadingToast() if result.isSuccess() { // 根据返回结果决定弹窗表现 self.showVMSOwnerDeleteAlert() } else { var errorMessage = result.error() if result.notification?.parameter0() == TPSS_EC_TIMEOUT || result.notification?.parameter0() == TPSS_EC_NET_ERROR || errorMessage == "" { errorMessage = LocalizedString(key: deviceSettingWifiNvrGetStatusFail) } ToastView.showTopWarningWithLeftIconToast(title: errorMessage, type: .info, existTime: 2) } }) } else { tpbShowAlert(withTitle: LocalizedString(key: editOrganizationLeaveOrganizationAlertTitle), messsage: nil, cancelText: LocalizedString(key: commonCancel), cancelCallback: nil, deleteText: LocalizedString(key: deviceSettingUpgradeLeave)) { [weak self] in self?.deleteOrg() } } #else let title = orgInfo.role == .owner ? LocalizedString(key: editOrganizationDeleteOrganizationAlertTitle) : LocalizedString(key: editOrganizationLeaveOrganizationAlertTitle) let deleteText = orgInfo.role == .owner ? LocalizedString(key: commonDelete) : LocalizedString(key: deviceSettingUpgradeLeave) tpbShowAlert(withTitle: title, messsage: nil, cancelText: LocalizedString(key: commonCancel), cancelCallback: nil, deleteText: deleteText) { [weak self] in self?.deleteOrg() } #endif } private func showVMSOwnerDeleteAlert() { if let vmsStatistics = appContext.getVmsStatistics() { let isCloudBackUp = TPSSAppContext.shared.getVMSIsSupportCloudStorage() != 0 if vmsStatistics.deviceNum == 0 { // 设备数为0 if vmsStatistics.orgManagerNum == 0 { // 用户为0 if isCloudBackUp { // 云备份开启 if vmsStatistics.hasActivePackages { showVMSOwnerDeleteUnableToDeleteAlertView() } else if vmsStatistics.hasOrgBackupVideos { showVMSOwnerDeleteCanDeleteAlertView() } else { showVMSOwnerDeleteCanDeleteAlertView() } } else { showVMSOwnerDeleteCanDeleteAlertView() } } else { showVMSOwnerDeleteCanDeleteAlertView() } } else { if isCloudBackUp { // 云备份开启 if vmsStatistics.hasActivePackages { showVMSOwnerDeleteUnableToDeleteAlertView() } else { showVMSOwnerDeleteUnableToDeleteAlertView() } } else { showVMSOwnerDeleteUnableToDeleteAlertView() } } } } // 可以删除提示 private func showVMSOwnerDeleteCanDeleteAlertView() { tpbShowAlert(withTitle: LocalizedString(key: editOrganizationVMSDeleteOrganizationTip), messsage: nil, cancelText: LocalizedString(key: commonCancel), cancelCallback: nil, deleteText: LocalizedString(key: commonDelete)) { [weak self] in self?.deleteOrg() } } // 不可以删除提示 private func showVMSOwnerDeleteUnableToDeleteAlertView() { tpbShowAlert(withTitle: LocalizedString(key: editOrganizationVMSUnabletoDeleteOrganizationTip), buttonText: LocalizedString(key: commonKnown)) } private func clickUserManagement() { if userManagementPermission { let vc = UserManagementViewController() navigationController?.pushViewController(vc, animated: true) } else { tpbShowAlertToastFailure(withTitle: TPSSAppContext.errorMsg(forLocalizedKey: IPC_EM_FINISH_REASON_PERMISSION_DENIED)) } } // MARK: - 发送请求 private func requestRolePermission(){ //适配多端修改问题 if currentOrgIsGuardOnly { appContext.requestCloudVMSRolePermission() } else { appContext.requestCentralRolePermission() } } private func getOrgDetailInfo() { RequestAsyncHandler.default.perform({ () -> TPSSCode in // 获取组织信息 #if APP_VIGI return appContext.requestVMSOrgInfo() #else return appContext.requestGetCloudOmadaOrgDetails(byVmsId: orgInfo.vmsId) #endif }, callback: { [weak self] result in guard let self = self else { return } if result.isSuccess() { let currentVMSId = appContext.currentVMSId if let org = self.appContext.getVmsInfo(byVmsId: currentVMSId) { // 为保证浅拷贝有效,此处仅修改值,而非直接用底层获取的值替换 self.orgInfo.vmsName = org.vmsName self.orgInfo.region = org.region self.orgInfo.countryCode = org.countryCode self.orgInfo.timeZone = org.timeZone self.orgInfo.networkVersion = org.networkVersion self.orgInfo.surveillanceVersion = org.surveillanceVersion self.reloadView() } else { self.orgInfo.vmsName = appContext.accountInfo.currentVmsName self.orgInfo.timeZone = appContext.accountInfo.currentVmsTimeZone self.orgInfo.countryCode = appContext.accountInfo.currentVmsCountryCode } } else { var errorMessage = result.error() if result.notification?.parameter0() == TPSS_EC_TIMEOUT || result.notification?.parameter0() == TPSS_EC_NET_ERROR || errorMessage == "" { errorMessage = LocalizedString(key: deviceSettingWifiNvrGetStatusFail) } ToastView.showTopWarningWithLeftIconToast(title: errorMessage, type: .info, existTime: 2) } }) } private func deleteOrg() { RequestAsyncHandler.default.perform({ () -> TPSSCode in ToastView.showLoadingToast(cirleWithMessage: nil) #if APP_VIGI return appContext.requestDeleteVms(byPassword: "") #else return appContext.requestForgetCloudOmadaOrg(byVmsId: orgInfo.vmsId) #endif }, callback: { [weak self] result in guard let self = self else { return } ToastView.dismissLoadingToast() if result.isSuccess() { self.appContext.initVms(.personal, organizationId: "") // 清空上一次选择的站点信息 UserDefaults.standard.deviceListSelectedType = nil FileManager.default.removeVmsSelectedSiteInfo() #if APP_VIGI // vigi需要在组织列表为空时跳帐密页,也需要登出 let getVMSOrganizationList = self.appContext.getVMSOrganizationList() let orgList = getVMSOrganizationList.filter { [weak self] info in guard let self2 = self else { return false } return info.vmsId != self2.orgInfo.vmsId } let unverifyOrgList = self.appContext.getUnverifyVMSOrganizationList() if orgList.isEmpty && unverifyOrgList.isEmpty { self.jumpToAccountLoginVC() } else { self.jumpToSelectOrganizationVC() } #else self.jumpToSelectOrganizationVC() #endif } else { var errorMessage = result.error() if result.notification?.parameter0() == TPSS_EC_TIMEOUT || result.notification?.parameter0() == TPSS_EC_NET_ERROR || errorMessage == "" { errorMessage = LocalizedString(key: deviceSettingWifiNvrGetStatusFail) } ToastView.showTopWarningWithLeftIconToast(title: errorMessage, type: .info, existTime: 2) } }) } private func jumpToSelectOrganizationVC() { let vc = AccountSelectOrganizationViewController() vc.getOrgStatusTypeFromLogin = .success vc.jumpToLastViewHandle = { //静默登出 TPAppContextFactory.shared().requestLogout() if(UIApplication.shared.isRegisteredForRemoteNotifications){ UIApplication.shared.unregisterForRemoteNotifications() } } UIApplication.shared.keyWindow?.rootViewController = BaseNavigationController(rootViewController: vc) } private func jumpToAccountLoginVC() { let destinationStoryboard = UIStoryboard(name: "AccountManager", bundle: nil) if let destinationViewController = destinationStoryboard.instantiateViewController(withIdentifier: "accountManagerLogin") as? AccountLoginViewController { //静默登出 TPAppContextFactory.shared().requestLogout() if(UIApplication.shared.isRegisteredForRemoteNotifications){ UIApplication.shared.unregisterForRemoteNotifications() } let navigationVC = BaseNavigationController(rootViewController: destinationViewController) UIApplication.shared.keyWindow?.rootViewController = navigationVC } } } // 自定义view fileprivate class EditOrganizationOrgHeaderView: TPBBaseView { // MARK: - 属性 private lazy var nameLabel: UILabel = { let label = UILabel() label.text = " " label.numberOfLines = 1 label.font = .tpr22Regular() label.textColor = .tpbTextPrimary label.textAlignment = .left label.lineBreakMode = .byTruncatingTail return label }() private lazy var orgCategoryContainerView: UIView = { let view = UIView() view.backgroundColor = .tpbPrimaryLight view.layer.cornerRadius = 3 view.layer.masksToBounds = true view.setContentHuggingPriority(.required, for: .horizontal) view.setContentCompressionResistancePriority(.required, for: .horizontal) return view }() private lazy var orgCategorylabel: UILabel = { let label = UILabel() label.text = LocalizedString(key: orgCategoryEssential) label.font = .tpr12Regular() label.textColor = .tpbPrimary label.numberOfLines = 1 label.lineBreakMode = .byTruncatingTail label.textAlignment = .left label.setContentHuggingPriority(.required, for: .horizontal) label.setContentCompressionResistancePriority(.required, for: .horizontal) return label }() // MARK: - View override func setupSubviews() { super.setupSubviews() backgroundColor = .tpbBackground addSubviews([nameLabel, orgCategoryContainerView]) orgCategoryContainerView.addSubview(orgCategorylabel) #if APP_VIGI orgCategoryContainerView.isHidden = true #endif } override func makeConstraint() { super.makeConstraint() nameLabel.snp.makeConstraints { make in make.leading.equalToSuperview().offset(20) make.top.equalToSuperview().offset(20) if orgCategoryContainerView.isHidden { make.trailing.equalToSuperview().offset(-20) } make.bottom.equalToSuperview().offset(-10) } orgCategoryContainerView.snp.makeConstraints { make in make.leading.equalTo(nameLabel.snp.trailing).offset(8) make.trailing.lessThanOrEqualToSuperview().offset(-20) make.centerY.equalTo(nameLabel) } orgCategorylabel.snp.makeConstraints { make in make.leading.equalToSuperview().offset(6) make.trailing.equalToSuperview().offset(-6) make.top.equalToSuperview().offset(2) make.bottom.equalToSuperview().offset(-2) } } // MARK: -更新函数 func updateWith(orgName: String, orgCategory: TPSSVMSOrgCategory, clickGeneralSettingsBlock: @escaping (() -> Void)) { nameLabel.text = orgName if orgCategory == .essential { orgCategorylabel.text = LocalizedString(key: orgCategoryEssential) orgCategorylabel.textColor = .tpbBlue orgCategoryContainerView.backgroundColor = .tpbBlueLight } else { orgCategorylabel.text = LocalizedString(key: deviceSettingSmartWhiteLampModeAutoWTL) orgCategorylabel.textColor = .tpbPrimary orgCategoryContainerView.backgroundColor = .tpbPrimaryLight } #if APP_VIGI #endif } }
最新发布
12-03
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值