Main page by calculation & delegate

Dark Mode

Getting finished with login & sign up, we started to develop the main page of our app. We planned to show main page even though user is not logined. Because we thought this method can appeal our apps to users. So we disconnected our login module from splash view and connected main view controller to splash view.

        let storyboard = UIStoryboard(name: "Master", bundle: nil).instantiateViewController(withIdentifier: "TabBarController") as! UITabBarController
        let nextViewController = storyboard
        window?.rootViewController = nextViewController

And as we planned our basic app structure as tab-bar, we embedded tab-bar to main view controller and connected other reference storyboards to the tabs. To make it simple, I’ll show you the image of how our storyboard looks like.

Coming back to main page of our app ‘Explog’, we thought to benchmark ‘Kakao place’ which is made by one of the biggest IT company in Korea. They have a look like this.

We thought that it has two scroll-views and each scroll-view has some elements like table-view or images. We started to try developing as our thought. I had hard time figuring out fundamentals of the ‘benchmarking page’. But as a result, we succeeded to make something similar to Kakao place. It looks like this.

And the code is like this.

//
//  ViewController.swift
//  Test
//
//  Created by developer on 2017. 12. 1..
//  Copyright © 2017년 becomingmacker. All rights reserved.
//

import UIKit

class MainViewController: UIViewController
{
    @IBOutlet weak var topScrollView: UIScrollView!
    @IBOutlet weak var bottomScrollView: UIScrollView!
    
    var images : [UIImage] = [#imageLiteral(resourceName: "Asia"), #imageLiteral(resourceName: "Europe"), #imageLiteral(resourceName: "South America"), #imageLiteral(resourceName: "North America"), #imageLiteral(resourceName: "Austrailia"), #imageLiteral(resourceName: "Africa")]
    var currentIndex: Int = 0
    var tableViews: [UITableView] = []
    
    override func viewDidLoad()
    {
        super.viewDidLoad()
        
        topScrollView.delegate = self
        topScrollView.decelerationRate = UIScrollViewDecelerationRateFast
        
        bottomScrollView.delegate = self
        bottomScrollView.decelerationRate = UIScrollViewDecelerationRateFast
        
    }
    
    override func viewDidLayoutSubviews()
    {
        super.viewDidLayoutSubviews()
        print("\(#function)")
        makeContinentsSelection()
        makeContinentTableView()
        
        for num in 0..<6
        {
            tableViews[num].delegate = self
            tableViews[num].dataSource = self
//            tableViews[num].rowHeight = 400
//            tableViews[num].estimatedRowHeight = 250
            tableViews[num].register(UINib.init(nibName: "CustomTableViewCell", bundle: nil), forCellReuseIdentifier: "cell")
        }
    }
    
    func makeContinentsSelection()
    {
        var contentWidth: CGFloat = self.topScrollView.frame.width / 2
        
        for num in 0..<6
        {
            let imageContinents = UIImageView()
            imageContinents.clipsToBounds = true
            topScrollView.addSubview(imageContinents)
            imageContinents.image = images[num]
            
            let scrollViewWidth = self.topScrollView.frame.width
            contentWidth += scrollViewWidth / 2
            
            let newX = scrollViewWidth / 2 + (scrollViewWidth / 2 * CGFloat(num))
            imageContinents.frame = CGRect(x: newX - 75, y: (self.topScrollView.frame.height / 2) - 75, width: 150, height: 150)
        }
        
        topScrollView.clipsToBounds = false
        topScrollView.contentSize = CGSize(width: contentWidth, height: self.view.frame.height * 0.3)
    }
    
    func makeContinentTableView()
    {
        var contentWidth: CGFloat = 0
        
        for num in 0..<6
        {
            let tableView: UITableView = UITableView()
            tableViews.append(tableView)
            bottomScrollView.addSubview(tableView)
            
            let scrollViewWidth = self.bottomScrollView.frame.width
            contentWidth += scrollViewWidth
            
            let newX: CGFloat = scrollViewWidth * CGFloat(num)
            tableView.frame = CGRect(x: newX, y: 0, width: self.bottomScrollView.frame.width, height: self.bottomScrollView.frame.height)
        }
        
        bottomScrollView.contentSize = CGSize(width: contentWidth, height: self.bottomScrollView.frame.height)
    }
}

extension MainViewController: UIScrollViewDelegate
{
    // Custom scrollview paging
    
    func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>)
    {
        if scrollView === topScrollView
        {
            let pageWidth = self.topScrollView.frame.width / 2
            let pageIndex = Int(targetContentOffset.pointee.x / pageWidth + 0.5)
            
            currentIndex = pageIndex
            
            DispatchQueue.main.async {
                self.topCustomPaging()
            }
        } else if scrollView == bottomScrollView
        {
            let pageWidth = self.bottomScrollView.frame.width
            let pageIndex = Int(targetContentOffset.pointee.x / pageWidth + 0.5)
            
            currentIndex = pageIndex
            
            DispatchQueue.main.async {
                self.bottomCustomPaging()
            }
        }
    }
    
    func topCustomPaging()
    {
        let newOffset = CGPoint(x: topGetNewOffsetX(), y: 0)
        self.topScrollView.setContentOffset(newOffset, animated: true)
    }
    
    func topGetNewOffsetX() -> CGFloat
    {
        let pageWidth = self.topScrollView.frame.width * 0.5
        
        return pageWidth * CGFloat(currentIndex)
    }
    
    func bottomCustomPaging()
    {
        let newOffset = CGPoint(x: bottomGetNewOffsetX(), y: 0)
        self.bottomScrollView.setContentOffset(newOffset, animated: true)
    }

    func bottomGetNewOffsetX() -> CGFloat
    {
        let pageWidth = self.bottomScrollView.frame.width

        return pageWidth * CGFloat(currentIndex)
    }
    
    
    // topScrollView, bottomScrollView scrolling together
    
    func scrollViewDidScroll(_ scrollView: UIScrollView)
    {
        if scrollView === topScrollView
        {
            self.upperDidScrolled()
        }
        else if scrollView === bottomScrollView
        {
            self.bottomDidScrolled()
        }
    }

    func upperDidScrolled()
    {
        let ratio = self.bottomScrollView.frame.width / (self.topScrollView.frame.width / 2)
        bottomScrollView.contentOffset = CGPoint(x: topScrollView.contentOffset.x * ratio, y: bottomScrollView.contentOffset.y)
    }

    func bottomDidScrolled()
    {
        let ratio = (self.topScrollView.frame.width / 2) / self.bottomScrollView.frame.width
        topScrollView.contentOffset = CGPoint(x: bottomScrollView.contentOffset.x * ratio, y: topScrollView.contentOffset.y)
    }
}

extension MainViewController: UITableViewDelegate, UITableViewDataSource
{
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
    {
        return 10
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
    {
        let cell = tableViews[currentIndex].dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CustomTableViewCell
        
        return cell
    }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat 
    {
        return UITableViewAutomaticDimension
    }
}

I used some advanced calculation and scroll-view, table-view delegates to embody it. Some hard parts of developing this is to selecting the position of each elements responsively by calculation. Also it needs delegate methods of scroll-view and table-view to act in real-time.

댓글

Please enter your comment!
Please enter your name here