32
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Flutter #2Advent Calendar 2020

Day 7

Flutterで湯婆婆を実装してみる

Last updated at Posted at 2020-11-11

はじめに

実装

シンプルにStatefulWidgetでゴリゴリ書いてます。
1時間くらいで書けました。

ざつーにレスポンシブ対応版に差し替えました。(2020/11/12 追記)

import 'dart:math';

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

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

enum ScreenType { lg, sm }

ScreenType screenType(BuildContext context) {
  var width = MediaQuery.of(context).size.width;
  if (width > 768) {
    return ScreenType.lg;
  } else {
    return ScreenType.sm;
  }
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Fu婆婆',
      theme: ThemeData(
        primarySwatch: Colors.brown,
      ),
      home: MyHomePage(title: 'Fu婆婆'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  String _yubabaText = "契約書だよ。\nそこに名前を書きな。";

  var _nameController = TextEditingController();

  String _zeitaku(String name) {
    if (name == null && name.isEmpty) {
      return "";
    }

    final rand = Random();
    int index = rand.nextInt(name.length);
    return name.substring(index, index + 1);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Stack(
        children: <Widget>[
          Container(
            decoration: BoxDecoration(
              image: DecorationImage(
                image: AssetImage('assets/chihiro016.jpg'),
                fit: BoxFit.cover,
              ),
            ),
          ),
          SingleChildScrollView(
            child: screenType(context) == ScreenType.sm
                ? Center(
                    child: Column(
                      children: [
                        _buildYubabaTextBox(context),
                        _buildContract(context),
                      ],
                    ),
                  )
                : Center(
                    child: Stack(
                      children: <Widget>[
                        Align(
                          alignment: Alignment.topLeft,
                          child: _buildYubabaTextBox(context),
                        ),
                        Align(
                          alignment: Alignment.bottomRight,
                          child: _buildContract(context),
                        ),
                      ],
                    ),
                  ),
          ),
        ],
      ),
    );
  }

  Widget _buildYubabaTextBox(BuildContext context) {
    return Container(
      margin: EdgeInsets.all(30),
      padding: EdgeInsets.all(30),
      decoration: new BoxDecoration(
        color: Colors.white.withAlpha(200),
        borderRadius: BorderRadius.all(Radius.circular(10)),
        border: Border.all(color: Colors.black.withAlpha(200), width: 5),
      ),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Text(
            _yubabaText,
            softWrap: true,
            style: TextStyle(fontSize: 30),
          ),
        ],
      ),
    );
  }

  Widget _buildContract(BuildContext context) {
    return Container(
      width: 500,
      height: 400,
      margin: EdgeInsets.all(20),
      color: Color(0xffe3ab7a).withAlpha(220),
      child: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          children: [
            Padding(
                padding: EdgeInsets.all(50),
                child: Text(
                  '契約書',
                  style: TextStyle(fontSize: 50),
                )),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                SizedBox(
                    width: 50,
                    child: Text(
                      '甲',
                      style: TextStyle(fontSize: 30),
                    )),
                SizedBox(
                  width: 300,
                  child: Text(
                    '油屋当主 湯婆婆',
                    style: TextStyle(fontSize: 30),
                  ),
                ),
              ],
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                SizedBox(
                  width: 50,
                  child: Text(
                    '乙',
                    style: TextStyle(fontSize: 30),
                  ),
                ),
                SizedBox(
                    width: 300,
                    child: TextField(
                      controller: _nameController,
                      cursorColor: Colors.brown,
                      style: TextStyle(fontSize: 30),
                      maxLength: 30,
                      decoration: InputDecoration(
                        hintText: '名前を入力',
                      ),
                    )),
              ],
            ),
            Padding(
              padding: EdgeInsets.all(30),
              child: RaisedButton(
                child: Padding(
                  padding: EdgeInsets.all(5),
                  child: Text(
                    '契約',
                    style: TextStyle(fontSize: 30, color: Colors.red),
                  ),
                ),
                color: Color(0xffe3ab7a),
                shape: const OutlineInputBorder(
                  borderRadius: BorderRadius.all(Radius.circular(10)),
                  borderSide: BorderSide(color: Colors.red),
                ),
                onPressed: () {
                  var name = _nameController.text;
                  if (name == null || name.isEmpty) {
                    return;
                  }
                  var newName = _zeitaku(name);

                  setState(
                    () {
                      _yubabaText =
                          'フン。\n$nameというのかい。\n贅沢な名だねぇ。\n\今からお前の名前は$newNameだ。\nいいかい、$newNameだよ。\n分かったら返事をするんだ、$newName!!\n';
                    },
                  );
                },
              ),
            ),
          ],
        ),
      ),
    );
  }
}

全コードはここ→GitHub

Hosting

今回は手軽に触ることができるようにWebアプリとしてビルドしFirebaseでHostingしました。
↓からどうぞ。
https://flutter-baba.web.app/#/

画面

image.png
image.png
※ 湯婆婆の画像はジブリ公式からお借りしています。(常識の範囲内だと思ってます・・・)

おわりに

今回、突発的にFlutterで実装してみました。
改めてですが、Flutterは素早くアプリが作れて良き良きの良きですね。
それと、私は普段Android系の開発をしているのですが、Flutter+Firebaseを活用すれば手軽にWebアプリを開発できるってのもありがたいです。
モバイルアプリだとこういうネタアプリのためだと配布がめんどいので。
Flutterやったことないって人はぜひ一度触ってみてください。

追記

32
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
32
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?