こんにちは。
Google IO 2019にて発表されたFlutetr for webが発表されましたね。
どんなもんかと思ってさっそく使ってみました。
github.com
私が試した方法です。
上のリポジトリをCloneします。
hello_wold
をディレクトリをコピーしてディレクトリ名を変更します。
pubspec.yml
を以下のように書き換えます。
name: qkuronekop.dev
environment:
# You must be using Flutter >=1.5.0 or Dart >=2.3.0
sdk: '>=2.3.0-dev.0.1 <3.0.0'
dependencies:
flutter_web: any
flutter_web_ui: any
dev_dependencies:
build_runner: ^1.4.0
build_web_compilers: ^2.0.0
dependency_overrides:
flutter_web:
git:
url: https://github.com/flutter/flutter_web
path: packages/flutter_web
flutter_web_ui:
git:
url: https://github.com/flutter/flutter_web
path: packages/flutter_web_ui
サンプルのままだとflutter_web
やflutter_web_ui
が相対パスになっているので直しただけですね。
あと、nameのところを変更しました。
ここまでできればあとはlib/main.dart
を自由に書き換えればOKですね。
動かし方はflutter_webのリポジトリのREADMEに詳しくあるのですが、flutter pub global activate webdev
でwevdevをインストールしておきます。
先ほど作ったプロジェクトのルートでflutter pub upgrade
します。
webdev serve
しビルドに成功するとhttp://127.0.0.1:8080
で接続できます。
開発中はwebdev serve --auto restart
で起動するとホットリロードしてくれます。
せっかくなので、Firbase hostingでページを公開してみました。
flutter for webで作ったページをfirebaseで公開する方法はこちらの記事を参考にさせていただきました。
qiita.com
作ったページはこちら。
https://qkuronekop.dev/#/
すごく簡素な感じなのでおいおい色々試して行きたいです。
あと、スマホで見ると文字が切れてるかも。
main.dart
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter_web/material.dart';
import 'dart:js' as js;
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.deepPurple,
primaryColorDark: Colors.deepPurpleAccent),
home: Scaffold(
appBar: AppBar(
title: Text(
'qkuronekop.dev',
textDirection: TextDirection.ltr,
),
),
body: SingleChildScrollView(
child: Stack(
children: <Widget>[
Column(
children: <Widget>[
Container(
margin: EdgeInsets.all(16.0),
child: Column(
children: <Widget>[
SizedBox(
height: 16.0,
),
Center(
child: Text(
'Profile',
textDirection: TextDirection.ltr,
style: TextStyle(
fontSize: 28.0,
fontWeight: FontWeight.bold),
),
),
SizedBox(
height: 24.0,
),
Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
height: 48.0,
width: 48.0,
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(
'画像URL'),
fit: BoxFit.fill),
borderRadius: BorderRadius.circular(24.0),
boxShadow: [
BoxShadow(
color: Colors.black38,
offset: Offset(2.0, 2.0))
],
),
),
SizedBox(
width: 16.0,
),
Container(
width: 400.0,
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: <Widget>[
Text('こんにちは。\n辻村里美(@qkuronekop)と申します。'),
Text(
'Androidアプリ開発が得意です。\n現在は、KotlinでのAndroid開発やFlutterでのAndroid、iOS開発をしています。'),
Text('上記以外に興味があるのはGo言語でのWebアプリ開発です。'),
],
),
)
],
),
),
Container(
margin: EdgeInsets.symmetric(vertical: 32.0),
width: 300.0,
height: 2.0,
color: Colors.purpleAccent,
),
Center(
child: Text(
'Github',
textDirection: TextDirection.ltr,
style: TextStyle(
fontSize: 28.0,
fontWeight: FontWeight.bold),
),
),
SizedBox(
height: 24.0,
),
GestureDetector(
child: Text(
'https://github.com/qkuronekop',
style: TextStyle(
color: Colors.deepPurpleAccent,
decoration: TextDecoration.underline,
decorationColor: Colors.deepPurpleAccent,
decorationStyle: TextDecorationStyle.solid,
),
),
onTap: () {
js.context.callMethod(
"open", ["https://github.com/qkuronekop"]);
},
),
Container(
margin: EdgeInsets.symmetric(vertical: 32.0),
width: 300.0,
height: 2.0,
color: Colors.purpleAccent,
),
Center(
child: Text(
'Blog',
textDirection: TextDirection.ltr,
style: TextStyle(
fontSize: 28.0,
fontWeight: FontWeight.bold),
),
),
SizedBox(
height: 24.0,
),
GestureDetector(
child: Text('http://qkuronekop.hatenablog.jp/',
style: TextStyle(
color: Colors.deepPurpleAccent,
decoration: TextDecoration.underline,
decorationColor: Colors.deepPurpleAccent,
decorationStyle: TextDecorationStyle.solid,
)),
onTap: () {
js.context.callMethod("open",
["http://qkuronekop.hatenablog.jp/"]);
},
),
Container(
margin: EdgeInsets.symmetric(vertical: 32.0),
width: 300.0,
height: 2.0,
color: Colors.purpleAccent,
),
SizedBox(
height: 24.0,
),
Center(
child: Text(
'App',
textDirection: TextDirection.ltr,
style: TextStyle(
fontSize: 28.0,
fontWeight: FontWeight.bold),
),
),
SizedBox(
height: 24.0,
),
GestureDetector(
child: Container(
width: 320.0,
child: Image.network(
'画像URL'),
),
onTap: () {
js.context.callMethod("open", [
"https://play.google.com/store/apps/developer?id=qkuronekop&hl=ja"
]);
},
)
],
),
),
],
),
],
),
)));
}
}
現状感じていること
- 外部リンクができないので
dart:js
で外部リンクを開くスクリプトを書かねばならない。リンクではなくonTapを使っているのでPCでみた時にカーソルが変化しないのがちょっと微妙かな。
- 当たり前だけど今あるNativeアプリに依存するようなpackageは使えないのでweb用のライブラリとかが充実してくるといいな。
- Image.assetが使えないんだけど私だけ???
- CSS書かなくてもいい感じのUIが作れるのは最高。
2019/6/26追記
Image.assetについて勘違いしていたことがあって、Nativeの時みたいにpubspec.ymlにパスかいて使うのではなくweb/assets/
にリソースを置いて、そこのパスを書けばいいんですね。
しかし、ローカルでは表示されるけどfirebase hostingにアップすると表示されなくなる……なぜだ。。。
ちょっと色々デザインいじってみました。
gitにも公開したので興味ある方はみてください!
github.com