Flutter入门——面向iOS开发者——用户界面基础
本博客介绍Flutter中UI开发的基础知识以及它与SwiftUI的比较。这包括如何开始开发您的应用程、显示静态文本、创建按钮、对按下事件做出反应、显示列表、网格等。
一、入口
在SwiftUI中,牛奶可以使用它App来启动您的应用程序。
@main
struct MyApp: App {
var body: some Scene {
WindowGroup{
HomePage()
}
}
}
另一种常见的SwiftUI做法是将应用程序主题放在struct
符合View
协议中。如下所示
struct HomePage: View {
var body: some View {
Text("Hello, World!")
}
}
要启动您的Flutter应用程序,请将您的应用程序实例传递给该runApp
函数。
void main() {
runApp(const MyApp());
}
App
是一个小部件。构建方法描述了他所带喵的用户界面部分。通常以WidgetApp
类开始您的应用程序,例如CupertinoApp
.
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
// Returns a CupertinoApp that, by default,
// has the look and feel of an iOS app.
return const CupertinoApp(
home: HomePage(),
);
}
}
上面使用的小部件HomePage
可能以类Scaffold
开头。Scaffold
实现应用程序的基本布局结构。
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: Text(
'Hello, World!',
),
),
);
}
}
请注意 Flutter 如何使用Center
小部件。SwiftUI 默认在其中心呈现视图的内容。Flutter 并非总是如此。 Scaffold
不会body
在屏幕中央呈现其小部件。要使文本居中,请将其包裹在一个Center
小部件中。要了解不同的小部件及其默认行为,请查看小部件目录。
二、添加按钮
在SwiftUI中,您使用Button
struct来创建按钮。
Button("Do something") {
// This clsure gets called when your
//button is tapped
}
要在Flutter
中获得相同的结果哦,请使用CupertinoButton
类:
CupertinoButton(
onPressed: () {
// This closure is called when your button is tapped.
},
child: const Text('Do something'),
)
Flutter使您可以访问具有预定义的各种按钮。该CupertinoButton
来自Cupertino库。Cupertino库中的小部件是为了Apple设计的系统。
三、水平对齐组件
在SwiftUI,堆栈视图在设计布局中起着重要作用。两个独立的结构允许您创建堆栈:
HStack
用于水平堆栈视图。VStack
用于垂直堆栈视图。
以下SwiftUI视图将地球图像和文本添加到水平堆栈视图:
HStack {
Image(systemName: "globe")
Text("Hello, world!")
}
Flutter使用Row
而不是HStack
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Icon(CupertinoIcons.globe),
Text('Hello, world!'),
],
)
该Row
小部件需要参数List<Widget>
中的一个children
。该mainAxisAlignment
属性告诉Flutter如何定位具有额外空间的子项。MainAxisAlignment.center
将孩子定位在主轴的中心。对于Row
,主轴是水平轴。
四、垂直对齐组件
在SwiftUI,您可以VStack
即将组件排列成垂直的柱子。
VStack {
Image(systemName: "globe")
Text("Hello, world!")
}
Flutter与上一个示例相同的代码。除了将Row
替换成Column
.
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Icon(CupertinoIcons.globe),
Text('Hello, world!'),
],
)
五、显示列表视图
在SwiftUI中,您使用List
基本组件来显示项目序列。要显示一系列模型对象,请确保用户识别您的模型对象。要使对象可识别,请使用Identifiable
协议。
struct Person: Identifiable {
var name: String
}
var persons = [ Person(name: "Person 1"), Person(name: "Person 2"), Person(name: "Person 3"),]
struct ListWithPersons: View {
let persons: [Person]
var body: some View {
List {
ForEach(persons) { person in
Text(person.name)
}
}
}
}
这类似于Flutter喜欢构建其类标小部件的方式。Flutter不需要列表时候可识别的。您设置要显示的项目数,然后为每个项目构建小部件。
class Person {
String name;
Person(this.name);
}
var items = [
Person('Person 1'),
Person('Person 2'),
Person('Person 3'),
];
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(items[index].name),
);
}
),
);
}
}
Flutter对列表有一些注意事项:
- 该
ListView
小部件具有构建方法。就像FoorEach SwiftUI List
结构中的一样。 itemCount
参数ListView
设置显示多少项目的ListView
.- 有一个索引参数,该
itemBuilder
参数介于零和比itemCount小一之间。
前面的示例ListTile
为每个项目返回了一个小部件。该ListTile
小部件包括属性像height
和font-size
.这些属性有助于构建列表。但是,Flutter允许您返回几乎所有代表您的数据的小部件。
六、显示网格
在SwiftUI中构建非条件网格时,您可以使用Grid with GridRow
Grid {
GridRow {
Text("Row 1")
Image(systemName: "square.and.arrow.down")
Image(systemName: "square.and.arrow.up")
}
GridRow {
Text("Row 2")
Image(systemName: "square.and.arrow.down")
Image(systemName: "square.and.arrow.up")
}
}
要在Flutter中显示网格,请使用GridView
小部件。这个小部件有各种构造函数。每个构造函数都有相似的目标,但使用不同的输入参数。以下示例使用.builder()
初始化程序:
const widgets = [
Text('Row 1'),
Icon(CupertinoIcons.arrow_down_square),
Icon(CupertinoIcons.arrow_up_square),
Text('Row 2'),
Icon(CupertinoIcons.arrow_down_square),
Icon(CupertinoIcons.arrow_up_square),
];
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisExtend: 40.0,
),
itemCount: widgets.length,
itemBuilder: (context, index) => widgets[index].
),
);
}
}
SliverGridDelegateWithFixedCrossAxisCount
委托确定网格用于布置其组件的各种参数。这包括crossAxisCount
规定每行显示的项目数。
SwiftUIGrid
和 Flutter 的GridView
不同之处在于Grid
需要GridRow
. GridView
使用委托来决定网格应如何布置其组件。
七、创建滚动视图
在SwiftUI中,您可以使用它ScrollView
来创建自定义滚动组件。以下示例以可滚动的方式显示一系列PersonView
实例。
ScrollView {
VStack(alignment: .leading) {
ForEach(persons) { person in
PersonView(person: person)
}
}
}
为了创建滚动视图,Flutter使用SingleChildScrollView
.再以下示例中,该函数mockPerson
模拟Person
类的实例以创建自定义PersonView
小部件。
SingleChildScrollView(
child: Column(
children: mockPersons
.map(
(person) => PersonView(
person: person,
),
)
.toList(),
),
)
八、响应式和自适应设计
在SwiftUI中,,您可以使用它GeometryReader
来出行间相对视图大小。
例如,您可以:
- 乘以
geometry.size.width
一些因素来设置宽度。 - 用作
GeometryReader
断点来更改应用程序的设计。 您还可以查看尺寸登记是否有.regular
或正在.compact
使用horizontalSizeClass
.
要在Flutter中创建相对视图,您可以使用以下两个选项之一:
- 获取类
BoxConstraints
中的对象LayooutBuilder
。 - 在构建函数中使用
MediaQuery.of()
来获取当前应用程序的大小和方向。 要了解更多信息,请查看创建响应式和自适应应用程序。
九、管理状态
在SwiftUI中,您使用@State
属性包装器来表示SwiftUI视图的内部状态。
strcut ContentView: View {
@State private var counter = 0;
var body: some View {
VStack{
Button("+") {counter+=1}
Text(String(counter))
}
}
}
SwiftUI还包括几个选项,用于更复杂的状态管理,例如ObservableObject
协议。
Flutter使用StatefulWidget
.使用以下两个类实现有状态小部件:
StatefulWidget
的子类State
的子类
该State
对象存储小部件的状态。要更改小部件的状态,请setState()
从State
子类调用以告诉框架重绘小部件。
以下示例显示了计数器应用程序的一部分:
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('$_counter'),
TextButton(
onPressed: () => setState(() {
_counter++;
}),
child: const Text('+'),
),
],
),
),
);
}
}
要了解更多管理状态的方法,请查看状态管理。
十、动画
存在两种主要类型的UI动画
- 隐式从当前值到新目标的动画
- 当被问到时,明确的动画。
10.1、隐式动画
SwiftUI和Flutter对动画采用了类似的当大。在这两个框架中,您都可以指定参数。例如duration
,和curve
。
在SwiftUI中,您使用animate()
修饰符来处理隐式动画。
Button("Yap me!"){
angle +=45
}
.rotationEffect(.degrees(angle))
.animation(.easeIn(duration: 1))
Flutter包含用于隐式动画的小部件。这简化了动画通用小部件。Flutter使用以下格式命名这些小部件:AnimatedFoo
.
例如:要旋转按钮,请使用AnimateRotation
类。这使Transform.rotate
小部件具有动画效果。
AnimatedRotation(
duration: const Duration(seconds: 1),
turns: turns,
curve: Curves.easeIn,
child: TextButton(
onPressed: () {
setState(() {
turns += .125;
});
},
child: const Text('Tap me!'),
),
),
Flutter允许您创建自定义隐式动画。要编写新的动画小部件,请使用TweenAnimationBuilder
10.2、显示动画
对于显示动画,SwiftUI使用该withAnimation()
函数。
Flutter包括名称格式类似于FooTransition
。一个例子就是RotationTransition
.
Flutterh还允许您使用AnimatedWidget
或创建自定义动画AnimatedBuilder
.
要了解有关 Flutter 中动画的更多信息,请参阅动画概述。
十一、在屏幕上绘图
在SwiftUI中,您可以CooreGraphics
用来在屏幕上绘制线条和形状。
Flutter有一个基于Canvas
类的API,有两个类可以帮你画图:
CustomPaint
需要painter
CustomPaint(
painter: SignaturePainter(_points),
size: Size.infinite,
),
CustomPainter
实现您的算法以绘制到画布上。
class SignaturePainter extends CustomPainter {
SignaturePainter(this.points);
final List<Offset?> points;
@override
void paint(Canvas canvas, Size size) {
fianl Paint paint = Paint()
..color = Colors.black
..strokeWidth = 5.0;
for (int i = 0; i < points.length - 1; i++) {
if (points[i] != null && points[i + 1] != null) {
canvas.drawLine(points[i]!, points[i + 1]!, paint);
}
}
}
@override
bool shouldRepaint(SignaturePainter oldDelegate) => oldDelegate.points != points;
}
转载自:https://juejin.cn/post/7184384388178640953