Swift iOS:通过代码创建基于UIButton与约束的响应式顶部菜单
Hey there, let's build this responsive button layout that behaves just like Bootstrap's grid—adapting to orientation changes and button text length. Here's a complete, clean implementation using Swift and Auto Layout:
Step-by-Step Implementation
1. Define Constants & Setup Base Views
First, we'll set up reusable constants and core views (a top container and a stack view to handle the responsive button layout):
class ViewController: UIViewController { // Button titles array private let buttonTitles = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"] // Padding inside each button private let buttonContentInsets = UIEdgeInsets(top: 8, left: 16, bottom: 8, right: 16) // Spacing between buttons private let buttonSpacing: CGFloat = 8 // Insets for the top container view private let containerInsets = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16) // Top container view (stays anchored to the top of the screen) private lazy var topContainer: UIView = { let view = UIView() view.translatesAutoresizingMaskIntoConstraints = false view.backgroundColor = .systemGray6 // Optional: for visibility during testing return view }() // Stack view to handle responsive button wrapping private lazy var buttonStack: UIStackView = { let stack = UIStackView() stack.translatesAutoresizingMaskIntoConstraints = false stack.axis = .horizontal stack.alignment = .center stack.distribution = .fillProportionally // Adjusts button width based on content stack.spacing = buttonSpacing stack.isLayoutMarginsRelativeArrangement = true stack.layoutMargins = containerInsets return stack }() }
2. Assemble Views & Add Constraints
Next, we'll add these views to the main view and set up Auto Layout constraints to keep the container anchored to the top:
override func viewDidLoad() { super.viewDidLoad() setupLayout() createAndAddButtons() } private func setupLayout() { view.backgroundColor = .white // Add container and stack view to the hierarchy view.addSubview(topContainer) topContainer.addSubview(buttonStack) // Pin the top container to the safe area top, left, and right NSLayoutConstraint.activate([ topContainer.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), topContainer.leadingAnchor.constraint(equalTo: view.leadingAnchor), topContainer.trailingAnchor.constraint(equalTo: view.trailingAnchor), // Let the container's height be determined by the stack view content topContainer.bottomAnchor.constraint(equalTo: buttonStack.bottomAnchor) ]) // Pin the stack view to fill the container NSLayoutConstraint.activate([ buttonStack.topAnchor.constraint(equalTo: topContainer.topAnchor), buttonStack.leadingAnchor.constraint(equalTo: topContainer.leadingAnchor), buttonStack.trailingAnchor.constraint(equalTo: topContainer.trailingAnchor), buttonStack.bottomAnchor.constraint(equalTo: topContainer.bottomAnchor) ]) }
3. Create Buttons with Adaptive Behavior
Now we'll loop through our title array, create each button, and configure it to adapt to text length and screen size:
private func createAndAddButtons() { for title in buttonTitles { let button = UIButton(type: .system) button.setTitle(title, for: .normal) // Make button text shrink if it's too long for the button width button.titleLabel?.adjustsFontSizeToFitWidth = true button.titleLabel?.minimumScaleFactor = 0.7 // Don't shrink below 70% of original size // Add padding inside the button for better touch target and appearance button.contentEdgeInsets = buttonContentInsets // Style the button (customize this as needed) button.backgroundColor = .systemBlue button.setTitleColor(.white, for: .normal) button.layer.cornerRadius = 8 // Ensure buttons prioritize their content width but can compress if needed button.setContentHuggingPriority(.defaultHigh, for: .horizontal) button.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal) // Add the button to the stack view buttonStack.addArrangedSubview(button) } }
Key Features Explained
- Responsive Wrapping: The
UIStackViewautomatically wraps buttons to new lines when there's not enough horizontal space—perfect for handling landscape/portrait orientation changes. - Text Adaptation: Buttons will shrink their text size if the title is too long, preventing text truncation.
- Flexible Layout: The stack view's
fillProportionallydistribution ensures buttons take up space based on their content, rather than forcing equal widths (though you can switch to.fillEquallyif you prefer uniform button sizes). - Auto Height: The top container's height adjusts dynamically to fit all buttons, even when they wrap to multiple lines.
内容的提问来源于stack exchange,提问作者user3180309
相关产品推荐
相关产品推荐

