궁금한 내용을 검색해보세요!
이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.
서근 개발노트
티스토리에 팔로잉
SWIFTUI/Others

SwiftUI : Mask

서근
QUOTE THE DAY

“ 당신의 컴퓨터에서 돌아가는 건 중요하지 않다. 당신의 컴퓨터로 서비스하는 게 아니기 때문이다. ”

- 비디우 플라톤 (Vidiu Platon)
Written by SeogunSEOGUN

목차

SwiftUI : Mask

Mask

SwiftUI에서는 mask()수정자를 사용하여 이미지 또는 텍스트를 마스크 할 수 있습니다.

 

간단한 예제를 보면서 어떻게 사용할 수 있는지 알아보도록 할게요.

swift
UNFOLDED
VStack {
Image("sample2")
.resizable()
.aspectRatio(contentMode: .fit)
.mask(
ZStack {
Circle()
.frame(width: 208, height: 208)
Circle()
.frame(width: 90, height: 90)
.offset(x: 80, y: 55)
}
)
.frame(maxHeight: .infinity)
}

SwiftUI : Mask - Mask

이제 mask를 활용해서 평점을 줄 수 있는 버튼을 하나 만들어 줄까 해요.

 

우선 별이 5개인 뷰를 만들어줍니다.

swift
UNFOLDED
import SwiftUI
struct maskView: View {
var body: some View {
ZStack {
starsView
}
}
private var starsView: some View {
HStack {
ForEach(1..<6) { star in
Image(systemName: "star.fill")
.foregroundColor(.gray)
}
}
}
}

그리고 starsViewoverlaymask를 사용하여 회색인 별을 노란색으로 채워주겠습니다.

swift
UNFOLDED
ZStack {
starsView
.overlay(
GeometryReader { geo in
Rectangle()
.fill(Color.yellow)
.mask(starsView)
}
)
}

이제 frame을 적용해서 숫자가 올라갈수록 rectangleframe넓이도 바뀔 수 있도록 구현해줘야 합니다.

 

@State 속성을 사용하여 rating0으로 설정해줍니다.

swift
UNFOLDED
struct maskView: View {
@State var rating: Int = 1
var body: some View {
ZStack {
starsView
.overlay(
GeometryReader { geo in
ZStack(alignment: .leading) {
Rectangle()
.foregroundColor(.yellow)
.frame(width: CGFloat(rating) / 5 * geo.size.width)
}
}
)
}
}

@Staterating값을 하나씩 올려보면 별의 색도 채워지는 것을 확인할 수 있습니다. 그리고 overlay뷰를 생성하고 위에 있는 코드를 옮겨줍니다.

swift
UNFOLDED
var body: some View {
ZStack {
starsView
.overlay(
overlayView
)
}
}
private var overlayView: some View {
GeometryReader { geo in
ZStack(alignment: .leading) {
Rectangle()
.foregroundColor(.yellow)
.frame(width: CGFloat(rating) / 5 * geo.size.width)
}
}
}

overlayView아래 mask를 적용해볼게요.

swift
UNFOLDED
.overlay(
overlayView
.mask(starsView)
)

SwiftUI : Mask - Mask

자, 그럼 starsView로 돌아가서 버튼을 눌렀을 때마다 별이 채워질 수 있도록해줘야겠죠? foregroundColor아래 onTapGesture을 추가해줍니다.

swift
UNFOLDED
private var starsView: some View {
HStack {
ForEach(1..<6) { star in
Image(systemName: "star.fill")
.foregroundColor(.gray)
.onTapGesture {
rating = star
}
}
}
}

withAnimation을 사용하면 더 보기 좋아집니다.

swift
UNFOLDED
.onTapGesture {
withAnimation(.easeInOut(duration: 0.3)) {
rating = star
}
}

그런데 한 가지 문제가 있습니다.

 

별 한 개 에서 -> 다섯 개로 높아질 때는 정상적으로 클릭이 가능한데, 5에서 4로 내리면 클릭이 되지를 않습니다.

 

이유는 우리는 지금 overlayView를 클릭하고 있기 때문입니다.

 

onTapGesturestarsView에 줬는데 말이죠. 이럴 때는 overlayView.allowsHitTesting(false)를 할당해주면 완벽히 해결됩니다.

swift
UNFOLDED
private var overlayView: some View {
GeometryReader { geo in
ZStack(alignment: .leading) {
Rectangle()
.foregroundColor(.yellow)
.frame(width: CGFloat(rating) / 5 * geo.size.width)
}
}
.allowsHitTesting(false)
}

SwiftUI : Mask - Mask

이제 앱을 닫았을 때도 평점이 저장될 수 있도록 UserDefaults를 한번 사용해볼게요.

 

starsViewonTapGestire아래에 다음과 같이 userDefaults를 추가합니다.

swift
UNFOLDED
private var starsView: some View {
HStack {
ForEach(1..<6) { star in
Image(systemName: "star.fill")
.foregroundColor(.gray)
.onTapGesture {
withAnimation(.easeInOut(duration: 0.3)) {
rating = star
UserDefaults.standard.setValue(rating, forKey: "rating_key")
}
}
}
}
}

그리고 @State도 아래와 같이 수정합니다.

swift
UNFOLDED
  @State var rating: Int = UserDefaults.standard.integer(forKey: "rating_key")

자 이렇게 앱을 종료 후 재 시작을 해도 부여해줬던 평점이 그대로 저장된 것을 확인할 수 있습니다.

swift
UNFOLDED
import SwiftUI
struct maskView: View {
@State var rating: Int = UserDefaults.standard.integer(forKey: "rating_key")
var body: some View {
ZStack {
starsView.overlay(overlayView.mask(starsView))
}
}
private var overlayView: some View {
GeometryReader { geo in
ZStack(alignment: .leading) {
Rectangle()
.foregroundColor(.yellow)
.frame(width: CGFloat(rating) / 5 * geo.size.width)
}
}
.allowsHitTesting(false)
}
private var starsView: some View {
HStack {
ForEach(1..<6) { star in
Image(systemName: "star.fill")
.foregroundColor(.gray)
.onTapGesture {
withAnimation(.easeInOut(duration: 0.3)) {
rating = star
UserDefaults.standard.setValue(rating, forKey: "rating_key")
}
}
}
}
}
}

이미지도 추가해볼게요.

전체 코드

swift
FOLDED

SwiftUI : Mask - Mask - 전체 코드

 

읽어주셔서 감사합니다🤟

 

본 게시글의 전체 코드 GitHub 👇🏻

 

Seogun95/SwiftUI_ContinuedLearning

SwiftUI 고급 기능 튜토리얼. Contribute to Seogun95/SwiftUI_ContinuedLearning development by creating an account on GitHub....

github.com

 

 


잘못된 내용이 있으면 언제든 피드백 부탁드립니다.


서근


위처럼 이미지 와 함께 댓글을 작성할 수 있습니다.