[TIL] UIButton.Configuration

Eden·2025년 9월 18일

아래 코드는 UIButton.Configuration API(UIKit iOS 15+)로 “오늘” 버튼을 구성하는 예시다.
텍스트/아이콘/여백/배경/테두리/코너를 설정하고, 가로 압축 우선순위를 높여 잘림을 방지한다.

let todayButton = UIButton(type: .system).then { btn in
    var config = UIButton.Configuration.plain()
    config.baseForegroundColor = .primary600

    // 텍스트
    let title = Typography.attributed(
      "오늘",
      style: .labelMd(weight: .semibold),
      color: .primary600
    )
    config.attributedTitle = AttributedString(title)

    // 아이콘 (왼쪽)
    config.image = UIImage.rotateCcw.withRenderingMode(.alwaysTemplate)
    config.imagePlacement = .leading
    config.imagePadding = Metrics.todayImageSpacing

    // 바깥 여백
    config.contentInsets = .init(
      top: Metrics.todayVerticalPadding,
      leading: Metrics.todayHorizontalPadding,
      bottom: Metrics.todayVerticalPadding,
      trailing: Metrics.todayHorizontalPadding
    )

    // 배경/테두리/코너
    var bg = UIBackgroundConfiguration.clear()
    bg.backgroundColor = .primary100
    bg.strokeColor = .primary200
    bg.strokeWidth = 1
    bg.cornerRadius = 18
    config.background = bg

    btn.configuration = config

    // 잘림 방지
    btn.setContentCompressionResistancePriority(.required, for: .horizontal)
}

핵심 포인트

1) UIButton.Configuration.plain()

  • iOS 15+의 구성 기반 버튼 API.
  • .plain()은 최소한의 배경/레이아웃을 제공하고, 텍스트/아이콘/여백을 개발자가 설정한다.
  • btn.configuration = config로 최종 적용.

2) baseForegroundColor

  • 텍스트/아이콘의 전경색(tint 포함)을 일괄 지정.
  • 이미지가 withRenderingMode(.alwaysTemplate)일 때 색상이 적용된다.
  • tintColor를 따로 만지지 않아도 구성값이 우선 반영된다.

3) attributedTitle

  • Typography.attributed(...)로 만든 NSAttributedStringAttributedString으로 변환해 설정.
  • 폰트/굵기/색상 등 텍스트 스타일을 일관되게 관리.
  • 구성 기반 버튼에서는 setAttributedTitle 대신 config.attributedTitle을 사용.

4) 이미지 배치와 간격

  • config.image에 심볼/커스텀 이미지를 지정.
  • imagePlacement = .leading으로 아이콘을 텍스트 왼쪽에 배치.
  • imagePadding으로 아이콘–텍스트 간격을 제어.

5) contentInsets

  • 버튼 안쪽 패딩. 세로/가로 패딩을 Metric으로 관리해 일관성 유지.
  • 텍스트가 짧거나 길어져도 터치 타깃 크기를 일정하게 유지시켜 접근성에 유리.

6) UIBackgroundConfiguration

  • UIBackgroundConfiguration.clear()로 시작해 필요한 속성만 지정.
    • backgroundColor: 배경색
    • strokeColor, strokeWidth: 테두리
    • cornerRadius: 모서리 반경
  • 구성 기반에서는 layer.*보다 background 설정이 우선이며 상태별 자동 처리에 유리.

7) 잘림 방지: Compression Resistance

  • setContentCompressionResistancePriority(.required, .horizontal)가로 압축 저항을 최상으로 올려
    레이아웃 엔진이 다른 뷰를 먼저 줄이도록 유도.
  • StackView에서 버튼이 눌려 텍스트가 잘리는 상황을 줄여준다.

상태(Highlighted/Disabled) 대응 팁

구성 기반 버튼은 상태별 속성 오버라이드가 가능하다.

config.baseForegroundColor = .primary600
config.background.backgroundColor = .primary100

btn.configurationUpdateHandler = { button in
    guard var cfg = button.configuration else { return }
    switch button.state {
    case .highlighted:
        cfg.background?.backgroundColor = .primary200
    case .disabled:
        cfg.baseForegroundColor = .primary300
        cfg.background?.strokeColor = .primary200
    default:
        break
    }
    button.configuration = cfg
}
  • configurationUpdateHandler에서 button.state를 보고 색/테두리/알파 등을 조절.
  • isEnabled, isHighlighted, isSelected 조합도 처리 가능.

Dynamic Type / 길이 변화 대책

  • 텍스트가 길어질 수 있다면
    todayButton.titleLabel?.lineBreakMode = .byTruncatingTail
    todayButton.titleLabel?.adjustsFontForContentSizeCategory = true
  • 아이콘 크기 통일:
    todayButton.setPreferredSymbolConfiguration(
        .init(pointSize: 14, weight: .medium),
        forImageIn: .normal
    )
  • StackView 내에서는 spacer와 Hugging/Compression 우선순위를 함께 설계하면 흔들림을 방지할 수 있다.

대안 구성(분리 설정)

  • 텍스트/아이콘을 상태별로 분리 지정 가능:
    config.title = "오늘"
    config.subtitle = nil
  • filled/borderedTinted 같은 다른 프리셋 사용:
    var config = UIButton.Configuration.filled()
    config.baseBackgroundColor = .primary500
    config.baseForegroundColor = .white

체크리스트

  • iOS 15 이상에서 UIButton.Configuration 사용.
  • 아이콘에 template 렌더링을 적용해야 baseForegroundColor가 반영됨.
  • 배경/테두리는 UIBackgroundConfiguration에서 지정.
  • 레이아웃 흔들림은 Compression/Hugging 우선순위로 제어.
  • 상태 변화는 configurationUpdateHandler에서 일관 처리.

요약

  • 구성 기반 버튼으로 텍스트/아이콘/여백/배경/테두리를 한 곳에서 선언적으로 관리할 수 있다.
  • baseForegroundColorUIBackgroundConfiguration을 조합하면 디자인 시스템을 깔끔하게 반영할 수 있다.
  • StackView 환경에서는 가로 압축 저항을 높이고 spacer 전략을 쓰면 잘림과 흔들림을 줄일 수 있다.
profile
iOS Dev

0개의 댓글