【Flutter】ファイルアクセス

import 'package:flutter/material.dart';
import 'dart:ui' as ui;
import 'dart:io';
import 'package:path_provider/path_provider.dart';

void main() {
  runApp(new MyApp());
}
class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Generated App',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
        primaryColor: const Color(0xFF2196f3),
        canvasColor: const Color(0xFFfafafa),
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final _controller = TextEditingController();
  final _fname = 'flutter_sampledata.txt';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Home'),
      ),
      body: Padding(
        padding: EdgeInsets.all(20),
        child:Column(
          children:<Widget> [
               Text('FILE ACESS.',
               style: TextStyle(fontSize: 32,
               fontWeight: ui.FontWeight.w500),
               ),
              Padding(padding: EdgeInsets.all(10.0)),
              TextField(
                controller: _controller,
                style: TextStyle(fontSize: 24),
                minLines: 1,
                maxLines: 5,
              )
              ],
            ),
          ),
          bottomNavigationBar: BottomNavigationBar(
            backgroundColor: Colors.blue,
            selectedItemColor: Colors.white,
            unselectedItemColor: Colors.white,
            currentIndex: 0,
            items: <BottomNavigationBarItem>[
              BottomNavigationBarItem(
                label: 'Save',
                icon: Icon(Icons.save, color: Colors.white, size: 32),
              ),
              BottomNavigationBarItem(
                label: 'Load',
                icon: Icon(Icons.open_in_new, color: Colors.white, size:32)
              ),
            ],
            onTap: (int value) async {
              switch (value) {
                case 0:
                  saveIt(_controller.text);
                  setState(() {
                    _controller.text = '';
                  });
                  showDialog(
                    context: context,
                    builder: (BuildContext context) => AlertDialog(
                      title: Text("saved!"),
                      content: Text("save message to file."),
                    )
                  );
                  break;
                case 1:
                  String value = await loadIt();
                  setState((){
                    _controller.text = value;
                  });
                  showDialog(
                    context: context,
                    builder: (BuildContext context) => AlertDialog(
                      title: Text("loaded!"),
                      content: Text("load message from file."),
                    )
                  );
                  break;
                default:
                  print('no default.');
              }
            },
          ),
    );
  }

  Future<File> getDataFile(String filename) async {
    final directory = await getApplicationDocumentsDirectory();
    return File(directory.path + '/' + filename);
  }

  void saveIt(String value) async {
    final file = await getDataFile(_fname);
    file.writeAsString(value);
  }

  Future<String> loadIt() async {
    try {
      final file = await getDataFile(_fname);
      return file.readAsString();
    } catch (e) {
      return '*** no data ***';
    }
  }
}

リソースファイルの読み込み
L assetsフォルダ内にdocumentsというフォルダを用意し、その中にdata.txtファイルを作成する
pubspec.yamlに追記

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'dart:ui' as ui;

void main() {
  runApp(new MyApp());
}
class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Generated App',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
        primaryColor: const Color(0xFF2196f3),
        canvasColor: const Color(0xFFfafafa),
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final _controller = TextEditingController();
  final _fname = 'documents/data.txt';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Home'),
      ),
      body: Padding(
        padding: EdgeInsets.all(20),
        child:Column(
          children:<Widget> [
               Text('RESOURCE ACCESS',
               style: TextStyle(fontSize: 32,
               fontWeight: ui.FontWeight.w500),
               ),
              Padding(padding: EdgeInsets.all(10.0)),
              TextField(
                controller: _controller,
                style: TextStyle(fontSize: 24),
                minLines: 1,
                maxLines: 5,
              )
              ],
            ),
          ),
          floatingActionButton: FloatingActionButton(
            child: Icon(Icons.open_in_new),
            onPressed: () async {
              final value = await loadIt();
              setState(() {
                _controller.text = value;
              });
              showDialog(
                context: context,
                builder: (BuildContext context) =>
                    AlertDialog(
                      title: Text("loaded!"),
                      content: Text("load message from Asset."),
                    )
              );
            }
          )
    );
  }

  Future<String> getDataAsset(String path) async {
    return await rootBundle.loadString(path);
  }

  Future<String> loadIt() async {
    try {
      final res = await getDataAsset(_fname);
      return res;
    } catch (e) {
      return '*** no data ***';
    }
  }
}

【flutter】アニメーション

class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
  late Animation<double> animation;
  late AnimationController controller;

  @override
  void initState(){
    super.initState();
    controller = AnimationController(
      duration: const Duration(seconds: 3),
      vsync: this
    );
    animation = Tween<double>(begin: 0, end: pi*2)
      .animate(controller)
      ..addListener(() {
        setState((){
        });
      });
    controller.repeat(reverse: false);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Color.fromARGB(255, 255,255,255),
      appBar: AppBar(
        title: Text('App Name', style: TextStyle(fontSize: 30.0),),
      ),
      body: Center(
        child:Column(
          children: [
            Padding(padding: EdgeInsets.all(10)),
            Container(
              width: 300,
              height: 300,
              child: CustomPaint(
                painter: MyPainter(animation.value),
                child: Center(),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class MyPainter extends CustomPainter {
  final double value;

  MyPainter(this.value);

  @override
  void paint(Canvas canvas, Size size){
    Paint p = Paint();
    canvas.save();

    p.style = PaintingStyle.fill;
    p.color = Color.fromARGB(100, 255, 0, 255);
    Rect r = Rect.fromLTWH(0,0,250,250);
    canvas.translate(150, 250);
    canvas.rotate(value);
    canvas.translate(-125, -125);
    canvas.drawRect(r, p);

    canvas.restore();
    p.style = PaintingStyle.stroke;
    p.strokeWidth = 25;
    p.color = Color.fromARGB(100, 0, 255, 255);
    r = Rect.fromLTWH(0, 0, 250, 250);
    canvas.translate(150, 250);
    canvas.rotate(value * - 1);
    canvas.translate(-125, -125);
    canvas.drawRect(r, p);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) => true;
}

アニメーションウィジェット

class _MyHomePageState extends State<MyHomePage> {
  bool flg = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('App Name', style: TextStyle(fontSize: 30.0),),
      ),
      body: Padding(
        padding: EdgeInsets.all(20),
        child:Column(
          children: [
                AnimatedAlign(
                  alignment: flg ? Alignment.topLeft : Alignment.topRight,
                  duration: const Duration(seconds: 1),
                  child: Container(
                    color: Colors.red,
                    width: 100,
                    height: 100,
                  ),
                  curve: Curves.linear,
                ),
              ],
            ),
            ),
          floatingActionButton: FloatingActionButton(
            onPressed:(){
              setState((){
                flg = !flg;
              });
            },
            child: const Icon(Icons.star),
          ),
    );
  }
}

AnimatedDefaultTextStyleによるテキスト操作

      body: Padding(
        padding: EdgeInsets.all(20),
        child:Column(
          children: [
                AnimatedDefaultTextStyle(
                  duration: const Duration(seconds: 1),
                  style: TextStyle(
                    fontSize: flg ? 48 : 96,
                    fontWeight: FontWeight.bold,
                    color: flg ? Colors.red : Colors.blue
                  ),
                  child: Text("Hello Flutter"),
                ),
              ],
            ),
            ),

ウィジェットを動かす

      body: Padding(
        padding: EdgeInsets.all(20),
        child:Stack(
          children: [
                AnimatedPositioned(
                  duration: const Duration(seconds: 3),
                  top: flg ? 300 : 0,
                  left: flg ? 0 : 300,
                  child: Container(
                    color: Colors.red,
                    width: 100,
                    height: 100,
                  )
                ),
              ],
            ),
            ),

AnimatedCrossFadeによるウィジェットの切り替え

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('App Name', style: TextStyle(fontSize: 30.0),),
      ),
      body: Padding(
        padding: EdgeInsets.all(20),
        child:Column(
          children: [
                AnimatedCrossFade(
                  duration: const Duration(seconds: 1),
                  firstChild: const FlutterLogo(
                    style: FlutterLogoStyle.horizontal,
                    size: 300.0),
                  secondChild: const FlutterLogo(
                  style: FlutterLogoStyle.stacked,
                  size: 300.0),
                  crossFadeState: flg ? CrossFadeState.showFirst : CrossFadeState.showSecond,
                ),
              ],
            ),
            ),

【flutter】パスと座標変換

class _MyHomePageState extends State<MyHomePage>{

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Color.fromARGB(255, 255,255,255),
      appBar: AppBar(
        title: Text('App Name', style: TextStyle(fontSize: 30.0),),
      ),
      body:Container(
        child: CustomPaint(
          painter: MyPainter(),
        ),
      ),
    );
  }
}

class MyPainter extends CustomPainter {

  @override
  void paint(Canvas canvas, Size size){
    Path path = Path();
    Rect r = Rect.fromLTWH(50.0, 50.0, 75.0, 75.0);
    path.addOval(r);
    r = Rect.fromLTWH(75.0, 75.0, 125.0, 125.0);
    path.addOval(r);
    r = Rect.fromLTWH(125.0, 125.0, 175.0, 175.0);
    path.addOval(r);
    Paint p = Paint();
    p.color = Color.fromARGB(150, 255, 0, 0);
    p.style = PaintingStyle.fill;
    canvas.drawPath(path, p);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) => true;
}
class MyPainter extends CustomPainter {

  @override
  void paint(Canvas canvas, Size size){
    Path path = Path();
    Rect r = Rect.fromLTWH(50.0, 50.0, 75.0, 75.0);
    path.addOval(r);
    r = Rect.fromLTWH(75.0, 75.0, 125.0, 125.0);
    path.addOval(r);
    r = Rect.fromLTWH(125.0, 125.0, 175.0, 175.0);
    path.addOval(r);

    canvas.save();

    Paint p = Paint();
    p.color = Color.fromARGB(150, 255, 0, 0);
    p.style = PaintingStyle.fill;
    canvas.drawPath(path, p);

    canvas.translate(0.0, 100.0);
    p.color = Color.fromARGB(150, 0, 0, 255);
    canvas.drawPath(path, p);

    p.color = Color.fromARGB(150, 0, 255, 0);
    canvas.rotate(-0.5 * pi);
    canvas.translate(-500.0, 50.0);
    canvas.scale(1 * 1.5);
    canvas.drawPath(path, p);

    canvas.restore();
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) => true;
}

【flutter】イメージの描画

イメージはアプリケーション内の「assets」というフォルダに配置するのが一般的
flutter_app/assets/images/image.jpg

pubspec.yamlにassetsを追加する

flutter:
 assets:
  - assets/images/image.jpg
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'dart:typed_data';
import 'dart:ui' as ui;

class _MyHomePageState extends State<MyHomePage>{

  static ui.Image? _img = null;
  static bool _flg = false;

  Future<void> loadAssetImage(String fname) async {
    final bd = await rootBundle.load("images/$fname");
    final Uint8List u8lst = await Uint8List.view(bd.buffer);
    final codec = await ui.instantiateImageCodec(u8lst);
    final frameInfo = await codec.getNextFrame();
    _img = frameInfo.image;
    setState(()=> _flg = true);
  }

  @override
  Widget build(BuildContext context) {
    loadAssetImage('image.jpg');

    return Scaffold(
      backgroundColor: Color.fromARGB(255, 255,255,255),
      appBar: AppBar(
        title: Text('App Name', style: TextStyle(fontSize: 30.0),),
      ),
      body:Container(
        child: CustomPaint(
          painter: MyPainter(_img),
        ),
      ),
    );
  }
}

class MyPainter extends CustomPainter {
  ui.Image? _img = null;

  MyPainter(this._img);

  @override
  void paint(Canvas canvas, Size size){
    Paint p = Paint();

    Offset off = Offset(50.0, 50.0);
    if(_img != null){
      canvas.drawImage(_img!, off, p);
    }
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) => true;
}

【flutter】グラフィック描画の基本

class _MyHomePageState extends State<MyHomePage>{

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Color.fromARGB(255, 255,255,255),
      appBar: AppBar(
        title: Text('App Name', style: TextStyle(fontSize: 30.0),),
      ),
      body:Container(
        child: CustomPaint(
          painter: MyPainter(),
        ),
      ),
    );
  }
}

class MyPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size){
    Paint p = Paint();

    p.style = PaintingStyle.fill;
    p.color = Color.fromARGB(150, 0, 200, 255);
    Rect r = Rect.fromLTWH(50.0, 50.0, 150.0, 150.0);
    canvas.drawRect(r, p);

    p.style = PaintingStyle.stroke;
    p.color = Color.fromARGB(150, 200, 0, 255);
    p.strokeWidth = 10.0;
    r = Rect.fromLTWH(100.0, 100.0, 150.0, 150.0);
    canvas.drawRect(r, p);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) => true;
}

楕円の描画

  void paint(Canvas canvas, Size size){
    Paint p = Paint();

    p.style = PaintingStyle.fill;
    p.color = Color.fromARGB(150, 0, 200, 255);
    Offset ctr = Offset(100.0, 100.0);
    canvas.drawCircle(ctr, 75.0, p);

    p.style = PaintingStyle.stroke;
    p.color = Color.fromARGB(150, 200, 0, 255);
    p.strokeWidth = 10.0;
    Rect r = Rect.fromLTWH(100.0, 50.0, 200.0, 150.0);
    canvas.drawRect(r, p);

    r = Rect.fromLTWH(50.0, 100.0, 150.0, 200.0);
    canvas.drawOval(r, p);
  }

直線の描画

    p.style = PaintingStyle.stroke;
    p.strokeWidth = 5.0;
    p.color = Color.fromARGB(150, 0, 200, 255);
    for (var i = 0; i <= 10; i++) {
      Rect r = Rect.fromLTRB(
        50.0 + 20 * i, 50.0,
        50.0, 250.0 - 20 * i);
      canvas.drawLine(r.topLeft, r.bottomRight, p);
    }

  }

テキストの描画

@override
  void paint(Canvas canvas, Size size){
    Paint p = Paint();

    ui.ParagraphBuilder builder = ui.ParagraphBuilder(
      ui.ParagraphStyle(textDirection: TextDirection.ltr),
    )
    ..pushStyle(ui.TextStyle(color: Colors.red, fontSize: 48.0))
    ..addText('Hello!')
      ..pushStyle(ui.TextStyle(color: Colors.blue[700], fontSize: 30.0))
      ..addText('This is a sample of paragraph text.')
    ..pushStyle(ui.TextStyle(color: Colors.blue[200], fontSize: 30.0))
    ..addText('You can draw Multi-font text!.');

    ui.Paragraph paragraph = builder.build()
    ..layout(ui.ParagraphConstraints(width: 300.0));

    Offset off = Offset(50.0, 50.0);
    canvas.drawParagraph(paragraph, off);

  }

【flutter】タブビューとドロワー

import 'package:flutter/material.dart';

void main() {
  runApp(new MyApp());
}
class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Generated App',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
        primaryColor: const Color(0xFF2196f3),
        canvasColor: const Color(0xFFfafafa),
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage>
  with SingleTickerProviderStateMixin {

  static const List<Tab> tabs = <Tab>[
    Tab(text: 'One'),
    Tab(text: 'Two'),
    Tab(text: 'Three'),
  ];

  late TabController _tabController;

  @override
  void initState() {
    super.initState();
    _tabController = TabController (
      vsync: this,
      length: tabs.length
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('My App'),
        bottom: TabBar(
          controller: _tabController,
          tabs: tabs,
        ),
      ),

      body: TabBarView(
        controller: _tabController,
        children: tabs.map((Tab tab) {
          return createTab(tab);
        }).toList(),
      ),
    );
  }

  Widget createTab(Tab tab){
    return Center(
      child: Text(
        'This is "${tab.text}" Tab.',
        style: const TextStyle(
          fontSize: 32.0,
          color: Colors.blue,
        ),
      )
    );
  }
} 

画面下部にタブバーを表示

  static const List<Tab> tabs = <Tab>[
    Tab(text: 'One', icon:Icon(Icons.star)),
    Tab(text: 'Two', icon:Icon(Icons.info)),
    Tab(text: 'Three', icon:Icon(Icons.home)),
  ];

  late TabController _tabController;

  @override
  void initState() {
    super.initState();
    _tabController = TabController (
      vsync: this,
      length: tabs.length
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('My App'),
      ),
      bottomNavigationBar:Container(
        color: Colors.blue,
        child:TabBar(
          controller: _tabController,
          tabs:tabs,
        ),
      ),

      body: TabBarView(
        controller: _tabController,
        children: tabs.map((Tab tab) {
          return createTab(tab);
        }).toList(),
      ),
    );
  }

drawer

class _MyHomePageState extends State<MyHomePage>{

  static var _items = <Widget>[];
  static var _message = 'ok.';
  static var _tapped = 0;

  @override
  void initState() {
    super.initState();
    for(var i = 0; i < 5; i++) {
      var item = ListTile(
          leading: const Icon(Icons.android),
          title: Text('No, $i'),
          onTap: () {
            _tapped = i;
            tapItem();
          }
      );
      _items.add(item);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter App'),
      ),
      body: Center(
        child: Text(
          _message,
          style: const TextStyle(
            fontSize: 32.0,
          ),
        ),
      ),
      drawer: Drawer(
        child: ListView(
          shrinkWrap: true,
          padding: const EdgeInsets.all(20.0),
          children: _items,
        ),
      ),
    );
  }

  void tapItem(){
      Navigator.pop(context);
      setState((){
        _message = 'tapped:[$_tapped]';
      });
  }
}

【flutter】ナビゲーションとルーティング

Navigation widgetを使用すると、新たなwidgetの作成が不要

移動先をpush
Navigator.push(,)
Navigator.pop()

import 'package:flutter/material.dart';

void main() {
  runApp(new MyApp());
}
class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Generated App',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
        primaryColor: const Color(0xFF2196f3),
        canvasColor: const Color(0xFFfafafa),
      ),
      home: FirstScreen(),
    );
  }
}

class FirstScreen extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Home"),
      ),
      body: Center(
        child: Container (
          child: const Text("Home Screen",
            style: const TextStyle(fontSize:32.0)),
        ),
      ),
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: 1,
        items: <BottomNavigationBarItem>[
          const BottomNavigationBarItem(
            label: 'Home',
            icon: const Icon(Icons.home, size:32),
          ),
          const BottomNavigationBarItem(
            label: 'next',
            icon: const Icon(Icons.navigate_next, size:32),
          ),
        ],
        onTap: (int value) {
          if (value == 1)
            Navigator.push(
              context,
              MaterialPageRoute(builder:
              (context)=> SecondScreen()),
            );
        }
      )
    );
  }
}

class SecondScreen extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text("Next"),
        ),
        body: Center(
          child: Container (
            child: const Text("Next Screen",
                style: const TextStyle(fontSize:32.0)),
          ),
        ),
        bottomNavigationBar: BottomNavigationBar(
            currentIndex: 0,
            items: <BottomNavigationBarItem>[
              const BottomNavigationBarItem(
                label: 'prev',
                icon: const Icon(Icons.navigate_before, size:32),
              ),
              const BottomNavigationBarItem(
                label: '?',
                icon: const Icon(Icons.android, size:32),
              ),
            ],
            onTap: (int value) {
              if (value == 0)
                Navigator.pop(
                  context
                );
            }
        )
    );
  }
}

表示間での値の引き渡しは、値を引数に指定してインスタンスを作成

class FirstScreen extends StatefulWidget {
  FirstScreen({Key? key}) : super(key: key);

  @override
  _FirstScreenState createState() => _FirstScreenState();
}


class _FirstScreenState extends State<FirstScreen> {
  static final _controller = TextEditingController();
  static var _input = "";

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Home"),
      ),
      body: Column(
        children: <Widget>[
          const Text('Home Screen',
          style: const TextStyle(fontSize: 32.0)),
          Padding(
            padding: const EdgeInsets.all(20.0),
            child: TextField(
              controller: _controller,
              style: const TextStyle(fontSize: 28.0),
              onChanged: changeField,
            ),
          ),
        ],
      ),
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: 1,
        items: <BottomNavigationBarItem>[
          const BottomNavigationBarItem(
            label: 'Home',
            icon: const Icon(Icons.home, size:32),
          ),
          const BottomNavigationBarItem(
            label: 'next',
            icon: const Icon(Icons.navigate_next, size:32),
          ),
        ],
        onTap: (int value) {
          if (value == 1)
            Navigator.push(
              context,
              MaterialPageRoute(builder:
              (context)=> SecondScreen(_input)),
            );
        }
      )
    );
  }

  void changeField(String val) => _input = val;
}

class SecondScreen extends StatelessWidget {

  final String _value;

  SecondScreen(this._value);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text("Next"),
        ),
        body: Center(
          child: Text(
            'you typed: "$_value".',
            style: const TextStyle(fontSize: 32.0),
          ),
        ),
        bottomNavigationBar: BottomNavigationBar(
            currentIndex: 0,
            items: <BottomNavigationBarItem>[
              const BottomNavigationBarItem(
                label: 'prev',
                icon: const Icon(Icons.navigate_before, size:32),
              ),
              const BottomNavigationBarItem(
                label: '?',
                icon: const Icon(Icons.android, size:32),
              ),
            ],
            onTap: (int value) {
              if (value == 0)
                Navigator.pop(
                  context
                );
            }
        )
    );
  }
}

routesによるルーティング

import 'package:flutter/material.dart';

void main() {
  runApp(new MyApp());
}
class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Generated App',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
        primaryColor: const Color(0xFF2196f3),
        canvasColor: const Color(0xFFfafafa),
      ),
      initialRoute: '/',
      routes: {
        '/': (context) => FirstScreen(),
        '/second': (context) => SecondScreen('Second'),
        '/third': (context) => SecondScreen('Third'),
      }
    );
  }
}

class FirstScreen extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Home"),
      ),
      body: Center(
        child:const Text("Home Screen",
          style: const TextStyle(fontSize: 32.0),
        ),
      ),
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: 1,
        items: <BottomNavigationBarItem>[
          const BottomNavigationBarItem(
            label: 'Home',
            icon: const Icon(Icons.home, size:32),
          ),
          const BottomNavigationBarItem(
            label: 'next',
            icon: const Icon(Icons.navigate_next, size:32),
          ),
        ],
        onTap: (int value) {
          if (value == 1)
            Navigator.pushNamed(context, '/second');
        }
      )
    );
  }
}

class SecondScreen extends StatelessWidget {

  final String _value;
  SecondScreen(this._value);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text("Next"),
        ),
        body: Center(
          child: Text(
            '$_value Screen',
            style: const TextStyle(fontSize: 32.0),
          ),
        ),
        bottomNavigationBar: BottomNavigationBar(
            currentIndex: 0,
            items: <BottomNavigationBarItem>[
              const BottomNavigationBarItem(
                label: 'prev',
                icon: const Icon(Icons.navigate_before, size:32),
              ),
              const BottomNavigationBarItem(
                label: '?',
                icon: const Icon(Icons.android, size:32),
              ),
            ],
            onTap: (int value) {
              if (value == 0)
                Navigator.pop(
                  context
                );
              if (value == 1)
                Navigator.pushNamed(context, '/third');
            }
        )
    );
  }
}

【flutter】複雑な構造のウィジェット

class _MyHomePageState extends State<MyHomePage> {

  static var _message = "ok.";
  static var _stars = '★★★★★';
  static var _star = 0;

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('App Name'),
        leading: BackButton(
          color: Colors.white,
        ),


      actions: <Widget>[
        IconButton(
          icon: Icon(Icons.android),
          tooltip: 'add star...',
          onPressed: iconPressedA,
        ),
        IconButton(
          icon: Icon(Icons.favorite),
          tooltip: 'subtract star...',
          onPressed: iconPressedB,
        )
      ],
      bottom: PreferredSize(
        preferredSize: const Size.fromHeight(30.0),
        child: Center(
          child: Text(_stars,
          style: TextStyle(
            fontSize: 22.0,
            color:Colors.white,
          ),),
        ),
      ),
    ),
    body:
      new Center(
        child: Text(
          _message,
          style: const TextStyle(
            fontSize: 28.0,
          ),
        )

      ),

    );
  }

  void iconPressedA(){
    _message = 'tap "Android".';
    _star++;
    update();
  }

  void iconPressedB(){
    _message = 'tap "favorite".';
    _star--;
    update();
  }

  void update(){
    _star = _star < 0 ? 0 : _star > 5 ? 5 : _star;
    setState((){
      _stars = '★★★★★☆☆☆☆☆'.substring(5 - _star, 5 - _star + 5);
      _message = _message + '[$_star]';
    });
  }
}

BottomNavigationBar

class _MyHomePageState extends State<MyHomePage> {
  static var _message = "ok.";
  static var _index = 0;

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('App Name'),
      ),
      body:
      new Center(
        child: Text(
          _message,
          style: const TextStyle(
            fontSize: 28.0,
          ),
        ),
      ),
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: _index,
        backgroundColor: Colors.lightBlueAccent,
        items: <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            label: 'Android',
            icon: Icon(Icons.android, color: Colors.black, size: 50),
          ),
          BottomNavigationBarItem(
            label: 'Favorite',
            icon: Icon(Icons.android, color: Colors.red, size: 50),
          ),
          BottomNavigationBarItem(
            label: 'Home',
            icon: Icon(Icons.android, color: Colors.white, size: 50),
          ),
        ],
        onTap: tapBottomIcon,
      ),
    );
  }

  void tapBottomIcon(int value) {
    var items = ['Android', 'Heart', 'Home'];
    setState((){
      _index = value;
      _message = 'you tapped: "' + items[_index] + '".';
    });
  }
}

List View

【flutter】UIその2

class _MyHomePageState extends State<MyHomePage> {

  static var _message = "ok.";
  static var _value = 0.0;

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('App Name'),
      ),
      body:
      new Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          mainAxisSize: MainAxisSize.max,
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: <Widget>[
            Padding(
              padding: EdgeInsets.all(20.0),
              child: Text(
                _message,
                style: TextStyle(
                  fontSize: 32.0,
                  fontWeight: FontWeight.w400,
                  fontFamily:"Robot"),
              ),
            ),
            Padding(
              padding: EdgeInsets.all(10.0),
            ),
            Slider (
              onChanged: sliderChanged,
              min: 0.0,
              max: 100.0,
              divisions: 20,
              value:_value,
            ),
          ],
        ),

      ),

    );
  }

  void sliderChanged(double value){
    setState((){
      _value = value.floorToDouble();
      _message = 'set value: $_value';
    });
  }
}
class _MyHomePageState extends State<MyHomePage> {

  static var _message = "ok.";

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('App Name'),
      ),
      body:
      new Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          mainAxisSize: MainAxisSize.max,
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: <Widget>[
            Padding(
              padding: EdgeInsets.all(20.0),
              child: Text(
                _message,
                style: TextStyle(
                  fontSize: 32.0,
                  fontWeight: FontWeight.w400,
                  fontFamily:"Robot"),
              ),
            ),
            Padding(
              padding: EdgeInsets.all(10.0),
            ),
            Padding(
              padding: EdgeInsets.all(10.0),
              child: ElevatedButton(
                onPressed:buttonPressed,
                child: Text(
                  "tap me!",
                  style: TextStyle(fontSize:32.0,
                  color: const Color(0xff000000),
                  fontWeight: FontWeight.w400,
                  fontFamily: "Roboto"),
                )
              )
            )
          ],
        ),

      ),

    );
  }

  void buttonPressed(){
    showDialog(
      context: context,
      builder: (BuildContext context) => AlertDialog(
        title: Text("Hello!"),
        content: Text("This is sample."),
        actions: <Widget>[
          TextButton(
              child: const Text('Cancel'),
              onPressed: () => Navigator.pop<String>(context, 'Cancel')
          ),
          TextButton(
              child: const Text('OK'),
              onPressed: () => Navigator.pop<String>(context, 'OK')
          ),
        ]
      ),
    ).then<void>((value)=> resultAlert(value));
  }

  void resultAlert(String value){
    setState((){
      _message = 'selected: $value';
    });
  }
}
class _MyHomePageState extends State<MyHomePage> {
  static var _message = "ok.";

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('App Name'),
      ),
      body:
      new Column(
        children: <Widget>[
          Text(
            _message,
            style: TextStyle(
              fontSize: 32.0,
            ),
          ),

          ListView(
            shrinkWrap: true,
            padding: const EdgeInsets.all(20.0),

            children: <Widget>[

              Text('First item',
              style: TextStyle(fontSize: 24.0),
              ),
              Text('Second item',
                style: TextStyle(fontSize: 24.0),
              ),
              Text('Third item',
                style: TextStyle(fontSize: 24.0),
              ),
            ],
          ),
        ],
      ),

    );
  }
}
class _MyHomePageState extends State<MyHomePage> {
  static var _message = "ok.";
  static var _index = 0;

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('App Name'),
      ),
      body:
      new Column(
        children: <Widget>[
          Text(
            _message,
            style: TextStyle(
              fontSize: 32.0,
            ),
          ),

          ListView(
            shrinkWrap: true,
            padding: const EdgeInsets.all(20.0),

            children: <Widget>[

              ListTile(
                leading: const Icon(Icons.android, size:32),
                title: const Text('first item',
                  style: TextStyle(fontSize: 28)),
                selected: _index == 1,
                onTap:() {
                  _index = 1;
                  tapTile();
                },
              ),
              ListTile(
                leading: const Icon(Icons.favorite, size:32),
                title: const Text('second item',
                    style: TextStyle(fontSize: 28)),
                selected: _index == 2,
                onTap:() {
                  _index = 2;
                  tapTile();
                },
              ),
              ListTile(
                leading: const Icon(Icons.home, size:32),
                title: const Text('third item',
                    style: TextStyle(fontSize: 28)),
                selected: _index == 3,
                onTap:() {
                  _index = 3;
                  tapTile();
                },
              ),

            ],
          ),
        ],
      ),

    );
  }

  void tapTile() {
    setState(() {
      _message = 'you tapped: No, $_index.';
    });
  }
}

SingleChildScrollView

class _MyHomePageState extends State<MyHomePage> {

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('App Name'),
      ),
      body: SingleChildScrollView(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: <Widget>[
            Container(
              color: Colors.blue,
              height: 120.0,
              child: const Center(
                child: Text('one',
                style: const TextStyle(fontSize:32.0)),
              ),
            ),
            Container(
              color: Colors.white,
              height: 120.0,
              child: const Center(
                child: Text('two',
                    style: const TextStyle(fontSize:32.0)),
              ),
            ),
            Container(
              color: Colors.blue,
              height: 120.0,
              child: const Center(
                child: Text('three',
                    style: const TextStyle(fontSize:32.0)),
              ),
            ),
            Container(
              color: Colors.white,
              height: 120.0,
              child: const Center(
                child: Text('four',
                    style: const TextStyle(fontSize:32.0)),
              ),
            ),
            Container(
              color: Colors.blue,
              height: 120.0,
              child: const Center(
                child: Text('five',
                    style: const TextStyle(fontSize:32.0)),
              ),
            ),
          ],
        ),
      )
    );
  }
}

【flutter】TextFieldなどのUI

class _MyHomePageState extends State<MyHomePage> {

  static var _message = "ok.";
  static final _controller = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('App Name'),
      ),
      body:
      new Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          mainAxisSize: MainAxisSize.max,
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: <Widget>[
            Padding(
              padding: EdgeInsets.all(20.0),
              child: Text(
                _message,
                style: TextStyle(
                  fontSize: 32.0,
                  fontWeight: FontWeight.w400,
                  fontFamily:"Robot"),
              ),
            ),
            Padding(
              padding: EdgeInsets.all(10.0),
              child: TextField(
                controller: _controller,
                style: TextStyle(
                    fontSize: 28.0,
                    color: const Color(0xffFF0000),
                    fontWeight: FontWeight.w400,
                    fontFamily:"Robot"),
              ),
            ),
              ElevatedButton(
                onPressed: buttonPressed,
                child: Text(
                  "Push me!",
                  style: TextStyle(
                    fontSize: 32.0,
                    color: const Color(0xff000000),
                    fontWeight: FontWeight.w400,
                    fontFamily: "Robot"),
              ),
            )
          ]
        ),

      ),

    );
  }

  void buttonPressed(){
    setState((){
      _message = "you said : " + _controller.text;
    });
  }
}
class _MyHomePageState extends State<MyHomePage> {

  static var _message = "ok.";
  static final _controller = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('App Name'),
      ),
      body:
      new Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          mainAxisSize: MainAxisSize.max,
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: <Widget>[
            Padding(
              padding: EdgeInsets.all(20.0),
              child: Text(
                _message,
                style: TextStyle(
                  fontSize: 32.0,
                  fontWeight: FontWeight.w400,
                  fontFamily:"Robot"),
              ),
            ),
            Padding(
              padding: EdgeInsets.all(10.0),
              child: TextField(
                onChanged: textChanged,
                controller: _controller,
                style: TextStyle(
                    fontSize: 28.0,
                    color: const Color(0xffFF0000),
                    fontWeight: FontWeight.w400,
                    fontFamily:"Robot"),
              ),
            ),
          ]
        ),

      ),

    );
  }

  void textChanged(String val){
    setState((){
      _message = val.toUpperCase();
    });
  }
}

checkbox

class _MyHomePageState extends State<MyHomePage> {

  static var _message = "ok.";
  static var _checked = false;

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('App Name'),
      ),
      body:
      new Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          mainAxisSize: MainAxisSize.max,
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: <Widget>[
            Padding(
              padding: EdgeInsets.all(20.0),
              child: Text(
                _message,
                style: TextStyle(
                  fontSize: 32.0,
                  fontWeight: FontWeight.w400,
                  fontFamily:"Robot"),
              ),
            ),
            Padding(
              padding: EdgeInsets.all(10.0),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.start,
                mainAxisSize: MainAxisSize.max,
                crossAxisAlignment: CrossAxisAlignment.end,
                children: <Widget> [
                  Checkbox(
                    value:_checked,
                    onChanged: checkChanged,
                  ),
                  Text(
                    "Checkbox",
                    style: TextStyle(fontSize:28.0,
                    fontWeight: FontWeight.w400,
                    fontFamily: "Roboto"),
                  )
                ]
              )
            ),
          ]
        ),

      ),

    );
  }

  void checkChanged(bool? value){
    setState((){
      _checked = value!;
      _message = value ? 'checked!' : 'not checked...';
    });
  }
}

Radio

class _MyHomePageState extends State<MyHomePage> {

  static var _message = "ok.";
  static var _selected = 'A';

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('App Name'),
      ),
      body:
      new Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          mainAxisSize: MainAxisSize.max,
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: <Widget>[
            Padding(
              padding: EdgeInsets.all(20.0),
              child: Text(
                _message,
                style: TextStyle(
                  fontSize: 32.0,
                  fontWeight: FontWeight.w400,
                  fontFamily:"Robot"),
              ),
            ),
            Padding(
              padding: EdgeInsets.all(10.0),
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.start,
              mainAxisSize: MainAxisSize.max,
              crossAxisAlignment:CrossAxisAlignment.center,
              children: <Widget>[
                Radio<String>(
                  value: 'A',
                  groupValue: _selected,
                  onChanged: checkChanged,
                ),
                Text(
                  "radio A",
                  style: TextStyle(fontSize:28.0,
                  fontWeight: FontWeight.w400,
                  fontFamily: "Roboto"),
                )
              ]
            ),
            Row(
                mainAxisAlignment: MainAxisAlignment.start,
                mainAxisSize: MainAxisSize.max,
                crossAxisAlignment:CrossAxisAlignment.center,
                children: <Widget>[
                  Radio<String>(
                    value: 'B',
                    groupValue: _selected,
                    onChanged: checkChanged,
                  ),
                  Text(
                    "radio B",
                    style: TextStyle(fontSize:28.0,
                        fontWeight: FontWeight.w400,
                        fontFamily: "Roboto"),
                  )
                ]
            )
          ]
        ),

      ),

    );
  }

  void checkChanged(String? value){
    setState((){
      _selected = value ?? 'nodata';
      _message = 'select: $_selected';
    });
  }
}

DropdownButton

class _MyHomePageState extends State<MyHomePage> {

  static var _message = "ok.";
  static var _selected = 'One';

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('App Name'),
      ),
      body:
      new Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          mainAxisSize: MainAxisSize.max,
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: <Widget>[
            Padding(
              padding: EdgeInsets.all(20.0),
              child: Text(
                _message,
                style: TextStyle(
                  fontSize: 32.0,
                  fontWeight: FontWeight.w400,
                  fontFamily:"Robot"),
              ),
            ),
            Padding(
              padding: EdgeInsets.all(10.0),
            ),
            DropdownButton<String>(
              onChanged: popupSelected,
              value: _selected,
              style: TextStyle(color:Colors.black,
                fontSize:28.0,
                fontWeight:FontWeight.w400,
                fontFamily: 'Robot'),

              items: <DropdownMenuItem<String>>[
                const DropdownMenuItem<String>(value: 'One', child: const Text('One')),
                const DropdownMenuItem<String>(value: 'Two', child: const Text('Two')),
                const DropdownMenuItem<String>(value: 'Three', child: const Text('Three')),
              ]
            )
          ]
        ),

      ),

    );
  }

  void popupSelected(String? value){
    setState((){
      _selected = value ?? 'not selected...';
      _message = 'select: $_selected';
    });
  }
}class _MyHomePageState extends State<MyHomePage> {

  static var _message = "ok.";
  static var _selected = 'One';

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('App Name'),
      ),
      body:
      new Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          mainAxisSize: MainAxisSize.max,
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: <Widget>[
            Padding(
              padding: EdgeInsets.all(20.0),
              child: Text(
                _message,
                style: TextStyle(
                  fontSize: 32.0,
                  fontWeight: FontWeight.w400,
                  fontFamily:"Robot"),
              ),
            ),
            Padding(
              padding: EdgeInsets.all(10.0),
            ),
            DropdownButton<String>(
              onChanged: popupSelected,
              value: _selected,
              style: TextStyle(color:Colors.black,
                fontSize:28.0,
                fontWeight:FontWeight.w400,
                fontFamily: 'Robot'),

              items: <DropdownMenuItem<String>>[
                const DropdownMenuItem<String>(value: 'One', child: const Text('One')),
                const DropdownMenuItem<String>(value: 'Two', child: const Text('Two')),
                const DropdownMenuItem<String>(value: 'Three', child: const Text('Three')),
              ]
            )
          ]
        ),

      ),

    );
  }

  void popupSelected(String? value){
    setState((){
      _selected = value ?? 'not selected...';
      _message = 'select: $_selected';
    });
  }
}