northpaddyのブログ

日々学んだプログラミングについてアウトプットしていきます

OSについて

概要

2021年よりIT業界に未経験で入り、知識不足が否めないので
日々学んだことをアウトプットしていきます

OSについて

OSは「Operating System」(オペレーティングシステム)の略であり、
直訳すると「操作するためのシステム」 となります。

OSは何をしているのか

OSの仕事は端末全体を管理、そして、制御することです。

うん。分かるようで分からない。

簡単な例を挙げると
キーボードの「a」ボタンを押します。すると画面に「a」と表示されます。

当たり前ですね。
この今では当たり前のことをOSはやってくれてます。

OSはハードウェアとソフトウェアを仲介する役割があるのです。
(厳密にはBIOS(Basic Input Output System)というプログラムが仲介している?)

ハードウェア‥目に見えるもの(マウス、キーボード、カメラなど)
ソフトウェア‥目に見えないもの(データ、プログラムのこと)

OSのおかげで私たちユーザーはパソコンやスマートフォンをわかりやすく
簡単に操作できるようになっているのです。

当たり前にできるけどOSは重要な役割を果たしているのです!

ソフトウェア

ハードウェアは目に見えてわかるけどソフトウェアって何?
ということで少しソフトウェアについて深ぼっていきます。

ソフトウェアには大きく分けて2種類あります
基本ソフトと応用ソフトです

ここでいう
基本ソフトがOSの事
応用ソフトがExcelやWordなど具体的な処理を担当するもののことを言います。

OSという基本的な機能が備わっている上で
応用ソフトが動いているイメージです。

OSの種類について

一般的に知られているOSには Windows macOS
スマホのOSとして Android iOS
などがあります。

開発者の方は知っているOSとして
Linux Unix
などというOSがあります。

もちろんこれだけではなくまだまだあるそうです。

まとめ

こういう基本的な勉強していて改めて思うことは
普段使っているパソコン、スマホなどの一つ一つの機能を自分で作ってみようと思うと
途方もなく、すごいことをいとも簡単に操作できていることがわかります。

まだまだ理解は追いついていないですが
すこしずつ理解できるようになっていきたいですね。

FareBaseについてまとめてみた

概要

現在Flutterでモバイルアプリケーションの勉強を行っているのですが
バックエンドの機能に「FareBase」を使って実装している記事を多く見かけます
では「FareBase」とは何なのか自分なりに調べてみたことをまとめてみます

公式サイト

FareBaseとは

Firebaseとは Google が提供しているモバイルおよび Web アプリケーションの
バックエンドサービス機能を提供するクラウドサービスです。

英語の頭文字をとってMBaaS(Mobile Backend as a Service)と呼ばれています
BaaSとも呼ばれています

「Firebase」はアプリ開発者向けのサービスで、
バックエンドの処理を代行することで開発にかかる時間・手間の省略が可能で、コスト節約にもつながっているそうです。

Firebaseの機能

Firebase Realtime Database

「Firebase Realtime Database」の最大の特長と言えるのが、リアルタイムでデータ同期ができる点
データはJSONフォーマットで保存されます
「Firebase Realtime Database」はクラウドホスト型 NoSQLデータベースで、
ユーザー同士でデータをリアルタイムで保存・同期ができる優れた機能で、
編集したデータはクラウドに保存され、
数ミリ秒で各端末に同期されるため、ユーザー同士はリアルタイムでの共同作業が可能になります
また、オフラインに対応しており、オフライン時にデータをキャッシュしてオンラインになった時に自動的にデータを同期してくれます

Cloud Firestore(ベータ版)

Realtime Database の性能をさらに向上させた
新しい主力のオブジェクト型データベースRealtime Database より高速でスケールアウトにも対応しています。
Google は Realtime Database より Cloud Firestore を推奨しているため、
今後は Realtime Database に取って代わるデータベースになりそう?

Cloud Storage for Firebase

写真や動画などバイナリーデータを保存できる
保存先は Cloud Storage となっており、 Firebase と Google Cloud の両方からアクセスできる
また、スケールアウト機能も兼ね備えており、急激なアプリケーションの拡大にも対応

Firebase Authentication

Firebase Authentication は「認証」という意味で
「Firebase Authentication」はユーザーの初期登録や認証を簡単に実装できる機能です
Google 以外のSNS認証ではFacebook GitHub Twitter などのサードパーティの認証情報を使用して
クライアントアプリケーションのログインを行うことができます
また、フェデレーション ID 以外にもパスワード認証や電話番号認証にも対応している

Firebase Cloud Messaging(FCM)

Firebase Cloud Messagingはクロスプラットフォームで動いているアプリケーションに対して
通知を無料で送信できる機能です
セグメントを使用してメッセージを送るターゲットを設定することも可能
送信したメッセージはダッシュボードでモニタリングできるので、アプリマーケティングの分析に活躍
今までは Google Cloud Message を使ってサーバからのプッシュ通知を行っていましたが
これからはFirebase Cloud Messaging を使うことが推奨されている

Google Cloud Functions for Firebase

Cloud Functions for Firebase を使うことでイベントドリブンなアプリケーションを作成することができます
SMS メッセージの送信などの処理のような外部サービス連携などを行うことが可能になる
また、クライアントアプリケーションに実装させるには重たすぎるような処理を
Cloud Functions for Firebase に委ねることができます

Firebase Hosting

Firebase Hosting はスタティックな Web ページを公開することができる
近年では HTML CSS Javascript を組み合わせて
アプリケーションのような Web ページを実現することができるようになりました
こういった Web ページも Firebase Hosting を使って公開することもできます

Firebase Crashlytics

「Firebase Crashlytics」は、AndroidiOS用のクラッシュ分析機能
リアルタイムでアプリのクラッシュ分析を行ってくれる機能で、
クラッシュがユーザーに与える影響の測定やクラッシュの原因となっているコードを特定してくれます
この機能を使えば「Firebase」がクラッシュ状況をリアルタイムで教えてくれる

Firebase向けGoogleアナリティクス

「Firebase」には、アクセス解析ツールの「Googleアナリティクス」の機能が組み込まれています
こちらはアプリ用のアクセス解析機能で、アプリの使用状況やユーザーエンゲージメントなどの解析が可能
「Firebase Cloud Messaging」や「Firebase Crash Reporting」といった他の機能や
「BigQuery」や「Googleタグマネージャ」といったGoogleが提供する他のサービスとの統合もできます

まとめ

Firebaseを使う事でバックエンドの処理をFirebaseに任せる事でアプリの開発は捗ります。
しかし、あまりに簡単なのでバックエンドの記述を自分で行えないと言うのも事実です。
初学者にはありがたい事ですが実力が身につくかと言われれば疑問なところです。
必要に応じて使っていければいいのかなと言う見解です。

Android StudioとGitHubを連携させてみた

概要

Android Studioで作成したprojectをGitHubと連携させる方法を
備忘録として残しておきます

プロジェクトの立ち上げ

まずはプロジェクトを立ち上げていきます
以前記事にしたこちらを参考に立ち上げていきます
paddy-north.hatenablog.com

リポジトリの作成

プロジェクトが立ち上がったら
VCS」→「Enable Version Control Integration...」を選択します
するとこのようなウィンドウが出てきますのでそのまま「OK」を押します
https://i.gyazo.com/c03f9d3194623fac02afcd277aecf005.png
リポジトリが作成されました

リポジトリにファイルの追加
project上で右クリックをし、「Git」→「Add」を選択します
f:id:paddy_north:20201130195805j:plain

次に「Git」→「Commit Directory」を選択します
f:id:paddy_north:20201130195813j:plain

するとこのような画面が出てくるので
commit messageを記入しCommitします
https://i.gyazo.com/b0d184509046ca523c57b7ebd99f309a.png

GitHubにShare

次に「VCS」→
「Import into Version Control」→
「Share Project on GitHub
を選択し、特に変更することがなければShareを押して終了です

GitHubにて確認

GitHubで確認します
https://i.gyazo.com/35ded603b46c5ae0f7f401c611a3b380.png
Flutter_appのリポジトリが作成されました!

ファイル変更をcommit&push

では実際にファイルを変更しGitHubにcommit&pushしていきます
現在変更されたファイルはありません
https://i.gyazo.com/0cc4440be017ef237f9575f16f8a6e96.png

ファイルの内容を変更していきます
ファイルを変更すると以下のように変更されたファイルが表示されます
https://i.gyazo.com/3b55325f18f7dcd8a377acbbd815fb14.png
commitしたいファイルにチェックマークを入れ、
commit messageを記入し、commitボタンを押します
一緒にpushしたい場合はcommitボタンの▼からcommit&pushを押します

このようなウィンドウが現れるのでPushを押します
https://i.gyazo.com/642755a5a05d50dbbe6e462fe1313235.png

GitHubにて確認

https://i.gyazo.com/223b6f46f1450bc30d8415bc61cb2226.png
反映されたことが分かります!

参考記事

tomokiit.hatenablog.jp

Flutterデモアプリをカスタマイズしてみよう⑧

概要

Flutterデモアプリを少しずつ弄っていってFlutterに慣れていくのが目的です
前回の記事はこちら

今回行うこと

前回までのListView

前回実装したListViewについてさらに深ぼっていこうと思います

前回までのListViewの中身を見ていきましょう

class MainPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('フラッターデモホームページ'),
      ),
      body: Padding(
        padding: EdgeInsets.symmetric(horizontal: 20),
        child: ListView(
          children: <Widget>[
            ListTile(
              contentPadding: EdgeInsets.all(10.0),
              leading: Image.asset(
                'images/owl.jpg',
              ),
              title: Text('フクロウ'),
              trailing: Icon(Icons.arrow_forward_ios),
              onTap: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => NextPage()),
                );
              },
            ),
            ListTile(
              contentPadding: EdgeInsets.all(10.0),
              leading: Image.asset(
                'images/owl.jpg',
              ),
              title: Text('フクロウ'),
              trailing: Icon(Icons.arrow_forward_ios),
              onTap: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => NextPage()),
                );
              },
            ),
            ListTile(
              contentPadding: EdgeInsets.all(10.0),
              leading: Image.asset(
                'images/owl.jpg',
              ),
              title: Text('フクロウ'),
              trailing: Icon(Icons.arrow_forward_ios),
              onTap: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => NextPage()),
                );
              },
            ),
          ],
        ),
      ),
    );
  }
}

上記のコードのListTileの部分に注目すると、
3つある各ListTile以下のコードは全て同じ記述です
このListTileを1つにまとめていきます

List型を作る

それを行う前にあらかじめデータを型に入れておきます

今回は画像のデータタイトルのデータの型を作っていきます
これをList型と言う型に入れていきます

  var imageLists = [
    'https://flutter.github.io/assets-for-api-docs/assets/widgets/owl.jpg', //フクロウの画像
    'https://cdn.pixabay.com/photo/2017/06/09/09/39/adler-2386314__340.jpg', //鷲の画像
    'https://cdn.pixabay.com/photo/2014/05/20/21/20/bird-349026__340.jpg', //ひよこの画像
    'https://cdn.pixabay.com/photo/2015/10/12/14/53/kingfisher-983944__340.jpg', //カワセミの画像
  ];

  var imageTitles = ['フクロウ', '鷲', 'ひよこ', 'カワセミ',];

画像のデータのListをimageLists
タイトルのデータのListをimageTitle
と名付けました

これをMainPageクラスに入れておきます

ListView.builder

次にListViewに.builderを追記していきます

ListView.builderとは
主に、表示する要素が事前にわからない場合に利用する書き方です。

ListView.builder以下にこう記述します

child: ListView.builder(
  itemCount: imageLists.length,
  itemBuilder: (context, int index) {

://省略

},

itemCountはimageListsの数だけ要素を表示
itemBuilderは一個一個の要素に対しての表示部を表しています

ListTileのリファクタリング

あらかじめデータを入れておいた型からデータを呼び出して表示してみます

return ListTile(
  contentPadding: EdgeInsets.all(10.0),
  leading: Image.network('${imageLists[index]}',
  ),
  title: Text('${imageTitles[index]}',
  ),
  trailing: Icon(Icons.arrow_forward_ios),
  onTap: () {
    Navigator.push(
      context,
      MaterialPageRoute(builder: (context) => NextPage()),
    );
  },
);

''に$を付けて、
imageListsとimageTitlesから[index]と記述すると
各要素を取り出すことが出来ます

ホットリロード
https://i.gyazo.com/929c93a28bc4bcd49f430047afe71e65.png
このような表示になりました!

コード全体

少しスタイルを変更し完成したコードがこちらです

import 'package:flutter/material.dart';

import 'next_page.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final title = 'フラッターデモホームページ';

    return MaterialApp(
        debugShowCheckedModeBanner: false,
        title: title,
        theme: ThemeData(
          primarySwatch: Colors.blue,
          visualDensity: VisualDensity.adaptivePlatformDensity,
        ),
        home: MainPage());
  }
}

class MainPage extends StatelessWidget {
  var imageLists = [
    'https://flutter.github.io/assets-for-api-docs/assets/widgets/owl.jpg',
    'https://cdn.pixabay.com/photo/2017/06/09/09/39/adler-2386314__340.jpg',
    'https://cdn.pixabay.com/photo/2014/05/20/21/20/bird-349026__340.jpg',
    'https://cdn.pixabay.com/photo/2015/10/12/14/53/kingfisher-983944__340.jpg',
  ];
  var imageTitles = ['フクロウ', '鷲', 'ひよこ', 'カワセミ',];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('フラッターデモホームページ'),
      ),
      body: Padding(
        padding: EdgeInsets.symmetric(horizontal: 20),
            child: ListView.builder(
              itemCount: imageLists.length,
              itemBuilder: (context, int index) {
                return ListTile(
                  contentPadding: EdgeInsets.all(10.0),
                  leading: Image.network('${imageLists[index]}',
                    height: 80,
                    width: 80,
                  ),
                  title: Text('${imageTitles[index]}',
                  ),
                  trailing: Icon(Icons.arrow_forward_ios),
                  onTap: () {
                    Navigator.push(
                      context,
                      MaterialPageRoute(builder: (context) => NextPage()),
                    );
                  },
                );
              },
          ),
      ),
    );
  }
}

3つあったListTileを1つにまとめて表示は要素の数表示することが出来ました。
https://i.gyazo.com/a5e5164deef459e95a2916c0ba595c9a.png

まとめ

今回はデータをあらかじめ入れておき、それを表示させるというのをやってみました
もしかしたらこのやり方より違うやり方の方がいいのかもしれません
(現状この二つのListをnextPageの方で使えない?為、鷲のページに飛んでもフクロウのままです)
詳しい方が居たらご教授いただけると幸いです。

Flutterデモアプリをカスタマイズしてみよう⑦

概要

Flutterデモアプリを少しずつ弄っていってFlutterに慣れていくのが目的です
前回の記事はこちら

今回行うこと

  • 今回の完成イメージの確認
    • 詳細ページ変更
    • メインページ変更
  • MainPageクラスの作成
    • ListViewを用いてリストを作る

今回の完成イメージ

前回までは
main.dartに画像を表示し、
next_page.dartにはtextのみの状態でした。

今回はもう少しアプリらしくしていきます
メインのページにリストを作りそこから詳細ページに遷移し、
画像を表示させるというようなアプリにしていきたいと思います

今回の完成イメージはこんな感じです
https://i.gyazo.com/9bdfb2dfe65ab2a79524b386b978a32b.gif

詳細ページ

main.dartに画像詳細について記述されているコードをnext_pageの方に移動させます
必要なのは

  • NextPageクラスをStatelessWidgetにする
  • MyHomePageStateの中身
  • Scaffoldの中身
  • デザインも少し変更
  • floatingActionButtonは必要ないので削除

それでは記述していきます

import 'package:flutter/material.dart';

class NextPage extends StatefulWidget { //StatefulWidgetに変更
  @override
  _NextPageState createState() => _NextPageState(); //State追加
}

class _NextPageState extends State<NextPage> { //NextPageStateクラスの作成
  int _counter = 0;
  bool favorite;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('フクロウ 詳細ページ'), //AppBarのText変更
      ),
      body: Container(
        child: Center(
          child: Column(mainAxisSize: MainAxisSize.min,
            children: [
            Padding( //Paddingを追加し、空白を付けます
              padding: const EdgeInsets.all(8.0),
              child: Text( 'フクロウ', //画像のタイトルを追加
                style: TextStyle( //スタイルの追加
                  fontWeight: FontWeight.bold,
                  fontSize: 25,
                )
              ),
            ),
            Image.asset(
              'images/owl.jpg',
              height: 250,
              width: 250,
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                RichText(
                  textScaleFactor: MediaQuery.of(context).textScaleFactor,
                  text: TextSpan(
                    style: TextStyle(color: Colors.black),
                    children: <TextSpan>[
                      TextSpan(text: 'いいね!した回数は '),
                      TextSpan(
                          text: '$_counter',
                          style: Theme.of(context).textTheme.headline4),
                      TextSpan(text: ' 回'),
                    ],
                  ),
                ),
              ],
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                FlatButton(
                  child: Icon(
                    favorite == true ? Icons.favorite : Icons.favorite_border,
                    color: favorite == true ? Colors.red : Colors.grey,
                  ),
                  onPressed: () {
                    setState(() {
                      if (favorite != true) {
                        favorite = true;
                      } else {
                        favorite = false;
                      }
                    });
                  },
                ),
                RaisedButton.icon(
                  icon: Icon(
                    Icons.sentiment_satisfied_alt_outlined,
                    color: Colors.white,
                  ),
                  label: Text('いいね!'),
                  color: Colors.blue,
                  textColor: Colors.white,
                  shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(10),
                  ),
                  onPressed: _incrementCounter,
                ),
              ],
            ),
          ]),
        ),
      ),
    );
  }
}

メインページ

メインのページは一回余計な記述は削除しておきます

import 'package:flutter/material.dart';

import 'next_page.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final title = 'フラッターデモホームページ';

    return MaterialApp(
        debugShowCheckedModeBanner: false,
        title: title,
        theme: ThemeData(
          primarySwatch: Colors.blue,
          visualDensity: VisualDensity.adaptivePlatformDensity,
        ),
        home: MainPage() //MainPageクラスを作成していきます
    );
  }
}

削除してスッキリしました!

次は新たにMainPageクラスを作成していきます

MainPageクラスの作成

MainPageクラスには
AppBarの作成やbodyにListを作ったり、画面遷移のナビゲーションを記述していきます

AppBarや画面遷移のナビゲーションについては
前回まででやっているので説明は省きます

まずMainPageクラスを作成していきます

class MainPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('フラッターデモホームページ'),
      ),
     body: //ここからListを作っていきます
    );
  }
}

AppBarまで出来ました

ListViewを用いてリストを作る

リストにもいろいろな種類がありますが(公式ドキュメント
今回は「ListView Widget」を使っていきます

ではまずListViewの書き方です
公式ドキュメントの例です

ListView(
  children: <Widget>[
    ListTile(
      leading: Icon(Icons.map),
      title: Text('Map'),
    ),
    ListTile(
      leading: Icon(Icons.photo_album),
      title: Text('Album'),
    ),
    ListTile(
      leading: Icon(Icons.phone),
      title: Text('Phone'),
    ),
  ],
);

ListViewの配下にListTileがあります
ListTileleading,titleプロパティがあり以下のような表示を行えます
https://i.gyazo.com/77bef966ecf6f4f62e4067535ddea146.png

ここに画像を表示し、タイトル、アイコンを表示させていきます
では記述していきます

class MainPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('フラッターデモホームページ'),
      ),
      body: ListView(
          children: <Widget>[
            ListTile(
              leading: Image.asset(
                'images/owl.jpg',
              ),
              title: Text('フクロウ'),
              trailing: Icon(Icons.arrow_forward_ios),
              onTap: () {
              },
            ),
          ],
        ),
    );
  }
}

bodyをListViewとし、配下にListTile
ListTileにleading、title、trailing、onTapを追加しました

さらにもう少しカスタマイズしていきます

  • 余白を持たせる為Paddingを追加
  • ListTileを3つ追加
  • 画面遷移のNavigatorを追加していきます
class MainPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('フラッターデモホームページ'),
      ),
      body: Padding(
        padding: EdgeInsets.symmetric(horizontal: 20),
        child: ListView(
          children: <Widget>[
            ListTile(
              contentPadding: EdgeInsets.all(10.0),
              leading: Image.asset(
                'images/owl.jpg',
              ),
              title: Text('フクロウ'),
              trailing: Icon(Icons.arrow_forward_ios),
              onTap: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => NextPage()),
                );
              },
            ),
            ListTile(
              contentPadding: EdgeInsets.all(10.0),
              leading: Image.asset(
                'images/owl.jpg',
              ),
              title: Text('フクロウ'),
              trailing: Icon(Icons.arrow_forward_ios),
              onTap: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => NextPage()),
                );
              },
            ),
            ListTile(
              contentPadding: EdgeInsets.all(10.0),
              leading: Image.asset(
                'images/owl.jpg',
              ),
              title: Text('フクロウ'),
              trailing: Icon(Icons.arrow_forward_ios),
              onTap: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => NextPage()),
                );
              },
            ),
          ],
        ),
      ),
    );
  }
}

ここでホットリロードで確認してみます
https://i.gyazo.com/9bdfb2dfe65ab2a79524b386b978a32b.gif
リストから詳細ページ飛ぶことが出来ました!

参考記事

tech-rise.net

まとめ

ここまでで少しアプリっぽくなってきました!
ですがデータの保存や追加機能などが出来ていません
今のところコードに記述しているだけです
その辺の知識を得たらまた書いていきたいと思います

Flutterデモアプリをカスタマイズしてみよう⑥

概要

Flutterデモアプリを少しずつ弄っていってFlutterに慣れていくのが目的です

前回の記事はこちら

今回行うこと

  • 文字の装飾(RichTextを使ってみる)
  • インデント修正コマンド
  • UI修正
  • お気に入りボタンの実装

文字の装飾

まずはこちらのコードをご覧ください

    Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        Text(
          'ボタンを押した回数は  ',
        ),
        Text(
          '$_counter',
          style: Theme.of(context).textTheme.headline4,
        ),
        Text(
          '  回',
        ),
      ],
    ),

これは画像の下のTextです
textを三つに分けて一つの文字列を表しています
またcounterによりボタンを押した回数の数字のフォントが変わっているのも分かります

これを今回やるRichTextを用いて実装していきます
それでは記述していきます

Row(
  mainAxisAlignment: MainAxisAlignment.center,
  children: <Widget>[
    RichText( //以下RichTextの記述
      textScaleFactor: MediaQuery.of(context).textScaleFactor,
      text: TextSpan(
        style: TextStyle(color: Colors.black),
        children: <TextSpan>[
          TextSpan(text: 'ボタンを押した回数は '),
          TextSpan(text: '$_counter',
         style: Theme.of(context).textTheme.headline4),
          TextSpan(text: ' 回'),
        ],
      ),
    ),
],
),

解説です

まずTextStyleでRichText内の文字のフォントの色をblackに指定しています
これは指定しないと白色の文字になってしまうからです

TextSpanで各Textの装飾を行えます
今回はcounterのみ指定を行いました

textScaleFactor: MediaQuery.of(context).textScaleFactor
という一文は
ユーザー側の文字の大きさの設定を変更している時に必要な記述みたいです
詳しくはこちら↓
qiita.com

画面的な変化はありませんが
これで3つあったTextを一つにまとめられました!
https://i.gyazo.com/0023cb543e1d49e748dbc894da5ef2ef.png

インデント修正コマンド

ここまでで色々弄りながら記述しているので
かなりインデントが崩れています笑(個人的問題w)
そこでインデントの自動修正コマンドが便利なので紹介します
cmd + alt + l(Lキー)
でインデントを修正してくれます
崩れてきたなと思ったらこのコマンドを実行してみて下さい!

UIを修正

現在は画像の下にボタンを押した回数の文字と
ただのボタンが置いてあるだけなので
その辺のUIも修正していきます

まずは画像に対していいねが押された回数をTextに表示させる想定なので
Textの中身を変えていきます

TextSpan(text: 'ボタンを押した回数は '),

TextSpan(text: 'いいね!された回数は '),

次にボタンを「いいね!ボタン」として分かりやすいように
RaisedButtonにアイコンをつけていいねボタンを表現します

RaisedButton.icon(
  icon: Icon(
    Icons.sentiment_satisfied_alt_outlined,
    color: Colors.white,
  ),
  label: Text('いいね!'), //childからlabelに変更
  color: Colors.blue,
  textColor: Colors.white,
  shape: RoundedRectangleBorder(
    borderRadius: BorderRadius.circular(10),
  ),
  onPressed: _incrementCounter,
),

解説です
RaisedButtonにiconをつけて今回はニコちゃんマークのアイコンをつけました
colorはTextに合わせてwhiteに

childだったtextをlabelに変更しました

以下のようなボタンになりました
https://i.gyazo.com/c7a936bb53123f398d13da06ed0fcae4.png


お気に入りボタン

次はお気に入りボタンを実装していきます
※今のところ、お気に入りされたデータの保存は出来ません。
あくまで「ボタンを押した時にボタンが変化する」実装のみになりますのでご了承ください。

今回はハートのアイコンに色を付けてお気に入りされたUIを実装していきます
イメージとしてはこんな感じ
https://i.gyazo.com/b9bf3501eea950c566fce5ef3f10634e.gif

まずboolean型というtrue(真)とfalse(偽)の2つの値から構成される
型の定義から行います
Widgetの外にboolean型を定義していきます

  bool favorite;

このfavoriteという値が使えるようになりました

次にFlatButtonにハートのアイコンを付けていきます

FlatButton(
  child: Icon(
    favorite == true ? Icons.favorite : Icons.favorite_border,
    color: favorite == true ? Colors.red : Colors.grey,
  ),

ここでfavoriteという値を用いて
アイコンが押されていればtrueが代入されるようになります

trueが代入されていれば色が赤いハートを表示し、
falseなら枠線のハートを表示し、色がgreyになる
という処理です。

onPressed: () {
  setState(() {
    if (favorite != true) {
      favorite = true;
    } else {
      favorite = false;
    }
  });
},

ここで上の処理の条件分岐をしています
setStateというのはカウントアップボタンにも実装されています
これにより読み込みの必要が無くハートのアイコンを変化させることが出来ます
参考にさせていただいた記事
qiita.com



これまでの実装で以下のような動作になりました
https://i.gyazo.com/5f0fdecb65cf605e75f992055081eceb.gif

FlatButtonとRaisedButtonをRowで囲って横並びにしてみましょう

Row(
  mainAxisAlignment: MainAxisAlignment.center,
  children: [
    FlatButton(
      child: Icon(
        favorite == true ? Icons.favorite : Icons.favorite_border,
        color: favorite == true ? Colors.red : Colors.grey,
      ),
      onPressed: () {
        setState(() {
          if (favorite != true) {
            //ハートが押されたときにfavoriteにtrueを代入している
            favorite = true;
          } else {
            favorite = false;
          }
        });
      },
    ),
    RaisedButton.icon(
      icon: Icon(
        Icons.sentiment_satisfied_alt_outlined,
        color: Colors.white,
      ),
      label: Text('いいね!'),
      color: Colors.blue,
      textColor: Colors.white,
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(10),
      ),
      onPressed: _incrementCounter,
    ),
  ],
),

これでボタンが横並びになりました!
https://i.gyazo.com/708707c431ee842f749fb15423441583.png

まとめ

今回は文字の装飾、UIの修正、お気に入りボタンを実装してみました
特にお気に入りボタンの条件分岐など難しい記述が出てきました
私自身まだ理解していませんがDart言語の方も勉強していきたいと思います

Flutterデモアプリをカスタマイズしてみよう⑤

概要

Flutterデモアプリを少しずつ弄っていってFlutterに慣れていくのが目的です

前回の記事はこちら

前回までの画面の状態とコードは以下のようになっています

今回行うこと(画像表示)

今回は画像の表示をやっていきたいと思います

  • 画像表示
    • ネット上にある画像をURLで呼び出す方法
    • アプリ自体に画像を保存しておく方法
  • 画像の大きさの変更

画像の表示

画像の表示の仕方には2つあります

  • ネット上にある画像をURLで呼び出す方法
  • アプリ自体に画像を保存しておく方法

ネット上にある画像をURLで呼び出す方法

画像をURLで呼び出す方法は2つあります。
今回は公式ドキュメントに紹介されてある画像を呼び出してみます
やり方はとても簡単で一つ目が

Image.network('https://flutter.github.io/assets-for-api-docs/assets/widgets/owl.jpg',)

二つ目が

const Image(
  image: NetworkImage('https://flutter.github.io/assets-for-api-docs/assets/widgets/owl.jpg'),
)

と記述するだけです
(どちらでもやっていることは変わりません。好きな方でやってみましょう!)

今回はTextの上に画像を表示させてみます
実際にコードに打ち込んでみましょう

body: Container( //Containerを追加
  child: Center( //その子供にCenter
    child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Image.network( //Image.networkを追加
            'https://flutter.github.io/assets-for-api-docs/assets/widgets/owl.jpg',
          ),
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text(
                'ボタンを押した回数は  ',
              ),
              Text(
                '$_counter',
                style: Theme.of(context).textTheme.headline4,
              ),
              Text(
                '  回',
              ),

ホットリロードしてみます
https://i.gyazo.com/1853cab7b0af6d60c38e5ff0bf5ae5e3.png
画像が表示されました!

アプリ自体に画像を保存しておく方法

今度はローカル環境に保存されている画像を
アプリに保存し表示させてみます
どんな画像でも良いですが
公式ドキュメントからフクロウの画像を保存しておきましょう

・imagesフォルダの作成
Project内のこのアプリの名前のところで右クリックを押し
new→Directoryを選択し、imagesフォルダを作ります
f:id:paddy_north:20201121160352j:plain

以下のように作成されていれば成功です
https://i.gyazo.com/0007cd1eaaaaa1659937dc1c26b2019d.png
Finderなどから先ほど保存した画像をドラック&ドロップしてimagesフォルダの中に入れていきます
https://i.gyazo.com/8b0f158de30585a7ec90a6b85d135d86.png
フォルダ内に画像ファイルがあれば成功です

・pubspec.yamlに記述
保存した画像を読み込ませる為には
pubspec.yamlにその画像がどこにあるのか記載しておかなければいけません
pubspec.yamlとはProject内のファイルにあります
開いてみると色々書いてあります
読みにくいのでコメントアウトを削除しておきます
https://i.gyazo.com/9b087dbfcc78e157880120f3afa88ad2.png
すっきりしました!

では画像の場所の記載をしていきます
一番下の

flutter:
  uses-material-design: true

の下にこう記述します

flutter:
  uses-material-design: true
  assets:
    - images/owl.jpg

assets内に保存した画像の場所を書いていく訳です

準備が終わりました
画像を表示されてみましょう
main.dartにて
先ほど追加した画像の下に追記していきましょう

Image.network(
  'https://flutter.github.io/assets-for-api-docs/assets/widgets/owl.jpg',
),
Image.asset('images/owl.jpg'), //追記

https://i.gyazo.com/d524f48544e397f28c357e1fd4b0ba23.png
このような画面になったと思います
表示が変なことになっていますがアプリ内に保存されている画像の表示が出来ました!

今回は「ネット上にある画像をURLで呼び出す方法」で表示させているコードは消しておきます

画像の大きさの変更

現在の表示はこのようになっています
https://i.gyazo.com/1b86a52e3b9bf09b9bf6023bfdd6a7f9.png
画像の大きさを変更していきましょう

Image.asset('images/owl.jpg',
  height: 250,
  width: 250,
),

heightとwidthの値を指定するだけです
https://i.gyazo.com/31502715f185c5a3e4975a2248c7038b.png
画像のサイズ変更が出来ました!
お好きなサイズに変更してみてください

まとめ

今回は画像の表示を行いました
表示の仕方には2つありましたが、必要に応じてやり方を変えてみると良いのかもしれませんね
私はその違いの理解はしていません笑