原作者: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

你在大公司工作吗?

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

是的,几乎每天!

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

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

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

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

2.研究:

我们都喜欢探索,对吧?

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

3.工作时间:

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

4.命名产品:

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

5.工作,工作,工作 !

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

选择的工具?!

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

它的发展实在是太快了:身为移动开发者,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

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

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

Navigator.*of*(context).pushAndRemoveUntil

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

PWA

是的,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(或任何其他文件夹中,但这样看起来不错)中,并且将是你的主屏幕/应用程序抽屉中使用的图标。

对于我那疯狂又好看的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:我是黑胡桃实验室社区的一名成员,最近经常在看一些老外做的有趣的人工智能项目,如果有兴趣或疑问可以在评论区留言或私信与我交流鸭~