[转载]你在大公司用Flutter写网页吗?谷歌让你从创意到实现只要2天了

原作者:Mariano Zorrilla

链接:https://medium.com/flutter-community/from-idea-to-reality-in-2-days-with-flutter-web-how-i-posted-a-meme-product-over-product-hunt-edf9620a650b

image

你在大公司工作吗?

我知道……你有没有想过(不止一次)“哦,天哪……早上9点,我的一天已经被会议和调bug挤满了!"

是的,几乎每天!

我敢肯定,每次你在无聊的会议中都会去刷朋友圈!(同意的点赞)

1.我从哪里开始(问题):

我知道每个人在家里都有很多时间做自己的事情,对吧?比如看电视节目、电影、社交媒体……

对于那些有足够财富的人来说,通过聊天、电子邮件和会议交流的唯一途径是什么?

2.研究:

我们都喜欢探索,对吧?

所以,我想“我怎样才能把探索和实际产品结合起来”。

3.工作时间:

好吧,我有8个小时的“办公室工作”。所以,我没有太多的Web知识,因为我主要是一个移动开发人员,现在他们做了更多的管理工作(我知道双方的痛苦),但我知道Flutter 和Flutter Web目前处于测试版,但,你懂的…!

4.命名产品:

首先,你要为你的产品想一个好名字!

image

5.工作,工作,工作 !

利用我的空闲时间开始一个新项目总是很有趣的,对吧?但这一次看起来真的很有潜力,范围也没那么大。

选择的工具?!

image

为什么?因为开始一个新的项目、设计和实际完成都很容易!

它的发展实在是太快了:身为移动开发者,Web对我来说有点不同,即使我们每天都在使用它,但我们需要考虑的路线(路径)比以往任何时候都多!不仅仅是深层次的联系。

我们在纽约和西蒙以及弗雷特纽约的朋友们开完会后,我突然想到了一个主意。

我的解决方案提供了一个小型的StatefulWidget导航器,没有什么新奇之处,也不是世界上最干净的工作:

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'TMSBAE',
      onGenerateRoute: (settings) => NavigatorRoute.route(settings.name),
    );
  }
}

每一条路径都将来自onGenerateRoute,然后将那个坏小子解析到我们的导航器中。

一旦我走上这条路,我就使用了核心机器学习……或者简称If/Else

@override
void initState() {
  super.initState();
  Future.delayed(Duration(milliseconds: 0), () {
    if (widget.path == '/') {
      Navigator.of(context).pushAndRemoveUntil(HomeScreen.route(), (_) => false);
      return;
    } else if (widget.path == '/join') {
      Navigator.of(context).pushAndRemoveUntil(JoinScreen.route(), (_) => false);
      return;
    } else if (widget.path.contains('/join/')) {
      Navigator.of(context).pushAndRemoveUntil(JoinScreen.routeCode(widget.path.split('/')[2]), (_) => false);
      return;
    } else if (widget.path == '/bae') {
      Navigator.of(context).pushAndRemoveUntil(BaeScreen.route(), (_) => false);
    } else if (widget.path.contains('/result/')) {
      Navigator.of(context).pushAndRemoveUntil(ResultScreen.routeCode(widget.path.split('/')[2]), (_) => false);
    } else if (widget.path == '/about') {

    } else {
      Navigator.of(context).pushAndRemoveUntil(HomeScreen.route(), (_) => false);
      return;
    }
  });
}
} else {
Navigator.*of*(context).pushAndRemoveUntil(HomeScreen.*route*(), (_) => false);
return;
}
});
}

这样做的目的是避免获得大量的页面,例如:

{URL}/join/djUdmd19m4

Will open:

  • “/” 主屏幕
  • “/join” join屏幕
  • “/join/djUdmd19m4” 我们要打开的实际屏幕。

这是Flutter开发人员使用常规onGenerateRoute方法最常见的问题。

6.设计:

我很幸运,我也是一个UI/UX设计/开发人员……所以,从技术上说,我是一个全栈开发人员?!

我查看了一些设计网站,以获得灵感,并知道更多与我的设计,调色板等…我也看了一些开放源码字体使用和废话。

但它们只有一/两个屏幕大小,没有什么新奇之处,没有数据库/业务逻辑,只是一个使用动画的简单而酷的例子。

7.编码:

再说一次,即使我有空闲时间,记住,我有一份全职工作,唯一的空闲时间是我日常工作之外的时间……但足以让这个新项目迅速完成。

做网站的时候,总有一个大字是“响应”的是的,拜托!记住这个!我们有智能手机、笔记本电脑、台式机、平板电脑等……您的设计应该在每一个屏幕上都是实用/有用的!。

SingleChildScrollView

是其中一个你会经常使用的小部件,如果你计划有动态列表的话就不是最有用的,因为这个小部件会把所有东西都加载到内存中。

MediaQuery

为了得到尺寸和方位,超级有用,现在每个人都应该知道,但是…是的。

LayoutBuilder

太棒了!在考虑不同的形状因素和屏幕时,这一个起到了很好的带头作用。

Screens

我有几个:登录页(主屏幕),创建屏幕,加入屏幕,结果屏幕,投票屏幕,关于屏幕。

image

我在屏幕之间移动的整个业务逻辑是通过使用:

Navigator.*of*(context).pushAndRemoveUntil

我不想为这个产品保留一个堆栈,因为我可以用我的AppBar和屏幕上的一些其他元素/按钮在屏幕之间移动,拜托,它变得对PWA更友好了。

PWA

image

是的,flutter支持PWA和否,这两者并不是不同的东西,它们只是两者之间的一个补充。

如果你使用的是Flutter v.1.5+,请确保运行“Flutter create.”来获取丢失的文件。如果由于任何原因您没有它,让我给您以下片段:

在index.html中<body>

<script>
  if ('serviceWorker' in navigator) {
    window.addEventListener('load', function () {
      navigator.serviceWorker.register('flutter_service_worker.js');
    });
  }
</script>

在您的/web文件夹上,您应该有一个manifest.json文件,如果没有,它如下所示:

{
    "name": "App Name",
    "short_name": "App Short Name",
    "start_url": ".",
    "display": "standalone",
    "background_color": "#A83EF6",
    "theme_color": "#A83EF6",
    "description": "App Description",
    "orientation": "portrait-primary",
    "prefer_related_applications": false,
    "icons": [
        {
            "src": "icons/Icon-192.png",
            "sizes": "192x192",
            "type": "image/png"
        },
        {
            "src": "icons/Icon-512.png",
            "sizes": "512x512",
            "type": "image/png"
        }
    ]
}

注意那边的一些元素:

"display": "standalone"

允许您拥有全屏/本地的外观和感觉。您可以在这里阅读更多信息

你的图标应该在/web/icons(或任何其他文件夹中,但这样看起来不错)中,并且将是你的主屏幕/应用程序抽屉中使用的图标。

image

对于我那疯狂又好看的header,我用了:

ClipPath

使用以下代码段:

class HeaderWaveClipper extends CustomClipper<Path> {
  @override
  Path getClip(Size size) {
    var path = Path();
    path.lineTo(0, 0);
    path.lineTo(0, size.height - 100);
    path.cubicTo(
      0,
      size.height - 90,
      size.width * 0.004,
      size.height - 70,
      size.width * 0.06,
      size.height - 75,
    );
    path.cubicTo(
      size.width * 0.07,
      size.height - 75,
      size.width * 0.14,
      size.height - 95,
      size.width * 0.12,
      size.height - 65,
    );
    path.cubicTo(
      size.width * 0.12,
      size.height - 65,
      size.width * 0.08,
      size.height - 10,
      size.width / 3 * 0.98,
      size.height - 40,
    );
    path.cubicTo(
      (size.width / 3) * 1.08,
      size.height - 40,
      (size.width / 3) - 60,
      size.height - 5,
      (size.width / 3) + 100,
      size.height - 5,
    );
    path.cubicTo(
      (size.width / 3) * 1.8,
      size.height - 5,
      (size.width / 2) * 1.6,
      size.height,
      (size.width / 2) * 1.52,
      size.height - 30,
    );
    path.cubicTo(
      (size.width / 2) * 1.52,
      size.height - 35,
      (size.width / 2) * 1.4,
      size.height - 60,
      size.width - (size.width * 0.05),
      size.height - 60,
    );
    path.cubicTo(
      size.width - (size.width * 0.05),
      size.height - 60,
      size.width,
      size.height - 60,
      size.width,
      size.height - 90,
    );
    path.lineTo(size.width, 0);
    return path;
  }

  @override
  bool shouldReclip(CustomClipper<Path> oldClipper) => false;
}

我花了几个小时来解决这个问题……数学很有趣,但是……是的,花了几个小时让它在每一个屏幕上都反应灵敏,看起来很漂亮。

我说过每件事都花了我大约12个小时的编码,而其中很多时间是在2天的工作框架内进行设计+测试。

在Firebase上托管花了我几秒钟的时间(字面上),而且由于G域的存在,使用我自己的域非常简单。

8. 裂变传播?(希望如此)

我知道有一个特定的网站有我需要的东西来发布我的新创作,那就是Product Hunt - The best new products in tech.

每一个新的/酷的/怪异的产品/项目都结束了,我想知道那是什么感觉!我想创建我的第一个病毒产品后,这么多年的编码没有许多酷/有趣的想法。

这个过程相当直接:

  • 创建帐户
  • 等待1周(或关注他们的时事通讯以获得即时访问)
  • 发布产品
  • 关注每个细节(标题、描述、图标、截图/视频等)
  • 发布!(你可以安排这个)

最后的想法

这真的很有趣,希望人们能经常使用它!我知道这只是一个迷因,但这个有潜力,也许团队会在他们的日历中包含我自动生成的链接,这样每个人都有机会决定会议是否应该是电子邮件。

PS:我是黑胡桃实验室社区的一名成员,最近经常在看一些老外做的有趣的人工智能项目,如果有兴趣或疑问可以在评论区留言或私信与我交流鸭~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350