훌이
후리스콜링개발
훌이

블로그 메뉴

  • 왈 (iOS APP)
  • Github
전체 방문자
오늘
어제
  • 전체 (171)
    • ⭐️ 개발 (140)
      • JAVA (4)
      • Web (5)
      • iOS & Swift (94)
      • iOS Concurrency (4)
      • Rx (18)
      • Git (6)
      • WWDC (1)
      • Code Refactor (3)
      • Server (1)
    • ⭐️ Computer Science (22)
      • 운영체제 (10)
      • 네트워크 (5)
      • PS (7)
    • 경제시사상식 (8)
    • 기타 등등 (0)

인기 글

최근 글

05-22 23:04

티스토리

hELLO · Designed By 정상우.
훌이

후리스콜링개발

[iOS] UIButton에 NSMutableAttributedString 적용해보기
⭐️ 개발/iOS & Swift

[iOS] UIButton에 NSMutableAttributedString 적용해보기

2021. 8. 4. 03:31
728x90
반응형

UIButton에 NSMutableAttributedString 적용해보기

 

 

 

오늘은 애플 기본 날씨앱의 위 사진과 같은 버튼을 만드는 방법에 대해 정리해보려고 합니다!

누르면 섭씨와 화씨로 온도를 바꿔주면서 버튼의 특정 부분의 색이 변하는 버튼입니다.

 

NSMutableAttributedString을 통해서 문자열의 특정 부분의 색상이나 폰트 등을 바꿔줄 수 있었는데

버튼도 이와 마찬가지입니다.

 

 


우선, 버튼 컴포넌트에 대한 코드부터 차례대로 봐봅시다.

* Then 라이브러리를 사용했습니다.

 

let switchButton = UIButton().then {
	// 버튼의 기본 특성 - 색상, 폰트, 동작
        $0.setTitleColor(.white, for: .normal)
        $0.titleLabel?.font = .systemFont(ofSize: 18, weight: .semibold)
        $0.addTarget(self, action: #selector(touchupSwitchButton(_:)), for: .touchUpInside)
        
        // 버튼 텍스트
        let buttonText = "℃ / ℉"
        let normalButtonText = NSMutableAttributedString(string: buttonText)
        normalButtonText.addAttribute(.foregroundColor, value: UIColor.lightGray, range: NSRange(location: 2, length: 3))
        let selectedButtonText = NSMutableAttributedString(string: buttonText)
        selectedButtonText.addAttribute(.foregroundColor, value: UIColor.lightGray, range: NSRange(location: 0, length: 3))
        
        $0.setAttributedTitle(normalButtonText, for: .normal)
        $0.setAttributedTitle(selectedButtonText, for: .selected)
}

 

 

1️⃣ 버튼이 normal 상태일 때의 색상과 폰트, 동작에 대한 코드입니다.

$0.setTitleColor(.white, for: .normal)
$0.titleLabel?.font = .systemFont(ofSize: 18, weight: .semibold)
$0.addTarget(self, action: #selector(touchupSwitchButton(_:)), for: .touchUpInside)

 

 

2️⃣ 버튼의 text 값을 입력해주고,

  • normalButtonText는 버튼이 normal 상태일 때 적용해줄 AttributedString 값을 상수로 선언해준 것입니다.
    • 기본 상태일 때는 섭씨 상태이기 때문에 [ / ℉ ] 부분을 lightGray로 설정해줄 겁니다.
    • NSRange(location: 2, length: 3) -> 문자열의 3번째 자리부터 3글자에 해당하는 범위

 

  • selectedButtonText는 버튼이 selected 상태일 때 적용해 줄 AttributedString 값을 상수로 선언해준 것이구요.
    • 선택한 상태일 때는 화씨 상태이기 때문에 [ ℃ / ] 부분을 lightGray로 설정해줍니다.
    • NSRange(location: 0, length: 3) -> 문자열의 1번째 자리부터 3글자에 해당하는 범위
let buttonText = "℃ / ℉"
let normalButtonText = NSMutableAttributedString(string: buttonText)
normalButtonText.addAttribute(.foregroundColor, value: UIColor.lightGray, range: NSRange(location: 2, length: 3))

let selectedButtonText = NSMutableAttributedString(string: buttonText)
selectedButtonText.addAttribute(.foregroundColor, value: UIColor.lightGray, range: NSRange(location: 0, length: 3))

 

 

 

3️⃣ 지금까지 normal / selected 일 때의 버튼 title을 설정해줬으니

실제로 버튼에 적용해주려면 setAttributedTitle(_: for: )을 사용하면 됩니다.

 

        $0.setAttributedTitle(normalButtonText, for: .normal)
        $0.setAttributedTitle(selectedButtonText, for: .selected)

 

 

4️⃣ 마지막으로 버튼의 동작 부분입니다. - addTarget 부분

    @objc func touchupSwitchButton(_ sender: UIButton) {
        if switchButton.isSelected {
            switchButton.isSelected = false
            print("섭씨 C")
            NotificationCenter.default.post(name: NSNotification.Name("changeUnitToC"), object: nil)
        } else {
            switchButton.isSelected = true
            print("화씨 F")
            NotificationCenter.default.post(name: NSNotification.Name("changeUnitToF"), object: nil)
        }
    }

 

기존 버튼은 selected 상태가 아닌 normal 상태이기 때문에 (즉, switchButton.isSelected == false 인 상태)

normalButtonText 인 상태로 버튼이 뜰 거고,

 

 

이 상태에서 버튼을 클릭해주면( = touch up inside) ,,

 

switchButton.isSelected = true 가 되어서 selectedButtonText가 될 겁니다

 

 

 

 


🔆 전체 코드

< 버튼이 있는 TableView FooterView 의 코드 >

//
//  ListFooterView.swift
//  AppleWeather_Clone
//
//  Created by Thisisme Hi on 2021/08/02.
//

import UIKit

class ListFooterView: UIView {
    // MARK: - Properties
    let switchButton = UIButton().then {
        $0.setTitleColor(.white, for: .normal)
        $0.titleLabel?.font = .systemFont(ofSize: 18, weight: .semibold)
        $0.addTarget(self, action: #selector(touchupSwitchButton(_:)), for: .touchUpInside)
        
        let buttonText = "℃ / ℉"
        let normalButtonText = NSMutableAttributedString(string: buttonText)
        normalButtonText.addAttribute(.foregroundColor, value: UIColor.lightGray, range: NSRange(location: 2, length: 3))
        let selectedButtonText = NSMutableAttributedString(string: buttonText)
        selectedButtonText.addAttribute(.foregroundColor, value: UIColor.lightGray, range: NSRange(location: 0, length: 3))
        
        $0.setAttributedTitle(normalButtonText, for: .normal)
        $0.setAttributedTitle(selectedButtonText, for: .selected)
    }
    
    let webButton = UIButton().then {
        $0.setImage(UIImage(named: "img_weather"), for: .normal)
        $0.tintColor = .white
    }
        
    let searchButton = UIButton().then {
        $0.setImage(UIImage(systemName: "magnifyingglass"), for: .normal)
        $0.tintColor = .white
    }
    
    // MARK: - Lifecycle
    override init(frame: CGRect) {
        super.init(frame: frame)
        configUI()
        setupAutoLayout()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    // MARK: - Custom Method
    func configUI() {
    }
    
    func setupAutoLayout() {
        addSubviews([switchButton, webButton, searchButton])
        
        switchButton.snp.makeConstraints { make in
            make.top.equalToSuperview().inset(10)
            make.leading.equalToSuperview().inset(20)
        }
        
        webButton.snp.makeConstraints { make in
            make.top.equalToSuperview().inset(15)
            make.centerX.equalToSuperview()
            make.width.height.equalTo(30)
        }

        searchButton.snp.makeConstraints { make in
            make.top.equalToSuperview().inset(15)
            make.trailing.equalToSuperview().inset(20)
        }
    }
    
    // MARK: - @objc
    @objc func touchupSwitchButton(_ sender: UIButton) {
        if switchButton.isSelected {
            switchButton.isSelected = false
            print("섭씨 C")
            NotificationCenter.default.post(name: NSNotification.Name("changeUnitToC"), object: nil)
        } else {
            switchButton.isSelected = true
            print("화씨 F")
            NotificationCenter.default.post(name: NSNotification.Name("changeUnitToF"), object: nil)
        }
    }
}

 

 

< TableViewCell의 TempLabel 바꿔주는 곳>

//
//  ListTVC.swift
//  AppleWeather_Clone
//
//  Created by Thisisme Hi on 2021/07/28.
//

import UIKit

import Then
import SnapKit

class ListTVC: UITableViewCell {
    static let identifier = "ListTVC"
    // MARK: - Properties
    let localLabel = UILabel().then { ///  나의 위치 첫 번째 cell
        $0.text = "마포구"
        $0.font = .systemFont(ofSize: 12, weight: .semibold)
        $0.textColor = .white
        $0.textAlignment = .left
    }
    
    let myLocalLabel = UILabel().then { ///  나의 위치 첫 번째 cell
        $0.text = "나의 위치"
        $0.font = .systemFont(ofSize: 22, weight: .semibold)
        $0.textColor = .white
        $0.textAlignment = .left
    }
    
    let tempLabel = UILabel().then {
        $0.text = "25"
        $0.font = .systemFont(ofSize: 60, weight: .regular)
        $0.textColor = .white
        $0.textAlignment = .left
    }
    
    let timeLabel = UILabel().then {
        $0.text = "오전 4:29"
        $0.font = .systemFont(ofSize: 12, weight: .semibold)
        $0.textColor = .white
        $0.textAlignment = .left
    }
    
    let countryLabel = UILabel().then {
        $0.text = "로스엔젤레스"
        $0.font = .systemFont(ofSize: 22, weight: .semibold)
        $0.textColor = .white
        $0.textAlignment = .left
    }
        
    // MARK: - Lifecycle
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        configUI()
        NotificationCenter.default.addObserver(self,
                                               selector: #selector(changeToC),
                                               name: NSNotification.Name("changeUnitToC"),
                                               object: nil)
        
        NotificationCenter.default.addObserver(self,
                                               selector: #selector(changeToF),
                                               name: NSNotification.Name("changeUnitToF"),
                                               object: nil)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
    }
    
    // MARK: - Custom Method
    func configUI() {
        localLabel.getShadow()
        myLocalLabel.getShadow()
        tempLabel.getShadow()
        timeLabel.getShadow()
        countryLabel.getShadow()
    }
    
    func setupFirstCellAutoLayout() { /// first cell
        addSubviews([localLabel, myLocalLabel, tempLabel])
        
        localLabel.snp.makeConstraints { make in
            make.leading.equalTo(20)
            make.bottom.equalTo(myLocalLabel.snp.top).offset(-1)
        }
        
        myLocalLabel.snp.makeConstraints { make in
            make.leading.equalTo(20)
            make.centerY.equalTo(tempLabel.snp.centerY)
        }
        
        tempLabel.snp.makeConstraints { make in
            make.trailing.equalToSuperview().inset(20)
            make.bottom.equalToSuperview().inset(5)
        }
    }
    
    func setupRemainCellAutoLayout() { /// 남은 cell들
        addSubviews([timeLabel, countryLabel, tempLabel])
        
        timeLabel.snp.makeConstraints { make in
            make.top.equalToSuperview().offset(15)
            make.leading.equalTo(20)
        }
        
        countryLabel.snp.makeConstraints { make in
            make.leading.equalTo(20)
            make.centerY.equalTo(tempLabel.snp.centerY)

        }
        
        tempLabel.snp.makeConstraints { make in
            make.trailing.equalToSuperview().inset(20)
            make.centerY.equalToSuperview()
        }
    }
    
    // MARK: - @objc
    @objc func changeToC(_ sender: Notification) {
        tempLabel.text = "\(5*(Int(tempLabel.text!)! - 32)/9)"
        print("F -> C")
    }
    
    @objc func changeToF(_ sender: Notification) {
        tempLabel.text = "\((9*(Int(tempLabel.text!)!)/5 + 32))"
        print("C -> F")
    }
}
728x90
반응형
저작자표시 비영리 변경금지 (새창열림)

'⭐️ 개발 > iOS & Swift' 카테고리의 다른 글

[iOS] MapKit 사용해서 위치 자동완성 검색 기능 구현해보기  (0) 2021.08.20
[iOS] Blur Effect 사용해보기  (2) 2021.08.05
[iOS] TableView 최상단 cell, safeArea 무시하고 배치하는 법?  (0) 2021.08.02
[iOS] 데이터 직접 전달 방식(4) - NotificationCenter을 통해 전달  (0) 2021.07.29
[iOS] NotificationCenter?  (0) 2021.07.29
    '⭐️ 개발/iOS & Swift' 카테고리의 다른 글
    • [iOS] MapKit 사용해서 위치 자동완성 검색 기능 구현해보기
    • [iOS] Blur Effect 사용해보기
    • [iOS] TableView 최상단 cell, safeArea 무시하고 배치하는 법?
    • [iOS] 데이터 직접 전달 방식(4) - NotificationCenter을 통해 전달
    훌이
    훌이

    티스토리툴바