You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:43:40