Swift中如何通过代码修改弹窗内自定义UIButton的尺寸
问题根因
当前代码同时混用Auto Layout约束和frame属性修改,当translatesAutoresizingMaskIntoConstraints设为false时,视图的尺寸、位置完全由激活的约束决定,直接修改frame的代码不会生效。代码中写的button.frame.size.width = 140属于冗余无效代码。
另外当前闭包初始化按钮时调用addTarget(self, ...)存在崩溃风险:非lazy的闭包初始化属性执行时,类实例还未完成初始化,此时self不存在,会导致异常。
方案1:保留Auto Layout布局(推荐,匹配当前代码逻辑)
你当前已经给按钮设置了固定宽度140的约束,要动态修改尺寸,只需要把需要调整的约束存为类属性,后续直接修改约束的constant值即可,不要操作frame属性。
修正后的代码示例:
class SuccessMessageView: UIView, UITextFieldDelegate { // 存储按钮宽度约束,方便后续修改 private var buttonWidthConstraint: NSLayoutConstraint! // 高度约束如果需要动态修改也可以同理存储 // private var buttonHeightConstraint: NSLayoutConstraint! // 改为lazy属性,等类实例初始化完成后再创建按钮,避免self引用崩溃 private lazy var buttonConfirm : UIButton = { let button = UIButton() button.setTitle("Ok", for: .normal) button.backgroundColor = UIColor(rgb: PreferenceManager.shared.hasDevice() ? purpleColour : orangeColour) button.setTitleColor(.white, for: .normal) button.layer.cornerRadius = 10 button.addTarget(self, action: #selector(confirmFunc), for: .touchUpInside) // 常规交互建议用touchUpInside,符合iOS交互习惯 button.translatesAutoresizingMaskIntoConstraints = false // 初始化默认宽度约束并赋值给类属性 buttonWidthConstraint = button.widthAnchor.constraint(equalToConstant: 140.0) buttonWidthConstraint.isActive = true // 高度如果是固定值可以直接在这里设置约束 button.heightAnchor.constraint(equalToConstant: 44).isActive = true return button }() // 需要修改按钮尺寸时调用该方法 private func updateButtonSize(width: CGFloat) { // 直接修改约束的constant值 buttonWidthConstraint.constant = width // 如果需要动画效果,就把layoutIfNeeded包在UIView.animate闭包中 self.layoutIfNeeded() } }
方案2:全Frame布局(不推荐,弹窗多屏幕适配成本高)
如果不想使用Auto Layout,需要删除所有约束相关代码,保持translatesAutoresizingMaskIntoConstraints为默认的true状态,之后直接修改frame即可调整尺寸:
class SuccessMessageView: UIView, UITextFieldDelegate { private var buttonConfirm : UIButton = { // 初始化时直接给默认frame let button = UIButton(frame: CGRect(x: 0, y: 0, width: 140, height: 44)) button.setTitle("Ok", for: .normal) button.backgroundColor = UIColor(rgb: PreferenceManager.shared.hasDevice() ? purpleColour : orangeColour) button.setTitleColor(.white, for: .normal) button.layer.cornerRadius = 10 // 注意:非lazy闭包初始化不要在这里addTarget,和之前一样会有self引用崩溃问题 return button }() // 视图完成布局后再设置位置、绑定事件 override func layoutSubviews() { super.layoutSubviews() // 这里设置按钮的位置,保证在弹窗中居中 buttonConfirm.center = CGPoint(x: self.bounds.midX, y: self.bounds.midY) buttonConfirm.addTarget(self, action: #selector(confirmFunc), for: .touchUpInside) } // 修改尺寸直接调整frame private func updateButtonSize(width: CGFloat) { buttonConfirm.frame.size.width = width // 修改尺寸后重新调整位置,避免错位 buttonConfirm.center.x = self.bounds.midX } }
内容的提问来源于stack exchange,提问作者Min Thein Win
相关产品推荐
相关产品推荐

