面向Android开发者的Flutter——Views(二)

179 阅读2分钟

书接上回

我如何布置我的小部件?我的XML布局文件在哪里?

在Android中,使用XML编辑布局,但在Flutter中,使用小部件树编写布局。

以下示例显示如何显示带填充的简单小部件

@override
Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
            title: const Text('Sample App'),
        ),
        body: Center(
            child: ElecatedButton(
                style: ElevatedButton.styleFrom(
                    padding: const EdgeInsset.only(left: 20.0, right: 30),
                ),
                onPressed: () {},
                child: const Text('Hello'),
            ),
        ),
    );
}

您可以在widget 目录中查看 Flutter 必须提供的一些布局 。

如何从我的布局中添加或删除小部件?

在Android中,调用addChild()或调用removeChild()父对象以动态添加或删除子视图。在Flutter中,因为小部件是不可变的,所以没有直接等同于addChild(),相反,可以将一个函数传递给返回小部件 的父级,并使用bool标志控制该子级的创建。

例如,以下是点击如何在两个小部件中切换FloatingActionButton。

import 'package:flutter/material.dart'

void main() {
    runApp(const SampleApp());
}

class SampleApp extends StatelessWidget {
    const SampleApp({super.key});
    
    // This widget is the root of your application
    @override
    Widget build(BuildContext context) {
        return MaterialApp(
            title: 'Sample App',
            theme: ThemeData(
                primarySwatch: Colors.blue,
            ),
            home: const SampleAppPage(),
        );
    }
}

class SampleAppPage extends SatefulWidget {
    const SampleAppPage({super.key});
    
    @override
    State<SampleAppPage> create() => _SampleAppPageState();
}

class _SampleAppPageState extends State<SampleAppPage> {
     //Default value for toggle
     bool toggle = true;
     void _toggle() {
         setState(() {
             toggle = !toggle;
         });
     }
     
     Widget _getToggleChild() {
         if (toggle) {
             return const Text('Toggle One');
         } else {
             return ElevatedButton(
                 onPressed: () {},
                 child: const Text('Toggle Two'),
             );
         }
     }
     
     @override
     Widget build(BuildContext context) {
         return Scaffold(
             appBar: AppBar(
                 title: const Text('Sample App'),
             ),
             body: Center(
                 child: _getToggleChild(),
             ),
             floatingActionButton: FloatingActionButton(
                 onPressed: _toggle,
                 tooltip: 'Update Text',
                 child: const Icon(Icons.update),
             ),
         );
     }
}

如何为小部件设置动画?

在Android中,你要么使用XML创建动画,要么animate()在视图上方调用方法。在Flutter中,通过将小部件包装在动画小部件中,使用动画库为小部件设置动画。

在Flutter中,使用AnimationController,一个Animation<double>可以暂停、寻找、停止和反转动画。它需要一个在vsync发生的Ticker信号,并在它运行时在每帧上产生0和1之间的线性插值。然后你创建一个或多个Animation并将他们添加到控制器。

例如,可以使用CurvedAnimation,它沿着差值曲线实现动画。从这个意义上讲,控制器是动画进度的“主要”来源,CurvedAnimation计算替代控制器默认先行运动的曲线。与小部件一样。

在构建小部件树时,将分配给小部件Animation的动画属性,例如一个有关透明度的FadeTransition,并告诉控制器启动动画。

例子:编写一个FadeTransition,在按下时使小部件淡入logo

import 'package:flutter/material.dart';

void main() {
    runApp(const FadeAppTest());
}

class FadeAppTest extends StatelessWidget {
    const FadeAppTest({super.key});
    //This widget iss the root of your application
    @override
    Widget build(BuildContext context) {
        return MaterialApp(
            title: 'Fade Demo',
            theme: ThemeData(
                primarySwatch: Colors.blue,
            ),
            home: const MyFadeTest(title: 'Fade Demo'),
        );
    }
}

class MyDadeTest extends StatefulWidget {
    const MyFadeTest({super.key, required this.title});
    
    final String title;
    @override
    State<MyFadeTest> createState() => _MyFadeTest();
}

class _MyFadeTest extends State<MyFadeTest> with TickerProviderStateMixin {
    late AnimationController controller;
    late CurvedAnimation curve;
    
    @override
    void initState() {
        super.initState();
        controller = AnimationController(
            duration: const Duration(milliseconds: 2000),
            vsync: this,
        );
        curve = CurveAnimation(
            parent: controller,
            curve: Curvess.easeIn,
        );
    }
    
    @override
    Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(
                title: Text(widget.title),
            ),
            body: Center(
                child: FadeTransition(
                    opacity: curve,
                    child: const FlutterLogo(
                        size: 100.0,
                    ),
                ),
            ),
            floatingActionButton: FloatingActionButton(
                tooltip: 'Fade',
                onPreseed: () {
                    coontroller.forward();
                },
                child: const Icon(Icons.brush),
            );
        );
    }
}

有关详细信息,请参阅 动画和动作小部件动画教程动画概述