20201120のiOSに関する記事は11件です。

Xamarin.FormsにてiOSのビルドエラー。画像がFile not foundとされる問題

以下の問題が発生していましたが解決したので記録しておきます。
同じような問題を抱える開発者もいると思うので参考になれば幸いです。

問題

以下のビルドエラーがでる

File not found: ~/Library/Caches/Xamarin/mtbs/builds/~/AppIcon.appiconset/[画像ファイル名].png

前提

  • Microsoft Visual Studio 2019 を使用
  • iOS ビルド時にエラー
  • Macbookの容量がないなどの理由でLibrary/Caches/内の削除など行った
  • AppIcons.appiconsetで設定している

原因

iOSのプロジェクトファイルにすでに使用されていないAssetの参照先が残っていた。
Macbook内のLibrary/Cachesフォルダ内に対象のファイルが存在しないためエラーを起こしていた。

解決策

iOSのプロジェクトファイルにすでに使用されていないAssetの参照先を削除する。

ProjectName.iOS.csproj
  <ItemGroup>
    <ImageAsset Include="Assets.xcassets\AppIcon.appiconset\appstore.png"> <!-- AppIconsではなくAppIconなど、以前設定していたパスが残っている(この部分を削除) -->
      <Visible>false</Visible>
    </ImageAsset>
    <!-- (略) -->
    <ImageAsset Include="Assets.xcassets\AppIcons.appiconset\appstore.png">  <!-- 以下は現在使用している正しいパス -->
      <Visible>false</Visible>
    </ImageAsset>
    <ImageAsset Include="Assets.xcassets\AppIcons.appiconset\Contents.json">
      <Visible>false</Visible>
    </ImageAsset>
    <ImageAsset Include="Assets.xcassets\AppIcons.appiconset\icon120.png">
      <Visible>false</Visible>
    </ImageAsset>
    <ImageAsset Include="Assets.xcassets\AppIcons.appiconset\icon152.png">
      <Visible>false</Visible>
    </ImageAsset>
    <ImageAsset Include="Assets.xcassets\AppIcons.appiconset\icon167.png">
      <Visible>false</Visible>
    </ImageAsset>
    <!-- (略) -->
  </ItemGroup>

結論

iOSのプロジェクトファイル内は普通は編集することはないはずでバグの一種で設定が残っていたと思われる。(改善されている可能性もある)
MacbookのLibrary/Caches/内の削除前は問題なくビルドが通っていたので削除を行ったことでエラーが表面化したと思われます。
以上、同様の問題で参考になれば幸いです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[iOS・Swift] iPhoneからjsonデータを取得する方法

はじめに

Swiftでjsonファイルを取り出す過程で詰まるポイントがありましたので、共有したいと思います。

①jsonファイルを作成するまで

Export Json Fileというボタンを押して、jsonファイルを吐き出すようにしました。
※Simulatorではなく、実機で動かしています

②jsonファイルをXcodeからダウンロードする

Devices and Simulatorsから作成したアプリケーションを選択します。

選択後、以下のような歯車ボタンからDownload Containerを開きます。

ダウンロード後、Finderよりダウンロードファイル(ex. com.kamimura.HealthKitDataCollection 2020-11-20 14/46.13.735.xcappdata)からパッケージの内容を表示で開きます。

その後、AppData -> Documents -> output.jsonで作成したjsonファイルが存在しております。

※ファイルの存在場所は、この限りではありませんのでご注意ください!

本アプリのGithub (https://github.com/Ryosukekamimura/HealthKit_Data_Collection)

最後まで読んでいただき、ありがとうございます。
誰かのためになれば、幸いです!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

プログラミング超初心者がFlutterの環境構築をしてみた

やったこと
KBOYさんのYouTubeを見ながら、Flutterの環境構築をしました。

1、Flutterのインストール
2、Flutterのパスを通す

2からすでに、苦戦するという「マジか」と思いつつなんとかできました。

.bash_profile にパスを記載しようとしたのですが、
最近のPCは bash ではなく 

.zshrc っていうのが最近の新しいパス設定の場所らしい

参考にした動画
https://www.youtube.com/watch?v=kpvVENfDCRc&list=PLuLRJz1UnJzE4-HlkLTG8ARbZ2TDBNHzZ

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Swift5]storyboardとコードでNavigationBarをカスタムする方法

なぜstoryboardだけでやらない?

Swiftで開発を進める際に、storyboardでUIを構築するか、コードのみでUIを構築するか初学者の方は悩まれるのでは?と私は思います。

storyboardのみで開発しても良いのですが、コードでカスタムした方が作業工数を減らせることや、デザインの変更などが必要な場合に、コードの方が編集しやすい点などからコードでカスタムを行います。しかし、コードのみだと画面遷移などが直感的に理解しずらいので、今回は最低限をstoryboardで構築し、カスタム内容はコードで記述します。

その他にも、storyboardのみで構築するとコンフリクトが発生しやすい問題や、コードのみで構築するとコードの記述量が多くなるなど双方にメリット,デメリットが存在します。

storyboardでNavigartionControllerの実装

まずstoryboardでNavigationBarを用意します。

①storyboardのiPhoneを選択(下記画像中央)
image.png
②Xcodeのメニューバー(Mac液晶最上部)から
/Editor/Embed In/NavigationController/を選択

③すると下記画像のようにNavigationControllerを継承したViewControllerが作成される。
image.png
これでstoryboardによるNavigationBarの準備が整いました。

コードのよるNavigationBarのカスタム

NavigationBarのカスタムをコードでおこないます。今回カスタムするのは以下の通り。

① NavigationBarの色
② NavigationBarのtitle
③ NavigationBarのtitleの文字色
④ NavigationBarのtitleのフォントとサイズ
⑤ すりガラスのような状態をfalseに
⑥ NavigationBarの下線を消す

それではコードを記述します。

ViewController.swift
class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        //NavigationBarのtitleとその色とフォント
        navigationItem.title = "サンプル文字列"
        self.navigationController?.navigationBar.titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 20.0)]

        //NavigationBarの色
        self.navigationController?.navigationBar.barTintColor = UIColor.red

        //一部NavigationBarがすりガラス?のような感じになるのでfalseを指定
        self.navigationController?.navigationBar.isTranslucent = false

        //NavigationBarの下線を消す
        navigationController?.navigationBar.setValue(true, forKey: "hidesShadow")
    }
}

ビルドすると下記画像の通りNavigationBarのデザインが変更されたのが確認できます!
image.png

//一部NavigationBarがすりガラス?のような感じになるのでfalseを指定
self.navigationController?.navigationBar.isTranslucent = false

//一部NavigationBarがすりガラス?のような感じになるのでfalseを指定に関しては、
falseを指定しない場合、想定外のカラーになるので記述。

実際に自身で色やフォントサイズをアレンジしてみると学びが深まると思いますのでぜひ!

最後に

冒頭でも述べましたが、storyboardでのUI構築とコードのみでのUI構築の双方にメリット&デメリットが存在するので、互いの特徴を理解して扱っていく必要がありますね!

最後までご覧いただきありがとうございます!
ぜひ参考にしてください。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Metal で サポートしている GPU family と feature set を調べる

M1 Mac mini がやってきた

我が家に M1 Chip の Mac mini がやってきました。これまで、Metal の試行錯誤は、Intel Mac の Simulator と 実際の iPhone や iPad でサポートしている機能が違うので、試行錯誤の効率が悪かったのですが、M1 Chip Mac を入手したので、A12相当の機能の試行錯誤などの効率があがるものと期待していました。しかし、M1 Chip の Mac の Simulator で検証コードを動かすと、思いもよらぬところで落ちました。

「あれ?」と思い、iPad Pro で実行すると、落ちません。そこで、色々調べ始めると、M1 Chip + Big Sur + Xcode 12.2 のシミュレータでは、A8相当にしかならない事に気がつきました。そこで、2020年10月21日つまり比較的最近アップデートされた、Metal Feature Set Tables を調べてみても、M1 の記述が全くありません。

Metal Feature Set Tables

Appleの公式ドキュメントはこれです。

https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf

iOS, macOSの実行環境は結構組み合わせが多い

よくよく考えると、macOS, iOS で動作するアプリの環境は様々です。

  • iOS native on A chip
  • iOS simulator on Intel Mac
  • iOS simulator on M chip
  • macOS native on Intel Mac
  • macOS native on M chip
  • macCatalyst on Intel Mac
  • macCatalyst on M chip

例えば最終的な実行環境はA chipのみを対象としていても、開発工程で simulator などを使うと効率が上がる場合があります。Metal で試行錯誤を繰り返すには、どの機能がどの環境で動作するのか明確にする必要があると思いました。

MetalFeatureQuery

そこで、簡単にテストできるプロジェクトを作ってみました。上記の組み合わせで動作する筈ですが、まだ全てで試した訳ではありません。

https://github.com/codelynx/MetalFeatureQuery

環境

執筆時点の環境は以下の通りです。

Apple Swift version 5.3.1 (swiftlang-1200.0.41 clang-1200.0.32.8)
Target: arm64-apple-darwin20.1.0

Xcode Version 12.2 (12B45b)
macOS Big Sur 11.0.1 (20B29)

License

MIT License

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【SwiftUI】経過時間の表示とListViewのセルデザイン

はじめに

SwiftUIでRelativeDateTimeFormatterクラスを用いて、経過時間を取得できるようにすることと、取得した経過時間を表示することを目的とする。

UIのデザインはcakesのnote風のデザインを参考にカード型のViewを作ります。
今後は今回作成したカードに前回までに実装した地図と都道府県市町村名を表示できるようにし、Firebaseで更新できるようにすることが目的です。
前回までの記事は以下を参考ください。

参考記事
【SwiftUI】Mapkitから取得した情報をFirebaseに保存する

開発環境

OSX 10.15.7 (Catalina)
Xcode 12.2.0
CocoaPods 1.10.0

RelativeDateTimeFormatterの実装

基準日時からの経過時間を出力するクラスです。Twitterなどの○秒前や○日前などを表示をすることができます。
ロケーションを設定することで英語表記や日本語表記に変更が可能になります。
以下では○秒前、○分前、○時間前、○日前、○年前をそれぞれ記載しています。

参考記事
How to show a relative date and time using RelativeDateTimeFormatter
Relative date time formatting in SwiftUI

import SwiftUI

let nowTime = Date()

print(nowTime)

let formatter = RelativeDateTimeFormatter()
formatter.locale = Locale(identifier: "ja_JP")

let fmt = ISO8601DateFormatter()

// ○秒前
let createdDate = "2020-11-19T16:12:30+0000"
print(createdDate)

let date1 = fmt.date(from: createdDate)!
let components = Calendar.current.dateComponents(
    [.day, .year, .month, .minute, .second],
    from: Date(),
    to: date1
)
let timeAgo1 = formatter.localizedString(from: components)

print(timeAgo1)

// ○分前
let createdDate2 = "2020-11-19T16:00:00+0000"
print(createdDate2)

let date2 = fmt.date(from: createdDate2)!
let components2 = Calendar.current.dateComponents(
    [.day, .year, .month, .minute, .second],
    from: Date(),
    to: date2
)
let timeAgo2 = formatter.localizedString(from: components2)

print(timeAgo2)


// ○時間前
let createdDate3 = "2020-11-19T11:00:00+0000"
print(createdDate3)

let date3 = fmt.date(from: createdDate3)!
let components3 = Calendar.current.dateComponents(
    [.day, .year, .month,.hour ,.minute, .second],
    from: Date(),
    to: date3
)
let timeAgo3 = formatter.localizedString(from: components3)

print(timeAgo3)

// ○日前
let createdDate4 = "2020-11-15T11:00:00+0000"
print(createdDate4)

let date4 = fmt.date(from: createdDate4)!
let components4 = Calendar.current.dateComponents(
    [.year, .month, .day, .hour , .minute, .second],
    from: Date(),
    to: date4
)
let timeAgo4 = formatter.localizedString(from: components4)

print(timeAgo4)

// ○年前
let createdDate5 = "2000-11-15T11:00:00+0000"
print(createdDate4)

let date5 = fmt.date(from: createdDate5)!
let components5 = Calendar.current.dateComponents(
    [.year, .month, .day, .hour , .minute, .second],
    from: Date(),
    to: date5
)
let timeAgo5 = formatter.localizedString(from: components5)

print(timeAgo5)

playgroundで出力した結果は以下のとおりです。

2020-11-19 16:12:35 +0000
2020-11-19T16:12:30+0000
5 秒前
2020-11-19T16:00:00+0000
12 分前
2020-11-19T11:00:00+0000
5 時間前
2020-11-15T11:00:00+0000
4 日前
2020-11-15T11:00:00+0000
20 年前

経過時間は自動で切り替えて表示されます。

RelativeDateTimeFormatterを実装し、経過時間を表示したカードを作る。

手順は以下のとおりです。
1. 地図、タイトル、作者、日時などを表示したカード型のViewをつくる
2. リストに先ほど作成したカードを表示

ContentView_swift.png

LocationRow.swift
import SwiftUI

struct ContentView: View {
    var user = "松尾芭蕉"
    var userImage = "basho"
    var haiku = "古池や 蛙飛びこむ 水の音"
    var mapImage = "mapImage"
    var place = "東京都江東区"

    static let formatter = RelativeDateTimeFormatter()

    var body: some View {

        // ○秒、○日、○年前を表示
        let createdDate = "1686-01-01T12:00:00+0009"

        ContentView.formatter.locale = Locale(identifier: "ja_JP")

        let fmt = ISO8601DateFormatter()
        let date1 = fmt.date(from: createdDate)!
        let components = Calendar.current.dateComponents(
            [.day, .year, .month, .minute, .second],
            from: Date(),
            to: date1
        )
        let timeAgo = ContentView.formatter.localizedString(from: components)

        return VStack {
            VStack {
                Image(mapImage)
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .cornerRadius(12.0, antialiased: /*@START_MENU_TOKEN@*/true/*@END_MENU_TOKEN@*/)
                HStack {
                    Spacer()
                    Text(place).font(.caption).foregroundColor(.gray)
                        .padding(.bottom, 5)
                }
            }

            Text(haiku).font(.title3).fontWeight(.bold)

            HStack {
                Image(systemName: "heart").font(.headline).foregroundColor(Color("pinkColor"))
                Text("225").font(.headline).foregroundColor(Color("pinkColor"))
                Spacer()
            }.padding(.top, 5)


            HStack {
                Image(userImage)
                    .resizable()
                    .frame(width: 30, height: 30)
                    .clipShape(Circle())

                HStack {
                    Text(user).font(.headline).fontWeight(.light)
                    + Text("・").font(.headline).fontWeight(.light)
                    + Text(timeAgo).font(.headline).fontWeight(.light)
                }
                Spacer()
                HStack {

                    Image(systemName: "text.bubble").font(.title).foregroundColor(.gray)
                    Image(systemName: "heart.fill").font(.title).foregroundColor(Color("pinkColor"))
                }
            }
        }.padding()
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
            .previewLayout(.fixed(width: 414, height: 391))
    }
}

今後は今回作成したカードをリストにし、表示できるようにします。

以上です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【SwiftUi】RelativeDateTimeFormatterクラス実装とListViewのセルデザイン

はじめに

SwiftUIでRelativeDateTimeFormatterクラスを用いて、経過時間を取得できるようにすることと、取得した経過時間を表示することを目的とする。

UIのデザインはcakesのnote風のデザインを参考にカード型のViewを作ります。
今後は今回作成したカードに前回までに実装した地図と都道府県市町村名を表示できるようにし、Firebaseで更新できるようにすることが目的です。
前回までの記事は以下を参考ください。

参考記事
【SwiftUI】Mapkitから取得した情報をFirebaseに保存する

開発環境

OSX 10.15.7 (Catalina)
Xcode 12.2.0
CocoaPods 1.10.0

RelativeDateTimeFormatterの実装

基準日時からの経過時間を出力するクラスです。Twitterなどの○秒前や○日前などを表示をすることができます。
ロケーションを設定することで英語表記や日本語表記に変更が可能になります。
以下では○秒前、○分前、○時間前、○日前、○年前をそれぞれ記載しています。

参考記事
How to show a relative date and time using RelativeDateTimeFormatter
Relative date time formatting in SwiftUI

import SwiftUI

let nowTime = Date()

print(nowTime)

let formatter = RelativeDateTimeFormatter()
formatter.locale = Locale(identifier: "ja_JP")

let fmt = ISO8601DateFormatter()

// ○秒前
let createdDate = "2020-11-19T16:12:30+0000"
print(createdDate)

let date1 = fmt.date(from: createdDate)!
let components = Calendar.current.dateComponents(
    [.day, .year, .month, .minute, .second],
    from: Date(),
    to: date1
)
let timeAgo1 = formatter.localizedString(from: components)

print(timeAgo1)

// ○分前
let createdDate2 = "2020-11-19T16:00:00+0000"
print(createdDate2)

let date2 = fmt.date(from: createdDate2)!
let components2 = Calendar.current.dateComponents(
    [.day, .year, .month, .minute, .second],
    from: Date(),
    to: date2
)
let timeAgo2 = formatter.localizedString(from: components2)

print(timeAgo2)


// ○時間前
let createdDate3 = "2020-11-19T11:00:00+0000"
print(createdDate3)

let date3 = fmt.date(from: createdDate3)!
let components3 = Calendar.current.dateComponents(
    [.day, .year, .month,.hour ,.minute, .second],
    from: Date(),
    to: date3
)
let timeAgo3 = formatter.localizedString(from: components3)

print(timeAgo3)

// ○日前
let createdDate4 = "2020-11-15T11:00:00+0000"
print(createdDate4)

let date4 = fmt.date(from: createdDate4)!
let components4 = Calendar.current.dateComponents(
    [.year, .month, .day, .hour , .minute, .second],
    from: Date(),
    to: date4
)
let timeAgo4 = formatter.localizedString(from: components4)

print(timeAgo4)

// ○年前
let createdDate5 = "2000-11-15T11:00:00+0000"
print(createdDate4)

let date5 = fmt.date(from: createdDate5)!
let components5 = Calendar.current.dateComponents(
    [.year, .month, .day, .hour , .minute, .second],
    from: Date(),
    to: date5
)
let timeAgo5 = formatter.localizedString(from: components5)

print(timeAgo5)

playgroundで出力した結果は以下のとおりです。

2020-11-19 16:12:35 +0000
2020-11-19T16:12:30+0000
5 秒前
2020-11-19T16:00:00+0000
12 分前
2020-11-19T11:00:00+0000
5 時間前
2020-11-15T11:00:00+0000
4 日前
2020-11-15T11:00:00+0000
20 年前

経過時間は自動で切り替えて表示されます。

RelativeDateTimeFormatterを実装し、経過時間を表示したカードを作る。

手順は以下のとおりです。
1. 地図、タイトル、作者、日時などを表示したカード型のViewをつくる
2. リストに先ほど作成したカードを表示

ContentView_swift.png

LocationRow.swift
import SwiftUI

struct ContentView: View {
    var user = "松尾芭蕉"
    var userImage = "basho"
    var haiku = "古池や 蛙飛びこむ 水の音"
    var mapImage = "mapImage"
    var place = "東京都江東区"

    static let formatter = RelativeDateTimeFormatter()

    var body: some View {

        // ○秒、○日、○年前を表示
        let createdDate = "1686-01-01T12:00:00+0009"

        ContentView.formatter.locale = Locale(identifier: "ja_JP")

        let fmt = ISO8601DateFormatter()
        let date1 = fmt.date(from: createdDate)!
        let components = Calendar.current.dateComponents(
            [.day, .year, .month, .minute, .second],
            from: Date(),
            to: date1
        )
        let timeAgo = ContentView.formatter.localizedString(from: components)

        return VStack {
            VStack {
                Image(mapImage)
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .cornerRadius(12.0, antialiased: /*@START_MENU_TOKEN@*/true/*@END_MENU_TOKEN@*/)
                HStack {
                    Spacer()
                    Text(place).font(.caption).foregroundColor(.gray)
                        .padding(.bottom, 5)
                }
            }

            Text(haiku).font(.title3).fontWeight(.bold)

            HStack {
                Image(systemName: "heart").font(.headline).foregroundColor(Color("pinkColor"))
                Text("225").font(.headline).foregroundColor(Color("pinkColor"))
                Spacer()
            }.padding(.top, 5)


            HStack {
                Image(userImage)
                    .resizable()
                    .frame(width: 30, height: 30)
                    .clipShape(Circle())

                HStack {
                    Text(user).font(.headline).fontWeight(.light)
                    + Text("・").font(.headline).fontWeight(.light)
                    + Text(timeAgo).font(.headline).fontWeight(.light)
                }
                Spacer()
                HStack {

                    Image(systemName: "text.bubble").font(.title).foregroundColor(.gray)
                    Image(systemName: "heart.fill").font(.title).foregroundColor(Color("pinkColor"))
                }
            }
        }.padding()
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
            .previewLayout(.fixed(width: 414, height: 391))
    }
}

今後は今回作成したカードをリストにし、表示できるようにします。

以上です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【SwiftUi】経過時間の表示とListViewのセルデザイン

はじめに

SwiftUIでRelativeDateTimeFormatterクラスを用いて、経過時間を取得できるようにすることと、取得した経過時間を表示することを目的とする。

UIのデザインはcakesのnote風のデザインを参考にカード型のViewを作ります。
今後は今回作成したカードに前回までに実装した地図と都道府県市町村名を表示できるようにし、Firebaseで更新できるようにすることが目的です。
前回までの記事は以下を参考ください。

参考記事
【SwiftUI】Mapkitから取得した情報をFirebaseに保存する

開発環境

OSX 10.15.7 (Catalina)
Xcode 12.2.0
CocoaPods 1.10.0

RelativeDateTimeFormatterの実装

基準日時からの経過時間を出力するクラスです。Twitterなどの○秒前や○日前などを表示をすることができます。
ロケーションを設定することで英語表記や日本語表記に変更が可能になります。
以下では○秒前、○分前、○時間前、○日前、○年前をそれぞれ記載しています。

参考記事
How to show a relative date and time using RelativeDateTimeFormatter
Relative date time formatting in SwiftUI

import SwiftUI

let nowTime = Date()

print(nowTime)

let formatter = RelativeDateTimeFormatter()
formatter.locale = Locale(identifier: "ja_JP")

let fmt = ISO8601DateFormatter()

// ○秒前
let createdDate = "2020-11-19T16:12:30+0000"
print(createdDate)

let date1 = fmt.date(from: createdDate)!
let components = Calendar.current.dateComponents(
    [.day, .year, .month, .minute, .second],
    from: Date(),
    to: date1
)
let timeAgo1 = formatter.localizedString(from: components)

print(timeAgo1)

// ○分前
let createdDate2 = "2020-11-19T16:00:00+0000"
print(createdDate2)

let date2 = fmt.date(from: createdDate2)!
let components2 = Calendar.current.dateComponents(
    [.day, .year, .month, .minute, .second],
    from: Date(),
    to: date2
)
let timeAgo2 = formatter.localizedString(from: components2)

print(timeAgo2)


// ○時間前
let createdDate3 = "2020-11-19T11:00:00+0000"
print(createdDate3)

let date3 = fmt.date(from: createdDate3)!
let components3 = Calendar.current.dateComponents(
    [.day, .year, .month,.hour ,.minute, .second],
    from: Date(),
    to: date3
)
let timeAgo3 = formatter.localizedString(from: components3)

print(timeAgo3)

// ○日前
let createdDate4 = "2020-11-15T11:00:00+0000"
print(createdDate4)

let date4 = fmt.date(from: createdDate4)!
let components4 = Calendar.current.dateComponents(
    [.year, .month, .day, .hour , .minute, .second],
    from: Date(),
    to: date4
)
let timeAgo4 = formatter.localizedString(from: components4)

print(timeAgo4)

// ○年前
let createdDate5 = "2000-11-15T11:00:00+0000"
print(createdDate4)

let date5 = fmt.date(from: createdDate5)!
let components5 = Calendar.current.dateComponents(
    [.year, .month, .day, .hour , .minute, .second],
    from: Date(),
    to: date5
)
let timeAgo5 = formatter.localizedString(from: components5)

print(timeAgo5)

playgroundで出力した結果は以下のとおりです。

2020-11-19 16:12:35 +0000
2020-11-19T16:12:30+0000
5 秒前
2020-11-19T16:00:00+0000
12 分前
2020-11-19T11:00:00+0000
5 時間前
2020-11-15T11:00:00+0000
4 日前
2020-11-15T11:00:00+0000
20 年前

経過時間は自動で切り替えて表示されます。

RelativeDateTimeFormatterを実装し、経過時間を表示したカードを作る。

手順は以下のとおりです。
1. 地図、タイトル、作者、日時などを表示したカード型のViewをつくる
2. リストに先ほど作成したカードを表示

ContentView_swift.png

LocationRow.swift
import SwiftUI

struct ContentView: View {
    var user = "松尾芭蕉"
    var userImage = "basho"
    var haiku = "古池や 蛙飛びこむ 水の音"
    var mapImage = "mapImage"
    var place = "東京都江東区"

    static let formatter = RelativeDateTimeFormatter()

    var body: some View {

        // ○秒、○日、○年前を表示
        let createdDate = "1686-01-01T12:00:00+0009"

        ContentView.formatter.locale = Locale(identifier: "ja_JP")

        let fmt = ISO8601DateFormatter()
        let date1 = fmt.date(from: createdDate)!
        let components = Calendar.current.dateComponents(
            [.day, .year, .month, .minute, .second],
            from: Date(),
            to: date1
        )
        let timeAgo = ContentView.formatter.localizedString(from: components)

        return VStack {
            VStack {
                Image(mapImage)
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .cornerRadius(12.0, antialiased: /*@START_MENU_TOKEN@*/true/*@END_MENU_TOKEN@*/)
                HStack {
                    Spacer()
                    Text(place).font(.caption).foregroundColor(.gray)
                        .padding(.bottom, 5)
                }
            }

            Text(haiku).font(.title3).fontWeight(.bold)

            HStack {
                Image(systemName: "heart").font(.headline).foregroundColor(Color("pinkColor"))
                Text("225").font(.headline).foregroundColor(Color("pinkColor"))
                Spacer()
            }.padding(.top, 5)


            HStack {
                Image(userImage)
                    .resizable()
                    .frame(width: 30, height: 30)
                    .clipShape(Circle())

                HStack {
                    Text(user).font(.headline).fontWeight(.light)
                    + Text("・").font(.headline).fontWeight(.light)
                    + Text(timeAgo).font(.headline).fontWeight(.light)
                }
                Spacer()
                HStack {

                    Image(systemName: "text.bubble").font(.title).foregroundColor(.gray)
                    Image(systemName: "heart.fill").font(.title).foregroundColor(Color("pinkColor"))
                }
            }
        }.padding()
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
            .previewLayout(.fixed(width: 414, height: 391))
    }
}

今後は今回作成したカードをリストにし、表示できるようにします。

以上です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Flutterチュートリアルを咀嚼する part1 -FlutterはWidgetまみれ-

Flutterって一つのソースを書くだけでiOSもAndroidもアプリ作ってくれるんだって
すごいなー
勉強してみよう

対象のチュートリアル

https://codelabs.developers.google.com/codelabs/first-flutter-app-pt1#0

コピペしてできあがったもの

スタートアップ企業の名前をつけてあげるために単語二つの組み合わせをリスト化してくれるアプリ

スクリーンショット 2020-11-17 16.02.22.png

ソースコード

main.dart
import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Startup Name Generator',
      home: RandomWords(),
    );
  }
}

class RandomWords extends StatefulWidget {
  @override
  _RandomWordsState createState() => _RandomWordsState();
}

class _RandomWordsState extends State<RandomWords> {
  final _suggestions = <WordPair>[];
  final _biggerFont = TextStyle(fontSize: 18.0);
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Startup Name Generator'),
      ),
      body: _buildSuggestions(),
    );
  }

  Widget _buildSuggestions() {
    return ListView.builder(
        padding: EdgeInsets.all(16.0),
        itemBuilder: /*1*/ (context, i) {
          if (i.isOdd) return Divider(); /*2*/

          final index = i ~/ 2; /*3*/
          if (index >= _suggestions.length) {
            _suggestions.addAll(generateWordPairs().take(10)); /*4*/
          }
          return _buildRow(_suggestions[index]);
        });
  }

  Widget _buildRow(WordPair pair) {
    return ListTile(
      title: Text(
        pair.asPascalCase,
        style: _biggerFont,
      ),
    );
  }
}

順々にみていこう

import

import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';

package:flutter/material.dart

これがないと始まらないっぽい
Flutterアプリの主役たち

クラス

Widget

https://api.flutter.dev/flutter/widgets/Widget-class.html
Flutterフレームワークの中心的なクラス
FlutterではほとんどのものがWidget
Widget単位でアプリが構築されていく

StatelessWidget

https://api.flutter.dev/flutter/widgets/StatelessWidget-class.html
State(状態)を持たないWidget
不変(immutable)であり静的(static)
親のWidgetから引数を与えてあげることで描画される
反対はStatefulWidget

※参考
https://tech-rise.net/difference-between-stateless-widget-and-stateful-widget

StatefulWidget

https://api.flutter.dev/flutter/widgets/StatefulWidget-class.html

チュートリアルの中で
Implementing a stateful widget requires at least two classes: 1) a StatefulWidget class that creates an instance of 2) a State class.

とあるように、statefulなWidgetを作るためには、②Stateクラスのインスタンスを生成する①StatefulWidgetクラスを用意する必要がある。
要はStateクラスとセットということらしい。

State

https://api.flutter.dev/flutter/widgets/State-class.html

StatefulWidgetとセットになるもの。
StatefulWidgetの中でインスタンス化される。
StatefulWidgetのロジックはここで実装する。
Stateクラスの名前の頭には_(アンダーバー)をつける。

BuildContext

https://api.flutter.dev/flutter/widgets/BuildContext-class.html

※参考
https://qiita.com/agajo/items/93d75aafe87bdc7b2026
https://itome.team/blog/2019/12/flutter-advent-calendar-day6/

MaterialApp

https://api.flutter.dev/flutter/material/MaterialApp-class.html
マテリアルデザインアプリケーションに一般的に必要とされる多くのウィジェットをラップする便利なウィジェット。

Scaffold

https://api.flutter.dev/flutter/material/Scaffold-class.html

AppBar

https://api.flutter.dev/flutter/material/AppBar-class.html

Text

https://api.flutter.dev/flutter/dart-html/Text-class.html

ListView

https://api.flutter.dev/flutter/widgets/ListView-class.html

EdgeInsets

https://api.flutter.dev/flutter/painting/EdgeInsets-class.html

Divider

https://api.flutter.dev/flutter/material/Divider-class.html

関数

runApp()

https://api.flutter.dev/flutter/widgets/runApp.html
指定されたウィジェットを膨らませて、画面に添付する。

メソッド

build()

https://api.flutter.dev/flutter/dart-ui/ParagraphBuilder/build.html
Widgetの主なお仕事の一つ
Widgetをどんな内容で描画するかを決定する

あたりが内包されているライブラリ
これを覚えていくことがはじめの一歩なんでしょう

package:english_words/english_words.dart

チュートリアルの中で追加したライブラリ
よく使われる英単語を提供してくれる

WordPair
generateWordPairs

main()

void main() => runApp(MyApp());

実行部はここだけ
runApp()関数で引数のクラス(MyApp())を膨らませている

main()関数はdartのもの
https://dart.dev/guides/language/language-tour#the-main-function

矢印(=>)構文だけど、これと同じ意味

void main() {
  runApp(MyApp());
}

MyAppクラス

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Startup Name Generator',
      home: RandomWords(),
    );
  }
}

main()に膨らまされるウィジェット
一番大元なのでStatelessWidgetを拡張したクラスである
build()メソッドを使ってMyAppの内容を描画するMaterialAppをreturnしている
MaterialAppではタイトルとホームの内容を設定している
ホームの中身であるRandomWords()は後述

RandomWords()

class RandomWords extends StatefulWidget {
  @override
  _RandomWordsState createState() => _RandomWordsState();
}

class _RandomWordsState extends State<RandomWords> {
  final _suggestions = <WordPair>[];
  final _biggerFont = TextStyle(fontSize: 18.0);
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Startup Name Generator'),
      ),
      body: _buildSuggestions(),
    );
  }

  Widget _buildSuggestions() {
    return ListView.builder(
        padding: EdgeInsets.all(16.0),
        itemBuilder: /*1*/ (context, i) {
          if (i.isOdd) return Divider(); /*2*/

          final index = i ~/ 2; /*3*/
          if (index >= _suggestions.length) {
            _suggestions.addAll(generateWordPairs().take(10)); /*4*/
          }
          return _buildRow(_suggestions[index]);
        });
  }

  Widget _buildRow(WordPair pair) {
    return ListTile(
      title: Text(
        pair.asPascalCase,
        style: _biggerFont,
      ),
    );
  }
}


大きく分けると
StatefulWidgetのRandomWords
そのStateクラスである_RandomWordsState
がある
チュートリアルが言うにはStatefulWidgetがWidgetそのもので
この中でロジックが記載されているStateクラスをインスタンス化することによってWidgetの内容をstatefulに変更しているとのこと
_RandomWordsStateにはランダムな単語の組み合わせを生成し、リスト形式で表示するためのロジックが記載されている

Flutterではほとんど全てのものがWidgetとあるようにこのクラスにはたくさんのWidgetがある
Scaffold
AppBar
Text
ListView
ListTile

そしてfunctionの戻り値も全てWidgetである
(全部についていて見落としてしまいそうだが頭についてるWidgetは戻り値の型である)
_buildSuggestions():複数行の単語ペアリストを生成する
_buildRow(WordPair pair):1行分の単語ペアリストを生成する

スマホのウィジェットを組み合わせてホーム画面をお好みにしていくように
FlutterでもいろんなWidgetを組み合わせてアプリを作っていくようだ

IMG_0690.jpg

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Flutterチュートリアルを咀嚼する part1 (基本

Flutterって一つのソースを書くだけでiOSもAndroidもアプリ作ってくれるんだって
すごいなー
勉強してみよう

対象のチュートリアル

https://codelabs.developers.google.com/codelabs/first-flutter-app-pt1#0

コピペしてできあがったもの

スタートアップ企業の名前をつけてあげるために単語二つの組み合わせをリスト化してくれるアプリ

スクリーンショット 2020-11-17 16.02.22.png

ソースコード

main.dart
import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Startup Name Generator',
      home: RandomWords(),
    );
  }
}

class RandomWords extends StatefulWidget {
  @override
  _RandomWordsState createState() => _RandomWordsState();
}

class _RandomWordsState extends State<RandomWords> {
  final _suggestions = <WordPair>[];
  final _biggerFont = TextStyle(fontSize: 18.0);
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Startup Name Generator'),
      ),
      body: _buildSuggestions(),
    );
  }

  Widget _buildSuggestions() {
    return ListView.builder(
        padding: EdgeInsets.all(16.0),
        itemBuilder: /*1*/ (context, i) {
          if (i.isOdd) return Divider(); /*2*/

          final index = i ~/ 2; /*3*/
          if (index >= _suggestions.length) {
            _suggestions.addAll(generateWordPairs().take(10)); /*4*/
          }
          return _buildRow(_suggestions[index]);
        });
  }

  Widget _buildRow(WordPair pair) {
    return ListTile(
      title: Text(
        pair.asPascalCase,
        style: _biggerFont,
      ),
    );
  }
}

順々にみていこう

import

import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';

package:flutter/material.dart

これがないと始まらないっぽい
Flutterアプリの主役たち

クラス

Widget

https://api.flutter.dev/flutter/widgets/Widget-class.html
Flutterフレームワークの中心的なクラス
FlutterではほとんどのものがWidget
Widget単位でアプリが構築されていく

StatelessWidget

https://api.flutter.dev/flutter/widgets/StatelessWidget-class.html
State(状態)を持たないWidget
不変(immutable)であり静的(static)
親のWidgetから引数を与えてあげることで描画される
反対はStatefulWidget

※参考
https://tech-rise.net/difference-between-stateless-widget-and-stateful-widget

StatefulWidget

https://api.flutter.dev/flutter/widgets/StatefulWidget-class.html

チュートリアルの中で
Implementing a stateful widget requires at least two classes: 1) a StatefulWidget class that creates an instance of 2) a State class.

とあるように、statefulなWidgetを作るためには、②Stateクラスのインスタンスを生成する①StatefulWidgetクラスを用意する必要がある。
要はStateクラスとセットということらしい。

State

https://api.flutter.dev/flutter/widgets/State-class.html

StatefulWidgetとセットになるもの。
StatefulWidgetの中でインスタンス化される。
StatefulWidgetのロジックはここで実装する。
Stateクラスの名前の頭には_(アンダーバー)をつける。

BuildContext

https://api.flutter.dev/flutter/widgets/BuildContext-class.html

※参考
https://qiita.com/agajo/items/93d75aafe87bdc7b2026
https://itome.team/blog/2019/12/flutter-advent-calendar-day6/

MaterialApp

https://api.flutter.dev/flutter/material/MaterialApp-class.html
マテリアルデザインアプリケーションに一般的に必要とされる多くのウィジェットをラップする便利なウィジェット。

Scaffold

https://api.flutter.dev/flutter/material/Scaffold-class.html

AppBar

https://api.flutter.dev/flutter/material/AppBar-class.html

Text

https://api.flutter.dev/flutter/dart-html/Text-class.html

ListView

https://api.flutter.dev/flutter/widgets/ListView-class.html

EdgeInsets

https://api.flutter.dev/flutter/painting/EdgeInsets-class.html

Divider

https://api.flutter.dev/flutter/material/Divider-class.html

関数

runApp()

https://api.flutter.dev/flutter/widgets/runApp.html
指定されたウィジェットを膨らませて、画面に添付する。

メソッド

build()

https://api.flutter.dev/flutter/dart-ui/ParagraphBuilder/build.html
Widgetの主なお仕事の一つ
Widgetをどんな内容で描画するかを決定する

あたりが内包されているライブラリ
これを覚えていくことがはじめの一歩なんでしょう

package:english_words/english_words.dart

チュートリアルの中で追加したライブラリ
よく使われる英単語を提供してくれる

WordPair
generateWordPairs

main()

void main() => runApp(MyApp());

実行部はここだけ
runApp()関数で引数のクラス(MyApp())を膨らませている

main()関数はdartのもの
https://dart.dev/guides/language/language-tour#the-main-function

矢印(=>)構文だけど、これと同じ意味

void main() {
  runApp(MyApp());
}

MyAppクラス

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Startup Name Generator',
      home: RandomWords(),
    );
  }
}

main()に膨らまされるウィジェット
一番大元なのでStatelessWidgetを拡張したクラスである
build()メソッドを使ってMyAppの内容を描画するMaterialAppをreturnしている
MaterialAppではタイトルとホームの内容を設定している
ホームの中身であるRandomWords()は後述

RandomWords()

class RandomWords extends StatefulWidget {
  @override
  _RandomWordsState createState() => _RandomWordsState();
}

class _RandomWordsState extends State<RandomWords> {
  final _suggestions = <WordPair>[];
  final _biggerFont = TextStyle(fontSize: 18.0);
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Startup Name Generator'),
      ),
      body: _buildSuggestions(),
    );
  }

  Widget _buildSuggestions() {
    return ListView.builder(
        padding: EdgeInsets.all(16.0),
        itemBuilder: /*1*/ (context, i) {
          if (i.isOdd) return Divider(); /*2*/

          final index = i ~/ 2; /*3*/
          if (index >= _suggestions.length) {
            _suggestions.addAll(generateWordPairs().take(10)); /*4*/
          }
          return _buildRow(_suggestions[index]);
        });
  }

  Widget _buildRow(WordPair pair) {
    return ListTile(
      title: Text(
        pair.asPascalCase,
        style: _biggerFont,
      ),
    );
  }
}


大きく分けると
StatefulWidgetのRandomWords
そのStateクラスである_RandomWordsState
がある
チュートリアルが言うにはStatefulWidgetがWidgetそのもので
この中でロジックが記載されているStateクラスをインスタンス化することによってWidgetの内容をstatefulに変更しているとのこと
_RandomWordsStateにはランダムな単語の組み合わせを生成し、リスト形式で表示するためのロジックが記載されている

Flutterではほとんど全てのものがWidgetとあるようにこのクラスにはたくさんのWidgetがある
Scaffold
AppBar
Text
ListView
ListTile

そしてfunctionの戻り値も全てWidgetである
(全部についていて見落としてしまいそうだが頭についてるWidgetは戻り値の型である)
_buildSuggestions():複数行の単語ペアリストを生成する
_buildRow(WordPair pair):1行分の単語ペアリストを生成する

スマホのウィジェットを組み合わせてホーム画面をお好みにしていくように
FlutterでもいろんなWidgetを組み合わせてアプリを作っていくようだ

IMG_0690.jpg

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Flutterチュートリアルを咀嚼する part1

Flutterって一つのソースを書くだけでiOSもAndroidもアプリ作ってくれるんだって
すごいなー
勉強してみよう

対象のチュートリアル

https://codelabs.developers.google.com/codelabs/first-flutter-app-pt1#0

コピペしてできあがったもの

スタートアップ企業の名前をつけてあげるために単語二つの組み合わせをリスト化してくれるアプリ

スクリーンショット 2020-11-17 16.02.22.png

ソースコード

main.dart
import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Startup Name Generator',
      home: RandomWords(),
    );
  }
}

class RandomWords extends StatefulWidget {
  @override
  _RandomWordsState createState() => _RandomWordsState();
}

class _RandomWordsState extends State<RandomWords> {
  final _suggestions = <WordPair>[];
  final _biggerFont = TextStyle(fontSize: 18.0);
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Startup Name Generator'),
      ),
      body: _buildSuggestions(),
    );
  }

  Widget _buildSuggestions() {
    return ListView.builder(
        padding: EdgeInsets.all(16.0),
        itemBuilder: /*1*/ (context, i) {
          if (i.isOdd) return Divider(); /*2*/

          final index = i ~/ 2; /*3*/
          if (index >= _suggestions.length) {
            _suggestions.addAll(generateWordPairs().take(10)); /*4*/
          }
          return _buildRow(_suggestions[index]);
        });
  }

  Widget _buildRow(WordPair pair) {
    return ListTile(
      title: Text(
        pair.asPascalCase,
        style: _biggerFont,
      ),
    );
  }
}

順々にみていこう

import

import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';

package:flutter/material.dart

これがないと始まらないっぽい
Flutterアプリの主役たち

クラス

Widget

https://api.flutter.dev/flutter/widgets/Widget-class.html
Flutterフレームワークの中心的なクラス
FlutterではほとんどのものがWidget
Widget単位でアプリが構築されていく

StatelessWidget

https://api.flutter.dev/flutter/widgets/StatelessWidget-class.html
State(状態)を持たないWidget
不変(immutable)であり静的(static)
親のWidgetから引数を与えてあげることで描画される
反対はStatefulWidget

※参考
https://tech-rise.net/difference-between-stateless-widget-and-stateful-widget

StatefulWidget

https://api.flutter.dev/flutter/widgets/StatefulWidget-class.html

チュートリアルの中で
Implementing a stateful widget requires at least two classes: 1) a StatefulWidget class that creates an instance of 2) a State class.

とあるように、statefulなWidgetを作るためには、②Stateクラスのインスタンスを生成する①StatefulWidgetクラスを用意する必要がある。
要はStateクラスとセットということらしい。

State

https://api.flutter.dev/flutter/widgets/State-class.html

StatefulWidgetとセットになるもの。
StatefulWidgetの中でインスタンス化される。
StatefulWidgetのロジックはここで実装する。
Stateクラスの名前の頭には_(アンダーバー)をつける。

BuildContext

https://api.flutter.dev/flutter/widgets/BuildContext-class.html

※参考
https://qiita.com/agajo/items/93d75aafe87bdc7b2026
https://itome.team/blog/2019/12/flutter-advent-calendar-day6/

MaterialApp

https://api.flutter.dev/flutter/material/MaterialApp-class.html
マテリアルデザインアプリケーションに一般的に必要とされる多くのウィジェットをラップする便利なウィジェット。

Scaffold

https://api.flutter.dev/flutter/material/Scaffold-class.html

AppBar

https://api.flutter.dev/flutter/material/AppBar-class.html

Text

https://api.flutter.dev/flutter/dart-html/Text-class.html

ListView

https://api.flutter.dev/flutter/widgets/ListView-class.html

EdgeInsets

https://api.flutter.dev/flutter/painting/EdgeInsets-class.html

Divider

https://api.flutter.dev/flutter/material/Divider-class.html

関数

runApp()

https://api.flutter.dev/flutter/widgets/runApp.html
指定されたウィジェットを膨らませて、画面に添付する。

メソッド

build()

https://api.flutter.dev/flutter/dart-ui/ParagraphBuilder/build.html
Widgetの主なお仕事の一つ
Widgetをどんな内容で描画するかを決定する

あたりが内包されているライブラリ
これを覚えていくことがはじめの一歩なんでしょう

package:english_words/english_words.dart

チュートリアルの中で追加したライブラリ
よく使われる英単語を提供してくれる

WordPair
generateWordPairs

main()

void main() => runApp(MyApp());

実行部はここだけ
runApp()関数で引数のクラス(MyApp())を膨らませている

main()関数はdartのもの
https://dart.dev/guides/language/language-tour#the-main-function

矢印(=>)構文だけど、これと同じ意味

void main() {
  runApp(MyApp());
}

MyAppクラス

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Startup Name Generator',
      home: RandomWords(),
    );
  }
}

main()に膨らまされるウィジェット
一番大元なのでStatelessWidgetを拡張したクラスである
build()メソッドを使ってMyAppの内容を描画するMaterialAppをreturnしている
MaterialAppではタイトルとホームの内容を設定している
ホームの中身であるRandomWords()は後述

RandomWords()

class RandomWords extends StatefulWidget {
  @override
  _RandomWordsState createState() => _RandomWordsState();
}

class _RandomWordsState extends State<RandomWords> {
  final _suggestions = <WordPair>[];
  final _biggerFont = TextStyle(fontSize: 18.0);
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Startup Name Generator'),
      ),
      body: _buildSuggestions(),
    );
  }

  Widget _buildSuggestions() {
    return ListView.builder(
        padding: EdgeInsets.all(16.0),
        itemBuilder: /*1*/ (context, i) {
          if (i.isOdd) return Divider(); /*2*/

          final index = i ~/ 2; /*3*/
          if (index >= _suggestions.length) {
            _suggestions.addAll(generateWordPairs().take(10)); /*4*/
          }
          return _buildRow(_suggestions[index]);
        });
  }

  Widget _buildRow(WordPair pair) {
    return ListTile(
      title: Text(
        pair.asPascalCase,
        style: _biggerFont,
      ),
    );
  }
}


大きく分けると
StatefulWidgetのRandomWords
そのStateクラスである_RandomWordsState
がある
チュートリアルが言うにはStatefulWidgetがWidgetそのもので
この中でロジックが記載されているStateクラスをインスタンス化することによってWidgetの内容をstatefulに変更しているとのこと
_RandomWordsStateにはランダムな単語の組み合わせを生成し、リスト形式で表示するためのロジックが記載されている

Flutterではほとんど全てのものがWidgetとあるようにこのクラスにはたくさんのWidgetがある
Scaffold
AppBar
Text
ListView
ListTile

そしてfunctionの戻り値も全てWidgetである
(全部についていて見落としてしまいそうだが頭についてるWidgetは戻り値の型である)
_buildSuggestions():複数行の単語ペアリストを生成する
_buildRow(WordPair pair):1行分の単語ペアリストを生成する

スマホのウィジェットを組み合わせてホーム画面をお好みにしていくように
FlutterでもいろんなWidgetを組み合わせてアプリを作っていくようだ

IMG_0690.jpg

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む