【Flutter】Scaffoldの中でFormを使いたい

https://pub.dev/packages/form_field_validator

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
      title: Text(widget.title),
      ),
      body: Form (
          key: _formKey,

Widget build(BuildContext context)は複数記述できないので、body: Formと書く

そうすると、TextFormFieldが使えるようになる

            Padding(
              padding: EdgeInsets.all(10.0),
              child: TextFormField(
                controller: _id_controller,
                style: TextStyle(
                    fontSize: 28.0,
                    color: const Color(0xffFF0000),
                    fontWeight: FontWeight.w400,
                    fontFamily:"Roboto"),
                validator: idValidator,
              ),
            ),

【Flutter】バリデーション その2

class MyCustomFormState extends State<MyCustomForm>{
  final _formKey = GlobalKey<FormState>();
  final textValidator = MultiValidator([
    RequiredValidator(errorText: '入力必須の項目です。'),
    MinLengthValidator(8, errorText: '8文字以上で入力してください。'),
  ]);

  @override
  Widget build(BuildContext context){
    return Form(
      key: _formKey,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          TextFormField(
                  validator: textValidator,
          ),
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 16.0),
            child: ElevatedButton(
              onPressed:() {
                if(_formKey.currentState!.validate()){
                  ScaffoldMessenger.of(context).showSnackBar(
                    const SnackBar(content: Text('送信完了')),
                  );
                }
              },
              child: const Text('送信'),
            )
          )
        ]
      )
    );
  }
}

【Flutter】バリデーション

class MyCustomFormState extends State<MyCustomForm>{
  final _formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context){
    return Form(
      key: _formKey,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          TextFormField(
            validator: (value){
              if(value == null || value.isEmpty){
                return 'テキストを入力してください';
              }
            },
          ),
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 16.0),
            child: ElevatedButton(
              onPressed:() {
                if(_formKey.currentState!.validate()){
                  ScaffoldMessenger.of(context).showSnackBar(
                    const SnackBar(content: Text('送信完了')),
                  );
                }
              },
              child: const Text('送信'),
            )
          )
        ]
      )
    );
  }
}

フォームを一意に認識するためのキー

final _formKey = GlobalKey<FormState>();
Form(
     key: _formKey,
     )

入力がない場合テキストを返す

if (_formKey.currentState!.validate()) {
                 ScaffoldMessenger.of(context).showSnackBar(
                   const SnackBar(content: Text('送信完了')),
                 );
               }

【Flutter】widgetのコンポーネント化

demoのソースコード

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

classにする

class BodyText extends StatelessWidget {
  final int counter;
  const BodyText({Key? key, required this.counter}):super(key: key);

  @override build(BuildContext context){
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          const Text(
            'You have pushed the button this many times:',
          ),
          Text(
            '$counter',
            style: Theme.of(context).textTheme.headlineMedium,
          ),
        ],
      ),
    );
  }
}

呼び出す
body: BodyText(counter: _counter),

なるほど、これをbottomNavigationBarでやりたいが、setStateがあるとclassで共通化できないのか…

【Flutter】ゲーム画面の端との衝突

import 'package:flutter/material.dart';
import 'package:flame/game.dart';
import 'package:flame/input.dart';
import 'package:flutter/services.dart';
import 'package:flame/components.dart';
import 'package:flame/collisions.dart';
import 'dart:math';

void main() async {
  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> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('My App'),
      ),
        body: GameWidget(game: SampleGame())
    );
  }
}

class SampleGame extends FlameGame with HasCollisionDetection, HasKeyboardHandlerComponents, HasTappableComponents {

  late final List<MySprite> _splayers;

  @override
  Color backgroundColor() => const Color(0xffCCCCFF);

  @override
  Future<void> onLoad() async {
    await super.onLoad();
    add(ScreenHitbox());

    _splayers = <MySprite>[];
    for(var i = 0; i < 10; i++) {
      await add(MySprite());
    }
  }
}

class MySprite extends CircleComponent with CollisionCallbacks, HasGameRef<SampleGame> {
  var _size = 50.0;
  late Vector2 _delta;
  late Color _color;

  @override
  Future<void> onLoad() async {
    await super.onLoad();
    final _rnd = Random();
    _color = Color.fromARGB(255,
      _rnd.nextInt(256),
      _rnd.nextInt(256),
      _rnd.nextInt(256));
    size = Vector2(_size, _size);
    final _loc = Vector2.random();
    _loc.x *= gameRef.canvasSize.x;
    _loc.y *= gameRef.canvasSize.y;
    position = _loc;
    _delta = Vector2.random() * 3.0;
    setColor(_color);
    CircleHitbox hitbox = CircleHitbox();
    add(hitbox);
  }

  @override
  void render(Canvas canvas) {
    super.render(canvas);
  }

  @override
  void update(double delta){
    super.update(delta);
    position += _delta * delta * 100;
  }

  @override
  void onCollision(Set<Vector2> points, PositionComponent other){
    if(other is ScreenHitbox) {
      if (position.x <= 0) {
        _delta.x = _delta.x.abs();
      } if (position.x >= other.width - _size) {
        _delta.x = -_delta.abs();
      }
      if (position.y <= 0) {
        _delta.y = _delta.y.abs();
      } if (position.y >= other.height - _size) {
        _delta.y = -_delta.y.abs();
      }
    } else {
      setColor(Colors.yellow);
    }
  }

  @override
  void onCollisionEnd(PositionComponent other) {
    setColor(_color);
  }
}
import 'package:flame/collisions.dart';
import 'package:flame/components.dart';
import 'package:flame/events.dart';
import 'package:flame/experimental.dart';
import 'package:flame/extensions.dart';
import 'package:flame/game.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  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> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('My App'),
      ),
        body: GameWidget(game: SampleGame())
    );
  }
}

class SampleGame extends FlameGame with HasCollisionDetection, HasKeyboardHandlerComponents {

  late final List<BlockSprite> _blocks;
  bool _flag = true;
  final List<Color> colors = [
    Colors.red,
    Colors.orange,
    Colors.yellow,
    Colors.green,
    Colors.cyan,
    Colors.blue,
    Colors.purple,
  ];

  @override
  Color backgroundColor() => const Color(0xffCCCCFF);

  @override
  Future<void> onLoad() async {
    await super.onLoad();
    add(ScreenHitbox());
    final _size = Vector2((size.x - 10) / 5 - 10, 25);
    _blocks = <BlockSprite>[];
    for(var i = 0; i < 7; i++){
      for(var j = 0; j < 5; j++){
        var sp = await BlockSprite(_size,
          Vector2(j * (_size.x + 10) + 10, 30 * i + 50),
          colors[i]);
        _blocks.add(sp);
        add(sp);
      }
    }
    await(await BallSprite());
    await add(BarSprite());
  }

  void gameOver(){
    _flag = false;
    add(TextSprite("FINISHED."));
  }
}

class BallSprite extends CircleComponent with CollisionCallbacks, HasGameRef<SampleGame> {
  var _size = 25.0;
  late Vector2 _delta;

  @override
  Future<void> onLoad() async {
    await super.onLoad();
    size = Vector2(_size, _size);
    final _loc = Vector2(
      gameRef.canvasSize.x / 2 - 12,
      gameRef.canvasSize.y - 100);
    position = _loc;
    _delta = Vector2(1, -1);
    setColor(Colors.white);
    add(CircleHitbox());
  }

  @override
  void update(double delta) {
    if (!gameRef._flag) {return;}
    super.update(delta);
    position += _delta * delta * 100;
  }

  @override
  void onCollision(Set<Vector2> points,
      PositionComponent other) {
    if (!gameRef._flag) { return; }
    if (other is ScreenHitbox) {
      if(position.x <= 0) {
        _delta.x = _delta.x.abs();
      } if (position.x > other.width - _size) {
        _delta.x = -_delta.x.abs();
      }
      if(position.y <= 0) {
        _delta.y = _delta.y.abs();
      } if (position.y >= other.height - _size) {
        _delta.y = -_delta.y.abs();
        gameRef.gameOver();
      }
    }
    if(other is BlockSprite) {
      if (position.x + size.x / 2 < other.position.x) {
        _delta.x = _delta.x.abs();
      } if (position.x + size.x / 2 > other.position.x + other.width) {
        _delta.x = _delta.x.abs();
      }
      if (position.y + size.y / 2  < other.position.y) {
        _delta.y = -_delta.y.abs();
      }
      if(position.y + size.y / 2 > other.position.y + other.height) {
        _delta.y = _delta.y.abs();
      }
    }
    if (other is BarSprite) {
      if (position.x + size.x / 2 < other.position.x) {
        _delta.x = _delta.x.abs();
      } if (position.x + size.x / 2 > other.position.x + other.width) {
        _delta.x = _delta.x.abs();
      }
      if (position.y + size.y / 2 < other.position.y) {
        _delta.y = -_delta.y.abs();
        final d = ((other.position.x + other.width / 2) - (position.x + size.x / 2));
        final p = (other.width / 5).floor();
        _delta.x -= (d/p);
        _delta.x = _delta.x > 3 ? 3 : _delta.x;
        _delta.y = -(5/ (gameRef._blocks.length/5).ceil() + 1);
      }
      if (position.y + size.y / 2 > other.position.y + other.height) {
        _delta.y = _delta.y.abs();
    }
    }
  }
}

class BlockSprite extends PositionComponent with CollisionCallbacks, HasGameRef<SampleGame> {
  late Vector2 _position;
  late Vector2 _size;
  late Paint _paint;
  late Color _color;

  BlockSprite(this._size, this._position, this._color): super();

  @override
  Future<void> onLoad() async {
    await super.onLoad();
    position = _position;
    size = _size;
    _paint = Paint()
      ..style = PaintingStyle.fill
      ..color = _color;
    add(RectangleHitbox());
  }

  @override
  void render(Canvas canvas) {
    super.render(canvas);
    final r = Rect.fromLTWH(0, 0, _size.x, _size.y);
    canvas.drawRect(r, _paint);
  }

  @override
  void onCollisionEnd(PositionComponent other) {
    if(!gameRef._flag) { return ; }
    gameRef.remove(this);
    gameRef._blocks.remove(this);
    if (gameRef._blocks.length == 0) {
      gameRef.gameOver();
    }
  }
}

class BarSprite extends PositionComponent with CollisionCallbacks, KeyboardHandler, HasGameRef<SampleGame> {
  Vector2 _delta = Vector2.zero();
  late Paint _paint;

  BarSprite(): super();

  @override
  Future<void> onLoad() async {
    await super.onLoad();
    size = Vector2(100, 25);
    position = Vector2(gameRef.canvasSize.x / 2 - 50, gameRef.canvasSize.y - 50);
    _paint = Paint()
      ..style = PaintingStyle.fill
      ..color = Colors.white;
    add(RectangleHitbox());
  }

  @override
  void update(double delta) {
    if (!gameRef._flag) { return; }
    position += _delta * delta * 100;
    super.update(delta);
  }

  @override
  void render(Canvas canvas) {
    super.render(canvas);
    final r = Rect.fromLTWH(0, 0, 100, 25);
    canvas.drawRect(r, _paint);
  }

  @override
  bool onKeyEvent(
      RawKeyEvent event,
      Set<LogicalKeyboardKey> keysPressed,
      ) {
    if(!gameRef._flag) { return false; }
    if (event is RawKeyUpEvent) {
      _delta = Vector2.zero();
    }
    if (event.character == 'j') {
      _delta.x = -3;
    }
    if (event.character == 'l') {
      _delta.x = 3;
    }
    return true;
  }
}

class TextSprite extends TextComponent with HasGameRef<SampleGame> {
  late String _message;

  TextSprite(this._message): super();

  @override
  Future<void> onLoad() async {
    await super.onLoad();
    anchor = Anchor.center;
    position = Vector2(gameRef.canvasSize.x / 2,
     gameRef.canvasSize.y / 2);
    text = _message;
    textRenderer = TextPaint(
      style: TextStyle(
        fontSize: 60.0,
        fontWeight: FontWeight.w300,
        color: Colors.red,
      ),
    );
  }
}

【Flutter】スプライトの衝突判定

class SampleGame extends FlameGame with HasCollisionDetection, HasKeyboardHandlerComponents {

  @override
  Color backgroundColor() => const Color(0xffCCCCFF);

  @override
  Future<void> onLoad() async {
    await super.onLoad();
    add(MySprite(Vector2(300, 300), true));
    add(MySprite(Vector2(100, 100), false));
  }
}

class MySprite extends CircleComponent with CollisionCallbacks, KeyboardHandler {
  var _size = 100.0;
  Vector2 _delta = Vector2.zero();
  late Color _color;
  late Vector2 _position;
  late bool _stay;

  MySprite(this._position, this._stay): super();

  @override
  Future<void> onLoad() async {
    await super.onLoad();
    _color = _stay ? Colors.green : Colors.red;
    size = Vector2(_size, _size);
    position = _position;
    setColor(_color);
    CircleHitbox hitbox = CircleHitbox();
    add(hitbox);
  }

  @override
  bool onKeyEvent(
      RawKeyEvent event,
      Set<LogicalKeyboardKey> keysPressed,
      )  {
    if (this._stay) { return false; }
    if (event is RawKeyUpEvent) {
      _delta = Vector2.zero();
    }
    if (event.character == 'j') {
      _delta.x = -1;
    }
    if (event.character == 'l') {
      _delta.x = 1;
    }
    if (event.character == 'i') {
      _delta.y = -1;
    }
    if (event.character == 'k') {
      _delta.y = 1;
    }
    return true;
  }

  @override
  void update(double delta){
    super.update(delta);
    position += _delta * delta * 100;
  }

  @override
  void onCollision(Set<Vector2> points, PositionComponent other) {
    setColor(Colors.yellow);
  }

  @override
  void onCollisionEnd(PositionComponent other){
    setColor(_color);
  }
}

【Flutter】スプライトの利用

class MySprite extends SpriteComponent {
  late final Vector2 _position;

  MySprite(this._position): super();

  @override
  Future<void> onLoad() async {
    await super.onLoad();
    sprite = await Sprite.load('chara.png');
    position = _position;
    size = Vector2(100, 100);
  }

  @override
  void update(double delta) {
    super.update(delta);
  }
}
class SampleGame extends FlameGame with HasTappableComponents {
  Vector2 _position = Vector2(100, 100);
  final List<PositionComponent> _sprites = <PositionComponent>[];

  @override
  Color backgroundColor() => const Color(0xffCCCCFF);

  @override
  Future<void> onLoad() async {
    await super.onLoad();
    var sp1 = GreenRectSprite(Vector2(200, 100));
    _sprites.add(sp1);
    add(sp1);
    var sp2 = RedCircleSprite(Vector2(100, 200));
    _sprites.add(sp2);
    add(sp2);
    add(WhiteTextSprite(Vector2(25, 25)));
  }

  @override
  void onTapDown(TapDownEvent event) {
    _position = event.canvasPosition - Vector2(50, 50);
    super.onTapDown(event);
  }
}

class RedCircleSprite extends CircleComponent
  with HasGameRef<SampleGame> {
  late Vector2 _position;

  RedCircleSprite(this._position): super();

  @override
  Future<void> onLoad() async {
    await super.onLoad();
    setColor(Colors.red);
    position = _position;
    size = Vector2(100, 100);
  }

  @override
  void update(double delta) {
    final d = (gameRef._position - position) / 10;
    position += d * delta * 100;
    super.update(delta);
  }
}

class GreenRectSprite extends PositionComponent with HasGameRef<SampleGame>{
  late Vector2 _position;
  late Paint _paint;

  GreenRectSprite(this._position): super();

  @override
  Future<void> onLoad() async {
    await super.onLoad();
    position = _position;
    size = Vector2(100, 100);
    _paint = Paint()
      ..style = PaintingStyle.fill
      ..color = Colors.green;
  }

  @override
  void update(double delta) {
    final d = (gameRef._position - position) / 50;
    position += d * delta * 100;
    super.update(delta);
  }
}

class GreenRectSprite extends PositionComponent
  with HasGameRef<SampleGame> {
  late Vector2 _position;
  late Paint _paint;

  GreenRectSprite(this._position): super();

  @override
  Future<void> onLoad() async {
    await super.onLoad();
    position = _position;
    size = Vector2(100, 100);
    _paint = Paint()
      ..style = PaintingStyle.fill
      ..color = Colors.green;
  }

  @override
  void update(double delta) {
    final d = (gameRef._position - position) / 50;
    position += d * delta * 100;
    super.update(delta);
  }

  @override
  void render(Canvas canvas) {
    super.render(canvas);
    final r = Rect.fromLTWH(0, 0, 100, 100);
    canvas.drawRect(r, _paint);
  }
}

class WhiteTextSprite extends TextComponent {
  late Vector2 _position;

  WhiteTextSprite(this._position): super();

  @override
  Future<void> onLoad() async {
    await super.onLoad();
    position = _position;
    text = "Hello Flame";
    textRenderer = TextPaint(
      style: TextStyle(
        fontSize: 48.0,
        fontWeight: FontWeight.bold,
        color: Colors.white,
      ),
    );
  }
}

【Flutter】flame

$ flutter pub add flame
$ flutter pub upgrade flame

import 'package:flutter/material.dart';
import 'package:flame/game.dart';

void main() async {
  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> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('My App'),
      ),
        body: GameWidget(game: SampleGame())
    );
  }
}

class SampleGame extends FlameGame {
  late final paint;

  @override
  Future<void> onLoad() async {
    await super.onLoad();
    paint = Paint();
    paint.color = Colors.blue;
  }

  @override
  void render(Canvas canvas) {
    super.render(canvas);
    final rect = Rect.fromLTWH(100, 100, 100, 100);
    canvas.drawOval(rect, paint);
  }
}

キーで図形を操作する

class _MyHomePageState extends State<MyHomePage> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('My App'),
      ),
        body: GameWidget(game: SampleGame())
    );
  }
}

class SampleGame extends FlameGame with KeyboardEvents {
  late final paint;
  late Vector2 _loc;

  @override
  Future<void> onLoad() async {
    await super.onLoad();
    paint = Paint();
    paint.color = Colors.blue;
    _loc = Vector2(100, 100);
  }

  @override
  void render(Canvas canvas) {
    super.render(canvas);
    final rect = Rect.fromLTWH(_loc.x, _loc.y, 100, 100);
    canvas.drawOval(rect, paint);
  }

  @override
    KeyEventResult onKeyEvent(
      RawKeyEvent event,
      Set<LogicalKeyboardKey> keysPressed,
      ) {
    final _dpos = Vector2(0, 0);

    if (event.character == 'j') {
      _dpos.x = -10;
    }
    if (event.character == 'l') {
      _dpos.x = 10;
    }
    if (event.character == 'i') {
      _dpos.y = -10.0;
    }
    if (event.character == 'k') {
      _dpos.y = 10;
    }
    _loc += _dpos;
    return KeyEventResult.handled;

  }
}

【Flutter】Firebase Authenticationによるユーザ認証

firestoreのセキュリティルール

rules_version = '2';

service cloud.firestore {
  match /databases/{database}/documents {

    match /{document=**} {
      allow read, write: if request.time < timestamp.date(2023, 10, 3);
    }
  }
}

認証されたユーザのみ許可に変更

    match /{document=**} {
      allow read, write: if request.auth != null && request.auth.uid != null;
    }

### Authenticationによるユーザ認証
FirebaseのauthenticationでGoogleを許可する
$ flutter pub add firebase_auth
$ flutter pub upgrade firebase_auth
$ flutter pub add google_sign_in
$ flutter pub upgrade google_sign_in

import 'package:flutter/material.dart';
import 'dart:ui' as ui;
import 'dart:convert';
import 'dart:io';
import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  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();
  static const url = 'https://jsonplaceholder.typicode.com/posts';

  @override
  void initState(){
    super.initState();
    fire();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Home'),
      ),
      body: Padding(
        padding: EdgeInsets.all(20.0),
        child:Column(
          children:<Widget> [
               Text('INTERNET 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: () {
              doSignin();
            }
          )
    );
  }

  void addDoc() async {
    var msg = _controller.text;
    final input = msg.split(',');
    final data = {
      'name': input[0],
      'mail': input[1],
      'age': input[2]
    };
    FirebaseFirestore firestore = FirebaseFirestore.instance;
    final snapshot = await firestore.collection('mydata')
      .add(data);
    fire();
  }

  void fire() async {
    var msg = '';
    FirebaseFirestore firestore = FirebaseFirestore.instance;
    final snapshot = await firestore.collection('mydata')
      .orderBy('name', descending: false).get();
    snapshot.docChanges.forEach((element) {
      final name = element.doc.get('name');
      final mail = element.doc.get('mail');
      final age = element.doc.get('age');
      msg += "\n${name} (${age}) <${mail}>";
    });
    _controller.text = msg;
  }

  Future<UserCredential> signInWithGoogle() async {
    final GoogleSignInAccount? googleUser = await GoogleSignIn().signIn();
    final GoogleSignInAuthentication? googleAuth = await googleUser?.authentication;
    final credential = GoogleAuthProvider.credential(
      accessToken: googleAuth?.accessToken,
      idToken: googleAuth?.idToken,
    );
    return await FirebaseAuth.instance.signInWithCredential(credential);
  }

  void doSignin() {
    signInWithGoogle().then((value) {
      if(value.user != null) {
        fire();
      }
    });
  }
}

【Flutter】Firebase検索とソート

  void fire() async {
    var msg = _controller.text;
    FirebaseFirestore firestore = FirebaseFirestore.instance;
    final snapshot = await firestore.collection('mydata')
      .where('name', isEqualTo: msg).get();
    snapshot.docChanges.forEach((element) {
      final name = element.doc.get('name');
      final mail = element.doc.get('mail');
      final age = element.doc.get('age');
      msg += "\n${name} (${age}) <${mail}>";
    });
    _controller.text = msg;
  }

final snapshot = await firestore.collection(‘mydata’)
.orderBy(‘name’, descending: false)
.startAt([msg])
.endAt([msg + ‘\utf8ff’])
.get();

descendingはflaseだと昇順、trueだと降順にデータが並べられる

### データの追加

  void addDoc() async {
    var msg = _controller.text;
    final input = msg.split(',');
    final data = {
      'name': input[0],
      'mail': input[1],
      'age': input[2]
    };
    FirebaseFirestore firestore = FirebaseFirestore.instance;
    final snapshot = await firestore.collection('mydata')
      .add(data);
    fire();
  }

  void fire() async {
    var msg = '';
    FirebaseFirestore firestore = FirebaseFirestore.instance;
    final snapshot = await firestore.collection('mydata')
      .orderBy('name', descending: false).get();
    snapshot.docChanges.forEach((element) {
      final name = element.doc.get('name');
      final mail = element.doc.get('mail');
      final age = element.doc.get('age');
      msg += "\n${name} (${age}) <${mail}>";
    });
    _controller.text = msg;
  }