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 |