태그: Swift, UIAlertController
- This topic has 4개 답변, 3명 참여, and was last updated 4 years, 7 months 전에 by 야곰.
-
글쓴이글
-
-
lidium참가자
- 글작성 : 9
- 답글작성 : 8
저번시간 PageViewController에 이어, 이번에는 UIAlertController와 같은 뷰를 구현하려 합니다.
위와 같은 형태를 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) window.addSubview(collectionView) 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()
에서는 BlackView와 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()가 실행이 됩니다.
후기를 써보자면…
저번에도 CollectionView로 만들었는데, 이번 뷰 커스텀을 하며 느낀 점은
컬렉션뷰는 생각보다 다재다능하고 여러군데에 사용이 가능하지만,
본래 목적에 가장 잘 어울린다는 점이기도 합니다(..)
이상입니다. 감사합니다!2020-04-17 오전 1:37 #6892 -
-
-
-
글쓴이글
- 답변은 로그인 후 가능합니다.