본문 바로가기

iOS

[iOS, Crecker] ActionSheet,

https://github.com/dillidon/alerts-and-pickers

위와 같은 형태를 ActionSheet라고 하고, 저렇게 커스텀된 요소들이 있지만, 좀 더 커스텀이 되기를 원합니다.

예를 들면 이렇게 생겼습니다.

선택된 항목은 Bold도 되어야 하고, 배경도 흰색으로 꽉 채워야 합니다. 예쁘게 만들어 보겠습니다.

누르면 아래에서 위로 애니메이션 되며 뷰를 띄워줘야 합니다. 스토리보드로는 한계가 있습니다

(스토리보드로 이런거 어떻게 만들어야할지 사실 감이 잘 안오기도 합니다)

따라서 코드로 만들어 보았습니다. CollectionView를 사용하였습니다.

 

class Setting: NSObject {
    let name: SettingName
    
    init(name: SettingName) {
        self.name = name
    }
}

Setting에 필요한 객체를 미리 enum이나 Struct로 선언해서 보관해 두고 사용할 것입니다.

 

Swift File 이름은 SettingLauncher입니다.

아래 생성할 CollectionView가

이런 화면을 만들어낼 것입니다.

 

    let collectionView: UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
        // 빈 CollectionView 선언, 있다가 CellSize를 부여할 것
        cv.backgroundColor = UIColor.white
        return cv
    }()

CollectionView를 선언하고, 아래와 같이 사이즈를 줍니다. CellHeight는 50입니다.

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        let setting = self.settings[indexPath.item]
        handleDismiss(setting: setting)
        
    }
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return settings.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! SettingCell
        
        let setting = settings[indexPath.item]
        cell.setting = setting
        
        return cell
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: collectionView.frame.width, height: cellHeight)
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return 0
    }

 

또한, 코드로 구현한 Layout은 

    override init() {
        super.init()
        
        collectionView.dataSource = self
        collectionView.delegate = self
        
        collectionView.register(SettingCell.self, forCellWithReuseIdentifier: cellId)
    }

와 같이 register, datasource, delegate를 선언해주어야 합니다.

 

CollectionView를 만들었으니, 이제 Action을 추가하겠습니다. 

네비게이션 바의 버튼을 눌렀을 때, Action이 수행되도록 하겠습니다. 

 

func showSettings() {
        //show menu
        
        //        if let window = UIApplication.shared.keyWindow {
        // shard.keyWindow가 Deprecated 되었다고 합니닷 아래와 같이 사용
        
        if let window = UIApplication.shared.windows.first(where: { $0.isKeyWindow }) {
            
            blackView.backgroundColor = UIColor(white: 0, alpha: 0.5)
            blackView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleDismiss)))
            
            window.addSubview(blackView)				//@@1
            window.addSubview(collectionView)			//@@2
            
            let height: CGFloat = CGFloat(settings.count) * cellHeight
            let y = window.frame.height - height
            //  y : collectionView가 그려지는 시작 위치
            
            collectionView.frame = CGRect(x: 0, y: window.frame.height, width: window.frame.width, height: height)
            
            blackView.frame = window.frame
            blackView.alpha = 0
            
            UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
                
                self.blackView.alpha = 1
                self.collectionView.frame = CGRect(x:0, y: y, width: self.collectionView.frame.width, height: self.collectionView.frame.height)
                
            }, completion: nil)
        }
    }
    

 

showSettings()는 CollectionView를  addSubView()로 넣고,

BlackView라는 View는 배경을 어둡게 해주는 역할을 합니다. 이렇게 됩니다.

 

해당 배경이 Opacity가 있는 BlackView입니다. UIView.Animate()에서는 BlackView의 Alpha와,

CollectionView의 frame이 변경됨을 알 수 있습니다.

 

또한, showSetting()은 호출이 되어야 하는데, 어느 버튼에서나 Selector를 사용해서 호출해내면 됩니다.

저는 위에서 이야기한 바와 같이 NavigationItem의 Button을 이용할 것입니다.

 

NavigationBar는 원래 ViewController파일에 존재하므로, ( 제 경우 - HomeViewController )

HomeVC에서

   lazy var settingsLauncher: SettingsLauncher = {
        let launcher = SettingsLauncher()
        launcher.homeController = self
        return launcher
    }()
    

,

    func setupNavBarButtons() {
        
        let moreButton = UIBarButtonItem(image: UIImage(named: "nav_more_icon")?.withRenderingMode(.alwaysOriginal), style: .plain, target: self, action: #selector(handleMore))
        
        navigationItem.rightBarButtonItem = moreButton
    }
    
    @objc func handleMore() {
         settingsLauncher.showSettings()
     }

를 만들어주면, 버튼을 누를 경우 showSettings()가 실행이 됩니다.

완성!

 

 

전체 코드는 깃헙에 업로드!

감사합니다.

 

 

 

'iOS' 카테고리의 다른 글

[iOS] Calendar (1)  (0) 2020.04.25
[iOS] LinkPresentation  (0) 2020.04.18
[Crecker, iOS] PageViewController (android : ViewPager)  (2) 2020.04.04
[Crecker,iOS] Swift ViewPager 구성  (4) 2020.03.28
[iOS] 8주차) Coredata  (0) 2020.03.21