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,堆栈视图在设计布局中起着重要作用。两个独立的结构允许您创建堆栈:

  1. HStack用于水平堆栈视图。
  2. 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小部件包括属性像heightfont-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 需要GridRowGridView使用委托来决定网格应如何布置其组件。

七、创建滚动视图

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,有两个类可以帮你画图:

  1. CustomPaint需要painter
CustomPaint(
    painter: SignaturePainter(_points),
    size: Size.infinite,
),
  1. 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;
}
© 版权声明
THE END
喜欢就支持一下吧
点赞5 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容