学习:https://flutter.cn/docs/get-started/flutter-for/android-devs
目录
1.视图在 Flutter 中的对应概念是什么?
Android 中的
View
是显示在屏幕上的一切的基础。按钮、工具栏、输入框以及一切内容都是View
。而 Flutter 中View
的大致对应物是Widget
。 Widget 并非完全对应于 Android 中的 View,但是在你熟悉 Flutter 的工作原理的过程中可以把它们看做“声明和构建 UI 的方式”。然而,widget 和
View
还是有一些差异。首先,widget 有着不一样的生命周期:它们是不可变的,一旦需要变化则生命周期终止。任何时候 widget 或它们的状态变化时, Flutter 框架都会创建一个新的 widget 树的实例。对比来看,一个 Android View 只会绘制一次,除非调用invalidate
才会重绘。
2.如何更新 widgets?
在 Android 中,你可以直接操作更新 View。然而在 Flutter 中,
Widget
是不可变的,无法被直接更新,你需要操作 Widget 的状态。这就是有状态 (Stateful) 和无状态 (Stateless) Widget 概念的来源。
StatelessWidget
如其字面意思—没有状态信息的 Widget。
StatelessWidget
用于你描述的用户界面的一部分不依赖于除了对象中的配置信息以外的任何东西的场景。这里需要着重注意的是,无状态和有状态的 Widget 本质上是行为一致的。它们每一帧都会重建,不同之处在于
StatefulWidget
有一个跨帧存储和恢复状态数据的State
对象。如果你有疑问,那么记住这条规则:如果一个 Widget 会变化(例如由于用户交互),它是有状态的。然而,如果一个 Widget 响应变化,它的父 Widget 只要本身不响应变化,就依然是无状态的。
3.如何更新widgets
import 'package:flutter/material.dart';
void main() {
runApp(SampleApp());
}
class SampleApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Sample App',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: SampleAppPage(),
);
}
}
class SampleAppPage extends StatefulWidget {
SampleAppPage({Key key}) : super(key: key);
@override
_SampleAppPageState createState() => _SampleAppPageState();
}
class _SampleAppPageState extends State<SampleAppPage> {
// Default placeholder text
String textToShow = "I Like Flutter";
void _updateText() {
setState(() {
// update the text
textToShow = "Flutter is Awesome!";
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Sample App"),
),
body: Center(child: Text(textToShow)),
floatingActionButton: FloatingActionButton(
onPressed: _updateText,
tooltip: 'Update Text',
child: Icon(Icons.update),
),
);
}
}
将参考代码拷贝到main.dart中,把test中的代码删掉,test中应该是自动生成的自动化测试代码
效果,点击浮动按钮更新Ui
class _SampleAppPageState extends State<SampleAppPage> {
// Default placeholder text
String textToShow = "I Like Flutter";
bool _isFlag = false;
void _updateText() {
setState(() {
// update the text
if (_isFlag) {
textToShow = "Flutter is Awesome!";
} else {
textToShow = "I Like Flutter!";
}
_isFlag = !_isFlag;
});
}
加个flag,可以每次点击显示不一样的字符串=-=
4.如何布局 Widget?
简单介绍了下padding这个属性
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Sample App"),
),
body: Center(
child:MaterialButton(
onPressed: () {},
child: Text('Hello'),
padding: EdgeInsets.only(left: 100.0, right: 100.0),
color: Colors.yellow,
),),
floatingActionButton: FloatingActionButton(
onPressed: _updateText,
tooltip: 'Update Text',
child: Icon(Icons.update),
),
);
}
我稍微改了下,加了个颜色背景,可以看到padding从50,50改到100,100背景区域是变大了,另外还发现flutter是不受Android开发者选项边界的支持的
5.如何在布局中添加或删除一个组件?
你可以给返回一个 Widget 的父 Widget 传入一个方法,并通过布尔标记值控制子 Widget 的创建。
import 'package:flutter/material.dart';
void main() {
runApp(SampleApp());
}
class SampleApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Sample App',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: SampleAppPage(),
);
}
}
class SampleAppPage extends StatefulWidget {
SampleAppPage({Key key}) : super(key: key);
@override
_SampleAppPageState createState() => _SampleAppPageState();
}
class _SampleAppPageState extends State<SampleAppPage> {
// Default value for toggle
bool toggle = true;
void _toggle() {
setState(() {
toggle = !toggle;
});
}
_getToggleChild() {
if (toggle) {
return Text('Toggle One');
} else {
return MaterialButton(onPressed: () {}, child: Text('Toggle Two'));
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Sample App"),
),
body: Center(
child: _getToggleChild(),
),
floatingActionButton: FloatingActionButton(
onPressed: _toggle,
tooltip: 'Update Text',
child: Icon(Icons.update),
),
);
}
}
效果
点击悬浮按钮字符串切换字符串,前面也参考写了一个
6. Widget 如何实现动画?
在 Android 中,你既可以通过 XML 文件定义动画,也可以调用 View 对象的
animate()
方法。在 Flutter 里,则使用动画库,通过将 Widget 嵌入一个动画 Widget 的方式实现 Widget 的动画效果。Flutter 通过
Animation<double>
的子类AnimationController
来暂停、播放、停止以及逆向播放动画。它需要一个Ticker
在垂直同步 (vsync) 的时候发出信号,并且在运行的时候创建一个介于 0 和 1 之间的线性插值。然后你就可以创建一个或多个Animation
,并将它们绑定到控制器上。例如,你可以使用
CurvedAnimation
来实现一个曲线插值的动画。在这种情况下,控制器决定了动画进度,CurvedAnimation
计算用于替换控制器默认线性动画的曲线值。和 Widget 一样,Flutter 中的动画效果也可以组合使用。在构建 Widget 树的时候,你需要将
Animation
对象赋值给某个 Widget 的动画属性,例如FadeTransition
的不透明度属性,并让控制器开始动画。
import 'package:flutter/material.dart';
void main() {
runApp(FadeAppTest());
}
class FadeAppTest extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Fade Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyFadeTest(title: 'Fade Demo'),
);
}
}
class MyFadeTest extends StatefulWidget {
MyFadeTest({Key key, this.title}) : super(key: key);
final String title;
@override
_MyFadeTest createState() => _MyFadeTest();
}
class _MyFadeTest extends State<MyFadeTest> with TickerProviderStateMixin {
AnimationController controller;
CurvedAnimation curve;
@override
void initState() {
super.initState();
controller = AnimationController(
duration: const Duration(milliseconds: 2000),
vsync: this,
);
curve = CurvedAnimation(parent: controller, curve: Curves.easeIn);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Container(
child: FadeTransition(
opacity: curve,
child: FlutterLogo(
size: 100.0,
)))),
floatingActionButton: FloatingActionButton(
tooltip: 'Fade',
child: Icon(Icons.brush),
onPressed: () {
controller.forward();
},
),
);
}
}
效果:会在中心空白处将flutter的图标慢慢显示出来