flutter开发中一些技巧和坑点

获取设备宽高

double width = MediaQuery.of(context).size.width;
double height = MediaQuery.of(context).size.height;

Android设置状态栏透明

  1. 原生修改
public class MainActivity extends FlutterActivity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
    {
         // api大于21设置状态栏透明
        getWindow().setStatusBarColor(0);
    }
    GeneratedPluginRegistrant.registerWith(this);
  }
}
  1. flutter修改(么有测试过,自己测试下反正不难)
// 输出渲染
void main() {
  runApp(App());
  if (Platform.isAndroid) {
    // 以下两行 设置android状态栏为透明的沉浸。写在组件渲染之后,是为了在渲染后进行set赋值,覆盖状态栏,写在渲染之前MaterialApp组件会覆盖掉这个值。
    SystemUiOverlayStyle systemUiOverlayStyle = SystemUiOverlayStyle(statusBarColor: Colors.transparent);
    SystemChrome.setSystemUIOverlayStyle(systemUiOverlayStyle);
  }
}

区别final与const

在Dart中,当你不需要去改变一个变量的时候,应该使用final或者const,而不是使用var去声明一个变量。一个final变量只允许被赋值一次,必须在定义时或者构造函数参数表中将其初始化。
const所修饰的是编译时常量,我们在编译时就已经知道了它的值,它的值是不可改变的。
const比final更加严格,看以下例子:

final List list = [];
list.add('1'); // 正确

const List list = [];
list.add('1'); // 错误,运行时报错:Cannot add to an unmodifiable list

final timestamp = new DateTime.now().millisecondsSinceEpoch; // 正确

const timestamp = new DateTime.now().millisecondsSinceEpoch; // 错误,编译前报错:Const variables must be initialized with a constant value

FocusScope转移焦点,隐藏输入法

flutter开发中一些技巧和坑点_第1张图片
166723349530a968.gif
Container(
        height: 500.0,
        child: new GestureDetector(
          onTap: () {
            // 通过GestureDetector捕获点击事件,再通过FocusScope将焦点转移至空焦点      new FocusNode()
            FocusScope.of(context).requestFocus(FocusNode());
          },
          child: Container(
              margin: EdgeInsets.all(30.0),
              child: ListView(children: [
                TextField(
                  decoration: InputDecoration(labelText: 'Username'),
                ),
                TextField(
                  decoration: InputDecoration(labelText: 'Password'),
                )
              ])),
        ),
      ),
  • 这里传递给FocusScope的context不能在MaterialApp下面,即你需要将这部分代码放到独立的一个Widget里面

定时任务

  1. 在我们的开发之中难免要用到定时,比如我们常用的获取验证码的需求,下面请看利用定时器来实现这一功能需求
  • 定义3个变量
int _seconds = 0;
String _verifyStr  = "获取验证码";
/// 定时器Timer
Timer _timer;
  • 实现timer,代码很清晰,简单的说我设了10秒的倒计时,利用Timer.periodic方法来执行,间隔时间是1秒
/// 倒计时
  _startTimer() {
    _seconds = 10;

    _timer = Timer.periodic(new Duration(seconds: 1), (timer){
      if(_seconds == 0){
        _cancleTimer();
        return;
      }
      _seconds--;
      _verifyStr = "${_seconds}s";
      if (_seconds == 0){
        _verifyStr = "重新发送";
      }
      setState(() {});
    });
  }

  _cancleTimer(){
    _timer?.cancel();
  }

@override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
   /// 页面销毁的时候,清除timer
    _cancleTimer();
  }
  • 执行,并不是每次按都执行_startTimer,加上判断条件只有_seconds == 0时才执行效果如下图
new Container(
          padding: const EdgeInsets.only(top: 15.0, left: 15.0),
          child: new RaisedButton(
            /// 触发定时任务
            onPressed: (_seconds == 0)?(){
              _startTimer();
            }:null,
            child: new Text(_verifyStr),
            shape: new RoundedRectangleBorder(
              borderRadius: new BorderRadius.all(new Radius.circular(15.0)),
            ),
            textColor: Colors.blue,
            color: Colors.yellowAccent,
            disabledColor: Colors.yellowAccent,
            disabledTextColor: Colors.blue,
          ),
        ),
flutter开发中一些技巧和坑点_第2张图片
GIF.gif

利用 Container的BoxDecoration装饰实现渐变

  • 例子如下
 Container(
        decoration: BoxDecoration(gradient: LinearGradient(
          colors: [const Color(0xFFFFFFEE), const Color(0xFF999999),const Color(0xFF862547),],
          tileMode: TileMode.repeated, // repeats the gradient over the canvas
        ),),
  • 效果如下


    渐变.png
  • BoxDecoration的属性

const BoxDecoration({
    this.color, // 盒子颜色
    this.image, // 图片
    this.border, 边框颜色和线宽度
    this.borderRadius, // 圆角度
    this.boxShadow, // 阴影
    this.gradient, // 渐变
    this.backgroundBlendMode, // 混合Mode
    this.shape = BoxShape.rectangle,  // 形状
  }) 
  • 边框圆角实现
decoration: new BoxDecoration(
  border: new Border.all(color: Color(0xFFFF0000), width: 1.0), // 边色与边宽度
  color: Color(0xFF999999), //  盒子颜色
  //        borderRadius: new BorderRadius.circular((15.0)), // 圆角度
  borderRadius: new BorderRadius.vertical(top: Radius.elliptical(20, 50)), // 也可控件一边圆角大小
),
  • Dart知识点(?. / ??)
  1. ?. 运算符在左边为null的情况下会阻断右边的调用。
  2. ?? 运算符表示在左侧表达式为null时为其设置默认值。

对于表达式:

tar[a]?.tars(b)

如果tar为null或tar[a]为null或tars(b)的值为null,都会导致表达式为null。

  1. operator重载操作符
    operator 是 Dart 的一个关键字,它和运算符(如=,+,-)一起使用,表示一个 运算符重载函数,在理解时可将operator和运算符(如operator=)视为一个函数名

关于混编中退出flutter页面的时候黑屏的情况

if(Navigator.canPop(context)){
  Navigator.pop(context, true);
}else {
  SystemNavigator.pop();
}

关于ListView中嵌套使用ListView,请在子组件中设置以下属性

shrinkWrap: true,

底部弹窗默认点击消失,如何保持面板点击不消失

  • 可以子组件外面包一层GestureDetector并设置onTap为false,拦截点击事件可以使点击底部面板区域时不消失。
 showModalBottomSheet(
        context: context,
        builder: (context) {
          return GestureDetector(
            onTap: () => false,
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                titleWidget,
                twoWidget,
                Expanded(
                  child: BottomUserRankingPage(
                    context,
                    lists: lists,
                  ),
                ),
              ],
            ),
          );
        });

实现跳转到广告按back返回是主界面

 Navigator.of(context).pushReplacementNamed('/Main');
 Navigator.of(context).push(WebPage);

如何强制竖屏

void main() {
  SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
    .then((_) {
      runApp(new MyApp());
    });
}

在线上的app,如果flutter报错,那一片红可是非常的辣眼睛,给用户的体验也很不好,其实我们可以自定义错误页面

ErrorWidget.builder = (FlutterErrorDetails details) {
    print(details.toString());
    return Center(
      child: Text("Sorry 我下班了"),
    );
  };

在Flutter中,加载本地图片会存在一个加载过程。比如点击图标做图标的切换时,那么首次会发生闪动的情况。尤其是做类似引导页这类需求是,通过左右滑动切换图片时会发生比较明显的白屏一闪而过。

解决方法很简单,就是使用 precacheImage,它将图像预存到图像缓存中。如果图像稍后被使用,它会被加载得更快。

precacheImage(AssetImage("assets/mylogo"), context);

在iOS 13中遇到了http网页打不开的问题,添加以下文字到Info.plist
yourdomain.com 是你请求的链接的域名

NSAppTransportSecurity
    
        NSExceptionDomains
        
            yourdomain.com
            
                NSExceptionAllowInsecureHTTPLoads
                
            
        
        NSAllowsArbitraryLoadsInWebContent
        
        NSAllowsArbitraryLoads
        
    

你可能感兴趣的:(flutter开发中一些技巧和坑点)