こんにちは uni928 です。
今回は SwiftUI で
レスポンシブな配置を行う方法について
自己流の方法を提案してみたいと思います。
全ての要素を
比率で配置していく形式になります。
サンプルコードを載せて
その解説を行う形式で
紹介したいと思います。
それではよろしくお願いいたします。
今回は次のような見た目の
配置を目指したいと思います。
文字とボタン 6 個だけの
簡単な画面になります。
完成コード
完成コード
import SwiftUI
struct ContentView: View {
var body: some View {
GeometryReader { bodyView in
getFirstView(bodyView.size.width, bodyView.size.height)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
/**
* 画面全体 View
*
* 9:19.5 をなるべく大きく切り取って
* そこに getMainContent を配置
*/
func getFirstView(_ width: CGFloat, _ height: CGFloat) -> some View {
//端末が 9:19.5 以上に縦長の場合
if 19.5 / 9.0 <= height / width
{
let myWidth = width
let myHeight = width * 19.5 / 9.0
return AnyView (
VStack(spacing: 0){
//上の余白
VStack(spacing: 0){}
.frame(width: width, height: ((height - myHeight) / 2))
//メインコンテンツ
getMainContent(myWidth, myHeight)
.frame(width: myWidth, height: myHeight)
//下の余白
VStack(spacing: 0){}
.frame(width: width, height: ((height - myHeight) / 2))
}
.frame(width: width, height: height)
)
}
else
{
let myWidth = height / 19.5 * 9.0
let myHeight = height
return AnyView (
HStack(spacing: 0) {
//左の余白
HStack(spacing: 0){}
.frame(width: ((width - myWidth) / 2), height: height)
//メインコンテンツ
getMainContent(myWidth, myHeight)
.frame(width: myWidth, height: myHeight)
//右の余白
HStack(spacing: 0){}
.frame(width: ((width - myWidth) / 2), height: height)
}
.frame(width: width, height: height)
)
}
}
/**
* 画面比率 9:19.5 のメインの配置
*/
func getMainContent(_ width: CGFloat, _ height: CGFloat) -> some View {
return VStack(spacing: 0) {
//上の空間
HStack{}
.frame(width: width, height: (height / 12 * 4.2))
//ボタンのある横1列
getHorizontalLine(width, height / 12 * 2, 0)
//ボタンとボタンの間の余白
HStack{}
.frame(width: width, height: (height / 12 * 0.6))
//ボタンのある横1列
getHorizontalLine(width, height / 12 * 2, 1)
//ボタンとボタンの間の余白
HStack{}
.frame(width: width, height: (height / 12 * 0.6))
//ボタンのある横1列
getHorizontalLine(width, height / 12 * 2, 2)
//下の空間
HStack{}
.frame(width: width, height: (height / 12 * 0.6))
}
.frame(width: width, height: height)
}
/**
* 横1列
*/
func getHorizontalLine(_ width: CGFloat, _ height: CGFloat, _ lineID: Int) -> some View{
return HStack(spacing: 0){
//左の余白
ZStack{}.frame(width: (width / 12 * 1.3), height: height)
//左のボタン
getButtonView(width / 12 * 4, height, lineID * 2)
//ボタンとボタンの間の余白
ZStack{}.frame(width: (width / 12 * 1.4), height: height)
//右のボタン
getButtonView(width / 12 * 4, height, lineID * 2 + 1)
//右の余白
ZStack{}.frame(width: (width / 12 * 1.3), height: height)
}
.frame(width: width, height: height)
}
/**
* ボタン部分のView
*/
func getButtonView (_ width: CGFloat, _ height: CGFloat, _ buttonID: Int) -> some View {
return Button(action: {buttonAction(buttonID)}){
Text("button")
.foregroundColor(Color.white)
.font(.system(size: width / 5))
.fontWeight(.bold)
}
.frame(width: width, height: height).background(.blue)
}
/**
* ボタンの処理
*/
func buttonAction(_ buttonID: Int) {
switch(buttonID){
case 0:
print("button0 が押されました")
case 1:
print("button1 が押されました")
case 2:
print("button2 が押されました")
case 3:
print("button3 が押されました")
case 4:
print("button4 が押されました")
case 5:
print("button5 が押されました")
default:
print("予期せぬボタンが押されました")
}
}
getFirstView メソッドの中で
9:19.5 のレイアウトを配置しています。
getMainContent メソッドの中で
次の図のようにレイアウトを配置しています
getHorizontalLine メソッドの中で
次の図のようにレイアウトを配置しています。
これらの配置を行えば
後はボタンとテキストを
レイアウト上に配置するだけです。
以上が私個人的な
SwiftUI のレスポンシブな配置方法になります。
恐らく独自の方法ではないでしょうか?
複雑な配置も
この方法なら意外と簡単にできます。
是非お試しください。
この記事が
皆さんの開発の役に立てれば幸いです。
閲覧ありがとうございました。