はじめに
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)
を実装しました。
参考文献
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"で設定しました。
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)
}
}
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()
}
}
}
以上です。