作成中です。
このPartでは、リストを使ってなんちゃってToDoリストを作ってみます。
では実装していきましょう。ToDoList
という名前でプロジェクトを作成してください。
レイアウト実装
まずは、レイアウトを作っていきましょう。
まずは、ナビゲーションバーを作りましょう。以下のように変更してください。
var body: some View { NavigationView { Text("Hello, world!") .padding() .navigationTitle("ToDoリスト") } }
次にリストを作りましょう。
NavigationView { List { Text("ジョギングする") Text("お花に水をやる") Text("部屋の掃除をする") Text("本を読む") } .navigationTitle("ToDoリスト") }
実行するとこのようなレイアウトになります。
一つ一つHStackで囲んで、Imageをつけましょう。
NavigationView { List { HStack { Image(systemName: "circle") Text("ジョギングする") } HStack { Image(systemName: "checkmark.circle.fill") Text("お花に水をやる") } HStack { Image(systemName: "checkmark.circle.fill") Text("部屋の掃除をする") } HStack { Image(systemName: "circle") Text("本を読む") } } .navigationTitle("ToDoリスト") }
このような見た目になるはずです。
これで見た目はいい感じになりました。
import SwiftUI struct ContentView: View { var body: some View { NavigationView { List { HStack { Image(systemName: "circle") Text("ジョギングする") } HStack { Image(systemName: "checkmark.circle.fill") Text("お花に水をやる") } HStack { Image(systemName: "checkmark.circle.fill") Text("部屋の掃除をする") } HStack { Image(systemName: "circle") Text("本を読む") } } .navigationTitle("ToDoリスト") } } }
ForEachで書く
現時点では、Listの中に、4回目もHStack
を書いています。ですが、なるべく同じような処理はひとまとまりにした方が綺麗です。
ということで、何回も書いているHStack
をまとめましょう。
まずは、データを配列で持ちましょう。
let taskData = ["ジョギングする", "お花に水をやる", "部屋の掃除をする", "本を読む"]
Listの中を以下のように変更してください。これでだいぶコードが短くなります。
List(0..<taskData.count, id:\.self) { index in HStack { Image(systemName: "circle") Text(taskData[index]) } }
実行して確認してみてください。アイコンは◯だけになっちゃいますが、先ほどと同じレイアウトになるはずです。
List(0..<taskData.count, id:\.self) { index in
List()
の中に、0..<5と書くと、中の処理が5回繰り返されセルが5つ表示されます。
今回は、taskDataの数だけ表示したいので、0..<taskData.count
というふうにしています。taskData
は、4個あるので、実質0..<4
と書いているのと同じです。
index
はなんなのかというと、繰り返している回数が入ります。繰り返し1回目はindex
が1で実行されます。2回目はindex
が2で実行されます。というふに現時点の繰り返しの回数が入ります。
Text(taskData[index])
taskData[0]
で"ジョギングする"
が取得できます。taskData[1]
だと、"お花に水をやる"
が取得できます。というふうに、taskData[]
の中に番号を入れることで、値を取得できます。
今回は、そこにindexを入れることで、すべてのデータを表示させています。
これで、コードが少なくなり、わかりやすいコードになりました。
import SwiftUI struct ContentView: View { let taskData = ["ジョギングする", "お花に水をやる", "部屋の掃除をする", "本を読む"] var body: some View { NavigationView { List(0..<taskData.count, id:\.self) { index in HStack { Image(systemName: "circle") Text(taskData[index]) } } .navigationTitle("ToDoリスト") } } }
機能をつける
では、ToDoリストっぽく、ボタンを押したらチェックマークがつくようにしましょう。
まずは、セルを押せるようにしましょう。以下のようにHStack
をButton
の中に入れましょう。
Button(action: { print("セルが押されたよ") }) { HStack { Image(systemName: "circle") Text(taskData[index]) } }
このようにセルを押せるようになってるはずです。
Buttonにしたら文字色が青になってしまったので、以下のモディファイアをつけて黒に戻します。
Button(action: { print("セルが押されたよ") }) { HStack { Image(systemName: "circle") Text(taskData[index]) } } .foregroundColor(.black)
黒に戻りました。
現状のデータは、タスクが終了しているかどうかの値がないため、ボタンを押したらチェックマークがつくという実装ができません。なので、データの構成を変更します。
クラス外に以下のモデルを追加してください。
struct TaskData: Identifiable { var title: String var completed: Bool var id = UUID() }
taskData
を以下のように変更してください。(現時点ではエラーになります。)
@State var taskData = [ TaskData(title: "ジョギングする", completed: false), TaskData(title: "お花に水をやる", completed: false), TaskData(title: "部屋の掃除をする", completed: false), TaskData(title: "本を読む", completed: false) ]
データを変更したので、Text(taskData[index])
のところでエラーになっています。以下のように変更してください。
HStack { Image(systemName: "circle") Text(taskData[index].title) }
もし、completed
がfalse
だったら◯で、true
だったら☑️にしましょう。Imageの部分を以下のように変更してください。
if taskData[index].completed { Image(systemName: "checkmark.circle.fill") } else { Image(systemName: "circle") }
このくらいのif文なら、三項演算子を使った方が良いです。Imageのif文を以下のように変更しましょう。
Image(systemName: taskData[index].completed ? "checkmark.circle.fill" : "circle")
ボタンを押したら、completed
の値を変更するようにしましょう。
Button(action: { print("セルが押されたよ") taskData[index].completed.toggle() }) {
セルを押すとチェックマークがついてもう一度押すとチェクマークが外れるようになると思います。
Bool型に.toggle()
とつけると、値が逆になります。つまり、false
だったらtrue
になり、true
だったらfalse
になります。
これで、なんちゃってToDoが完成しました!
ここから、ToDoの入力フォームを作って、データを保存できるようにすれば本格的なToDoになると思います!
import SwiftUI struct TaskData: Identifiable { var title: String var completed: Bool var id = UUID() } struct ContentView: View { @State var taskData = [ TaskData(title: "ジョギングする", completed: false), TaskData(title: "お花に水をやる", completed: false), TaskData(title: "部屋の掃除をする", completed: false), TaskData(title: "本を読む", completed: false) ] var body: some View { NavigationView { List(0..<taskData.count, id:\.self) { index in Button(action: { print("セルが押されたよ") taskData[index].completed.toggle() }) { HStack { Image(systemName: taskData[index].completed ? "checkmark.circle.fill" : "circle") Text(taskData[index].title) } } .foregroundColor(.black) } .navigationTitle("ToDoリスト") } } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }