Topic:
- pre/next ๋ฒํผ์ผ๋ก ์ด๋ฏธ์ง ์ฌ๋ผ์ด๋ ์๋
- ์ด๋ฏธ์ง ์ฌ๋ผ์ด๋
- tapGesture๋ก ๋ฒํผ ์จ๊ธฐ๊ธฐ ๋ฐ ๋๋ฌ๋ด๊ธฐ
- ์ธ๋ฑ์ค ๋๋ฒ์ ๋ฐ๋ผ ์ฒซ๋ฒ์งธ์ ๋ง์ง๋ง ์ธ๋ฑ์ค ์ผ ๋ next ๋๋ pre ๋ฒํผ ์จ๊ธฐ๊ธฐ
์ ๊ทผ:
- ์ด๋ฏธ์ง ์ฌ๋ผ์ด๋์ ๋ค์ด์ฌ ์ด๋ฏธ์ง ๋ฐฐ์ด์ ๋ง๋ค์ด์ tabView์ forEach๋ฅผ ํ์ฉํด์ผ๊ฒ ๋ค๊ณ ์๊ฐํ๋ค.
// ํ
์คํธ์ฉ ์ด๋ฏธ์ง๋ฐฐ์ด
private var images: [String] = [
"image1",
"image2",
"image3",
"image4"
]
ํ ์คํธ์ฉ์ผ๋ก ๋ฃ์ด๋ ์ด๋ฏธ์ง๋ก ํ์ธํ ์์ ์ด๋ผ, ์ด๋ฏธ์ง ๋ฐฐ์ด์ UIKit๊ณผ ๋๊ฐ์ด ๋ง๋ค์๋ค.
- tabView๋ฅผ ์จ์ ์ฌ๋ผ์ด๋๋ฅผ ๋ง๋ค์๋๋ฐ, ์ด๋ฏธ์ง ๊ฐ์์ ๋ฐ๋ผ ๋ฒํผ์ ๋ํ๋ด์ผํ๋ค๊ฑฐ๋, ์ด๋ฏธ์ง ๊ฐ์๋ฅผ ๋ํ๋ด์ผํ๋ค๊ฑฐ๋ ํ๊ธฐ ๋๋ฌธ์ ์ธ๋ฑ์ค๋ฅผ ์ผ๋ฐ ๋ณ์๊ฐ ์๋ @State๋ก ์์ฑํ๋ค.
- ๊ทธ๋ฆฌ๊ณ ์ด๋ฏธ์ง ๋ฐ์์ค๋ ์์ ๋ฑ์ ํ์คํ ํ๊ณ ์ถ์ด์ tag๋ก ์ธ๋ฑ์ค๋ฅผ ๋ฐ์๋ค.
struct MainGuideView: View {
// ํ
์คํธ์ฉ ์ด๋ฏธ์ง๋ฐฐ์ด
private var images: [String] = [
"image1",
"image2",
"image3",
"image4"
]
// ์ด๋ฏธ์ง์ฌ๋ผ์ด๋ ์ธ๋ฑ์ค
@State private var index: Int = 0
var body: some View {
ZStack {
// MARK: - ์ด๋ฏธ์ง (๋ฐฐ๋)
VStack {
TabView(selection: $index) {
ForEach(0..<images.count, id: \.self) { index in
Image(images[index])
.resizable()
.aspectRatio(contentMode: .fit)
.frame(
width: UIScreen.main.bounds.width,
height: 500,
alignment: .center
)
.clipped()
.cornerRadius(16)
.tag(index)
}
}
.tabViewStyle(
PageTabViewStyle(
indexDisplayMode: .never
)
)
} // Vstak
} // * Body
} // * View
- ๊ธฐํ์ ๊ธฐ์ค, ๋ฐฐ๋ ์ด๋ฏธ์ง๋ฅผ ํญํ์ ๋ ์ข์ฐ ๋ฒํผ์ด ๋์์ผ ํ๊ธฐ ๋๋ฌธ์, ์ก์ ์ ๊ฐ์งํ๋ ๋ณ์๋ฅผ ๋ @State์ผ๋ก ์ ์ธํ๋ค.
// ์ฌ์ฉ์ ๋ฐฐ๋ ํญ์ก์
๊ฐ์ง
@State private var isTapped: Bool = false
// ๋ฐฐ๋ ํญ ์ ์ข์ฐ๋ฒํผ + ์์ธํ๋ณด๊ธฐ ๋ฒํผ show
.onTapGesture {
isTapped.toggle()
}
onTapGesture๊ฐ UIKit์ tapGesutre ๋ฐ๋ ๊ฑฐ๋ ๋๊ฐ์์, ๊ฑฐ๊ธฐ์ ์ฌ์ฉ์ ์ก์ ๊ฐ์ง๋ฅผ ์ํ ๋ณ์๋ฅผ ํ ๊ธ ์ฒ๋ฆฌ ํด์ฃผ์๋ค.
- ์ธ๋ฑ์ค๋ฅผ ํ์ฉํด์ ์ธ๋ฑ์ค๊ฐ 0์ผ๋์ ๋ง์ง๋ง์ผ ๋, ๊ฐ๊ฐ ์ผ์ชฝ ๋๋ ์ค๋ฅธ์ชฝ ๋ฒํผ์ ์จ๊ฒจ์ฃผ์ด์ผ ํด์ ๊ทธ๋ถ๋ถ์ ์๋์ ๊ฐ์ด ์ฒ๋ฆฌํ๋ค.
- ๊ทธ๋ฆฌ๊ณ pre/next ๋ฒํผ์ ํญํ๋ฉด ์ด๋ฏธ์ง๊ฐ ์ธ๋ฑ์ค์ ๋ง๊ฒ ๋ฐ๋์ด์ผํด์ action์ ๊ทธ์ ๋ํ ์ฝ๋.
// MARK: - Buttons (pre/next)
/// ๋ฐฐ๋ ํญ ํ๋ฉด ๋ฑ์ฅ
if isTapped{
HStack {
/// ์ธ๋ฑ์ค ๋ฒํธ์ ๋ฐ๋ผ ์ข์ฐ ๋ฒํผ ์จ๊น
/// pre button
if index > 0 {
Button(action: {
if index > 0 {
index -= 1
}
}) {
Image(.ic32ArrowBack2)
.frame(width: 32, height: 32)
}
}
Spacer()
/// next button
if index < images.count - 1 {
Button(action: {
if index < images.count - 1 {
index += 1
}
}) {
Image(.ic32ArrowBack2)
.rotationEffect(.degrees(-180))
.frame(width: 32, height: 32)
}
}
} // * HStack (pre/next btn)
.padding(.horizontal, 26)
- ์ ์ ๊ทผ๋ฐฉ์์ผ๋ก ์์ฑํ ์ ์ฒด ์ฝ๋๋ ์๋์ ๊ฐ๋ค.
(๋ณธ๋ฌธ์ ๋ฐ๋ก ์ฝ๋ฉํธ๋ฅผ ์์ฑํ์ง ์์ ์ฝ๋๋ ํฌํจ๋์ด ์์.)
struct MainCoffeGuideTableSwiftUIView: View {
// ํ
์คํธ์ฉ ์ด๋ฏธ์ง๋ฐฐ์ด
private var images: [String] = [
"image1",
"image2",
"image3",
"image4"
]
// ์ด๋ฏธ์ง์ฌ๋ผ์ด๋ ์ธ๋ฑ์ค
@State private var index: Int = 0
// ์ฌ์ฉ์ ๋ฐฐ๋ ํญ์ก์
๊ฐ์ง
@State private var isTapped: Bool = false
var body: some View {
ZStack {
// BavkView
background
// MARK: - ์ด๋ฏธ์ง (๋ฐฐ๋)
VStack {
TabView(selection: $index) {
ForEach(0..<images.count, id: \.self) { index in
Image(images[index])
.resizable()
.aspectRatio(contentMode: .fit)
.frame(
width: UIScreen.main.bounds.width,
height: 500,
alignment: .center
) // -- ์๋ง ์์ ํ์
.clipped()
.cornerRadius(16)
.tag(index)
// ๋ฐฐ๋ ํญ ์ ์ข์ฐ๋ฒํผ + ์์ธํ๋ณด๊ธฐ ๋ฒํผ show
.onTapGesture {
print("banner tapped!")
isTapped.toggle()
}
.overlay (
VStack {
/// ๋ฐฐ๋ ๊ฐ์ ํ์
Text("\(index + 1)/ \(images.count)")
.font(Font.Pretendard(type: .Regular, size: 10))
.foregroundStyle(.uiColorWhite)
.frame(width: 30, height: 16, alignment: .center)
.background(Capsule().fill(Color.uiColorBlack).opacity(0.5))
.frame(
maxWidth: .infinity,
maxHeight: .infinity,
alignment: .topTrailing
)
.padding(.top, 24)
/// ์์ธํ๋ณด๊ธฐ ๋ฒํผ
/// ๋ฐฐ๋ ํญ ํ๋ฉด ๋ฑ์ฅ
if isTapped {
Button(action: {
print("์์ธํ๋ณด๊ธฐ ๋ฒํผ")
self.moveAction?(.timeSaleAction)
}, label: {
HStack {
Text("์์ธํ ๋ณด๊ธฐ")
.font(Font.Pretendard(type: .SemiBold, size: 12))
.foregroundStyle(.uiColorBlack)
Image(.ic32ArrowBlack)
.frame(width: 4, height: 8)
}
.padding(.leading, 12)
.padding(.trailing, 16)
.padding(.vertical, 8)
}) // * Button
.background(.uiColorWhite)
.cornerRadius(10, corners: .allCorners)
.frame(width: 97, height: 32)
.frame(
maxWidth: .infinity,
maxHeight: .infinity,
alignment: .bottomTrailing
)
.padding(.bottom, 40)
}
} // * Vstack (indexNm, ์์ธํ๋ณด๊ธฐ)
.padding(.trailing, 25)
)
}
}
.tabViewStyle(
PageTabViewStyle(
indexDisplayMode: .never
)
)
} // Vstak
// MARK: - Buttons (pre/next)
/// ๋ฐฐ๋ ํญ ํ๋ฉด ๋ฑ์ฅ
if isTapped{
HStack {
/// ์ธ๋ฑ์ค ๋ฒํธ์ ๋ฐ๋ผ ์ข์ฐ ๋ฒํผ ์จ๊น
/// pre button
if index > 0 {
Button(action: {
if index > 0 {
index -= 1
}
}) {
Image(.ic32ArrowBack2)
.frame(width: 32, height: 32)
}
}
Spacer()
/// next button
if index < images.count - 1 {
Button(action: {
if index < images.count - 1 {
index += 1
}
}) {
Image(.ic32ArrowBack2)
.rotationEffect(.degrees(-180))
.frame(width: 32, height: 32)
}
}
} // * HStack (pre/next btn)
.padding(.horizontal, 26)
}
}
.frame(
width: UIScreen.main.bounds.width,
height: 516,
alignment: .center
)
} // * Body
} // * View
๊ทธ๋ฐ๋ฐ ์ด๋ ๊ฒ ๋ณด๋๊น ๊ฐ๋ ์ฑ์ด ๋๋ฌด ์ ์ข์์...
ํ์ ๋คํธ์ํฌ ํต์ ํ๊ธฐ ์ํด ์ฝ๋๋ฅผ ์ผ๋ถ๋ถ ์์ ํ๋ฉด์ ๊ตฌ์กฐ์ฒด๋ฅผ ๋ ์ชผ๊ฐ๋ ์์ ์ ํด์ ๋ฉ์ธ์ผ๋ก ์ฝ๋๋ฅผ ๊ฒฐํฉํ๋ ๊ตฌ์กฐ์ฒด๋ฅผ ์๋์ ๊ฐ์ด ์์ ํ๋ค.
import SwiftUI
import Combine
struct MainCoffeeGuideTableSwiftUIView: View {
// ๋ฐฑ๊ทธ๋ผ์ด๋ ์์
let background = Color(UIColor(hexCode: "eeeeee"))
// ๋ฐฐ๋๋ฆฌ์คํธ ๋ฐฐ์ด
var bannerList: [BannerList] = []
// ์ด๋ฏธ์ง์ฌ๋ผ์ด๋ ์ธ๋ฑ์ค
@State private var index: Int = 0
// ์ฌ์ฉ์ ๋ฐฐ๋ ํญ์ก์
๊ฐ์ง
@State private var isTapped: Bool = false
var body: some View {
ZStack {
// BackView
background
// MARK: - ์ด๋ฏธ์ง ์ฌ๋ผ์ด๋ (๋ฐฐ๋)
MainCoffeeGuideImageSlider(
bannerImages: getImage(),
title: getTitle(),
bannerList: bannerList
)
// MARK: - Buttons (pre/next)
/// ๋ฐฐ๋ ํญ ํ๋ฉด ๋ฑ์ฅ
if isTapped{
MainCoffeeGuideBannerButtons(
index: $index,
total: getImage().count
)
}
}
.frame(
maxWidth: UIScreen.main.bounds.width,
minHeight: 516,
maxHeight: 601,
alignment: .center
)
} // * Body
} // * View
extension MainCoffeeGuideTableSwiftUIView {
/// ์ด๋ฏธ์ง๋ฐฐ์ด
func getImage() -> [String] {
return bannerList.map { $0.bannerImg ?? "" }
}
/// ํ
์คํธ๋ฐฐ์ด
func getTitle() -> [String] {
return bannerList.map { $0.title ?? "" }
}
/// ๋งํฌ๋ฐฐ์ด
func getLink() -> [String] {
return bannerList.map { $0.linkUrlL ?? "" }
}
}
Referances
https://developer.apple.com/documentation/swiftui/fitting-images-into-available-space
'๐ Dev > ๊ตฌํ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[SwiftUI] pagerView ๋ง๋ค๊ธฐ (iOS ๋ฒ์ ๋์) (2) | 2024.08.14 |
---|---|
[SwiftUI] CustomPopUpView ์ ๋๋ฉ์ด์ ํจ๊ณผ ํด๊ฒฐํ๊ธฐ (0) | 2024.06.27 |
[SwiftUI] ์ค์ ๋ก ์น์ ์ ์๋คํ๋ค ๊ตฌํํ๊ธฐ (0) | 2024.06.21 |
[SwiftUI] TabView page indicator ์ปค์คํ ํ๊ธฐ (1) | 2024.04.25 |
[UIKit] Enum with Reusable VC (0) | 2023.10.10 |