// // No comments for you. // It was hard to write, // so it should be hard to read. // // @author Mathias af Jochnick // @created on 2025-10-29 import UIKit class ViewController: UIViewController { var view1: UIView! var view2: UIView! var currentView: UIView! var button1: UIButton! var button2: UIButton! var tableView: UITableView! var gradientLayer: CAGradientLayer! var label1: UILabel! var label2: UILabel! override func viewDidLoad() { super.viewDidLoad() setupViews() setupView1() setupView2() currentView = view1 view.addSubview(view1) } override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() view1.frame = view.bounds view2.frame = view.bounds gradientLayer.frame = view2.bounds } func setupViews() { view1 = UIView() view2 = UIView() view1.backgroundColor = .systemBackground view2.backgroundColor = .systemBackground view1.frame = view.bounds view2.frame = view.bounds } func setupView1() { tableView = UITableView() tableView.delegate = self tableView.dataSource = self tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell") tableView.translatesAutoresizingMaskIntoConstraints = false view1.addSubview(tableView) button1 = UIButton(type: .system) button1.setTitle("Flip to View 2", for: .normal) button1.titleLabel?.font = .systemFont(ofSize: 20) button1.backgroundColor = .systemBlue button1.setTitleColor(.white, for: .normal) button1.layer.cornerRadius = 8 button1.addTarget(self, action: #selector(flipToView2), for: .touchUpInside) button1.translatesAutoresizingMaskIntoConstraints = false view1.addSubview(button1) NSLayoutConstraint.activate([ tableView.topAnchor.constraint(equalTo: view1.safeAreaLayoutGuide.topAnchor), tableView.leadingAnchor.constraint(equalTo: view1.leadingAnchor), tableView.trailingAnchor.constraint(equalTo: view1.trailingAnchor), tableView.bottomAnchor.constraint(equalTo: button1.topAnchor, constant: -20), button1.leadingAnchor.constraint(equalTo: view1.leadingAnchor, constant: 20), button1.trailingAnchor.constraint(equalTo: view1.trailingAnchor, constant: -20), button1.bottomAnchor.constraint(equalTo: view1.safeAreaLayoutGuide.bottomAnchor, constant: -20), button1.heightAnchor.constraint(equalToConstant: 50) ]) } func setupView2() { gradientLayer = CAGradientLayer() gradientLayer.colors = [ UIColor.systemPurple.cgColor, UIColor.systemPink.cgColor, UIColor.systemOrange.cgColor ] gradientLayer.locations = [0.0, 0.5, 1.0] gradientLayer.startPoint = CGPoint(x: 0, y: 0) gradientLayer.endPoint = CGPoint(x: 1, y: 1) view2.layer.insertSublayer(gradientLayer, at: 0) label1 = UILabel() label1.text = "Gradient View" label1.font = .boldSystemFont(ofSize: 32) label1.textColor = .white label1.textAlignment = .center label1.translatesAutoresizingMaskIntoConstraints = false view2.addSubview(label1) label2 = UILabel() label2.text = "This is some sample text to see if the flip animation is centered properly" label2.font = .systemFont(ofSize: 18) label2.textColor = .white label2.textAlignment = .center label2.numberOfLines = 0 label2.translatesAutoresizingMaskIntoConstraints = false view2.addSubview(label2) button2 = UIButton(type: .system) button2.setTitle("Flip to View 1", for: .normal) button2.titleLabel?.font = .systemFont(ofSize: 20) button2.backgroundColor = .systemGreen button2.setTitleColor(.white, for: .normal) button2.layer.cornerRadius = 8 button2.addTarget(self, action: #selector(flipToView1), for: .touchUpInside) button2.translatesAutoresizingMaskIntoConstraints = false view2.addSubview(button2) NSLayoutConstraint.activate([ label1.centerXAnchor.constraint(equalTo: view2.centerXAnchor), label1.centerYAnchor.constraint(equalTo: view2.centerYAnchor, constant: -60), label2.centerXAnchor.constraint(equalTo: view2.centerXAnchor), label2.topAnchor.constraint(equalTo: label1.bottomAnchor, constant: 30), label2.leadingAnchor.constraint(equalTo: view2.leadingAnchor, constant: 40), label2.trailingAnchor.constraint(equalTo: view2.trailingAnchor, constant: -40), button2.leadingAnchor.constraint(equalTo: view2.leadingAnchor, constant: 20), button2.trailingAnchor.constraint(equalTo: view2.trailingAnchor, constant: -20), button2.bottomAnchor.constraint(equalTo: view2.safeAreaLayoutGuide.bottomAnchor, constant: -20), button2.heightAnchor.constraint(equalToConstant: 50) ]) } @objc func flipToView2() { view.addSubview(view2) UIView.transition(from: currentView, to: view2, duration: 0.5, options: .transitionFlipFromRight, completion: nil) currentView = view2 } @objc func flipToView1() { view.addSubview(view1) UIView.transition(from: currentView, to: view1, duration: 0.5, options: .transitionFlipFromRight, completion: nil) currentView = view1 } } extension ViewController: UITableViewDelegate, UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 50 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) cell.textLabel?.text = "Row \(indexPath.row + 1): Lorem ipsum dolor sit amet, consectetur adipiscing elit" cell.textLabel?.numberOfLines = 0 return cell } }