写一个flutter程序2

需求

  • 完成一个简单的移动应用程序,功能是:为一个创业公司生成建议的名称。用户可以选择和取消选择的名称、保存(收藏)喜欢的名称。
  • 该代码一次生成十个名称,当用户滚动时,会生成一新批名称。
  • 用户可以点击导航栏右边的列表图标,以打开到仅列出收藏名称的新页面(route)。

这一部分,我们来写一下交互和打开新的页面

向列表里添加图标

将lib/main.dart的代码替换

import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';
void main(List<String> args) {
 runApp(const MyApp()); 
}
class MyApp extends StatelessWidget{
 const MyApp({super.key});
 
 @override
 Widget build(BuildContext context){
 return MaterialApp(
 title: 'Startup Name Generator',
 home: Scaffold(
 appBar: AppBar(
 title: const Text('Startup Name Generator'),
 ),
 body: Center(
 child: RandomWords(),
 ),
 ),
 );
 }
}
class RandomWords extends StatefulWidget {
 const RandomWords({super.key});
 @override
 State<RandomWords> createState() => _RandomWordsState();
}
class _RandomWordsState extends State<RandomWords> {
 //保存建议的单词对
 final List<WordPair> _suggesttions = <WordPair>[]; 
 // 这个集合存储用户喜欢的单词对。Set中不允许重复的值
 final Set<WordPair> _saved = new Set<WordPair>();
 final _biggerFont = const TextStyle(fontSize: 18);
 @override
 Widget build(BuildContext context) {
 return ListView.builder(
 padding: const EdgeInsets.all(16.0),
 itemBuilder: (context,i) {
 if(i.isOdd) return const Divider();
 final index = i~/2;
 if(index >= _suggesttions.length){
 _suggesttions.addAll(generateWordPairs().take(10));
 }
 return _buildRow(_suggesttions[index]);
 },
 );
 }
 Widget _buildRow(WordPair pair){
 final bool alreadySaved = _saved.contains(pair);
 return ListTile(
 title: Text(
 pair.asPascalCase,
 style: _biggerFont,
 ),
 trailing: Icon(
 alreadySaved?Icons.favorite:Icons.favorite_border,
 color: alreadySaved?Colors.red:null,
 ),
 );
 }
}

我们添加了一个函数用来展示列表的每行
可以看到效果如下

添加交互

下面我们给点击添加效果,这部分就是调用setState()通知框架状态已经改变

在Flutter的响应式风格的框架中,调用setState()会为State对象出发build()方法,从而导致对UI的更新。

将lib/main.dart代码更新为

import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';
void main(List<String> args) {
 runApp(const MyApp()); 
}
class MyApp extends StatelessWidget{
 const MyApp({super.key});
 
 @override
 Widget build(BuildContext context){
 return MaterialApp(
 title: 'Startup Name Generator',
 home: Scaffold(
 appBar: AppBar(
 title: const Text('Startup Name Generator'),
 ),
 body: Center(
 child: RandomWords(),
 ),
 ),
 );
 }
}
class RandomWords extends StatefulWidget {
 const RandomWords({super.key});
 @override
 State<RandomWords> createState() => _RandomWordsState();
}
class _RandomWordsState extends State<RandomWords> {
 //保存建议的单词对
 final List<WordPair> _suggesttions = <WordPair>[]; 
 // 这个集合存储用户喜欢的单词对。Set中不允许重复的值
 final Set<WordPair> _saved = new Set<WordPair>();
 final _biggerFont = const TextStyle(fontSize: 18);
 @override
 Widget build(BuildContext context) {
 return ListView.builder(
 padding: const EdgeInsets.all(16.0),
 itemBuilder: (context,i) {
 if(i.isOdd) return const Divider();
 final index = i~/2;
 if(index >= _suggesttions.length){
 _suggesttions.addAll(generateWordPairs().take(10));
 }
 return _buildRow(_suggesttions[index]);
 },
 );
 }
 Widget _buildRow(WordPair pair){
 final bool alreadySaved = _saved.contains(pair);
 return ListTile(
 title: Text(
 pair.asPascalCase,
 style: _biggerFont,
 ),
 trailing: Icon(
 alreadySaved?Icons.favorite:Icons.favorite_border,
 color: alreadySaved?Colors.red:null,
 ),
 onTap:(){
 setState(() {
 if(alreadySaved){
 _saved.remove(pair);
 }else{
 _saved.add(pair);
 }
 });
 }
 );
 }
}

导航到新页面

替换掉lib/main.dart中的内容

import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';
void main(List<String> args) {
 runApp(const MyApp()); 
}
class MyApp extends StatelessWidget{
 const MyApp({super.key});
 
 @override
 Widget build(BuildContext context){
 return const MaterialApp(
 title: 'Startup Name Generator',
 home: RandomWords()
 );
 }
}
class RandomWords extends StatefulWidget {
 const RandomWords({super.key});
 @override
 State<RandomWords> createState() => _RandomWordsState();
}
class _RandomWordsState extends State<RandomWords> {
 //保存建议的单词对
 final List<WordPair> _suggesttions = <WordPair>[]; 
 // 这个集合存储用户喜欢的单词对。Set中不允许重复的值
 final Set<WordPair> _saved = Set<WordPair>();
 final _biggerFont = const TextStyle(fontSize: 18);
 @override
 Widget build(BuildContext context) {
 return Scaffold(
 appBar: AppBar(
 title: const Text('Startup Name Generator'),
 actions: <Widget>[
 IconButton(onPressed: _pushSaved, icon: const Icon(Icons.list))
 ],
 ),
 body: _buildSuggestions(),
 );
 }
 Widget _buildSuggestions(){
 return ListView.builder(
 padding: const EdgeInsets.all(16.0),
 itemBuilder: (context,i) {
 if(i.isOdd) return const Divider();
 final index = i~/2;
 if(index >= _suggesttions.length){
 _suggesttions.addAll(generateWordPairs().take(10));
 }
 return _buildRow(_suggesttions[index]);
 },
 );
 }
 Widget _buildRow(WordPair pair){
 final bool alreadySaved = _saved.contains(pair);
 return ListTile(
 title: Text(
 pair.asPascalCase,
 style: _biggerFont,
 ),
 trailing: Icon(
 alreadySaved?Icons.favorite:Icons.favorite_border,
 color: alreadySaved?Colors.red:null,
 ),
 onTap:(){
 setState(() {
 if(alreadySaved){
 _saved.remove(pair);
 }else{
 _saved.add(pair);
 }
 });
 }
 );
 }
 void _pushSaved(){
 Navigator.of(context).push(
 MaterialPageRoute<void>(
 builder: (BuildContext context){
 final Iterable<ListTile> tiles = _saved.map((WordPair pair) {
 return ListTile(
 title: Text(
 pair.asPascalCase,
 style: _biggerFont,
 ),
 );
 });
 final List<Widget> divided = ListTile.divideTiles(
 context: context,
 tiles: tiles,
 ).toList();
 return Scaffold(
 appBar: AppBar(
 title: const Text('Saved Suggestions'),
 ),
 body: ListView(children: divided),
 );
 },
 ),
 );
 }
}

我们在appBar那行增加一个IconButton图表,当用户点击列表图表的时候,包含收藏夹的新路由页面入栈显示
给onPressed绑定一个_pushSaved函数
因为我们需要在_RandomWordsState类中使用函数,所以将return 的ListView抽象成一个函数
在_pushSaved中
添加 Navigator.push 调用,这会使路由入栈(以后路由入栈均指推入到导航管理器的栈)
添加MaterialPageRoute ,新页面的内容会在MaterialPageRoute的build属性中构建

使用Themes修改UI

通过ThemeData类更改应用程序的主题
将类MyApp中的代码替换

class MyApp extends StatelessWidget{
 const MyApp({super.key});
 
 
 @override
 Widget build(BuildContext context){
 return MaterialApp(
 title: 'Startup Name Generator',
 theme: ThemeData(
 colorScheme: const ColorScheme.light(
 primary: Colors.orange,
 onPrimary: Colors.white,
 onBackground: Colors.white,
 secondary: Colors.amber),
 ),
 home: RandomWords()
 );
 }
}

这里注意单独使用theme:ThemeData(primaryColor: Colors.red),是无效的
需要设置主题中的 colorScheme属性
这里使用ColorScheme.light

theme: ThemeData(
 colorScheme: const ColorScheme.light(
 primary: Colors.orange,
 onPrimary: Colors.white,
 onBackground: Colors.white,
 secondary: Colors.amber),
 ),


至此完成了一个可运行在 Android 和 iOS 系统上的、包含交互的 Flutter 应用,在这个 项目 里,你已经做了下面的事情:

  • 写了 Dart 代码
  • 使用热重载加速了开发进程
  • 实现了一个 stateful widget,为你的应用加入了交互功能
  • 创建了一个新的页面(route),为主页和这个新页面的跳转加入了逻辑
  • 学会了如何使用 themes 修改应用的 UI
作者:乐码客原文地址:https://segmentfault.com/a/1190000042973670

%s 个评论

要回复文章请先登录注册