[SwiftUI] pagerView ๋งŒ๋“ค๊ธฐ (iOS ๋ฒ„์ „๋Œ€์‘)

2024. 8. 14. 13:51ยท๐ŸŽ Dev/๊ตฌํ˜„

 

 

 

 

ํšŒ์‚ฌ์—์„œ ์ฐธ์—ฌ์ค‘์ธ ํ”„๋กœ์ ํŠธ์—์„œ ์Šคํฌ๋กค๋ทฐ๋กœ ๊ตฌํ˜„๋˜์–ด ์žˆ๋˜ ๋ถ€๋ถ„์— ํŽ˜์ด์ง• ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•ด๋‹ฌ๋ผ๋Š” ๊ธฐํš์„œ ์ˆ˜์ •์ด ์žˆ์—ˆ๋‹ค.

UIKit์œผ๋กœ ๊ตฌํ˜„๋˜์–ด ์žˆ์—ˆ์œผ๋ฉด UIPageViewController๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋˜๊ฒ ์ง€๋งŒ, ํ”„๋กœ์ ํŠธ๋ฅผ SwiftUI ์ค‘์‹ฌ์œผ๋กœ ์ž‘์—… ์ค‘์ธ ์ƒํ™ฉ์ด๋ผ ์ƒ๊ฐ๋ณด๋‹ค ๊ธฐํš์„œ๋Œ€๋กœ ๊ฐœ๋ฐœํ•˜๋Š” ๊ฒŒ ๊นŒ๋‹ค๋กœ์› ๋‹ค.

 

๊นŒ๋‹ค๋กœ์› ๋˜ ์ด์œ ๋Š” ๋‘ ๊ฐ€์ง€๊ฐ€ ์žˆ์—ˆ๋Š”๋ฐ,

 

1. SwiftUI์˜ ScrollView๋Š” ์ปค์Šคํ…€์ด ์ œํ•œ์ ์ด๋ผ๋Š” ์ 

2. ํšŒ์‚ฌ ํ”„๋กœ์ ํŠธ์˜ ์ตœ์†Œ ๋ฒ„์ „์ด 15์ด์ƒ์ธ ์ 

 

๋•Œ๋ฌธ์ด์—ˆ๋‹ค.

 

๊ทธ๋ž˜๋„ iOS 17์ด์ƒ๋ถ€ํ„ฐ ์• ํ”Œ์—์„œ ScrollView์˜ ๊ธฐ๋Šฅ์„ ๋Œ€ํญ ์ถ”๊ฐ€ ๋ฐ ๊ฐœ์„  ํ•ด์ฃผ์–ด์„œ 17 ์ด์ƒ๋ถ€ํ„ฐ๋Š” ์‚ฌ์‹ค์ƒ ๋ฌธ์ œ๊ฐ€ ์—†์—ˆ๋Š”๋ฐ, ๋ฌธ์ œ๋Š” ScrollView์˜ ๋ฒ„์ „๋Œ€์‘์ด์—ˆ๋‹ค.

 

 

 

 

 

https://developer.apple.com/support/app-store

 

App Store - Support - Apple Developer

App Store The App Store makes it simple for users to discover, purchase, and download apps for iPhone, iPad, Mac, Apple TV, and Apple Watch. Enroll in the Apple Developer Program to distribute your apps worldwide on the App Store.

developer.apple.com

 

๋Œ€๋žต 15~20%์˜ ์‚ฌ๋žŒ๋“ค์€ iOS 17 ๋ฏธ๋งŒ์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์—ˆ๊ณ , ๊ธฐ์—… ์ž…์žฅ์—์„  ์•„๋ฌด๋ž˜๋„ ๋†“์น˜๊ธฐ์—” ์•„๊นŒ์šด ์ˆ˜์ด๊ธฐ์— ...... ๋ฒ„์ „๋Œ€์‘์„ ํ•ด์ค˜์•ผํ–ˆ๋‹ค.

 

์—ฌ๋Ÿฌ ๊นƒํ—™์ด๋‚˜ ์ฝ”๋“œ๋“ค์„ ์ฐธ๊ณ ํ•ด์„œ ๊ตฌํ˜„ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋‚˜๋„ ์ •๋ฆฌํ•˜๋ฉด์„œ ์ตœ์ข…์ ์œผ๋กœ ์ดํ•ดํ•˜๋Š” ์‹œ๊ฐ„์ด ํ•„์š”ํ•˜๊ธฐ๋„ ํ–ˆ๊ณ , ํƒญ๋ทฐ๋ฅผ ์จ์•ผ์ง€! ํ–ˆ๋‹ค๊ฐ€ ์–‘ ์˜† ์—ฌ๋ฐฑ์— ์ขŒ์šฐ ์•„์ดํ…œ์ด ๋ณด์—ฌ์•ผํ•˜๋Š” ์กฐ๊ฑด์„ ์ถฉ์กฑ์‹œ์ผœ์•ผํ•ด์„œ ์—ฌ๊ธฐ์ €๊ธฐ ์ƒ˜ํ”Œ ์ฝ”๋“œ๋ฅผ ์ฐธ๊ณ ํ•˜๊ณ  ๋งŒ๋“ค๋ฉฐ ์‚ฝ์งˆ์„ ํ–ˆ์—ˆ๊ธฐ์—,

 

์ •๋ฆฌํ•˜๊ฒŒ ๋œ,

iOS 17 ์ด์ƒ ํŽ˜์ด์ง• ๊ธฐ๋Šฅ๊ณผ iOS 17๋ฏธ๋งŒ์—์„œ ํŽ˜์ด์ง• ๊ธฐ๋Šฅ ๊ตฌํ˜„ํ•˜๊ธฐ!

 

 

 

 

 

 


 

 

 

 

 

1.  iOS 17 ๋ฏธ๋งŒ์—์„œ ์Šคํฌ๋กค ๋ทฐ ์—†์ด ์Šคํฌ๋กค ๋ทฐ + ํŽ˜์ด์ง• ๊ธฐ๋Šฅ ๊ตฌํ˜„ํ•˜๊ธฐ

- scrollView๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋Œ€์‹  gesture๋ฅผ ํ™œ์šฉํ•œ ๋ฐฉ์‹

 

 

 

 

 

๊ตฌํ˜„ ์ฝ”๋“œ:

 

import SwiftUI

struct CarouselViewSwiftUI: View {

    /// Carousel์—์„œ ๋ณด์—ฌ์ค„ ์ƒ‰์ƒ ๋ฐฐ์—ด
    let colors: [Color] = [.red, .blue, .green, .pink, .purple]

    /// ๋“œ๋ž˜๊ทธ ์˜คํ”„์…‹ ์ €์žฅ
    @State var dragOffset: CGFloat = .zero
    /// ํ˜„์žฌ ์ธ๋ฑ์Šค ์ €์žฅ
    @State var currentIndex: Int = 0

    /// ์•„์ดํ…œ ์‚ฌ์ด ๊ฐ„๊ฒฉ
    let itemSpacing: CGFloat = 12

    var body: some View {

        /// ์•„์ดํ…œ ๋„ˆ๋น„
        let itemWidth = 200
        /// ํ˜„์žฌ ์ธ๋ฑ์Šค๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์•„์ดํ…œ ์˜คํ”„์…‹ ๊ณ„์‚ฐ
        let currentOffset = CGFloat(currentIndex) * (CGFloat(itemWidth) + itemSpacing)

        GeometryReader { proxy in
            
            HStack(alignment: .center, spacing: itemSpacing) {
                
                ForEach(colors, id: \.self) { color in
                    color
                        .frame(width: CGFloat(itemWidth), height: 300)
                        .cornerRadius(12)
                } // forEach
                
            } // hStack
            
            // ๋“œ๋ž˜๊ทธ ์ œ์Šค์ฒ˜ ์ถ”๊ฐ€
            .gesture(dragGesture)
            // ๋“œ๋ž˜๊ทธ ์˜คํ”„์…‹์— ๋”ฐ๋ผ ์•„์ดํ…œ ์ด๋™
            .offset(x: 24 + dragOffset - currentOffset)
            .frame(width: proxy.size.width,
                   height: proxy.size.height,
                   alignment: .leading)
        } // geo
        .frame(height: 96)
        
    } // body
} // view

extension CarouselViewSwiftUI {

    // ๋“œ๋ž˜๊ทธ ์ œ์Šค์ฒ˜ ์ •์˜
    private var dragGesture: some Gesture {
        DragGesture()
            .onChanged { newValue in
                // ๋“œ๋ž˜๊ทธ์ค‘์ธ ์˜คํ”„์…‹ ์‹ค์‹œ๊ฐ„ ์—…๋ฐ์ดํŠธ
                dragOffset = newValue.translation.width
            } // onChanged
            .onEnded { endValue in
                
                // - ๋“œ๋ž˜๊ทธ๊ฐ€ ๋๋‚ฌ์„ ๋•Œ์˜ ์ฒ˜๋ฆฌ
                /// ๋“œ๋ ˆ๊ทธ ์ธ์‹ ๊ฐ’
                let threshold: CGFloat = 30
                /// ์ธ๋ฑ์Šค ๊ฐฑ์‹ 
                var newIndex = currentIndex

                /// ๋“œ๋ž˜๊ทธ์˜ ๋ฐฉํ–ฅ์— ๋”ฐ๋ผ ์ธ๋ฑ์Šค ๋ณ€๊ฒฝ (์•„์ดํ…œ ์ขŒ์šฐ ์ด๋™)
                if endValue.translation.width > threshold {
                    newIndex -= 1
                } else if endValue.translation.width < -threshold {
                    newIndex += 1
                }

                /// ๋ฐ”๋€ ์ธ๋ฑ์Šค ๋ฒ”์œ„ ์กฐ์ ˆ
                newIndex = max(min(newIndex, colors.count - 1), 0)

                /// ์ธ๋ฑ์Šค ์—…๋ฐ์ดํŠธ + ๋“œ๋ž˜๊ทธ ์˜คํ”„์…‹ ์ดˆ๊ธฐํ™”
                withAnimation(.spring()) {
                    currentIndex = newIndex
                    dragOffset = .zero
                }
                
            } // onEnded
    }
}

 

์ œ์Šค์ฒ˜๋ฅผ ํŠธ๋ฆฌ๊ฑฐ๋กœ ๋“œ๋ž˜๊ทธ ์˜คํ”„์…‹๊ณผ ํ˜„์žฌ ์ธ๋ฑ์Šค๋ฅผ ๊ด€์ฐฐํ•˜์—ฌ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ฐ”๋€ ๊ฐ’์„ ์ €์žฅ ๋ฐ ์—…๋ฐ์ดํŠธ ํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค.

 

 

1-1. GeometryReader ์‚ฌ์šฉ

: GeometryReader๋Š” ์ƒ์œ„๋ทฐ๋‚˜ ์ „์ฒด ๋ทฐ ํฌ๊ธฐ์— ๋”ฐ๋ผ ํ•˜์œ„๋ทฐ์˜ ํฌ๊ธฐ ๋ฐ ์œ„์น˜๋ฅผ ์ •ํ•  ๋•Œ ์ฃผ๋กœ ์‚ฌ์šฉํ•œ๋‹ค. GeometryReade์˜ proxy๋กœ ์ „์ฒด ๋ทฐ์— ๋งž์ถฐ์„œ ์Šคํฌ๋กค ๊ฐ€๋Šฅํ•œ ์˜์—ญ์˜ ๋„ˆ๋น„(proxy.size.width)๋ฅผ ๋งž์ถ”๊ณ , ๋“œ๋ž˜๊ทธ ์‹œ ๊ณ„์‚ฐํ•œ offset ๊ฐ’์— ๋งž๋Š” color ์ธ๋ฑ์Šค๋กœ ๋ฐ”๋€Œ๋„๋ก ํ–ˆ๋‹ค.

 

 

1-2. ์Šคํฌ๋กค ์•ก์…˜์„ ์œ„ํ•ด offset ํ™œ์šฉ

: offset์€ ๋“œ๋ž˜๊ทธํ•œ ํฌ๊ธฐ์— ํ˜„์žฌ ์ธ๋ฑ์Šค์˜ ์˜คํ”„์…‹๊ฐ’์„ ๋นผ์ฃผ์—ˆ๋Š”๋ฐ, ์—ฌ๊ธฐ์— 24๋ฅผ ๋”ํ•ด๋†“์€ ์ด์œ ๋Š” leading ํŒจ๋”ฉ๊ฐ’์„ ์ž„์˜์ ์œผ๋กœ ์ฃผ๊ธฐ ์œ„ํ•ด์„œ๋‹ค. ์›๋ž˜๋นผ๋ฉด tabView๋ฅผ ์“ด ๊ฒƒ์ฒ˜๋Ÿผ ๋“œ๋ž˜๊ทธ ์•ก์…˜์ด ์ผ์–ด๋‚˜๋ฉด color๊ฐ€ ์™ผ์ชฝ์— ๋”ฑ ๋ถ™๋Š”๋‹ค. scrollView๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค๋ฉด ํ•ด๋‹น ํŒจ๋”ฉ์„ ์ฃผ๊ธฐ ์œ„ํ•ด์„œ LazyHStack์ด๋‚˜ HStack์— 24์˜ ํŒจ๋”ฉ๊ฐ’์„ ์ฃผ์—ˆ์„ ๊ฒƒ.

 

 

1-3. gesture ์‚ฌ์šฉ

 

์‚ฌ์‹ค gesture๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒŒ scrollView๋ฅผ ์“ฐ์ง€ ์•Š์€ pager ๊ตฌํ˜„์˜ ํ•ต์‹ฌ์ด๋‹ค.

 

.onChanged { newValue in
	// ๋“œ๋ž˜๊ทธ์ค‘์ธ ์˜คํ”„์…‹ ์‹ค์‹œ๊ฐ„ ์—…๋ฐ์ดํŠธ
    dragOffset = newValue.translation.width
}

 

๋“œ๋ž˜๊ทธ ๋œ ์˜คํ”„์…‹์„ ๋“œ๋ž˜๊ทธ ์ œ์Šค์ฒ˜๋กœ ๋ณ€ํ™”๋œ ๊ฐ’์˜ translation.width๋กœ ์ €์žฅํ•˜๊ณ  ์žˆ๋Š”๋ฐ, translation๊ฐ€ ๋ฌด์Šจ ๊ฐ’์ธ๊ฐ€! ์‹ถ์„ ์ˆ˜ ์žˆ๋‹ค.

 

์• ํ”Œ๋ฌธ์„œ์—์„œ translation์€ instance property๋กœ, The total translation from the start of the drag gesture to the current event of the drag gesture. ....๋ผ๊ณ  ์ •์˜๋ฅผ ํ•ด์ฃผ์—ˆ๋Š”๋ฐ, ๋“œ๋ž˜๊ทธ๋ฅผ ์‹œ์ž‘ํ•œ ์ง€์ ์—์„œ ํ˜„์žฌ ๋“œ๋ž˜๊ทธ ์œ„์น˜๊นŒ์ง€์˜ ์ด๋™ ๊ฑฐ๋ฆฌ๋ž€ ์˜๋ฏธ๋‹ค.

 

์ฆ‰, translation.width๋Š” ๋“œ๋ž˜๊ทธ๋ฅผ ์‹œ์ž‘ํ•œ ์ง€์ ์—์„œ ํ˜„์žฌ ๋“œ๋ž˜๊ทธ ์œ„์น˜๊นŒ์ง€ ์ˆ˜ํ‰์œผ๋กœ ์ด๋™ํ•œ ๊ฑฐ๋ฆฌ์ด๊ณ , translation.height์€ ์ˆ˜์ง์œผ๋กœ ์ด๋™ํ•œ ๊ฑฐ๋ฆฌ๋‹ค.

 

์—ฌ๊ธฐ์„œ ๋‚˜๋Š” HStack์„ ์“ฐ๊ณ  ์žˆ๊ณ , ๋“œ๋ž˜๊ทธ ์•ก์…˜์ด ์ขŒ์šฐ๋กœ ์ผ์–ด๋‚  ๊ฑฐ๋ผ translation.width๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋“œ๋ž˜๊ทธ ์•ก์…˜์ด ์ผ์–ด๋‚ ๋•Œ๋งˆ๋‹ค ๋“œ๋ž˜๊ทธ ์˜คํ”„์…‹์„ translation.width๊ฐ’์œผ๋กœ ์ €์žฅํ•ด ์ด๋™์‹œ์ผฐ๋‹ค.

 

https://developer.apple.com/documentation/swiftui/draggesture/value/translation

 

translation | Apple Developer Documentation

The total translation from the start of the drag gesture to the current event of the drag gesture.

developer.apple.com

 

 

 

.onEnded { endValue in

                /// ๋“œ๋ ˆ๊ทธ ์ธ์‹ ๊ฐ’
                let threshold: CGFloat = 30
                /// ์ธ๋ฑ์Šค ๊ฐฑ์‹ 
                var newIndex = currentIndex

                /// ๋“œ๋ž˜๊ทธ์˜ ๋ฐฉํ–ฅ์— ๋”ฐ๋ผ ์ธ๋ฑ์Šค ๋ณ€๊ฒฝ (์•„์ดํ…œ ์ขŒ์šฐ ์ด๋™)
                if endValue.translation.width > threshold {
                    newIndex -= 1
                } else if endValue.translation.width < -threshold {
                    newIndex += 1
                }

                /// ๋ฐ”๋€ ์ธ๋ฑ์Šค ๋ฒ”์œ„ ์กฐ์ ˆ
                newIndex = max(min(newIndex, colors.count - 1), 0)

                /// ์ธ๋ฑ์Šค ์—…๋ฐ์ดํŠธ + ๋“œ๋ž˜๊ทธ ์˜คํ”„์…‹ ์ดˆ๊ธฐํ™”
                withAnimation(.spring()) {
                    currentIndex = newIndex
                    dragOffset = .zero
                }
                
} // onEnded

 

๊ทธ๋ฆฌ๊ณ  ๋“œ๋ž˜๊ทธ ์•ก์…˜์ด ๋๋‚˜๋ฉด ๊ฐฑ์‹  ๋˜์•ผํ•˜๋Š” ๊ฐ’๋“ค์„ onEnded์— ์ž‘์„ฑํ•˜๋ฉด ๋œ๋‹ค. 

 

 

 

 

 

2.  iOS 17 ๋ฏธ๋งŒ์—์„œ ์Šคํฌ๋กค ๋ทฐ๋ฅผ ์จ์„œ ํŽ˜์ด์ง• ๊ธฐ๋Šฅ ๊ตฌํ˜„ํ•˜๊ธฐ

 

์ œ์Šค์ฒ˜๋กœ ๋งŒ๋“ค๋ฉด ๋‹ค ๋˜๋Š” ๊ฑฐ ์•„๋‹ˆ์•ผ? ์‹ถ์—ˆ๋˜ ๋‚ด๊ฒŒ ์Šคํฌ๋กค ๋ทฐ๋ฅผ ๊ผญ ์จ์•ผํ•˜๋Š” ์ƒํ™ฉ์ด ์ƒ๊ฒผ๋‹ค. ๋ฐ”๋กœ, ์•ก์…˜์ด ์ผ์–ด๋‚ฌ์„ ๋•Œ ์•„์ดํ…œ ์œ„์น˜์กฐ์ •๋ฅผ ์ž๋™์œผ๋กœ ์กฐ์ • ํ•ด์ฃผ์–ด์•ผ ํ•  ๋•Œ. ๋ณดํ†ต ์ด๋Ÿฐ ๊ฒฝ์šฐ scrollViewReader์˜ proxy.scrollTo(id, anchor: .center) ๋“ฑ์„ ์จ์„œ ์กฐ์ •ํ•ด์ฃผ๋Š”๋ฐ, 1์˜ ๋ฐฉ๋ฒ•์„ ์“ฐ๋ฉด ์ด ์‰ฌ์šด ๋ฐฉ๋ฒ•์„ ์“ธ ์ˆ˜๊ฐ€ ์—†์—ˆ๋‹ค.

 

๊ทธ๋ž˜์„œ ์ด ๋ถ€๋ถ„์€ ํŒ€์žฅ๋‹˜๊ณผ ๊ณ ๋ฏผ์„ ํ•˜๋‹ค๊ฐ€ ์ฝ”๋“œ์˜ ๊ฐ„๊ฒฐ์„ฑ์„ ์œ„ํ•ด

 

https://github.com/izakpavel/SwiftUIPagingScrollView

 

GitHub - izakpavel/SwiftUIPagingScrollView: implementation of generic paging scrollView in SwiftUI

implementation of generic paging scrollView in SwiftUI - izakpavel/SwiftUIPagingScrollView

github.com

 

์œ„ ๊นƒํ—™์˜ PagingScrollView ํŒŒ์ผ์„ ์“ฐ๊ธฐ๋กœ ํ•ด์„œ ์Šคํฌ๋กค๋ทฐ๊ฐ€ ์ œ๊ณตํ•ด์ฃผ๋Š” api๋ฅผ ํ™œ์šฉํ•ด์•ผํ•˜๋Š” ํŽ˜์ด์ง• ๋ถ€๋ถ„์€ ํ•ด๋‹น ์ฝ”๋“œ๋กœ ๋Œ€์ฒดํ•ด์„œ ์‚ฌ์šฉํ–ˆ๋‹ค. 

 

- ํŽ˜์ด์ง€ ์ธ๋ฑ์Šค

- ์•„์ดํ…œ ๋„ˆ๋น„

- ์•„์ดํ…œ ํŒจ๋”ฉ (๊ฐ„๊ฒฉ)

 

๋งŒ ์•Œ๋ฉด PagingScrollView ๋‚ด์˜ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์ˆ˜์ •ํ•ด์„œ ์‚ฌ์šฉํ•˜๋ฉด ๋ณต์žกํ•œ ๊ตฌํ˜„๋„ ํ”ผํ•˜๊ณ , ์ฝ”๋“œ๋ฅผ ๋œฏ์–ด ์ปค์Šคํ…€ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

 

 

 

3.  iOS 17 ์ด์ƒ ์Šคํฌ๋กค ๋ทฐ๋กœ ํŽ˜์ด์ง• ๊ธฐ๋Šฅ ๊ตฌํ˜„ํ•˜๊ธฐ

 

๊ทธ๋ฆฌ๊ณ  iOS 17๋ถ€ํ„ฐ๋Š” ์• ํ”Œ์ด scrollTargetLayout์™€ scrollTargetBehavior๋ฅผ ์จ์„œ ์•„์ฃผ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋„๋ก ScrollView API๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ์—ˆ๋‹ค.

 

์ € api ๊ธฐ๋Šฅ๋“ค์€ ๋Œ€์ฒด ๋ญ๊ณ , ์–ด๋–ป๊ฒŒ ์ ์šฉํ•  ์ˆ˜ ์žˆ์„๊นŒ?

 

์— ๋Œ€ํ•ด์„œ ์•„๋ž˜ ๊ฒŒ์‹œ๊ธ€์— ๋”ฐ๋กœ ์ •๋ฆฌํ–ˆ๋‹ค.

 

 

https://calliek.tistory.com/59

 

[SwiftUI] scrollTargetLayout๊ณผ ScrollTargetBehavior

iOS 17์ด์ „๊นŒ์ง€ ScrollView๋ฅผ ํ™œ์šฉํ•  ๋•Œ ์ œํ•œ์ ์ธ ๋ถ€๋ถ„์ด ๋งŽ์•˜๋‹ค. ํŠนํžˆ ์˜คํ”„์…‹์„ ์ง์ ‘ ๊ตฌํ˜„ํ•ด์„œ ํŽ˜์ด์ง• ๊ธฐ๋Šฅ์„ ์ปค์Šคํ…€์œผ๋กœ ๋งŒ๋“ค์–ด์•ผํ•œ๋‹ค๋Š” ๋ถˆํŽธํ•จ์ด ์žˆ์—ˆ๋Š”๋ฐ, ์• ํ”Œ์—์„œ scrollTargetLayout๊ณผ scrollTargetBe

calliek.tistory.com

 

 

 

 

 

 


 

References

 

https://www.hackingwithswift.com/books/ios-swiftui/moving-views-with-draggesture-and-offset

 

Moving views with DragGesture and offset() - a free Hacking with iOS: SwiftUI Edition tutorial

Was this page useful? Let us know! 1 2 3 4 5

www.hackingwithswift.com

 

์ €์ž‘์žํ‘œ์‹œ (์ƒˆ์ฐฝ์—ด๋ฆผ)

'๐ŸŽ Dev > ๊ตฌํ˜„' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[SwiftUI] Infinite Carousel ๊ตฌํ˜„ํ•˜๊ธฐ 2 (feat.Timer)  (0) 2024.09.11
[SwiftUI] Infinite Carousel ๊ตฌํ˜„ํ•˜๊ธฐ 1 (feat. Timer)  (0) 2024.09.05
[SwiftUI] CustomPopUpView ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ ํ•ด๊ฒฐํ•˜๊ธฐ  (0) 2024.06.27
[SwiftUI] ์Šค์œ ๋กœ ์„น์…˜ ์ ‘์—ˆ๋‹คํˆ๋‹ค ๊ตฌํ˜„ํ•˜๊ธฐ  (0) 2024.06.21
[SwiftUI] pre/next buttons๊ฐ€ ์žˆ๋Š” ์ด๋ฏธ์ง€ ์Šฌ๋ผ์ด๋” ๊ตฌํ˜„ํ•˜๊ธฐ  (2) 2024.05.16
'๐ŸŽ Dev/๊ตฌํ˜„' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€
  • [SwiftUI] Infinite Carousel ๊ตฌํ˜„ํ•˜๊ธฐ 2 (feat.Timer)
  • [SwiftUI] Infinite Carousel ๊ตฌํ˜„ํ•˜๊ธฐ 1 (feat. Timer)
  • [SwiftUI] CustomPopUpView ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ ํ•ด๊ฒฐํ•˜๊ธฐ
  • [SwiftUI] ์Šค์œ ๋กœ ์„น์…˜ ์ ‘์—ˆ๋‹คํˆ๋‹ค ๊ตฌํ˜„ํ•˜๊ธฐ
Callie_
Callie_
  • Callie_
    CalliOS
    Callie_
  • ์ „์ฒด
    ์˜ค๋Š˜
    ์–ด์ œ
    • ๋ถ„๋ฅ˜ ์ „์ฒด๋ณด๊ธฐ
      • ๐ŸŽ APPLE
      • ๐ŸŽ Dev
        • Swift
        • UIKit
        • SwiftUI
        • Issue
        • ๊ตฌํ˜„
      • ๐ŸŽ Design
        • HIG
      • โš™๏ธ CS
      • ๐Ÿ’ก ์•Œ๊ณ ๋ฆฌ์ฆ˜
        • ํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค
        • ๋ฐฑ์ค€
      • ๐ŸŸ๏ธ ์ง๊ด€๋กœ๊ทธ (์ถœ์‹œ์•ฑ)
        • ์—…๋ฐ์ดํŠธ
      • ๐ŸŒฑ SeSAC iOS 3๊ธฐ
  • ๋ธ”๋กœ๊ทธ ๋ฉ”๋‰ด

    • ํ™ˆ
    • ํƒœ๊ทธ
  • ๋งํฌ

  • ๊ณต์ง€์‚ฌํ•ญ

  • ์ธ๊ธฐ ๊ธ€

  • ํƒœ๊ทธ

    ํ™”๋ฉด์ „ํ™˜
    IBOutlet
    cornerradius
    clipsToBound
    ios
    ๋„คํŠธ์›Œํฌํ†ต์‹ 
    CocoaTouchFramework
    TableViewCell
    IBAction
    .fullScreen
    CustomView
    SwiftUI
    DidEndOnExit
    .OverFullScreen
    stroyboard
    apply
    Swift
    Enum
    Entry Point
    layer.shadow
    diffable
    ์ƒ๋ช…์ฃผ๊ธฐ
    Infoํƒญ
    DiffableDataSource
    SeSAC
    addTarget
    modalPresentStyle
    TapGestureRecognizer
    Snapshot
    assets
  • ์ตœ๊ทผ ๋Œ“๊ธ€

  • ์ตœ๊ทผ ๊ธ€

  • hELLOยท Designed By์ •์ƒ์šฐ.v4.10.0
Callie_
[SwiftUI] pagerView ๋งŒ๋“ค๊ธฐ (iOS ๋ฒ„์ „๋Œ€์‘)
์ƒ๋‹จ์œผ๋กœ

ํ‹ฐ์Šคํ† ๋ฆฌํˆด๋ฐ”

๋‹จ์ถ•ํ‚ค

๋‚ด ๋ธ”๋กœ๊ทธ

๋‚ด ๋ธ”๋กœ๊ทธ - ๊ด€๋ฆฌ์ž ํ™ˆ ์ „ํ™˜
Q
Q
์ƒˆ ๊ธ€ ์“ฐ๊ธฐ
W
W

๋ธ”๋กœ๊ทธ ๊ฒŒ์‹œ๊ธ€

๊ธ€ ์ˆ˜์ • (๊ถŒํ•œ ์žˆ๋Š” ๊ฒฝ์šฐ)
E
E
๋Œ“๊ธ€ ์˜์—ญ์œผ๋กœ ์ด๋™
C
C

๋ชจ๋“  ์˜์—ญ

์ด ํŽ˜์ด์ง€์˜ URL ๋ณต์‚ฌ
S
S
๋งจ ์œ„๋กœ ์ด๋™
T
T
ํ‹ฐ์Šคํ† ๋ฆฌ ํ™ˆ ์ด๋™
H
H
๋‹จ์ถ•ํ‚ค ์•ˆ๋‚ด
Shift + /
โ‡ง + /

* ๋‹จ์ถ•ํ‚ค๋Š” ํ•œ๊ธ€/์˜๋ฌธ ๋Œ€์†Œ๋ฌธ์ž๋กœ ์ด์šฉ ๊ฐ€๋Šฅํ•˜๋ฉฐ, ํ‹ฐ์Šคํ† ๋ฆฌ ๊ธฐ๋ณธ ๋„๋ฉ”์ธ์—์„œ๋งŒ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.