Flutter Widget

作者: Air_w | 来源:发表于2019-07-03 18:46 被阅读464次

    Flutter Widget



    Flutter的小部件是屏幕上显示的所有内容的基础,类似于Android和IOS的View概念

    1、显示小部件
    2、更新小部件的状态信息
    3、摆放小部件
    4、添加、删除小部件
    5、小部件设置动画
    6、使用Canvas绘画
    7、自定义Widget

    1、显示视图/小部件

    import 'package:flutter/material.dart';
    
    void main() {
      runApp(MaterialApp(
        home: Scaffold(
            body: Center(
          child: Text(
            'I like Flutter!',
            style: TextStyle(
                fontWeight: FontWeight.bold,
                fontSize: 16,
                color: Colors.blueAccent),
          ),
        )),
      ));
    }
    
    
    

    效果:

    view/widget

    2、更新视图/小部件的状态/显示信息

    import 'package:flutter/material.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: MyHomePage(title: 'Flutter Demo Home Page'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({Key key, this.title}) : super(key: key);
    
    
      final String title;
    
    //  @override
    //  _MyHomePageState createState() => _MyHomePageState();
      @override
      State<StatefulWidget> createState() {
        return _MyHomePageState();
      }
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      int _counter = 0;
    
      static String textToShowOne = "I like flutter!";
      static String textToShowTwo = "Flutter is Awesome!";
    
      String textToShow = textToShowOne;
    
      void _incrementCounter() {
        /*
        更新状态
        调用setState方法,将会触发build()调用
         */
        setState(() {
          //
          _counter++;
        });
      }
    
      void switchShowText() {
        setState(() {
          //operate something.
          _counter ++;
          if (_counter % 2 == 0) {
            textToShow = textToShowTwo;
          } else {
            textToShow = textToShowOne;
          }
        });
      }
    
      @override
      Widget build(BuildContext context) {
        
        return Scaffold(
          appBar: AppBar(
            // Here we take the value from the MyHomePage object that was created by
            // the App.build method, and use it to set our appbar title.
            title: Text(widget.title),
          ),
          body: Center(
            // Center is a layout widget. It takes a single child and positions it
            // in the middle of the parent.
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text(
                  'Click counter:$_counter',
                  style: TextStyle(fontSize: 16),
                ),
                Text(
                  '$textToShow',
                  style: Theme.of(context).textTheme.display1,
                ),
              ],
            ),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: () {
              switchShowText();
            },
            tooltip: 'Increment',
            child: Icon(Icons.plus_one),
          ), // This trailing comma makes auto-formatting nicer for build methods.
        );
      }
    }
    
    
    状态1 状态2

    3、摆放小部件

    Android和IOS既可以使用代码创建视图、摆放视图,又可以使用XML和Storyboard;
    而Flutter类似于React native只可以使用代码创建视图、摆放视图。

    @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: 10.0, right: 10.0),
          ),
        ),
      );
    }
    

    4、添加、删除小部件

    在Android中,可以调用父项的addChild()和removeChild()在父项上动态的添加和删除子视图。在Flutter中,因为小部件是不可变的,所以没有直接的addChild()等价物。相反,可以将函数传递给窗口小部件的父级,并使用布尔标志控制该子级的创建。

    核心示例:

    
      dynamic getWidget() {
        if (_counter % 2 == 0) {
          return Text('This is a text widget!');
        } else {
          return RaisedButton(
            onPressed: () {},
            child: Text('This is a button widget!'),
            color: Colors.blueAccent,
            textColor: Colors.white,
            shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(10))),
          );
        }
      }
    
    

    全部示例:

    import 'package:flutter/material.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: MyHomePage(title: 'Flutter Demo Home Page'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({Key key, this.title}) : super(key: key);
    
      final String title;
    
    //  @override
    //  _MyHomePageState createState() => _MyHomePageState();
      @override
      State<StatefulWidget> createState() {
        return _MyHomePageState();
      }
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      int _counter = 0;
    
      static String textToShowOne = "I like flutter!";
      static String textToShowTwo = "Flutter is Awesome!";
    
      String textToShow = textToShowOne;
    
      void _incrementCounter() {
        /*
        更新状态
        调用setState方法,将会触发build()调用
         */
        setState(() {
          //
          _counter++;
        });
      }
    
      void switchShowText() {
        setState(() {
          //operate something.
          _counter++;
          if (_counter % 2 == 0) {
            textToShow = textToShowTwo;
          } else {
            textToShow = textToShowOne;
          }
        });
      }
    
      dynamic getWidget() {
        if (_counter % 2 == 0) {
          return Text('This is a text widget!');
        } else {
          return RaisedButton(
            onPressed: () {},
            child: Text('This is a button widget!'),
            color: Colors.blueAccent,
            textColor: Colors.white,
            shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(10))),
          );
        }
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            // Here we take the value from the MyHomePage object that was created by
            // the App.build method, and use it to set our appbar title.
            title: Text(widget.title),
          ),
          body: Center(
            // Center is a layout widget. It takes a single child and positions it
            // in the middle of the parent.
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text(
                  'Click counter:$_counter',
                  style: TextStyle(fontSize: 16),
                ),
                Text(
                  '$textToShow',
                  style: Theme.of(context).textTheme.display1,
                ),
                getWidget(),
              ],
            ),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: () {
              switchShowText();
            },
            tooltip: 'Increment',
            child: Icon(Icons.plus_one),
          ), // This trailing comma makes auto-formatting nicer for build methods.
        );
      }
    }
    
    
    小部件1 小部件2

    5、小部件设置动画

    核心示例:

    
      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);
      }
    
                ......此处省略若干
    
    
                FadeTransition(
                    opacity: curve,
                    child: FlutterLogo(
                      size: 100.0,
                    )),
                FloatingActionButton(
                  onPressed: () {
                    /*
                    start animation.
                     */
    
                    if(controller.isAnimating){
                      return;
                    }
                    if(controller.isCompleted){
                      controller.reverse();
                      return;
                    }
    
                    controller.forward();
                  },
                  tooltip: 'play animation',
                  child: Icon(Icons.brush),
                ),
    

    全部示例:

    import 'package:flutter/material.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: MyHomePage(title: 'Flutter Demo Home Page'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({Key key, this.title}) : super(key: key);
    
      final String title;
    
    //  @override
    //  _MyHomePageState createState() => _MyHomePageState();
      @override
      State<StatefulWidget> createState() {
        return _MyHomePageState();
      }
    }
    
    class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
      int _counter = 0;
    
      static String textToShowOne = "I like flutter!";
      static String textToShowTwo = "Flutter is Awesome!";
    
      String textToShow = textToShowOne;
    
      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);
      }
    
      void _incrementCounter() {
        /*
        更新状态
        调用setState方法,将会触发build()调用
         */
        setState(() {
          //
          _counter++;
        });
      }
    
      void switchShowText() {
        setState(() {
          //operate something.
          _counter++;
          if (_counter % 2 == 0) {
            textToShow = textToShowTwo;
          } else {
            textToShow = textToShowOne;
          }
        });
      }
    
      dynamic getWidget() {
        if (_counter % 2 == 0) {
          return Text('This is a text widget!');
        } else {
          return RaisedButton(
            onPressed: () {},
            child: Text('This is a button widget!'),
            color: Colors.blueAccent,
            textColor: Colors.white,
            shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.all(Radius.circular(10))),
          );
        }
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            // Here we take the value from the MyHomePage object that was created by
            // the App.build method, and use it to set our appbar title.
            title: Text(widget.title),
          ),
          body: Center(
            // Center is a layout widget. It takes a single child and positions it
            // in the middle of the parent.
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text(
                  'Click counter:$_counter',
                  style: TextStyle(fontSize: 16),
                ),
                Text(
                  '$textToShow',
                  style: Theme.of(context).textTheme.display1,
                ),
                getWidget(),
                FadeTransition(
                    opacity: curve,
                    child: FlutterLogo(
                      size: 100.0,
                    )),
                FloatingActionButton(
                  onPressed: () {
                    /*
                    start animation.
                     */
    
                    if(controller.isAnimating){
                      return;
                    }
                    if(controller.isCompleted){
                      controller.reverse();
                      return;
                    }
    
                    controller.forward();
                  },
                  tooltip: 'play animation',
                  child: Icon(Icons.brush),
                ),
              ],
            ),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: () {
              switchShowText();
            },
            tooltip: 'Increment',
            child: Icon(Icons.plus_one),
          ), // This trailing comma makes auto-formatting nicer for build methods.
        );
      }
    }
    
    
    初始状态 动画完成状态 动画反转状态

    6、使用Canvas绘画
    在Android中,可以使用Canvas和Drawables在屏幕上绘制图像和形状。
    Flutter也有类似的CanvasAPI,因为他基于相同的低级渲染引擎Skia。Flutter中的CustomPaint和CustomPainter是绘制帮助类。

    import 'package:flutter/material.dart';
    
    void main() => runApp(MaterialApp(home: DemoApp()));
    
    class DemoApp extends StatelessWidget {
      Widget build(BuildContext context) => Scaffold(body: Signature());
    }
    
    class Signature extends StatefulWidget {
      SignatureState createState() => SignatureState();
    }
    
    class SignatureState extends State<Signature> {
      List<Offset> _points = <Offset>[];
      Widget build(BuildContext context) {
        return GestureDetector(
          onPanUpdate: (DragUpdateDetails details) {
            setState(() {
              RenderBox referenceBox = context.findRenderObject();
              Offset localPosition =
              referenceBox.globalToLocal(details.globalPosition);
              _points = List.from(_points)..add(localPosition);
            });
          },
          onPanEnd: (DragEndDetails details) => _points.add(null),
          child: CustomPaint(painter: SignaturePainter(_points), size: Size.infinite),
        );
      }
    }
    
    class SignaturePainter extends CustomPainter {
      SignaturePainter(this.points);
      final List<Offset> points;
      void paint(Canvas canvas, Size size) {
        var paint = Paint()
          ..color = Colors.black
          ..strokeCap = StrokeCap.round
          ..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);
        }
      }
      bool shouldRepaint(SignaturePainter other) => other.points != points;
    }
    

    7、自定义Widget

    在Flutter中,通过组合小部件来构建自定义小部件。
    类似于在Android中通过组合来实现ViewGroup。

    自定义小部件

    class CustomButton extends StatelessWidget {
      final String label;
    
      CustomButton(this.label);
    
      @override
      Widget build(BuildContext context) {
        return RaisedButton(onPressed: () {}, child: Text(label));
      }
    }
    

    使用自定义的小部件

    @override
    Widget build(BuildContext context) {
      return Center(
        child: CustomButton("Hello"),
      );
    }
    
    自定义小部件

    未完待续。。。

    相关文章

      网友评论

        本文标题:Flutter Widget

        本文链接:https://www.haomeiwen.com/subject/woqchctx.html