[iOS] 나만의 Floating Button 띄우기

김상우·2022년 2월 3일
0
  • 외부 라이브러리를 사용하지 않고 Floating Button 을 구현해봤습니다.

뷰 화면 gif (2022.02.04)


업데이트한 화면 gif (+ 2022.02.19)

구현 과정

  • 가운데 십자 버튼을 누르면 3개의 플로팅 버튼이 등장하고, 다시 누르면 사라지도록 구현했습니다.
  • 플로팅 버튼 관련 라이브러리도 많이 사용되고, 보통은 Stack View 의 isHidden 속성을 활용해서도 많이 구현합니다. Stack View 의 isHidden 은 차곡차곡 쌓이는 것처럼 보이게 하기 때문입니다.
  • 하지만 저는 십자 버튼의 Super View 와 그 위의 image View 가 서로 constraint 가 걸려있기 때문에 Stack View 를 사용하기 까다로웠습니다. Stack 을 위로 열면 image View 도 같이 올라가 버렸기 때문에..
  • 그래서 관련 라이브러리를 사용하지 않고, 직접 필요 사항에 맞춰 구현해봤습니다.
  • imageView 의 super View 는 UIScrollView 였습니다. 확대 축소를 자유롭게 하기 위해서 입니다.
  • 그래서 UIScrollView 의 frameLayoutGuide 를 활용해서 imageView 아래쪽에 3개의 버튼을 구성했습니다. 진짜로 십자 버튼이 있는 뷰에서 위로 출몰하는게 아니라, imageView 에서 투명하게 숨겨뒀다가 십자 버튼을 누르면 선명하게 나타나는 것처럼 보이게 했습니다.
  • frameLayoutGuide 를 사용하면 UIScrollView 에서도 독립적으로 움직이지 않는 뷰를 구성할 수 있습니다.
  • Snapkit 제약조건 설정
floatingView.snp.makeConstraints { make in
            make.left.right.bottom.equalTo(imageSuperScrollView.frameLayoutGuide)
            make.height.equalTo(100)
        }

주의할 것 (alpha를 사용할 때)

  • 버튼들을 담을 투명한 뷰를 floatingView 라고 이름지었습니다. 뷰를 생성할 때 주의점은 view. alpha = 1.0 으로 코드를 짜면 안된다는 겁니다.
let floatingView: UIStackView  = {
	let view = UIStackView()
  	// 이렇게 하면 안됨 !
    view.alpha = 1.0
  	// ...
    return view
}()

-> view.alpha = 1.0 으로 선언하면, 그 뷰에 담긴 객체들도 모두 투명하게 처리하기 때문입니다.

그래서 이렇게 코드를 짜는게 좋습니다.

let floatingView: UIStackView = {
  	let view = UIStackView()
	// 이렇게 합시다 :)
  	view.backgroundColor = UIColor(white: 1, alpha: 0)
  	// ...
  	return view
}()

이렇게 하면 배경이 되는 floatingView 는 투명하게 되고, button 들도 제대로 보이게 됩니다.


버튼 무빙 애니메이션 효과

  • 애니메이션 효과는 UIView.animate() 을 사용했습니다.
// 십자 플로팅 버튼
    @IBAction func tapBottomMiddleButton(_ sender: UIButton) {
        let gap = self.floatingLeftView.frame.width
        
        // 버튼들이 플로팅 되지 않은 상태이고, 움직이고 있지 않다면
        if !areButtonsFloated && !areButtonsMoving {
            areButtonsMoving = true
            
            // copyButton
            self.copyButton.alpha = 0
            self.copyButton.transform = CGAffineTransform(translationX: +gap, y: 0)
            UIView.animate(withDuration: 0.1) {
                self.copyButton.transform = CGAffineTransform(translationX: +(gap/2), y: 0)
            }
            UIView.animate(withDuration: 0.3) {
                self.copyButton.alpha = 1
                self.copyButton.transform = CGAffineTransform(translationX: 0, y: 0)
            }
            
            // wifiButton
            self.wifiButton.alpha = 0
            self.wifiButton.transform = CGAffineTransform(translationX: 0, y: +100)
            UIView.animate(withDuration: 0.3) {
                self.wifiButton.alpha = 1
                self.wifiButton.transform = CGAffineTransform(translationX: 0, y: 0)
            }
            
            // shareButton

            self.shareButton.alpha = 0
            self.shareButton.transform = CGAffineTransform(translationX: -gap, y: 0)
            UIView.animate(withDuration: 0.1) {
                self.shareButton.transform = CGAffineTransform(translationX: -(gap/2), y: 0)
            }
            UIView.animate(withDuration: 0.3, animations: {
                self.shareButton.alpha = 1
                self.shareButton.transform = CGAffineTransform(translationX: 0, y: 0)
            }, completion: { finished in
                self.areButtonsFloated = true
                self.areButtonsMoving = false
            })
        }
        
        // 버튼들이 플로팅 되어있고, 움직이고 있지 않다면
        else if areButtonsFloated && !areButtonsMoving {
            areButtonsMoving = true
            
            // copyButton
            UIView.animate(withDuration: 0.1) {
                self.copyButton.transform = CGAffineTransform(translationX: +(gap/2), y: 0)
            }
            UIView.animate(withDuration: 0.3) {
                self.copyButton.alpha = 0
                self.copyButton.transform = CGAffineTransform(translationX: +(gap), y: 0)
            }
            
            // wifiButton
            UIView.animate(withDuration: 0.3) {
                self.wifiButton.alpha = 0
                self.wifiButton.transform = CGAffineTransform(translationX: 0, y: +100)
            }
            
            // shareButton
            UIView.animate(withDuration: 0.1) {
                self.shareButton.transform = CGAffineTransform(translationX: -(gap/2), y: 0)
            }
            UIView.animate(withDuration: 0.3, animations: {
                self.shareButton.alpha = 0
                self.shareButton.transform = CGAffineTransform(translationX: -(gap), y: 0)
            }, completion: { finished in
                self.areButtonsFloated = false
                self.areButtonsMoving = false
            })
            
        }
        
    }
profile
안녕하세요, iOS 와 알고리즘에 대한 글을 씁니다.

0개의 댓글