Swift 3.0中ScrollView内固定非滚动按钮位置的技术求助
嘿,这个需求我之前做项目的时候刚好碰到过,给你两个在Swift 3.0里可行的实现方案,亲测能达到你要的效果——按钮属于ScrollView但不随内容滚动,还能固定在ScrollView frame外的位置!
方案一:重写ScrollView的layoutSubviews方法
这个方法的核心思路是:每次ScrollView滚动或者布局变化时,手动把按钮的位置拉回相对于ScrollView frame的固定位置,让它不跟着content滚动。
首先自定义一个UIScrollView子类,把按钮作为它的子视图,然后重写layoutSubviews方法来维护按钮的位置:
class FixedButtonScrollView: UIScrollView { // 声明固定按钮 var fixedActionButton: UIButton! override init(frame: CGRect) { super.init(frame: frame) setupFixedButton() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) setupFixedButton() } private func setupFixedButton() { fixedActionButton = UIButton(type: .system) fixedActionButton.backgroundColor = .yellow fixedActionButton.setTitle("固定按钮", for: .normal) fixedActionButton.setTitleColor(.black, for: .normal) self.addSubview(fixedActionButton) // 初始化按钮位置:比如在ScrollView右侧外10pt,距离顶部20pt fixedActionButton.frame = CGRect(x: self.bounds.width + 10, y: 20, width: 100, height: 44) } override func layoutSubviews() { super.layoutSubviews() // 每次ScrollView布局(包括滚动)时,更新按钮位置,保持相对于ScrollView的固定位置 let targetX = self.bounds.width + 10 let targetY = 20 fixedActionButton.frame = CGRect( x: targetX, y: targetY, width: fixedActionButton.bounds.width, height: fixedActionButton.bounds.height ) } }
之后你在ViewController里直接用这个自定义ScrollView就行,添加可滚动的内容视图后,按钮会一直固定在你设置的位置,不会跟着内容滚动。
方案二:用Auto Layout约束(更推荐)
如果你的项目用Auto Layout,这个方法更适配不同屏幕尺寸,也不需要自定义ScrollView子类。核心是给按钮设置相对于ScrollView本身的约束,而不是约束到ScrollView的内容视图或者contentLayoutGuide。
示例代码如下(在ViewController的viewDidLoad里):
override func viewDidLoad() { super.viewDidLoad() // 1. 创建并配置ScrollView let scrollView = UIScrollView() scrollView.backgroundColor = .blue scrollView.translatesAutoresizingMaskIntoConstraints = false self.view.addSubview(scrollView) self.view.backgroundColor = .green // 给ScrollView添加铺满父视图的约束 NSLayoutConstraint.activate([ scrollView.topAnchor.constraint(equalTo: self.view.topAnchor), scrollView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor), scrollView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor), scrollView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor) ]) // 2. 创建并添加固定按钮到ScrollView let fixedButton = UIButton(type: .system) fixedButton.backgroundColor = .yellow fixedButton.setTitle("固定按钮", for: .normal) fixedButton.setTitleColor(.black, for: .normal) fixedButton.translatesAutoresizingMaskIntoConstraints = false scrollView.addSubview(fixedButton) // 关键约束:按钮的位置相对于ScrollView本身的边缘,而不是内容 NSLayoutConstraint.activate([ fixedButton.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 20), fixedButton.leadingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: 10), fixedButton.widthAnchor.constraint(equalToConstant: 100), fixedButton.heightAnchor.constraint(equalToConstant: 44) ]) // 3. 添加ScrollView的可滚动内容视图(示例) let contentView = UIView() contentView.backgroundColor = .lightGray contentView.translatesAutoresizingMaskIntoConstraints = false scrollView.addSubview(contentView) NSLayoutConstraint.activate([ contentView.topAnchor.constraint(equalTo: scrollView.topAnchor), contentView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor), contentView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor), contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor), // 设置足够高的高度让内容可滚动 contentView.heightAnchor.constraint(equalToConstant: 1500) ]) }
重要注意点
- 要确保ScrollView的父视图(也就是你的绿色主视图)的
clipsToBounds属性设置为false,不然按钮超出ScrollView的部分会被父视图裁剪掉,看不到。 - 如果用Storyboard实现,操作逻辑一样:把按钮拖到ScrollView内部,然后在约束面板里选择把按钮的边距约束到ScrollView本身,而不是内部的内容视图。
内容的提问来源于stack exchange,提问作者Vijay Patidar
相关产品推荐
相关产品推荐

