zoukankan      html  css  js  c++  java
  • Flutter 你需要知道的那些事 01

    公众号「AndroidTraveler」首发。

    1. width 属性

    对于设置控件宽度填充父控件这件事情,在 Android 里面,只需要设置 MATCH_PARENT 即可。

    但是在 Flutter 里面却不是这样,因为 Flutter 要具体的数值。

    所以我们可以这样考虑,假设我这个值非常大,比所有市面上的设备宽度还要大,那么是不是表现出来就是充满父控件了。

    所以这边的做法是设置为无限,即 double.infinite

    我们以一个常用场景来说明。

    比如设置图片填充屏幕宽度。

    刚开始没有设置的代码如下:

    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
            home: Scaffold(
              appBar: AppBar(
                title: Text('My Flutter'),
              ),
              body: Center(
                child: Image.asset('assets/images/example.jpeg'),
              ),
            )
        );
      }
    }
    

    效果:

    可以看到没有设置的情况下,显示会根据图片自身的宽高显示。

    这个时候如果设置 width 为无穷大,修改代码如下:

    child: Image.asset('assets/images/example.jpeg',  double.infinity,),
    

    效果

    什么情况,没起作用?

    这个时候不要慌,我们来给大家分析分析。

    以后大家遇到类似问题也可以这样分析。

    我们通过给 Image 外面套上一层 Container,然后设置背景颜色来对比一下。

    代码如下:

    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
            home: Scaffold(
          appBar: AppBar(
            title: Text('My Flutter'),
          ),
          body: Center(
            child: Container(
              color: Colors.blue,
              //left
    //          child: Image.asset('assets/images/example.jpeg',),
              //right
              child: Image.asset('assets/images/example.jpeg',  double.infinity,),
            ),
          ),
        ));
      }
    }
    

    效果如下:

    可以看到,设置宽度之后,Image 确实是填充了宽度,只不过由于图片本身没有那么宽,因此看起来就以为是没有起作用。

    那么如何让图片可以填充宽度呢?

    这个就涉及到图片的填充模式了。

    2. fit 属性

    点击 Image 的 fit 属性进入源码可以看到如下:

    /// How to inscribe the image into the space allocated during layout.
    ///
    /// The default varies based on the other fields. See the discussion at
    /// [paintImage].
    final BoxFit fit;
    

    我们再点一下 BoxFit,可以看到如下:

    /// How a box should be inscribed into another box.
    ///
    /// See also [applyBoxFit], which applies the sizing semantics of these values
    /// (though not the alignment semantics).
    enum BoxFit {
      /// Fill the target box by distorting the source's aspect ratio.
      ///
      /// ![](https://flutter.github.io/assets-for-api-docs/assets/painting/box_fit_fill.png)
      fill,
    
      /// As large as possible while still containing the source entirely within the
      /// target box.
      ///
      /// ![](https://flutter.github.io/assets-for-api-docs/assets/painting/box_fit_contain.png)
      contain,
    
      /// As small as possible while still covering the entire target box.
      ///
      /// ![](https://flutter.github.io/assets-for-api-docs/assets/painting/box_fit_cover.png)
      cover,
    
      /// Make sure the full width of the source is shown, regardless of
      /// whether this means the source overflows the target box vertically.
      ///
      /// ![](https://flutter.github.io/assets-for-api-docs/assets/painting/box_fit_fitWidth.png)
      fitWidth,
    
      /// Make sure the full height of the source is shown, regardless of
      /// whether this means the source overflows the target box horizontally.
      ///
      /// ![](https://flutter.github.io/assets-for-api-docs/assets/painting/box_fit_fitHeight.png)
      fitHeight,
    
      /// Align the source within the target box (by default, centering) and discard
      /// any portions of the source that lie outside the box.
      ///
      /// The source image is not resized.
      ///
      /// ![](https://flutter.github.io/assets-for-api-docs/assets/painting/box_fit_none.png)
      none,
    
      /// Align the source within the target box (by default, centering) and, if
      /// necessary, scale the source down to ensure that the source fits within the
      /// box.
      ///
      /// This is the same as `contain` if that would shrink the image, otherwise it
      /// is the same as `none`.
      ///
      /// ![](https://flutter.github.io/assets-for-api-docs/assets/painting/box_fit_scaleDown.png)
      scaleDown,
    }
    

    相信大家看到源码的注释应该很清楚每个值的意义了。

    如果你还不清楚,可以点击注释里面对应的链接去查看示意图。

    比如以我们这个实际应用场景填充宽度为例,那么我们可以看到 fitWidth 应该是符合我们要求的,我们点击注释的链接,跳转可以看到图片如下:

    很形象的做了几种情况的示意。我们设置了 Image 的 fit 属性如下:

    child: Image.asset('assets/images/example.jpeg',  double.infinity, fit: BoxFit.fitWidth,),
    

    效果:

    可以看到已经满足我们的需求了。

    温馨提示:测试完之后不要忘记去掉测试的 Container 以及对应颜色哦~

    3. print

    我们知道在 Android 里面,当我们 try catch 之后,我们打印异常基本会写出类似下面代码:

    Log.e(TAG, "exception="+e);
    

    在 Flutter 也有异常捕获。

    你可能会习惯的写出如下代码:

    print('exception='+e);
    

    但是切记,不要使用上面的写法。

    因为当 e 为 null 时,上面的 print 不会执行打印。

    这可能会误导你。因为你在成功的时候加上打印语句,异常捕获也加上打印语句。但是程序就是没有打印。你就会觉得很奇怪。

    实际上当 e 为 null 时,print 语句会报错,+ 号连接的左右不能是 null,所以不会正常打印。因此请避免上面的写法。可以用下面的替换写法:

    //替换写法一
    print('exception=');
    print(e);
    //替换写法二
    print('exception='+(e ?? ''));
    //替换写法三
    var printContent = e ?? '';
    print('exception='+printContent);
    

    4. GestureDetector

    我们知道如果要给一个 Widget 增加点击事件,最简单的方法就是套一层 GestureDetector。

    但是有时候你这样做了,却发现有些“隐患”,或者说,有些你意料不到的事情。

    这里用一个场景来告诉你,你平时可能没有发现的细节。

    微博里面有点赞这个小组件,我们写下如下代码:

    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
            home: Scaffold(
          appBar: AppBar(
            title: Text('My Flutter'),
          ),
          body: Row(
            children: <Widget>[
              Image.asset('assets/images/2.0x/like.png',  20, height: 20,),
              SizedBox( 5,),
              Text('30')
            ],
          ),
        ));
      }
    }
    

    效果如下:

    假设我们要求给这个点赞组件加上点击事件,那么我们直接给 Row 套上 GestureDetector Widget。

    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
            home: Scaffold(
          appBar: AppBar(
            title: Text('My Flutter'),
          ),
          body: GestureDetector(
            onTap: (){
              print('onTap');
            },
            child: Row(
              children: <Widget>[
                Image.asset('assets/images/2.0x/like.png',  20, height: 20,),
                SizedBox( 5,),
                Text('30')
              ],
            ),
          ),
        ));
      }
    }
    

    点击点赞组件确实会打印 onTap,但是如果你点击了点赞图标和数字中间的白色区域,你会发现点击事件没有回调,没有打印。

    这个时候有两种解决方法:

    1. 给空白组件设置 color 属性,颜色值设置透明

    对于 Container 设置的 padding 可以直接设置,对于我们这里例子的 SizeBox 需要改为如下:

    SizedBox( 15, child: Container(color: Colors.transparent,),),
    

    为了方便测试,这边将宽度改为 15。

    所以对于设置 GestureDetector 的 Container,如果没有设置 color 属性,那么点击空白不会回调。

    2. 设置 GestureDetector 的 behavior 属性(推荐方式)

    其实如果你需要空白区域也响应点击,只需要设置一下 GestureDetector 的 behavior 属性即可。

    behavior 默认值为 HitTestBehavior.deferToChild,我们这里将其设置为 HitTestBehavior.translucent

    代码如下:

    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
            home: Scaffold(
          appBar: AppBar(
            title: Text('My Flutter'),
          ),
          body: GestureDetector(
            behavior: HitTestBehavior.translucent,
            onTap: (){
              print('onTap');
            },
            child: Row(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                Image.asset('assets/images/2.0x/like.png',  20, height: 20,),
                SizedBox( 15),
                Text('30')
              ],
            ),
          ),
        ));
      }
    }
    

    这里的点赞图片我直接从网上获取的,你测试可以用随便一张图片代替验证。或者用两个文本来验证也是可以的。

  • 相关阅读:
    LSMW TIPS
    Schedule agreement and Delfor
    Running VL10 in the background 13 Oct
    analyse idoc by creation date
    New Journey Prepare
    EDI error
    CBSN NEWS
    Listen and Write 18th Feb 2019
    Microsoft iSCSI Software Target 快照管理
    通过 Microsoft iSCSI Software Target 提供存储服务
  • 原文地址:https://www.cnblogs.com/nesger/p/10811505.html
Copyright © 2011-2022 走看看