관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] UIButton 버튼 탭 애니메이션 구현 방법 (isHighlighted) 본문

iOS 응용 (swift)

[iOS - swift] UIButton 버튼 탭 애니메이션 구현 방법 (isHighlighted)

jake-kim 2022. 2. 20. 13:22

버튼을 탭한 경우 잠깐 버튼이 커지는 애니메이션

isHighlighted

  • 버튼을 눌렀을 때, isHighlighted = true로 변경되었다가, isHighlighted = false로 다시 변경

* isHighlighted 상태 확인 방법 - UIButton의 isHighlighted 프로퍼티를 override하여 didSet으로 확인

public protocol AnimationButtonDelegate: AnyObject {
  func didChangeHighlighted(highlighted: Bool)
}

class AnimationButton: UIButton {
  weak var delegate: AnimationButtonDelegate?
  override var isHighlighted: Bool {
    didSet { self.delegate?.didChangeHighlighted(highlighted: self.isHighlighted) }
  }
}

사용하는 쪽)

import UIKit

final class ViewController: UIViewController {
  private lazy var button: AnimationButton = {
    let button = AnimationButton()
    button.setTitle("버튼", for: .normal)
    button.setTitleColor(.systemBlue, for: .normal)
    return button
  }()
  
  override func viewDidLoad() {
    super.viewDidLoad()
    
    self.button.delegate = self
    self.view.addSubview(self.button)
    self.button.translatesAutoresizingMaskIntoConstraints = false
    self.button.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
    self.button.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
  }
}

extension ViewController: AnimationButtonDelegate {
  func didChangeHighlighted(highlighted: Bool) {
    print("isHighlighted = \(highlighted)")
  }
}

버튼을 누르면 isHighlighted상태가 true -> false로 변경

애니메이션 구현 아이디어

  • AnimationButton이라는 클래스에서 isHighlighted  프로퍼티를 override하여 didSet에서 위에서 정의한 delegate 실행
  • 다른 버튼들은 AnimationButton을 상속받아서, 이 버튼을 사용하면 애니메이션이 동작하도록 사용
    • AnimationButton 준비
      class AnimationButton: UIButton {
        override var isHighlighted: Bool {
          didSet { self.animateWhenHighlighted() }
        }
        
        private func animateWhenHighlighted() {
          
        }
      }​
  • animation 정의 - 버튼이 눌린 경우 잠깐 커졌다가, 다시 돌아오는 애니메이션 정의
  private enum Animation {
    typealias Element = (
      duration: TimeInterval,
      delay: TimeInterval,
      options: UIView.AnimationOptions,
      scale: CGAffineTransform,
      alpha: CGFloat
    )
    
    case touchDown
    case touchUp
    
    var element: Element {
      switch self {
      case .touchDown:
        return Element(
          duration: 0,
          delay: 0,
          options: .curveLinear,
          scale: .init(scaleX: 1.3, y: 1.3),
          alpha: 0.8
        )
      case .touchUp:
        return Element(
          duration: 0,
          delay: 0,
          options: .curveLinear,
          scale: .identity,
          alpha: 1
        )
      }
    }
  }
  • button highlighted에 따라 위 애니메이션을 사용 정의
    override var isHighlighted: Bool {
      didSet { self.animateWhenHighlighted() }
    }
    
    private func animateWhenHighlighted() {
      let animationElement = self.isHighlighted ? Animation.touchDown.element : Animation.touchUp.element
      
      UIView.animate(
        withDuration: animationElement.duration,
        delay: animationElement.delay,
        options: animationElement.options,
        animations: {
          self.transform = animationElement.scale
          self.alpha = animationElement.alpha
        }
      )
    }​

사용하는 쪽)

import UIKit

final class ViewController: UIViewController {
  private lazy var button: AnimationButton = {
    let button = AnimationButton()
    button.setImage(UIImage(named: "button"), for: .normal)
    button.layer.cornerRadius = 25
    button.layer.masksToBounds = true
    return button
  }()
  
  override func viewDidLoad() {
    super.viewDidLoad()
    
    self.view.addSubview(self.button)
    self.button.translatesAutoresizingMaskIntoConstraints = false
    self.button.widthAnchor.constraint(equalToConstant: 120).isActive = true
    self.button.heightAnchor.constraint(equalToConstant: 120).isActive = true
    
    self.button.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
    self.button.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
  }
}

* 전체 코드: https://github.com/JK0369/ExAnimationButton

Comments