Skip to content

📖 Book Interface in Swift

License

Notifications You must be signed in to change notification settings

piemonte/BookLayout

Repository files navigation

BookLayout

PlatformSwiftSPMLicense

BookLayout Demo

A custom UICollectionView layout that creates a realistic book page-turning user interface effect.

Overview

This project contains a standalone implementation of a book-like page layout for iOS. The layout creates a 3D page-turning effect where pages flip like a real book, with proper shadows and perspective transforms.

Components

BookLayout

A custom UICollectionViewFlowLayout that handles the 3D transforms and page positioning.

Features:

  • Realistic 3D page turning effect
  • Configurable layout styles (centered or equal margins)
  • Automatic page sizing based on collection view bounds
  • Smooth scrolling with paging enabled
  • Left and right pages with proper anchor points
  • Customizable edge margins

BookPageModel

A data model representing a single page in the book.

Page Types:

  • .invisible - Hidden pages (used for proper book opening)
  • .blank - Empty white pages
  • .cover - Book cover with title and subtitle
  • .content(String) - Page with text content
  • .colored(UIColor) - Page with custom background color
  • .decorative(iconNames: [String], iconSize: CGFloat, spacing: CGFloat) - Decorative pattern page with SF Symbols arranged in a staggered diagonal grid

BookPageCell

A UICollectionViewCell that displays individual pages with:

  • Rounded corners
  • Dynamic shadows based on page position
  • Support for different page types
  • Proper anchor point handling for left/right pages

BookViewController

A view controller that manages the book's pages using the BookLayout.

Properties:

  • bookLayout: BookLayout? - Access to the underlying BookLayout for configuration
  • collectionView: UICollectionView - The collection view displaying the pages
  • delegate: BookViewControllerDelegate? - Delegate for page selection events

Methods:

  • setPages(_ pages: [BookPageModel], animated: Bool) - Set the book's pages
  • openToPage(at index: Int, animated: Bool) - Open to a specific page

Usage

Basic Setup

// Create the book view controller letbookViewController=BookViewController() bookViewController.delegate =self // Add it to your view hierarchy addChild(bookViewController) view.addSubview(bookViewController.view) bookViewController.didMove(toParent:self) // Create pages letpages:[BookPageModel]=[BookPageModel(pageType:.invisible),BookPageModel(pageType:.invisible),BookPageModel(pageType:.cover, title:"The Hacker's Manifesto", subtitle:"A Demo"),BookPageModel( pageType:.decorative( iconNames:["star.fill","heart.fill","circle.fill","square.fill"], iconSize:32, spacing:16)),BookPageModel(pageType:.content("Page 1"), subtitle:"First page content"),BookPageModel(pageType:.blank),BookPageModel(pageType:.colored(.systemBlue), title:"Blue Page"),BookPageModel(pageType:.blank)] // Set the pages bookViewController.setPages(pages, animated:false) // Open to a specific page bookViewController.openToPage(at:4, animated:true)

Layout Configuration

BookLayout supports two layout styles for positioning the book:

Classic Layout (Default)

bookViewController.bookLayout?.layoutStyle =.classic bookViewController.bookLayout?.edgeMargin =20 // Default is 20pt
  • Equal margins on both left and right sides
  • Spine positioned 20pt from the left edge
  • Right page edge positioned 20pt from the right edge
  • Ensures all content remains within screen bounds
  • Traditional, balanced book appearance

Centered Layout

bookViewController.bookLayout?.layoutStyle =.centered
  • Spine centered in the middle of the screen
  • Pages may extend beyond the screen edges
  • More immersive reading experience
  • Natural page-turning feel

Example:

letbookViewController=BookViewController() // Use classic layout with equal margins (default) bookViewController.bookLayout?.layoutStyle =.classic bookViewController.bookLayout?.edgeMargin =20 // Adjust as needed // Or use centered layout bookViewController.bookLayout?.layoutStyle =.centered

Page Turn Style

BookLayout supports two page turning styles that control how pages animate:

Elevated Style (Default)

bookViewController.bookLayout?.pageTurnStyle =.elevated
  • Pages rest with a subtle lift on the left edge
  • Creates a realistic book appearance where turned pages are slightly elevated
  • Smooth interpolation during page turns
  • More authentic physical book feel

Standard Style

bookViewController.bookLayout?.pageTurnStyle =.standard
  • Simple linear page turning animation
  • Pages lay completely flat when at rest
  • Cleaner, more minimalist appearance
  • Faster rendering with simpler transforms

Example:

letbookViewController=BookViewController() // Configure layout and page turn style bookViewController.bookLayout?.layoutStyle =.classic bookViewController.bookLayout?.pageTurnStyle =.elevated // Default // Or use standard turning for a simpler effect bookViewController.bookLayout?.pageTurnStyle =.standard

Understanding the Layout

The BookLayout works with a section-based collection view:

  • Each page is a separate section with 1 item
  • Even sections (0, 2, 4...) are right pages
  • Odd sections (1, 3, 5...) are left pages
  • Pages should always come in pairs for proper book effect

Page Structure

For a proper book effect, structure your pages like this:

  1. Two invisible pages (indices 0-1) - allows the book to start "closed"
  2. Cover page (right side, index 2)
  3. Blank or inside cover (left side, index 3)
  4. Content pages in pairs (right, left, right, left...)
  5. Back inside cover (last page)

Auto-Opening the Book

For a polished presentation effect, you can automatically open the book after a brief delay:

privatevarautoOpenTimer:Timer?privatefunc scheduleAutoOpen(){ // Only auto-open if the book is at the beginning (closed) guard bookViewController.collectionView.contentOffset.x <=0.0else{return} autoOpenTimer?.invalidate() autoOpenTimer =Timer.scheduledTimer(withTimeInterval:1.0, repeats:false){[weak self] _ inself?.autoOpenBook()}}privatefunc autoOpenBook(){ autoOpenTimer?.invalidate() autoOpenTimer =nil // Open to the first content page (after invisible pages and cover) bookViewController.openToPage(at:4, animated:true)} // Call after setting pages bookViewController.setPages(pages, animated:false)scheduleAutoOpen()

This creates a book-like presentation where the book starts closed and automatically opens after 1 second, similar to opening a physical book.

Demo

See Example/BookLayoutExample/ViewController.swift for a complete working example.

Installation

Swift Package Manager

Add BookLayout to your project using Swift Package Manager:

  1. In Xcode, select File > Add Package Dependencies
  2. Enter the repository URL: https://github.com/piemonte/BookLayout.git
  3. Select the version you want to use
  4. Add the BookLayout product to your target

Or add it to your Package.swift:

dependencies:[.package(url:"https://github.com/piemonte/BookLayout.git", from:"0.0.2")]

Manual Integration

To manually integrate these components into your project:

  1. Copy all .swift files from the Sources directory
  2. Add them to your Xcode project
  3. Use BookViewController in your view controller hierarchy
  4. Customize BookPageCell to fit your design needs

Example Project

An example iOS app is available in the Example directory. To run it:

Using XcodeGen (Recommended)

cd Example ./setup.sh open BookLayoutExample.xcodeproj

The setup script will install XcodeGen if needed and generate the Xcode project.

Manual Setup

If you prefer to set up manually:

  1. Install XcodeGen: brew install xcodegen
  2. Navigate to the Example directory
  3. Run xcodegen generate
  4. Open BookLayoutExample.xcodeproj in Xcode

See Example/README.md for more details.

Customization

Custom Page Types

Extend BookPageModel.PageType with your own page types:

publicenumPageType{case invisible case blank case cover case content(String)case colored(UIColor)case custom(MyCustomData) // Add your own }

Custom Cell Appearance

Modify BookPageCell.configure(with:) to customize how pages are displayed:

case .custom(let data): pageView.isHidden =false // Add your custom UI setup here

Layout Parameters

Adjust the page size calculation in BookLayout.collectionViewPageSize:

publicvarcollectionViewPageSize:CGSize{guardlet collectionView = collectionView else{return.zero } // Customize these values returnCGSize( width:(0.5* collectionView.bounds.width)-20, height: collectionView.bounds.height -50)}

Requirements

  • Swift 5.0+
  • UIKit

License

See original source files for copyright information.

Resources