Flutter开发小技巧

1.iOS中的模态视图

简单方法,设置fullscreenDialog属性

MaterialPageRoute(builder: (context)=>HomePage(),fullscreenDialog: true)

复杂方法,就是自己重写转场动画

Navigator.of(context).push(_createRoute());
                    
Route _createRoute(){
    return PageRouteBuilder(pageBuilder: (context, animation, secondaryAnimation) => DGXOperationGuidancePage(),
      transitionsBuilder: (context,animation,secondaryAnimation,child){
        const begin = Offset(0.0, 1.0);
        const end = Offset.zero;
        const curve = Curves.ease;

        var tween = Tween(begin: begin,end: end,).chain(CurveTween(curve: curve));

        return SlideTransition(position: animation.drive(tween),
          child: child,
        );
      },
    );
  }
2.一种更新状态的方法(是不是和Get的obs、Obx很像?)
// ValueNotifier是ValueListenableBuilder 需要传入的ValueListenable 抽象类的实现 . 接收一个泛型.
  final ValueNotifier new_counter = ValueNotifier(0);

  //按钮的点击方法
  void _incrementCounter() {
    new_counter.value += 1;
  }

// 每当监听的对象值发生变化时,会触发builder 方法进行刷新。
// 在点击时只需要改变 new_counter.value 的值,就会触发 _buildWithValue 从而将界面数字刷新。
  Widget _builderWithValue(BuildContext context , int value , Widget child){
    return Text('$value');
  }

Column(
  mainAxisAlignment: MainAxisAlignment.center,
  children: [
    Text(
      'You have pushed the button this many times:',
    ),
    ValueListenableBuilder(
      builder: _builderWithValue,
      valueListenable: new_counter,
    ),
  ],
),
3.解决print打印不全的问题
import 'dart:developer'
log();
4.通过旋转屏幕方向,动态改变列数
OrientationBuilder(builder: (context, orientation) {
    return GridView.count(
        // Create a grid with 2 columns in portrait mode, or 3 columns in landscape mode.
        crossAxisCount: orientation == Orientation.portrait ? 2 : 3,
        children: List.generate(100, (index) {
            return Center(child: Text('Item $index'),);
        }),
    );
},)
//如果你只想知道屏幕的方向,可以直接使用 MediaQuery.of(context).orientation,而不是使用 OrientationBuilder widget.
5.StatefulBuilder提供了局部更新控件的方法,当StatefulWidget中控件树较大时,更新一个属性导致整个树重建,消耗性能,而使用StatefulBuilder能有效的提高性能。
StateSetter _reloadTextSetter;
StatefulBuilder(builder: (BuildContext context, StateSetter stateSetter) {
    _reloadTextSetter = stateSetter;
    return Container();
});

在需要局部刷新的地方进行调用,刷新方法。
_reloadTextSetter(() {}); //_reloadTextSetter.call(() {});
6.利用dart:io中提供的属性进行设备查询
Text("操作系统:${Platform.operatingSystem}"),
Text("操作系统版本:${Platform.operatingSystemVersion}"),
Text("本地主机名localHostname:${Platform.localHostname}"),
Text("是否是Android平台:${Platform.isAndroid}"),
Text("是否是IOS平台:${Platform.isIOS}"),
Text("是否是Linux平台:${Platform.isLinux}"),
Text("是否是MacOS平台:${Platform.isMacOS}"),
Text("是否是Windows平台:${Platform.isWindows}"),
Text("是否是Fuchsia平台:${Platform.isFuchsia}"),
Text("CPU内核数量:${Platform.numberOfProcessors}"),
Text("当前区域设置的名称:${Platform.localeName}"),
Text("版本:${Platform.version}"),
Expanded(child: Text("环境:${Platform.environment}"),
7.媒体查询
Text("设备像素逻辑像素sp大小:${MediaQuery.of(context).size}"),
Text("设备像素逻辑像素sp大小:${MediaQuery.of(context).padding}"),
Text("每个逻辑像素的设备像素数:${MediaQuery.of(context).devicePixelRatio}"),
Text("每个逻辑像素的字体像素数:${MediaQuery.of(context).textScaleFactor}"),
Text("格式化时间时是否使用24小时格式:${MediaQuery.of(context).alwaysUse24HourFormat}"),
Text("是横屏还是竖屏:${MediaQuery.of(context).orientation}"),
Text("设备的亮度模式:${MediaQuery.of(context).platformBrightness}"),
Text("被系统遮挡的部分(通常指键盘):${MediaQuery.of(context).viewInsets}"),
Text("被系统遮挡的部分(常指“刘海屏”或系统状态栏):${MediaQuery.of(context).padding}"),
Text("当前窗口的宽度和高度:${MediaQuery.of(context).systemGestureInsets}"),
Text("当前窗口的宽度和高度缩放比例:${MediaQuery.of(context).textScaleFactor}"),
8.Flutter四种运行模式
Debug模式可以在真机和模拟器上同时运行
Release模式只能在真机上运行:会关闭所有断言和debugging信息,关闭所有debugger工具。
Profile模式只能在真机上运行,:基本和Release模式一致
test模式只能在桌面上运行:基本和Debug模式一致

debug模式能热更新页面,release模式不能热更新页面的原因为:
Debug模式下使用JIT编译模式,即Just in time(即时编译),Release下使用AOT模式,即Ahead of time(提前编译)。JIT模式因为需要边运行边编译,所以会占用运行时内存,导致卡顿现象,但是有动态编译效果对于开发者来说非常方便调试。AOT模式提前编译,不会占用运行时内存,相对来说运行流畅,但是会导致编译时间增加。

Flutter使用了独特的编译模式,开发阶段下(对应JIT编译),将dart代码生成标记化的源代码,运行时编译,解释执行;release阶段,iOS使用AOT编译,编译器将dart代码生成汇编代码,最终生成app.framwork,android使用了Core JIT编译,dart转化为二进制模式,在VM启动前载入。

Flutter通过将新的代码注入到正在运行的DartVM中,来实现Hot Reload这种神奇的效果,在DartVM将程序中的类结构更新完成后,Flutter会立即重建整个控件树,从而更新界面。
触发热刷新时Flutter会检测发生改变的Dart文件,将其同步到App私有缓存目录下,DartVM加载并且修改对应的类或者方法,重建控件树后立即可以在设备上看到效果。
9.单例
class Singleton {
  static final Singleton _singleton = Singleton._internal();
                
                factory Singleton() {
                    return _singleton;
                }
                
                Singleton._internal();
            }
10.能滚动的视图自动滚动到底部
_controller.jumpTo(_controller.position.maxScrollExtent)
11.去掉右上角的DEBUG标签
1、
return MaterialApp(
      home: HomeScreen(),
      debugShowCheckedModeBanner: false,//去掉右上角DEBUG标签
    );
2、构建release版本;
11.operator重载操作符
这里用js来举例,dart 判断两值相等,可以使用 == ,对一些基础数据类型进行判断。

如果你的需求是判断自定义类型相等,== 就不行了,这时候就要用===,但是dart不同于js,没有===。

但dart提供了operator重载操作符,这就是使用它的原因。

那如何使用呢,当然不能 A operator B 这么用了(js里当然可以 A === B),operator其实是类内部实现的,你在创建类的时候,就通过operator,为这个类提供一个对比方法,注意,dart是将这种对比,写成了自己的方法,栗子如下:

class A {
  bool operator ==(dynamic y) {
    return y == 1;
  }
}
  
main() {
  var a = new A();
  print(a == 1); // true
  print(a == 2); // false
}

这个对比的过程,被写成了类内部的一个方法。
12.退出APP
exit(1);///异常退出
exit(0);///常规退出
13.查看打包文件大小
flutter build apk --target-platform=android-arm /// Android32位 输出Built build/app/outputs/apk/release/app-release.apk (4.2MB)

flutter build apk --target-platform=android-arm64 /// Android64位 输出Built build/app/outputs/apk/release/app-release.apk (4.6MB)

flutter build ios && tar -zcf build/app.ipa build/ios/iphoneos/Runner.app && ls -lh build/app.ipa /// ios输出  example/helloworld app (as of this writing) is 8.3 MB
14.修改flutter应用名
1、ios
Info.plist =>  CFBundleNameXXXXX

2、Android
AndroidManifest.xml => android:label="XXXXX"
15.修改应用图标
1、ios
AppIcon.appiconset内替换相应分倍率icon,同时更新同目录的Contents.json文件;

2、Android
mipmap内替换相应分倍率icon,同时更新AndroidManifest.xml 文件;
16.滚动View撑满屏,无法被Column包括问题
1、View外面包裹Expanded;

2、View Widget添加 shrinkWrap: true 属性;

实际都是限制View的尺寸;
17.flutter中的度数
import 'dart:math' as math;

math.pi   /// 180deg
math.pi / 2    /// 90deg
math.pi * 2   /// 360deg
18.善于使用扩展语法
extension AlignExtensions on String {
  toAlign() {
    if (this.contains("left")) {
      return TextAlign.left;
    } else if (this.contains("center")) {
      return TextAlign.center;
    } else if (this.contains("right")) {
      return TextAlign.right;
    } else if (this.contains("end")) {
      return TextAlign.end;
    }
  }
}
19.字符串变量转颜色
var c = "dc380d";
Color(int.parse(c,radix:16)|0xFF000000) //通过位运算符将Alpha设置为FF
Color(int.parse(c,radix:16)).withAlpha(255)  //通过方法将Alpha设置为FF
20.设置appbar透明
AppBar(
    backgroundColor: Colors.transparent,
    elevation: 0,
}
一般将appbar设为透明后, 会将Scaffold的extendBodyBehindAppBar的属性设置为true。
21.Text下面出现黄色双下划线
style: TextStyle(
   decoration: TextDecoration.none
)
因为没有可继承的祖先样式widget;
22.收起键盘
// 1
FocusScope.of(context).requestFocus(FocusNode());
//2
SystemChannels.textInput.invokeMethod('TextInput.hide');
//3
FocusScope.of(context).unfocus();
23.禁止横屏
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
      .then((_) {
    runApp(MyApp());
});
24.给Container设置渐变背景色
decoration: BoxDecoration(
  gradient: LinearGradient(
    begin: Alignment.topLeft,
    end: Alignment.bottomRight,
    colors: [
      Colors.red,
      Colors.yellow,
    ]
  )
),

你可能感兴趣的:(Flutter开发小技巧)