Android 颤振,水平航行
在Codelab英语单词示例中。。。 iOS导航转换是水平的。。正如您所期望的,一个Segue将在一个UINavigationController中运行。从右到左。。。POP从左到右。Android 颤振,水平航行,android,flutter,Android,Flutter,在Codelab英语单词示例中。。。 iOS导航转换是水平的。。正如您所期望的,一个Segue将在一个UINavigationController中运行。从右到左。。。POP从左到右。 ANDROID,同样的例子是垂直的,从下到上。POP是从上到下的。 我的问题。。。我如何在安卓系统中强制执行水平转换,使其行为类似于iOS?我想我将不得不使用MaterialPageRoute /* Nguyen Duc Hoang(Mr) Programming tutorial channel: ht
ANDROID,同样的例子是垂直的,从下到上。POP是从上到下的。
我的问题。。。我如何在安卓系统中强制执行水平转换,使其行为类似于iOS?我想我将不得不使用MaterialPageRoute
/*
Nguyen Duc Hoang(Mr)
Programming tutorial channel:
https://www.youtube.com/c/nguyenduchoang
Flutter, React, React Native, IOS development, Swift, Python, Angular
* */
import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';
//Define "root widget"
void main() => runApp(new MyApp());//one-line function
//StatefulWidget
class RandomEnglishWords extends StatefulWidget {
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return new RandomEnglishWordsState();//return a state's object. Where is the state's class ?
}
}
//State
class RandomEnglishWordsState extends State<RandomEnglishWords>{
final _words = <WordPair>[];//Words displayed in ListView, 1 row contains 1 word
final _checkedWords = new Set<WordPair>();//set contains "no duplicate items"
@override
Widget build(BuildContext context) {
// TODO: implement build
//Now we replace this with a Scaffold widget which contains a ListView
return new Scaffold(
appBar: new AppBar(
title: new Text("List of English words"),
actions: <Widget>[
new IconButton(icon: new Icon(Icons.list),
onPressed: _pushToSavedWordsScreen)
],
),
body: new ListView.builder(itemBuilder: (context, index) {
//This is an anonymous function
//index = 0, 1, 2, 3,...
//This function return each Row = "a Widget"
if (index >= _words.length) {
_words.addAll(generateWordPairs().take(10));
}
return _buildRow(_words[index], index);//Where is _buildRow ?
}),
);
}
_pushToSavedWordsScreen() {
// print("You pressed to the right Icon");
//To navigate, you must have a "route"
final pageRoute = new MaterialPageRoute(builder: (context) {
//map function = Convert this list to another list(maybe different object's type)
//_checkedWords(list of WordPair) => map =>
// converted to a lazy list(Iterable) of ListTile
final listTiles = _checkedWords.map( (wordPair) {
return new ListTile(
title: new Text(wordPair.asUpperCase,
style: new TextStyle(fontSize: 20.0, fontWeight: FontWeight.bold),),
);
});
//Now return a widget, we choose "Scaffold"
return new Scaffold(
appBar: new AppBar(
title: new Text("Checked words"),
),
body: new ListView(children: listTiles.toList(),),//Lazy list(Iterable) => List
);
});
Navigator.of(context).push(pageRoute);
}
Widget _buildRow(WordPair wordPair, int index) {
//This widget is for each row
final textColor = index % 2 == 0 ? Colors.red : Colors.blue;
final isChecked = _checkedWords.contains(wordPair);
return new ListTile(
//leading = left, trailing = right. Is is correct ? Not yet
leading: new Icon(
isChecked ? Icons.check_box : Icons.check_box_outline_blank,
color: textColor,
),
title: new Text(
wordPair.asUpperCase,
style: new TextStyle(fontSize: 18.0, color: textColor),
),
onTap: () {
setState(() {
//This is an anonymous function
if (isChecked) {
_checkedWords.remove(wordPair);//Remove item in a Set
} else {
_checkedWords.add(wordPair);//Add item to a Set
}
});
},
);
}
}
class MyApp extends StatelessWidget {
//Stateless = immutable = cannot change object's properties
//Every UI components are widgets
@override
Widget build(BuildContext context) {
//build function returns a "Widget"
return new MaterialApp(
title: "This is my first Flutter App",
home: new RandomEnglishWords()
);//Widget with "Material design"
}
}
/*
阮德宏先生
编程教程频道:
https://www.youtube.com/c/nguyenduchoang
颤振、反应、反应本机、IOS开发、Swift、Python、角度
* */
进口“包装:颤振/材料.省道”;
导入“package:english_words/english_words.dart”;
//定义“根控件”
void main()=>runApp(新的MyApp())//单线函数
//状态控件
类RandomEnglishWords扩展StatefulWidget{
@凌驾
状态createState(){
//TODO:实现createState
return new RandomEnglishWordsState();//返回状态的对象。状态的类在哪里?
}
}
//陈述
类RandomEnglishWordsState扩展了状态{
final _words=[];//ListView中显示的单词,一行包含一个单词
final _checkedWords=new Set();//集合包含“无重复项”
@凌驾
小部件构建(构建上下文){
//TODO:实现构建
//现在我们用一个包含ListView的Scaffold小部件替换它
归还新脚手架(
appBar:新的appBar(
标题:新文本(“英文单词列表”),
行动:[
新图标按钮(图标:新图标(Icons.list),
按下按钮:_按保存或屏幕)
],
),
正文:new ListView.builder(itemBuilder:(上下文,索引){
//这是一个匿名函数
//索引=0,1,2,3,。。。
//此函数返回每行=“小部件”
如果(索引>=\u单词长度){
_words.addAll(generateWordPairs().take(10));
}
返回_buildRow(_words[index],index);//哪里是_buildRow?
}),
);
}
_PushToSavedWordScreen(){
//打印(“您按下了右侧图标”);
//要导航,必须有“路线”
最终页面路径=新材料路径(生成器:(上下文){
//映射函数=将此列表转换为另一个列表(可能是不同对象的类型)
//_选中的单词(单词对列表)=>map=>
//已转换为ListTile的惰性列表(Iterable)
final listTiles=\u checkedWords.map((字对){
返回新的ListTile(
标题:新文本(wordPair.asupercase,
样式:新的文本样式(fontSize:20.0,fontWeight:fontWeight.bold),
);
});
//现在返回一个小部件,我们选择“Scaffold”
归还新脚手架(
appBar:新的appBar(
标题:新文本(“勾选文字”),
),
正文:新建ListView(子项:listTiles.toList(),),//惰性列表(Iterable)=>list
);
});
导航器.of(上下文).push(页面路由);
}
小部件构建行(字对字对,int索引){
//此小部件适用于每行
最终文本颜色=索引%2==0?颜色。红色:颜色。蓝色;
final isChecked=\u checkedWords.contains(字对);
返回新的ListTile(
//前导=左,尾随=右。正确吗?还没有
领先:新图标(
isChecked?图标。复选框:图标。复选框\u轮廓\u空白,
颜色:textColor,
),
标题:新文本(
wordPair.asUpperCase,
样式:新的TextStyle(fontSize:18.0,颜色:textColor),
),
onTap:(){
设置状态(){
//这是一个匿名函数
如果(已检查){
_checkedWords.remove(字对);//删除集合中的项
}否则{
_checkedWords.add(字对);//将项添加到集合中
}
});
},
);
}
}
类MyApp扩展了无状态小部件{
//无状态=不可变=无法更改对象的属性
//每个UI组件都是小部件
@凌驾
小部件构建(构建上下文){
//构建函数返回一个“小部件”
返回新材料PP(
标题:“这是我的第一个颤振应用程序”,
首页:新英语单词()
);//带有“材质设计”的小部件
}
}
首先,关于材料路线
对您的案例没有帮助。以下是官方对此的解释:
MaterialPageRoute很方便,因为它可以转换到新的
使用特定于平台的动画显示屏幕
您看到的这些动画是特定于平台的动画
如果要实现自定义动画,需要使用PageRouteBuilder
手动实现。这是你可以做到的
这是您的\u pushtosavedwordscreen
的一个修改版本,它执行从右到左的转换。在谷歌像素上测试
final pageRoute = new PageRouteBuilder(
pageBuilder: (BuildContext context, Animation animation,
Animation secondaryAnimation) {
// YOUR WIDGET CODE HERE
final listTiles = _checkedWords.map((wordPair) {
return new ListTile(
title: new Text(
wordPair.asUpperCase,
style: new TextStyle(fontSize: 20.0, fontWeight: FontWeight.bold),
),
);
});
//Now return a widget, we choose "Scaffold"
return new Scaffold(
appBar: new AppBar(
title: new Text("Checked words"),
),
body: new ListView(
children: listTiles.toList(),
), //Lazy list(Iterable) => List
);
},
transitionsBuilder: (BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation, Widget child) {
return SlideTransition(
position: new Tween<Offset>(
begin: const Offset(1.0, 0.0),
end: Offset.zero,
).animate(animation),
child: new SlideTransition(
position: new Tween<Offset>(
begin: Offset.zero,
end: const Offset(1.0, 0.0),
).animate(secondaryAnimation),
child: child,
),
);
},
);
Navigator.of(context).push(pageRoute);
final pageRoute=新的PageRouteBuilder(
pageBuilder:(构建上下文、动画、,
动画(二级动画){
//您的小部件代码在这里
final listTiles=\u checkedWords.map((字对){
返回新的ListTile(
标题:新文本(
wordPair.asUpperCase,
样式:新的文本样式(fontSize:20.0,fontWeight:fontWeight.bold),
),
);
});
//现在返回一个小部件,我们选择“Scaffold”
归还新脚手架(
appBar:新的appBar(
标题:新文本(“勾选文字”),
),
正文:新列表视图(
子项:listTiles.toList(),
),//惰性列表(Iterable)=>list
);
},
transitionsBuilder:(构建上下文、动画、,
动画辅助动画,小部件子项){
返回幻灯片转换(
职位:新吐温(
开始:常数偏移(1.0,0.0),
结束:偏移0.0,
).制作动画(动画),
子:新幻灯片转换(
职位:新吐温(
开始:Offset.zero,
结束:常数偏移(1.0,0.0),
).制作动画(第二动画),
孩子:池
dependencies:
flutter:
sdk: flutter
english_words: ^3.1.0 #version 3.1.0 or above
/*
Nguyen Duc Hoang(Mr)
Programming tutorial channel:
https://www.youtube.com/c/nguyenduchoang
Flutter, React, React Native, IOS development, Swift, Python, Angular
* */
import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';
//Define "root widget"
void main() => runApp(new MyApp());//one-line function
//StatefulWidget
class RandomEnglishWords extends StatefulWidget {
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return new RandomEnglishWordsState();//return a state's object. Where is the state's class ?
}
}
//State
class RandomEnglishWordsState extends State<RandomEnglishWords> {
final _words = <WordPair>[
]; //Words displayed in ListView, 1 row contains 1 word
final _checkedWords = new Set<WordPair>(); //set contains "no duplicate items"
@override
Widget build(BuildContext context) {
// TODO: implement build
//Now we replace this with a Scaffold widget which contains a ListView
return new Scaffold(
appBar: new AppBar(
title: new Text("List of English words"),
actions: <Widget>[
new IconButton(icon: new Icon(Icons.list),
onPressed: _pushToSavedWordsScreen)
],
),
body: new ListView.builder(itemBuilder: (context, index) {
//This is an anonymous function
//index = 0, 1, 2, 3,...
//This function return each Row = "a Widget"
if (index >= _words.length) {
_words.addAll(generateWordPairs().take(10));
}
return _buildRow(_words[index], index); //Where is _buildRow ?
}),
);
}
_pushToSavedWordsScreen() {
// print("You pressed to the right Icon");
//To navigate, you must have a "route"
//======================================================================
//======= original solution - ANDROID transitions Vertically
// final pageRoute = new MaterialPageRoute(builder: (context) {
// //map function = Convert this list to another list(maybe different object's type)
// //_checkedWords(list of WordPair) => map =>
// // converted to a lazy list(Iterable) of ListTile
// final listTiles = _checkedWords.map( (wordPair) {
// return new ListTile(
// title: new Text(wordPair.asUpperCase,
// style: new TextStyle(fontSize: 20.0, fontWeight: FontWeight.bold),),
// );
// });
// //Now return a widget, we choose "Scaffold"
// return new Scaffold(
// appBar: new AppBar(
// title: new Text("Checked words"),
// ),
// body: new ListView(children: listTiles.toList(),),//Lazy list(Iterable) => List
// );
// });
// Navigator.of(context).push(pageRoute);
// }
//=========== OLD solution... ANDROID transitions Vertically
//==================================================================
//==================================================================
//=========== new solution... transition Horizontal
final pageRoute = new PageRouteBuilder(
pageBuilder: (BuildContext context, Animation animation,
Animation secondaryAnimation) {
// YOUR WIDGET CODE HERE
final listTiles = _checkedWords.map((wordPair) {
return new ListTile(
title: new Text(
wordPair.asUpperCase,
style: new TextStyle(fontSize: 20.0, fontWeight: FontWeight.bold),
),
);
});
//Now return a widget, we choose "Scaffold"
return new Scaffold(
appBar: new AppBar(
title: new Text("Checked words"),
),
body: new ListView(
children: listTiles.toList(),
), //Lazy list(Iterable) => List
);
},
transitionsBuilder: (BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation, Widget child) {
return SlideTransition(
position: new Tween<Offset>(
begin: const Offset(1.0, 0.0),
end: Offset.zero,
).animate(animation),
child: new SlideTransition(
position: new Tween<Offset>(
begin: Offset.zero,
end: const Offset(1.0, 0.0),
).animate(secondaryAnimation),
child: child,
),
);
},
);
Navigator.of(context).push(pageRoute);
}
//========= end of solution
//=============================================================
Widget _buildRow(WordPair wordPair, int index) {
//This widget is for each row
final textColor = index % 2 == 0 ? Colors.red : Colors.blue;
final isChecked = _checkedWords.contains(wordPair);
return new ListTile(
//leading = left, trailing = right. Is is correct ? Not yet
leading: new Icon(
isChecked ? Icons.check_box : Icons.check_box_outline_blank,
color: textColor,
),
title: new Text(
wordPair.asUpperCase,
style: new TextStyle(fontSize: 18.0, color: textColor),
),
onTap: () {
setState(() {
//This is an anonymous function
if (isChecked) {
_checkedWords.remove(wordPair); //Remove item in a Set
} else {
_checkedWords.add(wordPair); //Add item to a Set
}
});
},
);
}
}
class MyApp extends StatelessWidget {
//Stateless = immutable = cannot change object's properties
//Every UI components are widgets
@override
Widget build(BuildContext context) {
//build function returns a "Widget"
return new MaterialApp(
title: "This is my first Flutter App",
home: new RandomEnglishWords()
);//Widget with "Material design"
}
}