題名通り、それっぽくViewを並べてみました。
とりあえず配置してみただけですが、色々勉強できました。
今回は適当にViewを並べてみましたが、SwiftUIはpaddingやSpacerというものがあるおかげでViewを綺麗に配置できるのがかなりいいなと個人的に思いました。
コードで学べるものとしていくつかあげてみたので、興味があれば実装してみてください。
学べるもの
・Identifiableプロトコルの実装
・View間のデータの受け渡し
・@State,@Bindingを使うタイミング
・HStack, VStack, ScrollView
・各Viewが持つそれぞれのプロパティ
・ForEachの使い方
・画像を丸くする
・toggle()
などなど
実装
Identifiableプロトコルの実装
struct Images:Identifiable {
var id = UUID() //←識別子のプロパティを必ず用意ければいけないようです。
var name: String
var img:String
}
メインとなるView
struct ContentView: View {
//@Stateをつけると変更時View再描写される
//@BindingをつけるとView間での双方向のデータ共有が可能
@State var flag:Bool = false
@State var tapName:String = "tapNAME"
private var images = [Images(name: "Xxxx Xxxx", img: "myimage"),
Images(name: "Aaaaa Aaaa", img: "myimage"),
Images(name: "Bbbbb Bbbb", img: "myimage"),
Images(name: "Ccccc Cccc", img: "myimage"),
Images(name: "Ddddd Dddd", img: "myimage"),
Images(name: "Eeeee Eeee", img: "myimage"),
Images(name: "Fffff Ffff", img: "myimage"),
Images(name: "Ggggg Gggg", img: "myimage")]
var body: some View {
VStack {
ScrollView(.vertical, showsIndicators: false, content: {
HStack {
Image(images.first?.img ?? "NoImage")
.resizable()
.frame(width: 75, height: 75)
.clipShape(Circle())
.overlay(Circle().stroke(Color.white,lineWidth: 1))
.shadow(radius: 10)
.padding(.leading)
Text(images.first?.name ?? "NoName")
.font(.title2)
.fontWeight(.bold)
.foregroundColor(Color.white)
.padding(.leading)
Spacer()
Image(systemName: "bell.badge")
.font(.title)
.foregroundColor(Color.white)
.padding(.trailing)
}.padding(.top)
Text(tapName).foregroundColor(.white)
ScrollView(.horizontal, showsIndicators: false, content: {
HStack {
ForEach(images) { image in
CustomBtn(img: Image(image.img), name: image.name, flag: $flag, tapName: $tapName) //CustomBtnに変数を受け渡すため$を頭につける
}
}
HStack {
ForEach(images) { image in
CustomBtn(img: Image(image.img), name: image.name, flag: $flag, tapName: $tapName)
}
}
}).padding(.top)
//MARK:- First CollectionView
VStack(alignment: .leading, spacing: nil, content: {
Text("First CollectionView")
.font(.title)
.foregroundColor(Color.white)
.fontWeight(.bold)
.padding(.top).padding(.leading)
ScrollView(.horizontal, showsIndicators: false, content: {
HStack {
ForEach(images) { image in
Image(image.img)
.resizable()
.frame(width: 150, height: 150, alignment: .center)
.cornerRadius(5.0)
}
}.padding(.leading).padding(.trailing) //左右のみスペース
})
})
//MARK:- Seccond CollectionView
VStack(alignment: .leading, spacing: nil, content: {
Text("Seccond CollectionView")
.font(.title)
.foregroundColor(Color.white)
.fontWeight(.bold)
.padding(.top).padding(.leading)
ScrollView(.horizontal, showsIndicators: false, content: {
HStack {
ForEach(images) { image in
Image(image.img)
.resizable()
.frame(width: 150, height: 150, alignment:.center)
.cornerRadius(5.0)
.clipShape(Circle())
}
}.padding(.leading).padding(.trailing)
})
})
//MARK:- Third CollectionView
VStack(alignment: .leading, spacing: nil, content: {
Text("Third CollectionView")
.font(.title)
.foregroundColor(Color.white)
.fontWeight(.bold)
.padding(.top).padding(.leading)
ScrollView(.horizontal, showsIndicators: false, content: {
HStack {
ForEach(images) { image in
Image(image.img)
.resizable()
.frame(width: 250, height: 150, alignment:.center)
.cornerRadius(5.0)
}
}.padding(.leading).padding(.trailing).padding(.bottom)
})
})
//-------
})
}.padding(.top)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color(#colorLiteral(red: 0.09886621684, green: 0.1093793288, blue: 0.2782805264, alpha: 1)))
.edgesIgnoringSafeArea(.all)
}
}
画面上部のボタン(画像とテキスト)は以下Structを作成して参照しています。
//CustomBtn
struct CustomBtn: View {
let img:Image
let name:String
@Binding var flag:Bool
@Binding var tapName:String //@BindingをつけるとView間での双方向のデータ共有が可能
var body:some View {
//Button
Button(action: {
//ここのセクション内にボタンを押したときの動作を書く
self.flag.toggle() //false・true反転してくれる
self.tapName = name
}){
img
.resizable() //画像をいい感じにリサイズ
.frame(width: 50, height: 50) //フレームサイズ
Text(name)
.font(.subheadline) //サイズ変更
.fontWeight(.heavy) //太字
.minimumScaleFactor(0.7) //最小文字サイズ(自動サイズ変更されるため)
.lineLimit(2) //最大行数
.foregroundColor(Color.white)
Spacer()
}.background(Color(#colorLiteral(red: 0.1695919633, green: 0.164103806, blue: 0.3997933269, alpha: 1)))
.cornerRadius(5.0) //角を少し丸く
.padding(.horizontal)
}
}
基本的なViewの配置からView間のデータ受け渡しなどなどアウトプットしました。
どうしても独学だと、プログラムとしては動作しているけど、これが本当にベストプラクティスなのかいつも迷っています。。なのでもしこっちの方が綺麗に書けるとか早いなどなどあればコメントで教えていただけると嬉しいです。
今後も備忘録として、残していきたいと思います。