Flutter高仿谷歌翻译项目课程

    出版本教程主要是为了让小伙伴们快速学习,上手工作更容易。


视频链接:https://www.bilibili.com/video/av44583612/

图片资源:https://www.lanzous.com/i3c380b

(免费的,禁止倒卖)


flutter教程网送给学员的一句话:

    (每天进步一点点,无形跨出一大步)

学习方法:

    你们看完教程推荐第一次遍的时候不要直接跟着敲,不然很多思路没有学到,或者没有跟上,第一遍推荐不要加速,不要跟着敲,直接完整看完一遍,和边思考,然后第二遍试着跟着敲,写完一个widget或者void就暂停然后跟着敲一遍出来,第二遍推荐1.5倍速度,

    如果时间允许的话就第三遍直接不看教程直接敲出来试试,只为高效学习,不然思路不对怎么学都很容易忘记,浪费时间。

记录笔记

    大家有什么觉得比较重要的点可以用云笔记记录,下次写的时候忘记了可以直接拿出来,没有谁是能看一遍就直接完全记住而且多年不忘的,也没有谁是天生就什么都会的。

文档说明

    本文档是第九课完全更新完才开始写的文档,可能会有些内容不匹配,建议大家直接看视频就好。


教程目录

01 软件开启动画效果制作

02 左上角收缩栏制作

03 Drawer图标美化并完整

04 英语和中文转换器界面行

05 翻译内容编辑框设计

06 工具栏Icon布局设计

07 工具栏图标完善及小细节

08 翻译记录列表设计锥形

09 翻译记录完整列表编写

QQ群 or 微信群:

QQ群:874592746 (直接申请)

微信群:(秒拉进群)

mmqrcode1551797274417.png

效果查看:



01 软件开启动画效果制作

链接地址:https://www.bilibili.com/video/av44583612/?p=1

我们要做的第一个界面就是他的开启动画,先有个默认的main.dart

import 'package:flutter/material.dart';
import 'animation/open_animation.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: MaterialApp(
        title: 'Google Translate',
        theme: ThemeData(
          primaryColor: Colors.blue[600],
          primarySwatch: Colors.blue,
        ),
        home: OpenAnimation(),
      ),
    );
  }
}

然后就是要有个OpenAnimation的home,是在animation/open_animation.dart文件里的,

import 'package:flutter/material.dart';
import '../pages/index_page.dart'; // 导入包

// 动态 widget 类
class OpenAnimation extends StatefulWidget {
  _OpenAnimationState createState() => _OpenAnimationState();
}

class _OpenAnimationState extends State<OpenAnimation>
    with SingleTickerProviderStateMixin {
  AnimationController _controller; // 控制器
  Animation _animation; // 动画

  // 初始化
  @override
  void initState() {
    super.initState();
    // 控制器的初始化
    _controller = AnimationController(
      duration: Duration(
        seconds: 1,
      ),
      vsync: this,
    );
    // 动画的初始化
    _animation = Tween(begin: 0, end: 1).animate(_controller);

    // 监听状态
    _animation.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        Navigator.of(context).pushAndRemoveUntil(
            MaterialPageRoute(builder: (context) => IndexPage()),
            (route) => route == null);
      }
    });

    // 动画播放
    _controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    // 淡入浅出
    return FadeTransition(
      opacity: _controller,
      child: Image.asset(
        'images/Open_animation.png',
        fit: BoxFit.cover,
      ),
    );
  }
} 

然后后面有个yaml环境要写:
  assets:
    - images/Open_animation.png

开启动画图片,记得要放images目录里:

Open_animation.png

然后有个开启动画之后的../pages/index_page.dart

import 'package:flutter/material.dart';


class IndexPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: Scaffold(
        appBar: AppBar(
          title: Text('Google Translate'),
          elevation: 0.0,
        ),
        body: Center(
          child: Text('动画过后的界面'),
        )
      ),
    );
  }
}


02 左上角收缩栏制作

链接地址:https://www.bilibili.com/video/av44583612/?p=2

要在../pages/index_page.dart中scaffold中写个drawer并且导入一个../pages/drawer_page.dart

import 'package:flutter/material.dart';
import '../pages/drawer_page.dart';

class IndexPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: Scaffold(
        ...
        drawer: DrawerPage(),
      ),
    );
  }
}


drawer_page.dart整体代码:


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

class DrawerPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Drawer(
        child: ListView(
      children: <Widget>[
        UserAccountsDrawerHeader(
          accountName: null,
          accountEmail: null,
          currentAccountPicture: null,
          decoration: BoxDecoration(
            image: DecorationImage(
              fit: BoxFit.cover,
              image: AssetImage(
                'images/bg_account_switcher.png',
              ),
            ),
          ),
        ),
        ListTile(
          title: Text(
            '首页',
            style: TextStyle(color: Colors.blue[600]),
          ),
          leading: ImageIcon(
            AssetImage('images/quantum_ic_home_black_24.png'),
            color: Colors.blue[600],
          ),
          onTap: () {},
        ),
        ListTile(
          title: Text(
            '翻译收藏夹',
            style: TextStyle(
              color: Colors.black,
            ),
          ),
          leading: ImageIcon(
            AssetImage('images/quantum_ic_stars_black_24.png'),
          ),
          onTap: () {},
        ),
        ListTile(
          title: Text(
            '离线翻译',
            style: TextStyle(
              color: Colors.black,
            ),
          ),
          leading: ImageIcon(
            AssetImage('images/quantum_ic_offline_pin_black_24.png'),
          ),
          onTap: () {},
        ),
        ListTile(
          title: Text(
            '设置',
            style: TextStyle(
              color: Colors.black,
            ),
          ),
          leading: ImageIcon(
            AssetImage('images/quantum_ic_settings_black_24.png'),
          ),
          onTap: () {},
        ),
      ],
    ));
  }
}


03 Drawer图标美化并完整

链接地址:https://www.bilibili.com/video/av44583612/?p=3

这个就很简单了,直接放源码,上面也有。

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

class DrawerPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Drawer(
        child: ListView(
      children: <Widget>[
        ...
        ListTile(
          title: Text(
            '首页',
            style: TextStyle(color: Colors.blue[600]),
          ),
          leading: ImageIcon(
            AssetImage('images/quantum_ic_home_black_24.png'),
            color: Colors.blue[600],
          ),
          onTap: () {},
        ),
        ListTile(
          title: Text(
            '翻译收藏夹',
            style: TextStyle(
              color: Colors.black,
            ),
          ),
          leading: ImageIcon(
            AssetImage('images/quantum_ic_stars_black_24.png'),
          ),
          onTap: () {},
        ),
        ListTile(
          title: Text(
            '离线翻译',
            style: TextStyle(
              color: Colors.black,
            ),
          ),
          leading: ImageIcon(
            AssetImage('images/quantum_ic_offline_pin_black_24.png'),
          ),
          onTap: () {},
        ),
        ListTile(
          title: Text(
            '设置',
            style: TextStyle(
              color: Colors.black,
            ),
          ),
          leading: ImageIcon(
            AssetImage('images/quantum_ic_settings_black_24.png'),
          ),
          onTap: () {},
        ),
      ],
    ));
  }
}

04 英语和中文转换器界面行

链接地址:https://www.bilibili.com/video/av44583612/?p=4

直接在IndexPage里的列colum里面写个调用的,然后导入那个文件包,

index_page.dart

import 'package:flutter/material.dart';
import '../pages/drawer_page.dart';
// 下面就是我们这节课的文件导入,
import '../pages/body_page.dart';


class IndexPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    ....
        body: Column(
          children: <Widget>[
            IndexBody(),
          ],
        ),
        drawer: DrawerPage(),
      ),
    );
  }
}

然后就是我们的Indexbody了

../pages/body_page.dart


import 'package:flutter/material.dart';

Color primaryColor = Colors.blue[600];

class IndexBody extends StatefulWidget {
  IndexBody({Key key}) : super(key: key);
  _IndexBodyState createState() => _IndexBodyState();
}

class _IndexBodyState extends State<IndexBody> {
  String _firstLanguage = '英语';
  String _sencondLnaguage = '中文(简体)';

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 55.0,
      decoration: BoxDecoration(
        color: Colors.white,
        border: Border(
            bottom: BorderSide(
          width: 0.5,
          color: Colors.grey[500],
        )),
      ),
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.center,
        mainAxisAlignment: MainAxisAlignment.start,
        children: <Widget>[
          Expanded(
            child: Material(
              color: Colors.white,
              child: InkWell(
                onTap: () {},
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    Text(
                      this._firstLanguage,
                      style: TextStyle(
                        color: primaryColor,
                      ),
                    ),
                    ImageIcon(
                      AssetImage('images/spinner_blue.9.png'),
                      color: primaryColor,
                    ),
                  ],
                ),
              ),
            ),
          ),
          Material(
            color: Colors.white,
            child: IconButton(
              icon: Icon(Icons.compare_arrows),
              onPressed: (){},
              color: primaryColor,
            ),
          ),
          Expanded(
            child: Material(
              color: Colors.white,
              child: InkWell(
                onTap: () {},
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    Text(
                      this._sencondLnaguage,
                      style: TextStyle(
                        color: primaryColor,
                      ),
                    ),
                    ImageIcon(
                      AssetImage('images/spinner_blue.9.png'),
                      color: primaryColor,
                    ),
                  ],
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}


05 翻译内容编辑框设计

链接地址:https://www.bilibili.com/video/av44583612/?p=5

前面跟上节差不多,在colum里面加个

TextFieldPage
index_page.dart


import 'package:flutter/material.dart';
import '../pages/drawer_page.dart';
import '../pages/body_page.dart';
import '../pages/textfield_page.dart';


class IndexPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: Scaffold(
       ...
        body: Column(
          children: <Widget>[
            IndexBody(),
            TextFieldPage(),
          ],
        ),
        drawer: DrawerPage(),
      ),
    );
  }
}


然后就是textfield_page.dart


import 'package:flutter/material.dart';
import '../pages/icondemo_page.dart';

class TextFieldPage extends StatefulWidget {
  _TextFieldPageState createState() => _TextFieldPageState();
}

class _TextFieldPageState extends State<TextFieldPage> {
  @override
  Widget build(BuildContext context) {
    return Card(
      elevation: 4,
      margin: EdgeInsets.all(0.0),
      child: Container(
        height: 200.0,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: <Widget>[
            TextDemo(),
            IconDemo(),
            
          ],
        ),
      ),
    );
  }
}

class TextDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: Container(
        height: MediaQuery.of(context).size.height,
        padding: EdgeInsets.only(
          left: 18.0,
          right: 18.0,
          bottom: 20.0,
          top: 2.0,
        ),
        child: TextField(
          decoration: InputDecoration(
            border: InputBorder.none,
            hintText: '点按即可输入文本',
          ),
          style: TextStyle(
            color: Colors.black,
            fontSize: 25.0,
          ),
          maxLines: 999,
          cursorColor: Colors.grey[500],
          cursorWidth: 2.0,
        ),
      ),
    );
  }
}


06 工具栏Icon布局设计

链接地址:https://www.bilibili.com/video/av44583612/?p=6

textfield_page.dart里面有一个列,我们就在里面写东西

import 'package:flutter/material.dart';
import '../pages/icondemo_page.dart';//这节课的

class TextFieldPage extends StatefulWidget {
  _TextFieldPageState createState() => _TextFieldPageState();
}

class _TextFieldPageState extends State<TextFieldPage> {
  @override
  Widget build(BuildContext context) {
    return Card(
      elevation: 4,
      margin: EdgeInsets.all(0.0),
      child: Container(
        height: 200.0,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: <Widget>[
            TextDemo(),
            IconDemo(), //这节课的
          ],
        ),
      ),
    );
  }
}

class TextDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: Container(
        height: MediaQuery.of(context).size.height,
        padding: EdgeInsets.only(
          left: 18.0,
          right: 18.0,
          bottom: 20.0,
          top: 2.0,
        ),
        child: TextField(
          decoration: InputDecoration(
            border: InputBorder.none,
            hintText: '点按即可输入文本',
          ),
          style: TextStyle(
            color: Colors.black,
            fontSize: 25.0,
          ),
          maxLines: 999,
          cursorColor: Colors.grey[500],
          cursorWidth: 2.0,
        ),
      ),
    );
  }
}

导入完那个IconDemo当然是创建文件,


../pages/icondemo_page.dart
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';

class IconDemo extends StatefulWidget {
  _IconDemoState createState() => _IconDemoState();
}

class _IconDemoState extends State<IconDemo> {
  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: <Widget>[
        Container(width: 10,),
        ActionButton(
          title: '相机',
          icon: Icons.camera_alt,
        ),
        ActionButton(
          title: '手写',
          icon: CupertinoIcons.pen,
        ),
        ActionButton(
          title: '对话',
          image: AssetImage(
            'images/ic_double_mic_24dp.png',
          ),
        ),
        ActionButton(
          title: '语音',
          icon: Icons.keyboard_voice,
        ),
        Container(width: 10,),
      ],
    );
  }
}

class ActionButton extends StatefulWidget {
  final String title;
  final IconData icon;
  final AssetImage image;
  ActionButton({Key key, @required this.title, this.icon, this.image})
      : super(key: key);
  _ActionButtonState createState() => _ActionButtonState();
}

class _ActionButtonState extends State<ActionButton> {
  @override
  Widget build(BuildContext context) {
    return FlatButton(
      onPressed: () {},
      padding: EdgeInsets.only(
        left: 10.0,
        right: 10.0,
        top: 2.0,
        bottom: 2.0,
      ),
      child: Column(
        children: <Widget>[
          _displayIcon(),
          Text(
            widget.title,
            style: TextStyle(
              color: Colors.black,
              fontSize: 15.0,
            ),
          ),
        ],
      ),
    );
  }

  Widget _displayIcon() {
    if (widget.icon != null) {
      return Icon(
        widget.icon,
        color: Color(0xff3F51B5),
        size: 25.0,
      );
    } else if (widget.image != null) {
      return ImageIcon(
        widget.image,
        color: Color(0xff3F51B5),
        size: 25.0,
      );
    } else {
      return Container();
    }
  }
}


07 工具栏图标完善及小细节

链接地址:https://www.bilibili.com/video/av44583612/?p=7

其实上面的代码是已经完善的了,都差不多的,我再弄到这里,

../pages/icondemo_page.dart
     ....
    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: <Widget>[
        Container(width: 10,),
        ActionButton(
          title: '相机',
          icon: Icons.camera_alt,
        ),
        ActionButton(
          title: '手写',
          icon: CupertinoIcons.pen,
        ),
        ActionButton(
          title: '对话',
          image: AssetImage(
            'images/ic_double_mic_24dp.png',
          ),
        ),
        ActionButton(
          title: '语音',
          icon: Icons.keyboard_voice,
        ),
        Container(width: 10,),
      ],
    );
  }
}
.....


08 翻译记录列表设计锥形

链接地址:https://www.bilibili.com/video/av44583612/?p=8

我们在index_page.dart里加一个container然后写个高度10,再写下面的,这次直接完整的,

../pages/index_page.dart
import 'package:flutter/material.dart';
import '../pages/drawer_page.dart';
import '../pages/body_page.dart';
import '../pages/textfield_page.dart';
import '../pages/recording_page.dart';


class IndexPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: Scaffold(
        appBar: AppBar(
          title: Text('Google Translate'),
          elevation: 0.0,
        ),
        body: Column(
          children: <Widget>[
            IndexBody(),
            TextFieldPage(),
            Container(height: 10,),
            RecordingT(),
          ],
        ),
        drawer: DrawerPage(),
      ),
    );
  }
}
然后

../pages/recording_page.dart


import 'package:flutter/material.dart';
import '../const/const_page.dart';

class RecordingT extends StatefulWidget {
  _RecordingTState createState() => _RecordingTState();
}

class _RecordingTState extends State<RecordingT> {
  List<Translate> _items = [
    
  ];

  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: ListView.builder(
        itemCount: _items.length,
        itemBuilder: (context, index) {
          return _displayList(index);
        },
      ),
    );
  }

  Widget _displayList(int index) {
    return Container(
      padding: EdgeInsets.only(
        bottom: 2.0,
        left: 2.0,
        right: 2.0,
      ),
      child: Card(
        margin: EdgeInsets.only(
          left: 8.0,
          right: 8.0,
        ),
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.all(
            Radius.circular(0.0),
          ),
        ),
        child: Container(
          padding: EdgeInsets.only(
            left: 15.0,
            top: 15.0,
            bottom: 15.0,
          ),
          height: 80.0,
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: <Widget>[_flexible(index), _collection(index)],
          ),
        ),
      ),
    );
  }

  Widget _flexible(int index) {
    return Flexible(
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        children: <Widget>[
          Text(
            _items[index].title,
            style: Theme.of(context).textTheme.title,
            maxLines: 1,
            overflow: TextOverflow.ellipsis,
          ),
          Text(
            _items[index].subTitle,
            style: TextStyle(
              color: Colors.grey[600],
              fontSize: 18.0
            ),
            maxLines: 1,
            overflow: TextOverflow.ellipsis,
          ),
        ],
      ),
    );
  }

  Widget _collection(int index) {
    return IconButton(
      onPressed: () {},
      icon: Icon(
        _items[index].isCollection ? Icons.star : Icons.star_border,
        size: 25.0,
        color:
            _items[index].isCollection ? Colors.yellow[600] : Colors.grey[700],
      ),
    );
  }
}


09 翻译记录完整列表编写

链接地址:https://www.bilibili.com/video/av44583612/?p=9

我们这节课跟上节课差不多的,就是直接在里面传数据

../pages/recording_page.dart
    ...
List<Translate> _items = [
    Translate(
      'Darwer',
      '抽屉',
      true,
    ),
    Translate(
      'title',
      'subtitle',
      false,
    ),
    Translate(
      'title',
      'subtitle',
      false,
    ),
    Translate(
      'title',
      'subtitle',
      false,
    ),
    Translate(
      'title',
      'subtitle',
      false,
    ),
    Translate(
      'title',
      'subtitle',
      false,
    ),
    Translate(
      'title',
      'subtitle',
      false,
    ),
    Translate(
      'title',
      'subtitle',
      false,
    ),
    Translate(
      'title',
      'subtitle',
      false,
    ),
  ];
   ...


然后还有传的常量的那个包


../const/const_page.dart
class Translate {
  String title;
  String subTitle;
  bool isCollection;

  Translate(String title, String subTitle, bool isCollection) {
    this.title = title;
    this.subTitle = subTitle;
    this.isCollection = isCollection;
  }
}


本博客所有文章如无特别注明均为原创。作者:flutter教程网复制或转载请以超链接形式注明转自 Flutter教程网
原文地址《Flutter高仿谷歌翻译项目课程
分享到:更多

相关推荐


Flutter教程网 官方QQ群:874592746

扫描下面二维码 加入Flutter教程网微信群:


发表评论

路人甲 表情
Ctrl+Enter快速提交

网友评论(0)