阅读 4448

Flutter 萌新高频问题(加班猿妈妈叫你回家吃饭了)

想写这个很久了,每个人都是从萌新来的,在一些国内Flutter群里(482462250,422833104)呆着, 经常有很多重复的问题在群里反复出现,导致群里大佬都不爱搭理了。 下面的目录会不断更新,如果内容太多,我会拆分掉。

FlutterCandies QQ群:181398081

目录

以下集合由 什么都懂一些的财经龙 big nao 授权

大佬有很多有用插件Github

我是谁,我从哪里来,我要做什么

Flutter跟其他混合开发模式比怎么样?

安卓IOS原生是不是灭亡了?

有没有线上的Flutter产品?

这应该是每个程序猿选择新的领域的一种焦虑吧,其实我们可以根据自己的情况,以及该领域的发展前景来进行自己的判断。答案肯定不是唯一的。在塞班灭亡之前,没人可以那么肯定它就这样亡了。一个程序猿当然也不可能一辈子只是接触一个技术一个领域,学习难道不是作为程序猿来说的一种乐趣吗。对于前2个问题,我没法说出标准答案,第三个,有,咸鱼,爱奇艺,东方财富都在原生的基础上嵌入了Flutter。

萌新入门看啥

Google官方的widget介绍,有中文字幕

Flutter官网

Dart官网

萌新的自己解决问题的能力

每个人都从萌新而来,如果你想开森的写代码,自己解决问题是必须的

  • 英语是很重要的。

  • GoogleSO能解决你大部分的问题

  • 问问题的时候,尽量上代码,或者说明你的意图,因为可能你的想法或者解决方向就是错误的

状态栏怎么透明

还是原生大法好,已经有插件支持,安心食用 flutter_statusbarcolor

怎么去掉列表上拉或者下拉时候的波纹

glow_notification_widget

该组件在插件loading_more_list当中

下拉刷新

掘金-下拉刷新

上拉加载更多

掘金-上拉加载更多

NestedScrollView的使用

官方的NestedScrollView是有一些缺陷的,在使用这个组件之前,强烈建议食用,里面的Demo也有NestedScrollView的用法。

掘金-NestedScrollView

我的列表怎么了

列表或者说ScrollView其实有一个可视区域的概念(Viewport),就是滚动时候的可见的部分,这个区域的大小往往需要你自己告诉他。

  • 列表放在Column里面

错误示例

   child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              '测试',
            ),
            ListView.builder(itemBuilder: (context,index){})
          ],
        ),
复制代码

你想在列表上面加个Text,当然可能是别的。你把2个组件放到了Column里面,但是注意,Column里面的元素,默认是自动大小的,就autosize.这就会造成ListView认为外面的区域是无限大的,它会构建出全部的Items,超出的部分会被截掉,列表也会失去滚动的效果。

正确示例

child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              '测试',
            ),
            Expanded(
              child: ListView.builder(itemBuilder: (context, index) {}),
            )
          ],
        ),
复制代码

将列表放进一个Expanded,表示列表的可视区域是除去Text之后的剩下的区域,这样列表就有了它确定的可视区域

  • List里面可以放List吗?

大部分人有这种想法。其实是想水平和垂直区域都要有对应的滚动。

代码示例

 CustomScrollView(
        slivers: <Widget>[
          //水平
          SliverToBoxAdapter(
            child: Container(
              height: 40.0,
              child: ListView.builder(
                itemBuilder: (context, index) {
                  return Text("测试${index}");
                },
                itemCount: 50,
                scrollDirection: Axis.horizontal,
              ),
            ),
          ),
          //垂直
          SliverList(
            delegate: SliverChildBuilderDelegate((context, index) {
              return Text("测试${index}");
            }, childCount: 50),
          )
        ],
      ),
复制代码

注意你要给水平的列表增加指定的高度,因为对于垂直方向来说。。这个水平列表如果没有固定高度,那么垂直方法的viewport将没法进行计算

  • 使用ListView还是SliverList?

这2者的区别在于 1.SliverList必须放在Sliver系列里面,常见的是CustomScrollView,NestedScrollView的header里面。 请牢牢记住,Sliver系列只能放Sliver系列,别直接把其他widget比如Container/ListView直接放里面。 2.ListView内部其实也是包裹了ScrollView,而SliverList依靠的是外部的CustomScrollView或者NestedScrollView的header 里面的ScrollView 来进行控制的。

这里我们提一下常用的Sliver组件

CustomScrollView

是Sliver组件的老祖宗,全部的Sliver都放在这个里面。

SliverList, which is a sliver that displays linear list of children.

SliverFixedExtentList, which is a more efficient sliver that displays linear list of children that have the same extent along the scroll axis. 比SliverList多一个就是相同的行高。这样性能会更好

SliverGrid, which is a sliver that displays a 2D array of children. 可以设置每行的个数的Grid

SliverPersistentHeader A sliver whose size varies when the sliver is scrolled to the leading edge of the viewport. This is the layout primitive that SliverAppBar uses for its shrinking/growing effect.

非常好用的组件,SliverAppBar就是用这个实现的。这个组件的特点是可以创建出随着滑动变化的可以Pinned的元素,大家经常用的什么吸顶组件可以用这个很方便的构建

SliverToBoxAdapter 当你想把一个非Sliver的Widget放在CustomScrollview里面的时候,你需要用这个包裹一下。千万别把非Sliver widget直接放在Sliver里面,记得用这个

SliverFillRemaining sizes its child to fill the viewport in the cross axis and to fill the remaining space in the viewport in the main axis. 使用这个它会填充完剩余viewport里面的全部空间

SliverPadding, which is a sliver that adds blank space around another sliver. 你可以把不是Sliver系列的widget放这个里面,跟SliverToBoxAdapter效果差不多,其实你也可以用SliverToBoxAdapter 里面放个Padding来实现

SliverAppBar, which is a sliver that displays a header that can expand and float as the scroll view scrolls.

SliverSafeArea A sliver that insets another sliver by sufficient padding to avoid intrusions by the operating system. For example, this will indent the sliver by enough to avoid the status bar at the top of the screen.为了防止各种边界的越界,比如说越过顶部的状态栏,跟SafeArea效果一样。只是这个是放Sliver里面的

除了Sliver列表之外,SliverToBoxAdapter,SliverFillRemaining是Sliver系列里面高频使用的组件。

圆角

ClipRRect(
        borderRadius: new BorderRadius.circular(radius),child:child)
复制代码

点击水波纹

 return InkWell(
                    child: Text("测试${index}"),
                    onTap: () {},
                  );
复制代码

点击空白透明区域没事件响应

 return GestureDetector(
                    behavior: HitTestBehavior.translucent,
                    child: Text("测试${index}"),
                    onTap: () {},
                  );
复制代码

设置HitTestBehavior

enum HitTestBehavior {
  /// Targets that defer to their children receive events within their bounds
  /// only if one of their children is hit by the hit test.
  deferToChild, //只生效在child的区域比如文字

  /// Opaque targets can be hit by hit tests, causing them to both receive
  /// events within their bounds and prevent targets visually behind them from
  /// also receiving events.
  opaque,//GestureDetector的整个区域,不包括它下面的区域

  /// Translucent targets both receive events within their bounds and permit
  /// targets visually behind them to also receive events.
  translucent,// GestureDetector的整个区域以及它下面的区域
}
复制代码

Flutter错误提示

Flutter中如果有错误,将会在控制台当中显示出错误信息(虽然有时候信息不能反映出准确的位置),你可以根据这个信息来了解错误的原因和地方

I/flutter ( 9746): The following assertion was thrown building NotificationListener<ScrollNotification>: I/flutter ( 9746): A RenderViewport expected a child of type RenderSliver but received a child of type I/flutter ( 9746): RenderRepaintBoundary. I/flutter ( 9746): RenderObjects expect specific types of children because they coordinate with their children during I/flutter ( 9746): layout and paint. For example, a RenderSliver cannot be the child of a RenderBox because a I/flutter ( 9746): RenderSliver does not understand the RenderBox layout protocol.

E/flutter ( 9746): #6 runApp (package:flutter/src/widgets/binding.dart:756:7) E/flutter ( 9746): #7 main (package:flutter_app123123213/main.dart:3:16)

上面错误是我尝试将ListView(非Sliver组件)放进CustomScrollView中,上面是错误信息,下面的是错误发生在我写的代码的哪里。

这个东西没别的方法,多被坑几次就会好了。。

键盘挡住页面了

请使用一些能滚动的组件包住你的页面。比如SingleChildScrolView,

Appbar/Tabbar/StatusBar的高度

Appbar kToolbarHeight 这个是一个系统的Const可以直接获得

Tabbar 可以用tabbar.preferredSize获取 如果你看源码。其实它也还是一个Const 多看源码吧。。

StatusBar

  final double statusBarHeight = MediaQuery.of(context).padding.top;
复制代码

处理安卓/IOS系统中文本缩放对Flutter文字的影响以及根据App的文字大小设置某个页面的文字大小

获取MediaQuery并且对它的textScaleFactor进行重定义 下面是实现

  import 'dart:math' as math;

import 'package:flutter/material.dart';

class NoScaleTextWidget extends StatelessWidget {
  final Widget child;

  const NoScaleTextWidget({
    Key key,
    @required this.child,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaxScaleTextWidget(
      max: 1.0,
      child: child,
    );
  }
}

class MaxScaleTextWidget extends StatelessWidget {
  final double max;
  final Widget child;

  const MaxScaleTextWidget({
    Key key,
    this.max = 1.2,
    @required this.child,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    var data = MediaQuery.of(context);
    var scale = math.min(max, data.textScaleFactor);
    return MediaQuery(
      data: data.copyWith(textScaleFactor: scale),
      child: child,
    );
  }
}

class ScaleTextWidget extends StatelessWidget {
  final double scale;

  final Widget child;

  const ScaleTextWidget({
    Key key,
    @required this.scale,
    @required this.child,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    var data = MediaQuery.of(context);
    var scale = this.scale ?? data.textScaleFactor;
    return MediaQuery(
      data: data.copyWith(textScaleFactor: scale),
      child: child,
    );
  }
}
复制代码

使用方式如下,当然你也使用这个来实现对某个页面字体大小缩放的功能(比如app里面的有调整字体大小)

return MaterialApp(
    builder: (c, w) {
      //不应用系统的字体缩放
      return NoScaleTextWidget(
        child: w,
      );
    },
    home: child,
  );
复制代码

好用的图片,支持网络缓存,缩放,拖拽,剪切,自定义Loading/Failed 效果,圆角,边框,拖拽,缩放等效果等效果

extended_image 相关文章

好用的富文本库,支持图片,自定义背景效果,自定义文本溢出效果

extended text 相关文章

好用的输入框,支持图片,自定义背景效果效果

extended_text_field 相关文章

发布插件

执行flutter packages pub publish --server=https://pub.dartlang.org

pub中国镜像

pub官方经常打不开,别问我为什么,下面是中国镜像,我一直都用这个 中国镜像

全局禁用水波纹

NoSplashFactory

最后放上 Flutter_Candies,如果你觉得有什么问题也是常常被萌新问到的,请告诉我,我会增加到汇总当中.

关注下面的标签,发现更多相似文章
评论