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

如何在Swift中通过代码创建带Page Controller的水平UIScrollView(无Storyboard)

How to Create a Horizontal UIScrollView with UIPageControl in Swift (No Storyboards)

Hey there! Let's walk through building a fully code-based horizontal scroll view paired with a page control—no Storyboards required. I'll break this down step by step so it's easy to follow and adapt to your project.

Step 1: Set Up Your View Controller

First, we'll start with a view controller initialized entirely via code (no nibs or Storyboards). We'll also declare our core UI components upfront:

import UIKit

class PageScrollViewController: UIViewController {
    
    // Core UI elements
    private let scrollView = UIScrollView()
    private let pageControl = UIPageControl()
    private let contentView = UIView()
    
    // Define how many pages you want to display
    private let pageCount = 3
    
    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        setupInitialConfig()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    private func setupInitialConfig() {
        view.backgroundColor = .systemBackground
    }
}

Step 2: Add and Configure UI Components

Next, we'll add our components to the main view and set up Auto Layout constraints. The contentView acts as a container for all our pages—this makes managing page layout way simpler than adding pages directly to the scroll view.

Add this method and call it in viewDidLoad:

override func viewDidLoad() {
    super.viewDidLoad()
    setupUI()
}

private func setupUI() {
    // Configure Scroll View
    scrollView.translatesAutoresizingMaskIntoConstraints = false
    scrollView.isPagingEnabled = true // Enables snap-to-page behavior
    scrollView.showsHorizontalScrollIndicator = false
    scrollView.delegate = self
    view.addSubview(scrollView)
    
    // Configure Content View (holds all pages)
    contentView.translatesAutoresizingMaskIntoConstraints = false
    scrollView.addSubview(contentView)
    
    // Configure Page Control
    pageControl.translatesAutoresizingMaskIntoConstraints = false
    pageControl.numberOfPages = pageCount
    pageControl.currentPage = 0
    pageControl.addTarget(self, action: #selector(pageControlTapped(_:)), for: .valueChanged)
    view.addSubview(pageControl)
    
    // Set up all constraints
    NSLayoutConstraint.activate([
        // Scroll View constraints
        scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
        scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
        scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
        scrollView.bottomAnchor.constraint(equalTo: pageControl.topAnchor, constant: -20),
        
        // Content View constraints (width = scroll view width * number of pages)
        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(equalTo: scrollView.heightAnchor),
        contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor, multiplier: CGFloat(pageCount)),
        
        // Page Control constraints
        pageControl.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -20),
        pageControl.centerXAnchor.constraint(equalTo: view.centerXAnchor),
        pageControl.heightAnchor.constraint(equalToConstant: 30)
    ])
    
    // Add individual pages to the content view
    setupPages()
}

Step 3: Create and Add Pages to Content View

Now let's build the actual pages. For this example, I'll make simple colored views with labels, but you can swap these out for any custom view you need:

private func setupPages() {
    let pageColors: [UIColor] = [.systemBlue, .systemGreen, .systemOrange]
    
    for index in 0..<pageCount {
        let pageView = UIView()
        pageView.translatesAutoresizingMaskIntoConstraints = false
        pageView.backgroundColor = pageColors[index]
        contentView.addSubview(pageView)
        
        // Add a label to each page
        let pageLabel = UILabel()
        pageLabel.translatesAutoresizingMaskIntoConstraints = false
        pageLabel.text = "Page \(index + 1)"
        pageLabel.font = .systemFont(ofSize: 24, weight: .bold)
        pageLabel.textColor = .white
        pageView.addSubview(pageLabel)
        
        // Page constraints (each page takes full width of scroll view)
        NSLayoutConstraint.activate([
            pageView.topAnchor.constraint(equalTo: contentView.topAnchor),
            pageView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor),
            pageView.widthAnchor.constraint(equalTo: scrollView.widthAnchor),
            pageView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: CGFloat(index) * view.frame.width)
        ])
        
        // Label constraints (centered on the page)
        NSLayoutConstraint.activate([
            pageLabel.centerXAnchor.constraint(equalTo: pageView.centerXAnchor),
            pageLabel.centerYAnchor.constraint(equalTo: pageView.centerYAnchor)
        ])
    }
}

Step 4: Sync Scroll View and Page Control

We need two key behaviors: updating the page control when the user scrolls, and scrolling to the selected page when the user taps the page control. Add these extensions to your view controller:

extension PageScrollViewController: UIScrollViewDelegate {
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        // Calculate current page based on scroll offset
        let currentPage = scrollView.contentOffset.x / scrollView.frame.width
        pageControl.currentPage = Int(round(currentPage))
    }
}

extension PageScrollViewController {
    @objc private func pageControlTapped(_ sender: UIPageControl) {
        // Scroll to the selected page with smooth animation
        let targetOffset = CGFloat(sender.currentPage) * scrollView.frame.width
        scrollView.setContentOffset(CGPoint(x: targetOffset, y: 0), animated: true)
    }
}

Key Tips to Keep in Mind

  • isPagingEnabled: This property makes the scroll view snap to each page automatically—critical for the page-based experience.
  • Content View Width: Setting the content view's width to scrollView.width * pageCount ensures the scroll view has enough horizontal space to display all pages.
  • Scroll Delegate: Using scrollViewDidScroll keeps the page control in perfect sync with the user's scrolling.
  • Smooth Transitions: The setContentOffset(_:animated:) method gives a polished feel when tapping the page control.

How to Use This Controller

Since we're not using Storyboards, set this controller as your root view controller in SceneDelegate (iOS 13+):

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    var window: UIWindow?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let windowScene = (scene as? UIWindowScene) else { return }
        let window = UIWindow(windowScene: windowScene)
        window.rootViewController = PageScrollViewController()
        self.window = window
        window.makeKeyAndVisible()
    }
}

That's it! You now have a fully functional horizontal scroll view with page control, built entirely in Swift without any Storyboards.

内容的提问来源于stack exchange,提问作者Sanjana Nanjappa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:26:41