flutter初体验之编写的第一个flutter app

随着flutter环境的搭建成功,我趁热打铁照着教程做起了第一个app的demo
 
这个教程分两步,
第一步
我还是跟他(https://flutter.cn/docs/get-started/codelab)一步步下来,感觉挺有收获的,编码习惯,编码语法之类的;项目也正常运行起来,没有问题:
第二步
 
  1. 像列表添加图标
  2. 添加交互
  3. 导航到新页面
  4. 使用themes修改UI
 
 
第一部分的时候,就犯难了
教程里是组件化的,这个没有问题,但是在使用widget组件的时候,出现问题了。
Widget _buildRow(WordPair pair) {
  final bool alreadySaved = _saved.contains(pair);
  return new ListTile(
    title: new Text(
      pair.asPascalCase,
      style: _biggerFont,
    ),
    trailing: new Icon(   // 新增代码开始 ...
      alreadySaved ? Icons.favorite : Icons.favorite_border,
      color: alreadySaved ? Colors.red : null,
    ),                    // ... 新增代码结束
  );}
 
在使用每个组件UI的时候 都要 new 一下,常规代码逻辑中是直接使用的如下
 
body: ListView.builder(
  padding: const EdgeInsets.all(16.0),
  itemBuilder: /*1*/ (context,i){
    if(i.isOdd) return const Divider(); /*2*/
    final index = i ~/2; /*3*/
    if(index >= _suggestions.length){
      _suggestions.addAll(generateWordPairs().take(10));/*4*/
    }
    return ListTile(
      title: Text(
        _suggestions[index].asPascalCase,
        style: _biggerFont,
      )
    );
  }
),
// /*1*/ 对于每个建议的单词对都会调用一次 itemBuilder,然后将单词对添加到 ListTile 行中。在偶数行,该函数会为单词对添加一个 ListTile row,在奇数行,该函数会添加一个分割线的 widget,来分隔相邻的词对。注意,在小屏幕上,分割线看起来可能比较吃力。
// /*2*/ 在 ListView 里的每一行之前,添加一个 1 像素高的分隔线 widget。
// /*3*/ 语法 i ~/ 2 表示 i 除以 2,但返回值是整型(向下取整),比如 i 为:1, 2, 3, 4, 5 时,结果为 0, 1, 1, 2, 2,这个可以计算出 ListView 中减去分隔线后的实际单词对数量。
// /*4*/ 如果是建议列表中最后一个单词对,接着再生成 10 个单词对,然后添加到建议列表。
// 对于每一个单词对,_buildSuggestions() 都会调用一次 _buildRow()。这个函数在 ListTile 中显示每个新词对,这使你在下一步中可以生成更漂亮的显示行,详见本 codelab 的第二部分。
 
导致跟着教程编写的时候一直报错,于是我去掉了 new  的关键字之后,重启了服务,列表中添加图标的功能实现了,如下图
 
但是这里没有交互
 
完整代码
import 'package:english_words/english_words.dart';
import 'package:flutter/material.dart';
 
 
void main() {
  runApp(const MyApp());
}
 
 
class RandomWords extends StatefulWidget{
  const RandomWords({Key? key}): super(key:key);
  @override
  _RandomWordsState createState()=> _RandomWordsState();
}
class _RandomWordsState extends State<RandomWords>{
  final List<WordPair> _suggestions = <WordPair>[];
  final Set<WordPair> _saved = new Set<WordPair>();
  final TextStyle _biggerFont = const TextStyle(fontSize: 18.0);
//  3 导航到新页面
  void _pushSaved(){
    Navigator.of(context).push(
        MaterialPageRoute<void>(
            builder: (BuildContext context){
              final Iterable<ListTile> titls = _saved.map(
                (WordPair pair){
                  return ListTile(
                      title: Text(
                        pair.asPascalCase,
                        style: _biggerFont,
                      )
                  );
                }
              );
              final List<Widget> divided  = ListTile.divideTiles(
                  context: context,
                  tiles: titls,
                ).toList();
              return Scaffold(
                appBar: AppBar(
                  title: const Text('saved name is huYe'),
                ),
                body: ListView(children: divided),
              );
            }
        )
    );
  }
  @override
  Widget build(BuildContext context){
    return Scaffold(
      appBar: AppBar(
        title: const Text('Startup Name Cenerator'),
        actions: <Widget>[
          IconButton(onPressed: _pushSaved, icon: const Icon(Icons.list))
        ],
      ),
      body: _buildSuggestions()
    );
  }
 
 
  Widget _buildSuggestions() {
    return ListView.builder(
        padding: const EdgeInsets.all(16.0),
        itemBuilder: (BuildContext _context, int i) {
          if (i.isOdd) {
            return const Divider();
          }
          final int index = i ~/ 2;
          if (index >= _suggestions.length) {
            _suggestions.addAll(generateWordPairs().take(10));
          }
          return _buildRow(_suggestions[index]);
        });
  }
  // 2.1 添加图标
  Widget _buildRow(WordPair wp){
    final bool alreadySaved = _saved.contains(wp);
    return ListTile(
      title: Text(
        wp.asPascalCase,
        style: _biggerFont,
      ),
      trailing: Icon(
        alreadySaved? Icons.favorite : Icons.favorite_border,
        color: alreadySaved? Colors.red : null,
      ),
      // 2.2 添加交互
      onTap: (){
        setState(() {//在 Flutter 的响应式风格的框架中,调用 setState() 会为 State 对象触发 build() 方法,从而导致对 UI 的更新
          if(alreadySaved){
            _saved.remove(wp);
          }else{
            _saved.add(wp);
          }
        });
      },
    );
  }
}
 
 
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    // 这里自己用了const 代码报错,应该用final
    return MaterialApp(
      title: 'Startup Name Generators',
      home: const RandomWords(),
      theme: ThemeData(
        primaryColor: Colors.red // 不论如何设置都无效(后续补充这的原因)
      ),
    );
 

 

 
posted @ 2022-03-23 11:19  莽莽他老婆  阅读(155)  评论(0)    收藏  举报