2
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 3 years have passed since last update.

【SwiftUI】GeometryReaderを使ったグリッドシステムを考える

Last updated at Posted at 2020-12-01

はじめに

SwiftUIでそれぞれのViewのレイアウトをデザインする時に必要なGeometryReaderを用いて、グリッドシステムを考えることを目的とする。

ただし、今回Iphone11、Iphone8、IpadPro12inchのそれぞれをSimulatorで確認しましたが、心から満足できるデザインになっていません。まだまだ改善が必要な点をご了承ください。

前回までの記事は以下を参考ください。

参考記事
【SwiftUI】AppデザインのためにGeometryReaderを理解する

開発環境

OSX 10.15.7 (Catalina)
Xcode 12.2.0
CocoaPods 1.10.0

SwiftUIのレイアウトシステム

画面サイズいっぱいの1ページのViewを想定します。
縦にスクロールせず、横にスクロールもしない場合のAppデザインを考えます。
まずは画面全体を10分割しました。
そのためにGeometryReaderを用いて、それぞれのRow部分のframeに.frame(width: container.size.width, height: container.size.height/10)を実装しました。

ContentView_swift_—_Edited.png

参考文献
How to provide relative sizes using GeometryReader

struct ContentView: View {
    
    var body: some View {
        
        // parent View
        VStack {
            // クロージャーの"g"は任意で設定可能
            GeometryReader { container in
                
                // Container
                VStack {
                    
                    // section1
                    ZStack {
                        
                        // a horizontal line
                        HStack{
                            
                            Image(systemName: "doc")
                            Text("First One")
                        }
                    // parentViewの幅いっぱい、縦は全体の1/10に設定。
                    }.frame(width: container.size.width, height: container.size.height/10, alignment: .center)
                    .border(Color.blue)
                    
                    // section2
                    ......
                }
            }
        }
    }
}

グリッドシステムを考える

GeometryReaderを使って、画面サイズを10分割しました。
それらをX個分の高さを設定するために、frame(width: container.size.width, height: container.size.height/10 * 4)と記載内容を変更しました。"*4"を追加することによって、グリッドシステムを考えます。合計の比率を10になるように設定すれば、画面の高さの計算を簡単にすることができます。

下のイメージでは一つ目のセクションを"4"、二つ目のセクションを"4"、そして、三つ目のセクションを"2"で設定しました。

gridView_swift.png

struct gridView: View {
    var body: some View {
        
        // parent View
        VStack {
            // クロージャーの"g"は任意で設定可能
            GeometryReader { container in
                
                // Container
                VStack {
                    
                    // section1
                    ZStack {
                        
                        // a horizontal line
                        HStack{
                            
                            Image(systemName: "doc")
                            Text("First One")
                        }
                    // parentViewの幅いっぱい、縦は全体の1/10に設定。
                    // Row部分を4つ分の高さを設定する。
                    }.frame(width: container.size.width, height: container.size.height/10 * 4, alignment: .center)
                    .border(Color.blue)
                    
                    // section2
                    ZStack {
                        
                        // a horizontal line
                        HStack{
                            
                            Image(systemName: "doc")
                            Text("Second One")
                        }
                    // parentViewの幅いっぱい、縦は全体の1/10に設定。
                    // Row部分を4つ分の高さを設定する。
                    }.frame(width: container.size.width, height: container.size.height/10 * 4, alignment: .center)
                    .border(Color.blue)
                    
                    // section3
                    ZStack {
                        
                        // a horizontal line
                        HStack{
                            
                            Image(systemName: "doc")
                            Text("Third One")
                        }
                    // parentViewの幅いっぱい、縦は全体の1/10に設定。
                    // Row部分を2つ分の高さを設定する。
                    }.frame(width: container.size.width, height: container.size.height/10 * 2, alignment: .center)
                    .border(Color.blue)
                    
                }
            }
        }.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
    }
}

#実装のイメージ
Iphone11
iPhone_11_–_14_2.png

Iphone8
iPhone_8_–_14_2.png

iPad Pro(12.9inch)
iPad_Pro__12_9-inch__–4th_generation–_14_2.png

iPad Pro(12.9inch)の方はデザインとバランスがあまり美しくないですね。Iphone8も悪くはないけど...って感じです。

特にPaddingの設定など余白については改善が必要です。

参考文献
SwiftUI Shifting Display Left

struct imageView: View {
    
    @State var color = Color.black.opacity(0.7)
    @State var email = ""
    @State var pass = ""
    
    @State var visible = false
    
    var body: some View {
        
        ZStack(alignment: .topTrailing) {
            
            VStack {
                
                GeometryReader{container in
                    Color.init("pinkColor")
                    VStack {
                        
                        // Logo Section
                        VStack(alignment: .center) {
                            
                            GeometryReader{rowSection1 in
                                
                                VStack(alignment: .center) {

                                    Image("logo")
                                        .resizable()
                                        .frame(width: rowSection1.size.height/10 * 7, height: rowSection1.size.height/10 * 7, alignment: .center)
                                        
                                    Text("Haiku de Go")
                                        .font(.largeTitle)
                                        .fontWeight(.heavy)
                                        .foregroundColor(Color.white)
                                        
                                }.padding(.top, rowSection1.size.height/10 * 0.5)
                                .frame(maxWidth: .infinity, maxHeight: .infinity)

                            }
                            
                        }.frame(width: container.size.width, height: container.size.height/10 * 4, alignment: .center)
                        
                        // Email,password Section
                        VStack(alignment: .center) {
                            
                            Text("Log in to your account")
                                .font(.title)
                                .fontWeight(.bold)
                                .foregroundColor(self.color)
                            
                            TextField("Email", text: self.$email)
                                .padding()
                                .font(.title2)
                                .background(RoundedRectangle(cornerRadius: 4).stroke(self.email != "" ? Color("borderColor") : self.color, lineWidth: 2))
                                .background(Color.white)
                                .padding()
                            
                            HStack {
                                
                                VStack {
                                
                                    if self.visible {
                                        
                                        TextField("Password", text: self.$pass)
                                            .font(.title2)
                                    } else {
                                        
                                        SecureField("Password", text: self.$pass)
                                            .font(.title2)
                                    }
                                }
                                Button(action: {
                                    
                                }, label: {
                                    Image(systemName: self.visible ? "eye.slash.fill" : "eye.fill")
                                        .font(.title2)
                                        .foregroundColor(color)
                                })
                                
                            }
                            .padding()
                            .background(RoundedRectangle(cornerRadius: 4).stroke(self.pass != "" ? Color("borderColor") : self.color, lineWidth: 2))
                            .background(Color.white)
                            .padding()
                            
                            HStack {
                                
                                Spacer()
                                Button (action: {
                                    
                                }, label: {
                                    Text("Forget passward")
                                        .fontWeight(.bold)
                                        .foregroundColor(self.color)
                                })
                            }.padding()
                        }.frame(width: container.size.width, height: container.size.height/10 * 4, alignment: .center)
                        
                        // Login Button Section
                        VStack(alignment: .center) {
                            
                            Button (action: {
                                
                                // self.verify()
                            }, label: {
                                Text("Log in")
                                    .foregroundColor(color)
                                    .font(.title2)
                                    .fontWeight(.bold)
                                    .padding(.vertical)
                                    .frame(width: UIScreen.main.bounds.width - 200)
                            }).background(Color.white)
                            .cornerRadius(10)
                        }.frame(width: container.size.width, height: container.size.height/10, alignment: .center)
                    }
                }
            }
            
            // RegisterButton 右上に配置
            Button(action: {
                
            }, label: {
                Text("Register")
                    .fontWeight(.bold)
                    .foregroundColor(self.color)
            })
            .padding()
        }
    }
}

以上です。

2
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
2
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?