1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

SwiftUIで、一行一列を固定したスプシの動作を再現したい時

Last updated at Posted at 2023-05-25

画面収録_2023-05-25_13_26_55_AdobeExpress-3.gif

参考:

import SwiftUI

struct SyncedScrollViews<Content:View,VSyncedContent:View,HSyncedContent:View>: View {
    
    let content:Content
    let verticallySyncedContent:VSyncedContent
    let horizontallySyncedContent:HSyncedContent
    
    init(@ViewBuilder content: () -> Content, @ViewBuilder vSyncedContent: () -> VSyncedContent, @ViewBuilder hSyncedContent: () -> HSyncedContent) {
        self.content = content()
        self.verticallySyncedContent = vSyncedContent()
        self.horizontallySyncedContent = hSyncedContent()
    }
    
    @State private var offset = CGPoint(x: 0, y: 0)
    
    var body: some View {
        VStack(alignment: .leading,spacing: 0){
            Spacer()
            // Synchronised with main ScrollView
            ScrollView(.horizontal) {
                HStack {
                    horizontallySyncedContent
                }
                .offset(x: -offset.x)
            }
            .disabled(true)
            
            HStack(alignment: .top,spacing: 0) {
                // Synchronised with main ScrollView 
                ScrollView {
                    VStack {
                        verticallySyncedContent
                    }
                    .offset(y: -offset.y)
                }
                .disabled(true)
                
                // MainScrollView
                ScrollView([.vertical, .horizontal]) {
                    VStack {
                        content
                    }
                    .background( GeometryReader {
                        Color.clear.preference(key: ViewOffsetKey.self,
                                               value: CGPoint(x:-$0.frame(in: .named("scroll")).origin.x,y:-$0.frame(in: .named("scroll")).origin.y) )
                    })
                    .onPreferenceChange(ViewOffsetKey.self) { value in
                        print("offset >> \(value)")
                        offset = value
                        
                    }
                }
                .coordinateSpace(name: "scroll")
                
                
            }
        }
    }
}

struct ViewOffsetKey: PreferenceKey {
    static var defaultValue = CGPoint.zero
    
    typealias Value = CGPoint
    static func reduce(value: inout Value, nextValue: () -> Value) {
        value.x += nextValue().x
        value.y += nextValue().y
    }
}



struct SyncedScrollViews_Previews: PreviewProvider {
    static var previews: some View {
        SyncedScrollViews{
            HStack{
                ForEach(1..<100) { column in
                    VStack{
                        ForEach(1..<100) { row in
                            Text("R:\(row)\nC:\(column)")
                                .frame(width: 80, height: 80)
                        }.background(.green)
                    }
                }
            }
        }vSyncedContent:{
            ForEach(1..<100) { row in
                Text("R:\(row)\nC:\(0)")
                    .frame(width: 80, height: 80)
            }.background(.pink)
                .padding(.trailing,8)
            
        }hSyncedContent:{
            ForEach(0..<100) { column in
                Text("R:\(0)\nC:\(column)")
                    .frame(width: 80, height: 80)
            }.background(.yellow)
                .padding(.bottom,8)
        }
        }
}


より抽象化できる部分があるなど、改善点など教えていただけると嬉しいです。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?