園児に水分補給を促す保育士のためのカウントタイマー【iphone・Apple Watch アプリ】
Apple Watchアプリについて
→Apple WatchとiPhoneを連携させるための重要なツール
手首の上で便利な機能や情報を提供する小型アプリケーション
perplexityとGPTで調べました。
GPT より主な機能について
おすすめなアプリも教えてくれました。
アプリ開発をする方法
「WatchKit App」をターゲットとして追加する必要がある
Apple Watchアプリは、iPhoneアプリと連携して動作することが多く、
iPhoneにインストールされたアプリがBluetooth経由でApple Watchに転送される
これにより、Apple Watch上でiPhoneアプリの一部機能を利用することができる
新規作成のところでの参考
開発環境を整える
まずはiphoneアプリを開発してみる
→Appleのスマートフォン「iPhone」上で動作するモバイルアプリ
- macを準備
- App StoreからXcodeをダウンロード
- Apple IDの作成: Apple IDが必要(アプリの公開はまだしなくて良い
Xcodeとは・・・??
参考:https://hnavi.co.jp/knowledge/blog/xcode-development/
早速作ってみよう!!
参考:https://qiita.com/yoshi-eng/items/52f7b9aa1d8d7826bdba
とりあえずプロジェクト新規作成までできた!!
理解しづらかった。YOUTUBEで探すことにした。
参考:https://www.youtube.com/watch?v=EHdAqVVzAIE
・新規プロジェクト作成
・Hello World を こんにちは、世界! にしたら反映された!!
・ボタンをつけて、ボタンを押したら実行したことが表示された!
・varだったのでconstに直した!!!
→constに直したら怒られたので、とりあえずvarのまま勉強して
のちに直すことにする
【VStack】縦に文字列が並ぶ
【HStack】横に文字列が並ぶ
【ZStack】文字列が重なる
・色がついたぞ!!!
・形が変わったぞ!!
・色の形やどうやって構成していくのかを実践してみた。
ひとまず基礎はおしまいにし、企画を立てて
作成しながら二次情報を使いながらやっていきたいと思う。
参考に作ってみる
参考:
・新規プロジェクトを作成
・さっきのSwiftUIとは違く、簡単に引っ張ってこれる。
Labelをおみくじアプリに変更
途中でファイルがなんか変になった。
気晴らしに違うの作ってみよう。
これも今度作りたい
Apple Watchアプリ開発やっていくぞ!!
iphoneとの連携の記事があまりない・・・・
とりあえずAppleWatchだけで実装してみる!!
AppleWatchだけのシュミレーター
参考:
・varを使わないで欲しい
・どうしてもViewのところはvarw使う必要があるらしい・・・
iphoneとの連携アプリを作る
アイデア出し
AppleWatchの特徴
腕に装着しているため、素早くアクセスでき、情報を即座に確認できる
iPhoneを取り出す必要がなく、移動中や運動中でも簡単に利用できる
→これを踏まえ、保育現場で使えると考えた。
保育現場では、iphoneを見ている暇もなく
常に両手を開けていないと予想外の出来事に対応できない。
インタビュー
そして先日保育行事に遊びに行ってきて
現状の保育環境を少しきいてみた。
やはり今年は暑すぎて、廊下もかなりモワモワとしている。
外で遊ぶのは熱中症アラートが出ていたため
最近では部屋でエアコンをかけすごしているという。
そして夏といえばやはり水分補給。
勤めていた時に、隣のクラスの子があまり水分を飲まない子で
熱中症になってしまったことがあった。
当時は何人もいる中で15分という目安の時間で
子ども達に水分補給を促していたが
タイマーなどがないと色々なことに対応する中で
15ふんすぎてしまうこともあった。
全然飲まない子もいるし
そういうときになんとかなんとか
自然な流れで飲めるように声の掛け方を工夫していたが
やはり、子どもにも水分補給という意識をして欲しい。
1つのものが水分補給を促してくれる目安があり
保育者も子どもも同じ立場で一緒に水分補給をとる
生活習慣ができると良いと考えた。
今は保育者が子どもたちにうながしている。
「先生も飲もうーかんぱい!」とかするが
きっかけを作っているのは変わらず保育士だ。
なので同じ目線で水分補給が取れるものを作りたい。
水分補給リマインダー を作りたい!!
水分補給リマインダーをつくる!!
ただの数字のリマインダーだと
子どもたちに強制的・義務感がある。
かといって人型で水分がなくなっていくより
遊び感覚で飲めた方がすすんで飲んでくれる。
どんどん潤ったり萎んだりするかわいい水のキャラクターを作りたい。
これはゲームの方じゃなきゃダメなのかな?
(パックちゃんみたいなシュールなものは避けたい。)
ちなみに、タイマーは欲しいが何十人もいるので
ボタンを押していると誰の基準に合わせるか分からなくなるため
繰り返し機能にする
本当は1人一人のタイマーがあったら良い。
調べて・・・
コード挿入してシンプルデザインになった!!
・エラーで使えないっぽい・・・
・ぱっくちゃんみたいになっちゃった。
形や手足をつけてみる。
・ 手足がついて、ぽくなってきた!!
が時計は下に入れたいな・・・・
・時計を下に入れて、フォントも少し丸目にしてみた。
キャラクターは黒い線で縁取り、中の水がなくなるようなところを
子供達が見てわかるようにしたかった
・0秒になったらお知らせしたい
音声をつけたい
→ぴー!とかではんく、水の音のような子どもたちの中の世界観を壊さないような
音をフリー素材で探す。
フリー素材: https://dova-s.jp/
雫があまりなかった。バブルな音にして水感があるものにした。
追加できた。
→音が鳴らなかった
・振動するのはできるのか?
→振動できなかった
期限が迫っているためここで終了。
シュミレーターをiphoneとAppleWatchどっちにも表示させたい
え、なんかだめだ・・・・
連携ができないので一旦iphone用とAppleWatch用で別々で
作ってみることにする。
import SwiftUI
import UserNotifications
struct ContentView: View {
@State private var timeRemaining = 900 // 15分 = 900秒
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
var body: some View {
ZStack {
Color.blue.opacity(0.2)
.edgesIgnoringSafeArea(.all)
VStack {
Text("いっしょに、のもう")
.font(.largeTitle)
.padding()
// キャラクターを表示する
WaterCharacterView(timeRemaining: timeRemaining)
.frame(width: 200, height: 300)
.padding()
// その他のUI要素
}
.onReceive(timer) { _ in
if timeRemaining > 0 {
timeRemaining -= 1
} else {
sendNotification()
timeRemaining = 900 // リセットして再スタート
}
}
}
}
func timeString(time: Int) -> String {
let minutes = Int(time) / 60 % 60
let seconds = Int(time) % 60
return String(format:"%02i:%02i", minutes, seconds)
}
func sendNotification() {
let content = UNMutableNotificationContent()
content.title = "水を飲む時間です!"
content.body = "休憩して水を飲みましょう。"
content.sound = .default
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: nil)
UNUserNotificationCenter.current().add(request)
}
}
struct WaterCharacterView: View {
let timeRemaining: Int
let totalTime = 900
var body: some View {
VStack {
ZStack {
// 水滴の形
Circle()
.stroke(Color.black, lineWidth: 2)
.background(
Circle()
.fill(LinearGradient(
gradient: Gradient(colors: [Color.blue.opacity(0.7), Color.blue]),
startPoint: .top,
endPoint: .bottom))
.scaleEffect(x: 1, y: CGFloat(timeRemaining) / CGFloat(totalTime), anchor: .bottom)
)
.clipShape(Circle())
// 顔のパーツ
VStack {
Spacer()
HStack {
Eye()
Eye()
}
.padding(.bottom, 20)
Mouth()
Spacer()
.frame(height: 50)
}
// 手と足
Hand()
.rotationEffect(.degrees(-45))
.offset(x: -70, y: 60)
Hand()
.rotationEffect(.degrees(45))
.offset(x: 70, y: 60)
Foot()
.rotationEffect(.degrees(20))
.offset(x: -30, y: 120)
Foot()
.rotationEffect(.degrees(-20))
.offset(x: 30, y: 120)
}
.clipped()
.animation(.easeInOut(duration: 1), value: timeRemaining)
// 時間の表示
Text(timeString(time: timeRemaining))
.font(.custom("Avenir Next", size: 24)) // 丸っぽいフォントを使用
.foregroundColor(.black) // テキストカラーを黒に設定
.bold()
.padding(.top, 10) // 少し余白を追加
}
}
func timeString(time: Int) -> String {
let minutes = Int(time) / 60 % 60
let seconds = Int(time) % 60
return String(format:"%02i:%02i", minutes, seconds)
}
}
struct Eye: View {
var body: some View {
Circle()
.fill(Color.black)
.frame(width: 20, height: 20)
.padding(.horizontal, 10)
}
}
struct Mouth: View {
var body: some View {
Path { path in
path.move(to: CGPoint(x: 0, y: 0))
path.addQuadCurve(to: CGPoint(x: 40, y: 0), control: CGPoint(x: 20, y: 20))
}
.stroke(Color.black, lineWidth: 2)
.frame(width: 40, height: 20)
.offset(y: 10)
}
}
struct Hand: View {
var body: some View {
Capsule()
.fill(Color.blue)
.frame(width: 20, height: 60)
}
}
struct Foot: View {
var body: some View {
Capsule()
.fill(Color.blue)
.frame(width: 20, height: 40)
}
}
struct WaterReminderApp_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
コードの中の水を飲む時間です・・・
って画面に表示されてないけどなんでだ・・・
func sendNotification() {
let content = UNMutableNotificationContent()
content.title = "水を飲む時間です!"
content.body = "休憩して水を飲みましょう。"
content.sound = .default
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: nil)
UNUserNotificationCenter.current().add(request)
}
iphoneも無事できた!!
AppleWatchの画面に対して大きすぎたので修正する。
できたー!!
プロンプトは、キャラクターの手足がバラバラになりやすいので
キャラクターはグループ化にした上で とお願いした。
この聞き方が1番良かったl。動作がイメージとあっていた。
AppleWatch用のコード
import SwiftUI
import UserNotifications
struct ContentView: View {
@State private var timeRemaining = 900 // 15分 = 900秒
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
var body: some View {
GeometryReader { geometry in
ZStack {
Color.blue.opacity(0.2)
.edgesIgnoringSafeArea(.all)
VStack {
Text("いっしょに、のもう")
.font(.system(size: geometry.size.width * 0.06))
.padding(.top, geometry.size.height * 0.05)
Spacer()
// キャラクターを表示する
WaterCharacterView(timeRemaining: timeRemaining)
.frame(width: geometry.size.width * 0.7, height: geometry.size.height * 0.6)
Spacer()
// 時間の表示
Text(timeString(time: timeRemaining))
.font(.system(size: geometry.size.width * 0.08, weight: .bold))
.foregroundColor(.white) // テキストカラーを白に設定
.padding(.bottom, geometry.size.height * 0.05)
}
}
.onReceive(timer) { _ in
if timeRemaining > 0 {
timeRemaining -= 1
} else {
sendNotification()
timeRemaining = 900 // リセットして再スタート
}
}
}
}
func timeString(time: Int) -> String {
let minutes = Int(time) / 60 % 60
let seconds = Int(time) % 60
return String(format:"%02i:%02i", minutes, seconds)
}
func sendNotification() {
let content = UNMutableNotificationContent()
content.title = "水を飲む時間です!"
content.body = "休憩して水を飲みましょう。"
content.sound = .default
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: nil)
UNUserNotificationCenter.current().add(request)
}
}
struct WaterCharacterView: View {
let timeRemaining: Int
let totalTime = 900
var body: some View {
GeometryReader { geometry in
ZStack {
WaterDropShape(progress: CGFloat(timeRemaining) / CGFloat(totalTime))
CharacterFace()
.frame(width: geometry.size.width * 0.6, height: geometry.size.height * 0.3)
.position(x: geometry.size.width / 2, y: geometry.size.height * 0.4)
CharacterLimbs()
.frame(width: geometry.size.width, height: geometry.size.height)
}
.animation(.easeInOut(duration: 1), value: timeRemaining)
}
}
}
struct WaterDropShape: View {
let progress: CGFloat
var body: some View {
Circle()
.stroke(Color.black, lineWidth: 2)
.background(
Circle()
.fill(LinearGradient(
gradient: Gradient(colors: [Color.blue.opacity(0.7), Color.blue]),
startPoint: .top,
endPoint: .bottom))
.scaleEffect(x: 1, y: progress, anchor: .bottom)
)
.clipShape(Circle())
}
}
struct CharacterFace: View {
var body: some View {
VStack {
HStack {
Eye()
Eye()
}
Mouth()
}
}
}
struct CharacterLimbs: View {
var body: some View {
GeometryReader { geometry in
Group {
Hand()
.rotationEffect(.degrees(-45))
.position(x: geometry.size.width * 0.2, y: geometry.size.height * 0.6)
Hand()
.rotationEffect(.degrees(45))
.position(x: geometry.size.width * 0.8, y: geometry.size.height * 0.6)
Foot()
.rotationEffect(.degrees(20))
.position(x: geometry.size.width * 0.35, y: geometry.size.height * 0.85)
Foot()
.rotationEffect(.degrees(-20))
.position(x: geometry.size.width * 0.65, y: geometry.size.height * 0.85)
}
}
}
}
struct Eye: View {
var body: some View {
Circle()
.fill(Color.black)
.frame(width: 8, height: 8)
.padding(.horizontal, 4)
}
}
struct Mouth: View {
var body: some View {
Path { path in
path.move(to: CGPoint(x: 0, y: 0))
path.addQuadCurve(to: CGPoint(x: 16, y: 0), control: CGPoint(x: 8, y: 8))
}
.stroke(Color.black, lineWidth: 1)
.frame(width: 16, height: 8)
.offset(y: 4)
}
}
struct Hand: View {
var body: some View {
Capsule()
.fill(Color.blue)
.frame(width: 8, height: 24)
}
}
struct Foot: View {
var body: some View {
Capsule()
.fill(Color.blue)
.frame(width: 8, height: 16)
}
}
struct WaterReminderApp_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
今後、できたら保育現場に置くならば
先生の時計をつけてリマインダーすることも大切だけど
子どもたちに自主的な水分補給を促すなら
大きな画面(例えばipadとか)で子どもたちが
見に行けるようなものを設置すると良いかも・・・
実機で動かしてみたい!
参考にさせていただきました
まだ挑戦中・・・
ときメーターに使えるかも?!
・自分のときめき度を可視化する上で心拍のバイタルを取る
→AppleWatchが必要になってくるかも・・・
→iphone開発もあるかもしれない・・・
AppleWatch使うとしてもみんながみんな持っているわけではないから
使うか迷うけど幅としては持っておこう・・