Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
4
Help us understand the problem. What is going on with this article?
@syo2255

ハンズオンで学ぶFlutter(UI構築編)

Flutterとは??

Google製の1つのコードで、androidアプリ、iosアプリを作成できるマルチプラットフォームです。
以下のURLはFlutterの公式ホームページです。
https://flutter.dev/?gclid=CjwKCAiA_Kz-BRAJEiwAhJNY783VvB3S3Nk5DjqVD2Rs4uQavLOakmvbjAKYd0IRpvVvTiWCQEDzexoCgJEQAvD_BwE&gclsrc=aw.ds

FlutterはGoogleが本腰を入れているため、ドキュメントがしっかりしています。

また、FlutterはDartという言語で書かれています。
DartもGoogle製の言語で、JavascriptやJavaに影響を受けて作られた言語なので、経験のある方は飲み込みやすいと思われます。

Flutterのハンズオン

それでは早速本題に入りましょう。
この記事では、FlutterでのUIの構築方法、状態管理の方法を簡単なアプリを作りながら学んでいきます。
今回は、UI構築編なので見た目の部分を作っていきましょう。

最終的な成果物

123.jpg

今回作成するアプリは、見ての通りニュースの一覧を表示するアプリです。
ニュースの内容はnewapiからとってきたものを表示しています。
以下のurlから確認してみてください。
https://newsapi.org/

本来は、apiを取ってくるところまでコードを書かないといけないのですが、今回は「FlutterでのUI構築」と「状態管理」にフォーカスするので、いったん飛ばします(必要なコードはこちらで提供)。
それでは、「FlutterでのUI構築」から行っていきましょう。

UI構築(見た目の作成)

早速コードを見ていきましょう!
最初にFlutterのプロジェクトを作成すると、以下のようなカウントアプリがmain.dartの中にデフォルトで作られると思います。
default_app.jpg

とりあえず、必要のない部分は消して、以下の画面を作成して準備オッケーです!
125.jpg

今の段階のコードは、以下です。

lib/main.dart

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MainPage(),
    );
  }
}
class MainPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Demo"),
        centerTitle: true,
      ),
      body: Center(
        child: Text("I am ready to go"),
      ),
    );
  }
}

このMainPageクラスは、statelesswidgetを継承しているwidgetです。
Flutterでは、このようにクラスを作成し、基本的にはstatefulwidgetか、statelesswidgetのwidgetを継承します。それらのwidgetを組み合わせ、階層構造を作ることによって、UIを作成します。

詳細

lib/main.dart
class MainPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Demo"),
        centerTitle: true,
      ),
      body: Center(
        child: Text("I am ready to go"),
      ),
    );
  }
}

statelesswidgetの中にあるbuildメソッドはUIを構築していくメソッドになります。ここでは、Scaffoldというwidgetを返しています。Scaffoldはシンプルなデザインを提供してくれるwidgetになり、appbar、bodyなどの部分に新たなwidgetを与えることで画面を生成していきます。

StatelessWidgetとStatefulwidgetの違いは?

先ほどの、MainPageクラスはstatelesswidgetを継承していますが、statefulwidgetというものもあります。この違いを見ていきます。

StatelessWidget

stateがlessなので、名前の通り状態を持たないwidgetです。 厳密的に言うと、状態をもってもいいが、widgetが作成された後は値の状態を変更できないwidgetになります。もし、値の状態を変更したい場合は一度widgetを破棄して、新しいwidgetを作成する必要があります。

StatefulWidget

逆にstatefulwidgetは、状態を持つことが出来、状態の変更も可能です。
詳しくは、statefulwidgetの説明 から調べてみてください。

Scaffold内のbodyを変更する

長くなりましたが、Scaffoldのbodyを変更してニュースリストページを作っていきましょう。
最初は、ニュースのデータを持ってこずに見た目の部分だけ作成します。
完成図は以下になります。
122.jpg

ニュースの画像(newsimage)とニュースのタイトル(newsexample)を表示するwidget(ArticleTile)を一つ作り、それをリスト表示できるwidget(ListView)で複数個並べています。(背景色はわかりやすいようにするためのものです)

コードは以下の通りです。

lib/main.dart

class MainPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text("Demo"),
          centerTitle: true,
        ),
        body: Padding(
          padding: const EdgeInsets.only(top: 10),
          child: Container(
            margin: EdgeInsets.symmetric(horizontal: 10),
            //ListView.builderはリストを作成するwidget
            child: ListView.builder(
              //リストで表示する数を記入
              itemCount: 10,
              //リストで表示するwidgetを記入(ここではArticleTileというwidgetをリストで表示)
              itemBuilder: (context, index) {
                //下にあるArticleTileをreturnしている。
                return ArticleTile();
              },
            ),
          ),
        ));
  }
}

//ニュースの内容を表示するwidget
class ArticleTile extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    //子要素にpaddingをつけることのできるwidget
    return Padding(
      padding: const EdgeInsets.only(bottom: 6),
      //Containerは背景色や子のサイズ、またwidgetの形を変えたりすることがが出来るwidget
      child: Container(
        //形を変更できる
        decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(8.0),
        ),
        //Rowは子要素を横に並べることが出来るwidget
        child: Row(
          children: [
            //ニュース画像を表示するエリア
            //RowやColumnの子Widget間の隙間を目一杯埋めたいときに使うwidget
            Expanded(
                //比を操作できる
                flex: 2,
                child: Container(
                  height: 150,
                  child: Center(child: Text("newsimage")),
                  color: Colors.grey,
                )),
            //ニュースタイトルを表示するエリア
            Expanded(
                //比を操作できる
                flex: 5,
                child: Container(
                  height: 150,
                  child: Center(child: Text("newsexample")),
                  color: Colors.amber,
                )),
          ],
        ),
      ),
    );
  }
}

ここで出てきたwidget一覧は、

・Container
・Row
・Center
・Padding
・Expanded
・ListView

です。
このようにFlutterで用意されているWidgetを使いながら見た目の部分を作成していきます。
これらのWidgetはすべてStatelessWidgetもしくはStatefulWidgetを継承しています。ここからも、flutterはすべてWidgetであることがわかると思います。

また、ここでは出てきてませんがColumnやCard、Stackなど多くのwidgetがFlutterでは用意されています。
詳しくは以下の記事をご覧ください。
Flutter開発のために知っておくべきwidget

今回は、見た目の部分の大枠だけ作成しましたが、次から実際にニュースのデータを取ってきて表示するところまでやっていきます。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
4
Help us understand the problem. What is going on with this article?