Flutter 常见问题总结

2023-10-30

文章目录

喜欢记得点个赞哟,我是王睿,很高兴认识大家!

1、内容简介

本文主要总结了开发时遇到的Bug、报错、开发时遇到的技术难题等。同时,让大家能够快速解决自己遇到额问题和避免采坑。如果对您有帮助,希望在文章的末尾能点个赞,谢谢!

2、使用Column等容器包裹ListView报错的问题

报错如下所示:

I/flutter ( 4625): EXCEPTION CAUGHT BY RENDERING LIBRARY
I/flutter ( 4625): The following assertion was thrown during performResize():
I/flutter ( 4625): Vertical viewport was given unbounded height.
I/flutter ( 4625): Viewports expand in the scrolling direction to fill their container.In this case, a vertical
I/flutter ( 4625): viewport was given an unlimited amount of vertical space in which to expand. This situation
I/flutter ( 4625): typically happens when a scrollable widget is nested inside another scrollable widget.
I/flutter ( 4625): If this widget is always nested in a scrollable widget there is no need to use a viewport because
I/flutter ( 4625): there will always be enough vertical space for the children. In this case, consider using a Column
I/flutter ( 4625): instead. Otherwise, consider using the “shrinkWrap” property (or a ShrinkWrappingViewport) to size
I/flutter ( 4625): the height of the viewport to the sum of the heights of its children.

解决方案:

使用扩展小部件Expanded包裹ListView

new Expanded(
child: new ListView(
          .....
          )
);

这告诉ListView尽可能地获取宽度和高度。

3、Navigator operation requested … does not include a Navigator.

原错误: Navigator operation requested with a context that does not include a Navigator.

flutter 最容易报的一个错误就是does not include,因为其思想是组合

这种情况即使是外面包裹了materialapp也是无效的,因为flutter会根据这个context一直上溯,一直到根节点的widget,注意,上溯是根据context的,会上溯到这个context相关的widget的最根节点

14down vote

This error is unrelated to the destination. It happens because you used a context that doesn’t contain a Navigator instance as parent.

How do I create a Navigator instance then ?

This is usually done by inserting in your widget tree a MaterialApp or WidgetApp. Although you can do it manually by using Navigator directly but less recommended. Then, all children of such widget can access NavigatorState using Navigator.of(context).

Wait, I already have a MaterialApp/WidgetApp !

That’s most likely the case. But this error can still happens when you use a context that is a parent of MaterialApp/WidgetApp.

This happens because when you do Navigator.of(context), it will start from the widget associated to the context used. And then go upward in the widget tree until it either find a Navigator or there’s no more widget.

In the first case, everything is fine. In the second, it throws a

Navigator operation requested with a context that does not include a Navigator.

So, how do I fix it ?

First, let’s reproduce this error :

import 'package:flutter/material.dart';
 
void main() => runApp(MyApp());
 
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Center(
        child: RaisedButton(
          child: Text("Foo"),
          onPressed: () => Navigator.pushNamed(context, "/"),
        ),
      ),
    );
  }
}

This example creates a button that attempts to go to ‘/’ on click but will instead throw an exception.

Notice here that in the

onPressed: () => Navigator.pushNamed(context, “/”),
we used context passed by to build of MyApp.

The problem is, MyApp is actually a parent of MaterialApp. As it’s the widget who instantiate MaterialApp! Therefore MyApp’s BuildContext doesn’t have a MaterialApp as parent!

To solve this problem, we need to use a different context.

In this situation, the easiest solution is to introduce a new widget as child of MaterialApp. And then use that widget’s context to do the Navigator call.

There are a few ways to achieve this. You can extract home into a custom class :

import 'package:flutter/material.dart';
 
void main() => runApp(MyApp());
 
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHome()
    );
  }
}
 
class MyHome extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
        child: RaisedButton(
          child: Text("Foo"),
          onPressed: () => Navigator.pushNamed(context, "/"),
        ),
      );
  }
}

Or you can use Builder :

import 'package:flutter/material.dart';
 
void main() => runApp(MyApp());
 
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Builder(
        builder: (context) => Center(
              child: RaisedButton(
                child: Text("Foo"),
                onPressed: () => Navigator.pushNamed(context, "/"),
              ),
            ),
      ),
    );
  }
}

4、设置Container背景色

child: Container(

  decoration: new BoxDecoration(
    color: Colors.grey,
  ),

5、去除AppBar 阴影

页面本身是白色,所以我想将appbar 也设置成白色,并且需要去除阴影

child: Scaffold(
          appBar: AppBar(
            title: Text("xixi"),
            backgroundColor: Colors.white,
            elevation: 0,  //默认是4, 设置成0 就是没有阴影了
          ),
          backgroundColor: Colors.white,

6、组件描边,圆角

通常用Container组件的decoration来做

Container(
              padding: EdgeInsets.symmetric(horizontal: 4.0, vertical: 2.0),
              decoration: BoxDecoration(
                  border: Border.all(color: Colors.grey, width: 1.0),
                  borderRadius: BorderRadius.circular(3.0)),
              child: Text(_products[index]['description'])),

padding内边距属性,如果不添加描边会紧贴文字image加上边距之后image

EdgeInsets支持多种自定义方法

EdgeInsets.all() 全方向
EdgeInsets.only(left,top,right,bottom) 自定义各方向的边距
EdgeInsets.symmetric(vertical, horizontal)自定义垂直,水平对称边距
EdgeInsets.fromWindowPadding(ui.WindowPadding padding, double devicePixelRatio) 根据机型屏幕尺寸定义
decoration这里用到BoxDecoration组件 常用属性

color颜色
border 描边宽度
borderRadius 圆角值
boxShadow 阴影 支持gradient 梯度,混合模式backgroundBlendMode shape自定义形状 Border BorderRadius同样支持多种自定方法.

7、如何给row或column布局添加手势监听?

直接在需要坚挺的布局外面套一层如下的代码即可!

GestureDetector(
  behavior: HitTestBehavior.translucent,
  onTap(){		//监听器
	Navigator.pushNamed(context, '/guide');//处理一些相关逻辑
	
}

8、ListView和GridView嵌套报错?

直接在GridView布局里,加上这两句代码,即可解决问题!

physics: new NeverScrollableScrollPhysics(),//增加
shrinkWrap: true,//增加

例子如下:

GridView.count(
      physics: new NeverScrollableScrollPhysics(),//增加
      shrinkWrap: true, //增加
      ...
      ...
      children: <Widget>[
       ...
       ...
      ],
    );

9、在Android studio中导入Flutter项目报错

第一步:左上角File→Settings→Dart
配置如下:
在这里插入图片描述
第二步:
在这里插入图片描述

10、给新页面传值

效果图一:
点击跳转

在这里插入图片描述
效果图二:

点击第四项后并传值到下一个页面来显示
在这里插入图片描述

代码+注释:

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

/**
 * 定义主页。
    添加一个打开选择页面的按钮。
    在选择页面上显示两个按钮。
    点击一个按钮时,关闭选择的页面。
    主页上弹出一个snackbar以显示用户的选择。
 */
class Todo {
  final String title;
  final String description;

  Todo(this.title, this.description);
}

void main() {
  runApp(new MaterialApp(
    title: 'Passing Data',
    home: new TodosScreen(
      todos: new List.generate(
        20,
            (i) => new Todo(
          'Todo $i',
          'A description of what needs to be done for Todo $i',
        ),
      ),
    ),
  ));
}

class TodosScreen extends StatelessWidget {
  final List<Todo> todos;

  TodosScreen({Key key, @required this.todos}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Todos'),
      ),
      body: new ListView.builder(
        itemCount: todos.length,
        itemBuilder: (context, index) {
          return new ListTile(
            title: new Text(todos[index].title),
            // When a user taps on the ListTile, navigate to the DetailScreen.
            // Notice that we're not only creating a new DetailScreen, we're
            // also passing the current todo through to it!
            /**
             *当用户点击ListTile时,导航到DetailScreen。请注意,我们不仅在创建新的DetailScreen,而且还在传递当前的待办事项!
             */
            onTap: () {
              Navigator.push(
                context,
                new MaterialPageRoute(
                  builder: (context) => new DetailScreen(todo: todos[index]),   //传入Todo对象
                ),
              );
            },
          );
        },
      ),
    );
  }
}

class DetailScreen extends StatelessWidget {
  // Declare a field that holds the Todo
  final Todo todo;  //接收Todo 对象

  // In the constructor, require a Todo
  DetailScreen({Key key, @required this.todo}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    // Use the Todo to create our UI
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("${todo.title}"),
      ),
      body: new Padding(
        padding: new EdgeInsets.all(16.0),
        child: new Text('${todo.description}'),
      ),
    );
  }
}

喜欢记得点个赞哟,我是王睿,很高兴认识大家!

更多原理请参考谷歌官网:给新页面传值

11、实现滑动关闭、删除item

效果图一:

在这里插入图片描述

效果图二:
右滑删除第六个item
在这里插入图片描述

效果图三:
左滑删除第4个item
在这里插入图片描述

效果图四:
最后看到,第四项和第六项都被删除了

在这里插入图片描述

代码+注释:

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(new MyApp(
    items: new List<String>.generate(20, (i) => "Item ${i + 1}"),
  ));
}

class MyApp extends StatelessWidget {
  final List<String> items;

  MyApp({Key key, @required this.items}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final title = 'Dismissing Items';

    return new MaterialApp(
      title: title,
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text(title),
        ),
        body: new ListView.builder(
          itemCount: items.length,
          itemBuilder: (context, index) {
            final item = items[index];

            return new Dismissible(
              // Each Dismissible must contain a Key. Keys allow Flutter to
              // uniquely identify Widgets.
              /**
               * 每个可豁免项都必须包含一个密钥。 键使Flutter能够唯一标识小部件。
               */
              key: new Key(item),
              // We also need to provide a function that will tell our app
              // what to do after an item has been swiped away.
              /**
               * 我们还需要提供一个可以告诉我们应用程序的功能刷掉物品后该怎么办。
               * onDismissed —— 被解雇
               * direction —— 方位表示:删除方向是左边还是右边,startToEnd 左边,endToStart 右边
               */
              onDismissed: (direction) {
                print(direction);
                items.removeAt(index);    //根据坐标移除具体的item项
                // 显示移除了哪一条item
                Scaffold.of(context).showSnackBar(
                    new SnackBar(content: new Text("$item dismissed")));
              },
              // Show a red background as the item is swiped away
              // 滑动删除item时显示红色背景
              background: new Container(color: Colors.red),
              child: new ListTile(title: new Text('$item')),
            );
          },
        ),
      ),
    );
  }
}

喜欢记得点个赞哟,我是王睿,很高兴认识大家!

更多原理请参考谷歌官网:实现滑动关闭、删除item

12、添加Material触摸水波效果

效果图一:

点击按钮出现灰色水波纹特效
在这里插入图片描述

效果图二:

显示底部弹出框
在这里插入图片描述

代码+注释:

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final title = 'InkWell Demo';

    return new MaterialApp(
      title: title,
      home: new MyHomePage(title: title),
    );
  }
}

class MyHomePage extends StatelessWidget {
  final String title;

  MyHomePage({Key key, this.title}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(title),
      ),
      body: new Center(child: new MyButton()),
    );
  }
}

class MyButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // The InkWell Wraps our custom flat button Widget
    /// InkWell 有水波纹, GestureDetector 没有水波纹
    return new InkWell(
      // When the user taps the button, show a snackbar
      // 当用户点击按钮时,显示 snackbar
      onTap: () {
        Scaffold.of(context).showSnackBar(new SnackBar(
          content: new Text('Tap'),
        ));
      },
      child: new Container(
        padding: new EdgeInsets.all(12.0),
        child: new Text('Flat Button'),
      ),
    );
  }
}

喜欢记得点个赞哟,我是王睿,很高兴认识大家!

更多原理请参考谷歌官网:添加Material触摸水波效果

13、处理点击

效果图一:
点击按钮

在这里插入图片描述

效果图二:

显示底部弹出框
在这里插入图片描述

代码+注释:

import 'package:chapter02one/Api.dart';
import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final title = 'Gesture Demo';

    return new MaterialApp(
      title: title,
      home: new MyHomePage(title: title),
    );
  }
}

class MyHomePage extends StatelessWidget {
  final String title;

  MyHomePage({Key key, this.title}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(title),
      ),
      body: new Center(child: new MyButton()),
    );
  }
}

class MyButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // Our GestureDetector wraps our button
    ///我们的GestureDetector包裹了我们的按钮
    return new GestureDetector(
      // When the child is tapped, show a snackbar
      ///监听器
      onTap: () {
        /**
         * 准备: 底部弹出框对象
         * content 是一个组件,可以是自定义的任何类型组件,也可以是复合型组合组件,例如Column
         */
        final snackBar = new SnackBar(content: Text('底部弹出框呀'));
        // 显示 SnackBar
        Scaffold.of(context).showSnackBar(snackBar);
      },
      // Our Custom Button!
      child: new Container(
        padding: new EdgeInsets.all(12.0),
        decoration: new BoxDecoration(
          color: Theme.of(context).buttonColor,
          borderRadius: new BorderRadius.circular(8.0),
        ),
        child: new Text('My Button'),
      ),
    );
  }
}

喜欢记得点个赞哟,我是王睿,很高兴认识大家!

更多原理请参考谷歌官网:处理点击

14、实现Icon可以用Image替换

flutter实现Icon可以用Image替换
23/100
发布文章
qq_27494201
未选择任何文件
在这里插入图片描述
flutter的Icon可以用Image替换

15、验证码倒计时功能

效果图:
在这里插入图片描述

import 'dart:async';

import 'package:flutter/material.dart';
import '../widget/JdText.dart';
import '../widget/JdButton.dart';
import '../services/ScreenAdapter.dart';
import 'dart:async'; //Timer定时器需要引入
import '../config/Config.dart';
import 'package:dio/dio.dart';
import 'package:fluttertoast/fluttertoast.dart';

/**
 * 注册 — 第二步
 */
class RegisterSecondPage extends StatefulWidget {
  Map arguments;
  RegisterSecondPage({Key key, this.arguments}) : super(key: key);

  _RegisterSecondPageState createState() => _RegisterSecondPageState();
}

class _RegisterSecondPageState extends State<RegisterSecondPage> {
  String tel;         //手机号码
  bool sendCodeBtn = false; //判断发送短信按钮是否点击过标志
  int seconds = 10;   //倒计时 10秒
  String code;    //验证码

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    this.tel = widget.arguments['tel'];
    this._showTimer();
  }

  //倒计时
  _showTimer() {
    Timer t;
    t = Timer.periodic(Duration(milliseconds: 1000), (timer) {
      setState(() {
        this.seconds--;
      });
      if (this.seconds == 0) {
        t.cancel(); //清除定时器
        setState(() {
          this.sendCodeBtn = true;
        });
      }
    });
  }

  //重新发送验证码
  sendCode() async {
    setState(() {
      this.sendCodeBtn = false;
      this.seconds = 10;
      this._showTimer();
    });
    var api = '${Config.domain}api/sendCode';
    var response = await Dio().post(api, data: {"tel": this.tel});
    if (response.data["success"]) {
      print(response); //演示期间服务器直接返回  给手机发送的验证码
    }
  }
  //验证验证码

  validateCode() async {
    var api = '${Config.domain}api/validateCode';
    var response =
    await Dio().post(api, data: {"tel": this.tel, "code": this.code});
    if (response.data["success"]) {
      Navigator.pushNamed(context, '/registerThird',arguments: {
        "tel":this.tel,
        "code":this.code
      });
    } else {
      Fluttertoast.showToast(
        msg: '${response.data["message"]}',
        toastLength: Toast.LENGTH_SHORT,
        gravity: ToastGravity.CENTER,
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("用户注册-第二步"),
      ),
      body: Container(
        padding: EdgeInsets.all(ScreenAdapter.width(20)),
        child: ListView(
          children: <Widget>[
            SizedBox(height: 50),
            Container(
              padding: EdgeInsets.only(left: 10),
              child: Text("验证码已经发送到了您的${this.tel}手机,请输入${this.tel}手机号收到的验证码"),
            ),
            SizedBox(height: 40),
            Stack(
              children: <Widget>[
                Container(
                  child: JdText(
                    text: "请输入验证码",
                    onChanged: (value) {
                      // print(value);
                      this.code = value;
                    },
                  ),
                  height: ScreenAdapter.height(100),
                ),
                Positioned(
                  right: 0,
                  top: 0,
                  child: this.sendCodeBtn
                      ? RaisedButton(
                    child: Text('重新发送'),
                    onPressed: this.sendCode,
                  )
                      : RaisedButton(
                    child: Text('${this.seconds}秒后重发'),
                    onPressed: () {},
                  ),
                )
              ],
            ),
            SizedBox(height: 20),
            JdButton(
              text: "下一步",
              color: Colors.red,
              height: 74,
              cb: this.validateCode,
            )
          ],
        ),
      ),
    );
  }
}

16、从新页面返回数据给上一个页面

效果图一:

点击按钮
在这里插入图片描述

效果图二:
点击YES后,返回上一级页面并传值

在这里插入图片描述

效果图三:

收到值,并用底部弹出框显示结果
在这里插入图片描述

注释+代码:

import 'package:flutter/material.dart';

void main() {
  runApp(new MaterialApp(
    title: 'Returning Data',
    home: new HomeScreen(),
  ));
}

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Returning Data Demo'),
      ),
      body: new Center(child: new SelectionButton()),
    );
  }
}

class SelectionButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new RaisedButton(
      onPressed: () {
        _navigateAndDisplaySelection(context);
      },
      child: new Text('Pick an option, any option!'),
    );
  }

  // A method that launches the SelectionScreen and awaits the result from
  // Navigator.pop!
  /**
   * 一种启动SelectionScreen并等待以下结果的方法 Navigator.pop!
   */
  _navigateAndDisplaySelection(BuildContext context) async {
    // Navigator.push returns a Future that will complete after we call
    // Navigator.pop on the Selection Screen!
    /**
     * Navigator.push返回一个Future,它将在我们调用后完成选择屏幕上的Navigator.pop!
     */
    final result = await Navigator.push(
      context,
      new MaterialPageRoute(builder: (context) => new SelectionScreen()),
    );

    // After the Selection Screen returns a result, show it in a Snackbar!
    ///选择屏幕返回结果后,将其显示在小吃栏中!
    Scaffold
        .of(context)
        .showSnackBar(new SnackBar(content: new Text("$result")));
  }
}

class SelectionScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Pick an option'),
      ),
      body: new Center(
        child: new Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            new Padding(
              padding: const EdgeInsets.all(8.0),
              child: new RaisedButton(
                onPressed: () {
                  // Close the screen and return "Yep!" as the result
                  /// 关闭屏幕并返回“是!” 作为结果
                  Navigator.pop(context, 'Yep!');
                },
                child: new Text('Yep!'),
              ),
            ),
            new Padding(
              padding: const EdgeInsets.all(8.0),
              child: new RaisedButton(
                onPressed: () {
                  // Close the screen and return "Nope!" as the result
                  /// 关闭屏幕并返回“不!” 作为结果
                  Navigator.pop(context, 'Nope.');
                },
                child: new Text('Nope.'),
              ),
            )
          ],
        ),
      ),
    );
  }
}

喜欢记得点个赞哟,我是王睿,很高兴认识大家!

更多原理请参考谷歌官网:从新页面返回数据给上一个页面

17、创建一个 grid List

效果图:

在这里插入图片描述

代码+注释:

import 'package:flutter/material.dart';

void main() {
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final title = 'Grid List';

    return new MaterialApp(
      title: title,
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text(title),
        ),
        body: new GridView.count(
          // Create a grid with 2 columns. If you change the scrollDirection to
          // horizontal, this would produce 2 rows.
          /**
           * 创建一个包含2列的网格。 如果将scrollDirection更改为水平,这将产生2行。
           */
          crossAxisCount: 2,
          // Generate 100 Widgets that display their index in the List
          // 生成100个在列表中显示其索引的小部件,参数一: 数量,参数二: 下标
          children: new List.generate(100, (index) {
            return new Center(
              child: new Text(
                'Item $index',
                style: Theme.of(context).textTheme.headline,
              ),
            );
          }),
        ),
      ),
    );
  }
}

喜欢记得点个赞哟,我是王睿,很高兴认识大家!

更多原理请参考谷歌官网:创建一个 grid List

18、使用不同类型的子项创建列表

效果图:

在这里插入图片描述

代码+注释:

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(new MyApp(
    //  List.generate构造函数 —— 生成拥有1000个字符串的列表
    items: new List<ListItem>.generate(
      1000,
          (i) => i % 6 == 0       //根据规律: 每一个标题后面会跟着五条内容
          ? new HeadingItem("Heading $i")     //标题类型
          : new MessageItem("Sender $i", "Message body $i"),    //内容类型
    ),
  ));
}

class MyApp extends StatelessWidget {
  final List<ListItem> items;

  MyApp({Key key, @required this.items}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final title = 'Mixed List';

    return new MaterialApp(
      title: title,
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text(title),
        ),
        body: new ListView.builder(
          // Let the ListView know how many items it needs to build
          // 让ListView知道需要构建多少个项目
          itemCount: items.length,
          // Provide a builder function. This is where the magic happens! We'll
          //  提供构建器功能。 这就是魔术发生的地方! 好
          // convert each item into a Widget based on the type of item it is.
          //  根据项目类型将每个项目转换为Widget。
          itemBuilder: (context, index) {
            final item = items[index];      //得到具体的items

            if (item is HeadingItem) {    //是否为标题类型
              return new ListTile(
                title: new Text(
                  item.heading,
                  style: Theme.of(context).textTheme.headline,
                ),
              );
            } else if (item is MessageItem) { //是否为内容类型
              return new ListTile(
                title: new Text(item.sender),
                subtitle: new Text(item.body),
              );
            }
          },
        ),
      ),
    );
  }
}

// The base class for the different types of items the List can contain
// 列表可以包含的不同类型的项目的基类
abstract class ListItem {}

// A ListItem that contains data to display a heading
// 一个ListItem,其中包含显示标题的数据
class HeadingItem implements ListItem {
  final String heading;

  HeadingItem(this.heading);
}

// A ListItem that contains data to display a message
// 一个ListItem包含显示消息的数据
class MessageItem implements ListItem {
  final String sender;
  final String body;

  MessageItem(this.sender, this.body);
}

喜欢记得点个赞哟,我是王睿,很高兴认识大家!

更多原理请参考谷歌官网:使用不同类型的子项创建列表

19、使用长列表

效果图:
利用 List.generate构造函数 —— 配合 ListView 生成拥有10000个字符串的列表
在这里插入图片描述

代码+注释:

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(new MyApp(
    //  List.generate构造函数 —— 生成拥有10000个字符串的列表
    items: new List<String>.generate(10000, (i) => "Item $i"),
  ));
}

class MyApp extends StatelessWidget {
  final List<String> items;

  MyApp({Key key, @required this.items}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final title = 'Long List';

    return new MaterialApp(
      title: title,
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text(title),
        ),
        body: new ListView.builder(
          itemCount: items.length,          //List长度
          itemBuilder: (context, index) {   //Item构造者
            return new ListTile(
              title: new Text('${items[index]}'),
            );
          },
        ),
      ),
    );
  }
}

喜欢记得点个赞哟,我是王睿,很高兴认识大家!
更多原理请参考谷歌官网:
使用长列表

20、用占位符淡入淡出的显示图片

效果图一:
由于是网络图片,加载速度由网速决定,所以先显示进度条圈圈
在这里插入图片描述

效果图二:
加载完毕后,淡入淡出的显示图片,不是一下子显示的哟!

在这里插入图片描述

导入依赖:

transparent_image: ^1.0.0

代码+注释:

import 'package:chapter02one/Api.dart';
import 'package:flutter/material.dart';
import 'package:transparent_image/transparent_image.dart';

void main() {
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final title = 'Fade in images';

    return new MaterialApp(
      title: title,
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text(title),
        ),
        body: new Stack(
          children: <Widget>[
            new Center(child: new CircularProgressIndicator()),
            new Center(
              /**
               * FadeInImage.memoryNetwork
               * 正在加载时,会显示加载进度条
               * 加载完毕后,会慢慢淡入淡出的显示图片
               */
              child: new FadeInImage.memoryNetwork(
                placeholder: kTransparentImage,
                image:
                '${Api.URL}/aa.png',
              ),
            ),
          ],
        ),
      ),
    );
  }
}

喜欢记得点个赞哟,我是王睿,很高兴认识大家!

更多原理请参考谷歌官网:
用占位符淡入图片

21、Dart中dynamic,var,object三者的区别

void main()//dynamic,var,object三者的区别
{
  //dynamic
  dynamic x = 'hello';//编译时不会揣测数据类型,但是运行时会推断
  print(x.runtimeType);//String
  print(x);
  //但是这样的坏处就是会让dart的语法检查失效,所以有可能会造成混乱而不报错
  //所以不要直接使用dynamic
  x = 123;
  print(x.runtimeType);//int,说明类型是可变的
  print(x);
 
  //var
  var a = 'hello';
  print(a.runtimeType);
  print(a);
  //a = 123;//会报错
  a = '123';
  print(a);
 
  //Object
  Object w = 1;
  print(w.runtimeType);
  print(w);
  //不能调用Object不存在的方法
  
}

22、TextField设置默认值默认值和光标位置

TextField(
          //输入键盘类型
              keyboardType: TextInputType.text,
              autofocus: true,
              decoration: InputDecoration(
                border: OutlineInputBorder(
                    borderRadius: BorderRadius.circular(),
                    borderSide: BorderSide.none),
              ),
              onChanged: (value) {
                this._keyword = value;
              },
              controller: TextEditingController.fromValue(TextEditingValue(
                  text: '${this._keyword == null ? "" : this._keyword}',  //判断keyword是否为空
                  // 保持光标在最后
 
                  selection: TextSelection.fromPosition(TextPosition(
                      affinity: TextAffinity.downstream,
                      offset: '${this._keyword}'.length)))),
            ),

23、限制TextField只能输入汉字或英文字母或数字,并限制输入最多中文10字符,英文20字符

原文地址

第一步,给textfield设置输入法则:

inputFormatters: [
WhitelistingTextInputFormatter(RegExp(
“[a-zA-Z]|[\u4e00-\u9fa5]|[0-9]”)), //只能输入汉字或者字母或数字
LengthLimitingTextInputFormatter(maxLength),//最大长度
],
第二步,动态修改最大字长:

onChanged: (value) {
_changeMaxLimit(value);
},
/// 改字数限制,每输入一个中文字符,要减1。
/// 字符要求:10个汉字或20个英文
void _changeMaxLimit(String value) {
maxLength = 20;
for (int i = 0; i < value.length; i++) {
if (value.codeUnitAt(i) > 122) {
maxLength–;
}
}
setState(() {});
}
我这里简略写了关键部分,关于maxLength的初始化,textfield别的参数设置,大家还请自行解决。

24、Dart之正则表达式相关方法总结

原文地址

【Dart学习】–Dart之正则表达式相关方法总结
一,部分属性
RegExp exp = new RegExp(r"(\w+)");

返回正则表达式的哈希码
print(exp.hashCode);
正则表达式是否区分大小写
print(exp.isCaseSensitive);
正则表达式是否匹配多行
print(exp.isMultiLine);
返回源正则表达式字符串
print(exp.pattern);
返回对象运行时的类型
print(exp.runtimeType);
二,常用方法

25、使用正则表达式验证手机号

RegExp exp = RegExp(
          r'^((13[0-9])|(14[0-9])|(15[0-9])|(16[0-9])|(17[0-9])|(18[0-9])|(19[0-9]))\d{8}$');
bool matched = exp.hasMatch(mobileTextController.text);

26、去掉输入框最大字数显示

new TextField(
       maxLength:11 ,
       enabled:widget.phone == null?true:false,
       keyboardType: TextInputType.number,
       decoration: InputDecoration(`在这里插入代码片`
       counterText: "",//此处控制最大字符是否显示
       hintText: widget.phone == null?'手机号':widget.phone,
       hintStyle: TextStyle(fontSize: 14,color: AppColors.colorGrayText),
       border: InputBorder.none,
     ),
     controller: _phoneContro,    ));

27、TextField 限制只允许输入数字,字母,小数,设置限制小数位数

原文地址

TextField(
          inputFormatters: [
          //只允许输入字母
            WhitelistingTextInputFormatter(RegExp("[a-zA-Z]")),
          ],
   ),
    TextField(
    //只允许输入数字
          inputFormatters: [WhitelistingTextInputFormatter.digitsOnly],
   ),
    TextField(
      			inputFormatters: [
                          //只允许输入小数
                            WhitelistingTextInputFormatter(RegExp("[0-9.]")),
                          ],,
    TextField(
      			inputFormatters: [
                          //限制小数位数
                            _MyNumberTextInputFormatter(digit:5),
                          ],// 限制小数位数
class _MyNumberTextInputFormatter extends TextInputFormatter {
  static const defaultDouble = 0.001;
  ///允许的小数位数,-1代表不限制位数
  int digit;
  _MyNumberTextInputFormatter({this.digit=-1});
  static double strToFloat(String str, [double defaultValue = defaultDouble]) {
    try {
      return double.parse(str);
    } catch (e) {
      return defaultValue;
    }
  }
  ///获取目前的小数位数
  static int getValueDigit(String value){
    if(value.contains(".")){
      return value.split(".")[1].length;
    }else{
      return -1;
    }
  }


  @override
  TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) {
    String value = newValue.text;
    int selectionIndex = newValue.selection.end;
    if (value == ".") {
      value = "0.";
      selectionIndex++;
    } else if (value != ""
        && value != defaultDouble.toString()
        && strToFloat(value, defaultDouble) == defaultDouble
        ||getValueDigit(value)>digit) {
      value = oldValue.text;
      selectionIndex = oldValue.selection.end;
    }
    return new TextEditingValue(
      text: value,
      selection: new TextSelection.collapsed(offset: selectionIndex),
    );
  }
}

28、TextField 文本输入框的基本属性及详解

const TextField({
    Key key,
    this.controller,                    // 控制正在编辑文本
    this.focusNode,                     // 获取键盘焦点
    this.decoration = const InputDecoration(),              // 边框装饰
    TextInputType keyboardType,         // 键盘类型
    this.textInputAction,               // 键盘的操作按钮类型
    this.textCapitalization = TextCapitalization.none,      // 配置大小写键盘
    this.style,                         // 输入文本样式
    this.textAlign = TextAlign.start,   // 对齐方式
    this.textDirection,                 // 文本方向
    this.autofocus = false,             // 是否自动对焦
    this.obscureText = false,           // 是否隐藏内容,例如密码格式
    this.autocorrect = true,            // 是否自动校正
    this.maxLines = 1,                  // 最大行数
    this.maxLength,                     // 允许输入的最大长度
    this.maxLengthEnforced = true,      // 是否允许超过输入最大长度
    this.onChanged,                     // 文本内容变更时回调
    this.onEditingComplete,             // 提交内容时回调
    this.onSubmitted,                   // 用户提示完成时回调
    this.inputFormatters,               // 验证及格式
    this.enabled,                       // 是否不可点击
    this.cursorWidth = 2.0,             // 光标宽度
    this.cursorRadius,                  // 光标圆角弧度
    this.cursorColor,                   // 光标颜色
    this.keyboardAppearance,            // 键盘亮度
    this.scrollPadding = const EdgeInsets.all(20.0),        // 滚动到视图中时,填充边距
    this.enableInteractiveSelection,    // 长按是否展示【剪切/复制/粘贴菜单LengthLimitingTextInputFormatter】
    this.onTap,                         // 点击时回调
})

29、实现农历(阴历)转公历(阳历)

/**
 * 农历的工具类
 */
class LunarCalendarUtil {
  /**
   * 支持转换的最小农历年份
   */
  static final int MIN_YEAR = 1900;

  /**
   * 支持转换的最大农历年份
   */
  static final int MAX_YEAR = 2099;
  /**
   * 公历每月前的天数
   */
  static final List<int> DAYS_BEFORE_MONTH = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365];

  /**
   * 用来表示1900年到2099年间农历年份的相关信息,共24位bit的16进制表示,其中:
   * 1. 前4位表示该年闰哪个月;
   * 2. 5-17位表示农历年份13个月的大小月分布,0表示小,1表示大;
   * 3. 最后7位表示农历年首(正月初一)对应的公历日期。
   * 以2014年的数据0x955ABF为例说明:
   * 1001 0101 0101 1010 1011 1111
   *  闰九月   农历正月初一对应公历1月31号
   */
  static final List<int> LUNAR_INFO = [
    /*1900*/
    0x84B6BF,
    /*1901-1910*/
    0x04AE53, 0x0A5748, 0x5526BD, 0x0D2650, 0x0D9544, 0x46AAB9, 0x056A4D, 0x09AD42, 0x24AEB6, 0x04AE4A,
    /*1911-1920*/
    0x6A4DBE, 0x0A4D52, 0x0D2546, 0x5D52BA, 0x0B544E, 0x0D6A43, 0x296D37, 0x095B4B, 0x749BC1, 0x049754,
    /*1921-1930*/
    0x0A4B48, 0x5B25BC, 0x06A550, 0x06D445, 0x4ADAB8, 0x02B64D, 0x095742, 0x2497B7, 0x04974A, 0x664B3E,
    /*1931-1940*/
    0x0D4A51, 0x0EA546, 0x56D4BA, 0x05AD4E, 0x02B644, 0x393738, 0x092E4B, 0x7C96BF, 0x0C9553, 0x0D4A48,
    /*1941-1950*/
    0x6DA53B, 0x0B554F, 0x056A45, 0x4AADB9, 0x025D4D, 0x092D42, 0x2C95B6, 0x0A954A, 0x7B4ABD, 0x06CA51,
    /*1951-1960*/
    0x0B5546, 0x555ABB, 0x04DA4E, 0x0A5B43, 0x352BB8, 0x052B4C, 0x8A953F, 0x0E9552, 0x06AA48, 0x6AD53C,
    /*1961-1970*/
    0x0AB54F, 0x04B645, 0x4A5739, 0x0A574D, 0x052642, 0x3E9335, 0x0D9549, 0x75AABE, 0x056A51, 0x096D46,
    /*1971-1980*/
    0x54AEBB, 0x04AD4F, 0x0A4D43, 0x4D26B7, 0x0D254B, 0x8D52BF, 0x0B5452, 0x0B6A47, 0x696D3C, 0x095B50,
    /*1981-1990*/
    0x049B45, 0x4A4BB9, 0x0A4B4D, 0xAB25C2, 0x06A554, 0x06D449, 0x6ADA3D, 0x0AB651, 0x095746, 0x5497BB,
    /*1991-2000*/
    0x04974F, 0x064B44, 0x36A537, 0x0EA54A, 0x86B2BF, 0x05AC53, 0x0AB647, 0x5936BC, 0x092E50, 0x0C9645,
    /*2001-2010*/
    0x4D4AB8, 0x0D4A4C, 0x0DA541, 0x25AAB6, 0x056A49, 0x7AADBD, 0x025D52, 0x092D47, 0x5C95BA, 0x0A954E,
    /*2011-2020*/
    0x0B4A43, 0x4B5537, 0x0AD54A, 0x955ABF, 0x04BA53, 0x0A5B48, 0x652BBC, 0x052B50, 0x0A9345, 0x474AB9,
    /*2021-2030*/
    0x06AA4C, 0x0AD541, 0x24DAB6, 0x04B64A, 0x6a573D, 0x0A4E51, 0x0D2646, 0x5E933A, 0x0D534D, 0x05AA43,
    /*2031-2040*/
    0x36B537, 0x096D4B, 0xB4AEBF, 0x04AD53, 0x0A4D48, 0x6D25BC, 0x0D254F, 0x0D5244, 0x5DAA38, 0x0B5A4C,
    /*2041-2050*/
    0x056D41, 0x24ADB6, 0x049B4A, 0x7A4BBE, 0x0A4B51, 0x0AA546, 0x5B52BA, 0x06D24E, 0x0ADA42, 0x355B37,
    /*2051-2060*/
    0x09374B, 0x8497C1, 0x049753, 0x064B48, 0x66A53C, 0x0EA54F, 0x06AA44, 0x4AB638, 0x0AAE4C, 0x092E42,
    /*2061-2070*/
    0x3C9735, 0x0C9649, 0x7D4ABD, 0x0D4A51, 0x0DA545, 0x55AABA, 0x056A4E, 0x0A6D43, 0x452EB7, 0x052D4B,
    /*2071-2080*/
    0x8A95BF, 0x0A9553, 0x0B4A47, 0x6B553B, 0x0AD54F, 0x055A45, 0x4A5D38, 0x0A5B4C, 0x052B42, 0x3A93B6,
    /*2081-2090*/
    0x069349, 0x7729BD, 0x06AA51, 0x0AD546, 0x54DABA, 0x04B64E, 0x0A5743, 0x452738, 0x0D264A, 0x8E933E,
    /*2091-2099*/
    0x0D5252, 0x0DAA47, 0x66B53B, 0x056D4F, 0x04AE45, 0x4A4EB9, 0x0A4D4C, 0x0D1541, 0x2D92B5
  ];

  /**
   * 将农历日期转换为公历日期
   * @param year    农历年份
   * @param month   农历月
   * @param monthDay   农历日
   * @param isLeapMonth   该月是否是闰月(该参数可以根据本类中leapMonth()方法,先判断一下要查询的年份是否有闰月,并且闰的几月)
   * @return 返回农历日期对应的公历日期,year0, month1, day2.
   */
  static  List<int> lunarToSolar(int year, int month, int monthDay, bool isLeapMonth) {
    int dayOffset;
    int leapMonth;
    int i;
    if (year < MIN_YEAR || year > MAX_YEAR || month < 1 || month > 12
        || monthDay < 1 || monthDay > 30) {
      throw new Exception(
          "Illegal lunar date, must be like that:\n\t" +
              "year : 1900~2099\n\t" +
              "month : 1~12\n\t" +
              "day : 1~30");
    }
    dayOffset = (LUNAR_INFO[year - MIN_YEAR] & 0x001F) - 1;
    if (((LUNAR_INFO[year - MIN_YEAR] & 0x0060) >> 5) == 2) {
      dayOffset += 31;
    }
    for (i = 1; i < month; i++) {
      if ((LUNAR_INFO[year - MIN_YEAR] & (0x80000 >> (i - 1))) == 0) {
        dayOffset += 29;
      } else {
        dayOffset += 30;
      }
    }
    dayOffset += monthDay;
    leapMonth = (LUNAR_INFO[year - MIN_YEAR] & 0xf00000) >> 20;
    // 这一年有闰月
    if (leapMonth != 0) {
      if (month > leapMonth || (month == leapMonth && isLeapMonth)) {
        if ((LUNAR_INFO[year - MIN_YEAR] & (0x80000 >> (month - 1))) == 0) {
          dayOffset += 29;
        } else {
          dayOffset += 30;
        }
      }
    }
    if (dayOffset > 366 || (year % 4 != 0 && dayOffset > 365)) {
      year += 1;
      if (year % 4 == 1) {
        dayOffset -= 366;
      } else {
        dayOffset -= 365;
      }
    }
    List<int> solarInfo = new List(3);
    for (i = 1; i < 13; i++) {
      int iPos = DAYS_BEFORE_MONTH[i];
      if (year % 4 == 0 && i > 2) {
        iPos += 1;
      }
      if (year % 4 == 0 && i == 2 && iPos + 1 == dayOffset) {
        solarInfo[1] = i;
        solarInfo[2] = dayOffset - 31;
        break;
      }
      if (iPos >= dayOffset) {
        solarInfo[1] = i;
        iPos = DAYS_BEFORE_MONTH[i - 1];
        if (year % 4 == 0 && i > 2) {
          iPos += 1;
        }
        if (dayOffset > iPos) {
          solarInfo[2] = dayOffset - iPos;
        } else if (dayOffset == iPos) {
          if (year % 4 == 0 && i == 2) {
            solarInfo[2] = DAYS_BEFORE_MONTH[i] - DAYS_BEFORE_MONTH[i - 1] + 1;
          } else {
            solarInfo[2] = DAYS_BEFORE_MONTH[i] - DAYS_BEFORE_MONTH[i - 1];
          }
        } else {
          solarInfo[2] = dayOffset;
        }
        break;
      }
    }
    solarInfo[0] = year;
    return solarInfo;
  }

  /**
   * 传回农历year年month月的总天数
   *
   * @param year   要计算的年份
   * @param month        要计算的月
   * @return 传回天数
   */
  static int daysInMonth(int year, int month) {
    return daysInMontaThree(year, month, false);
  }

  /**
   * 传回农历year年month月的总天数
   *
   * @param year   要计算的年份
   * @param month    要计算的月
   * @param leap   当月是否是闰月
   * @return 传回天数,如果闰月是错误的,返回0.
   */
  static int daysInMontaThree(int year, int month, bool leap) {
    int mLeapMonth = leapMonth(year);
    int offset = 0;
    // 如果本年有闰月且month大于闰月时,需要校正
    if (leapMonth != 0 && month > mLeapMonth) {
      offset = 1;
    }
    // 不考虑闰月
    if (!leap) {
      return daysInLunarMonth(year, month + offset);
    } else {
      // 传入的闰月是正确的月份
      if (leapMonth != 0 && leapMonth == month) {
        return daysInLunarMonth(year, month + 1);
      }
    }
    return 0;
  }

  /**
   * 传回农历 year年的总天数
   *
   * @param year 将要计算的年份
   * @return 返回传入年份的总天数
   */
  static int daysInLunarYear(int year) {
    int i, sum = 348;
    if (leapMonth(year) != 0) {
      sum = 377;
    }
    int monthInfo = LUNAR_INFO[year - MIN_YEAR] & 0x0FFF80;
    for (i = 0x80000; i > 0x7; i >>= 1) {
      if ((monthInfo & i) != 0) {
        sum += 1;
      }
    }
    return sum;
  }

  /**
   * 传回农历 year年month月的总天数,总共有13个月包括闰月
   *
   * @param year  将要计算的年份
   * @param month 将要计算的月份
   * @return 传回农历 year年month月的总天数
   */
  static int daysInLunarMonth(int year, int month) {
    if ((LUNAR_INFO[year - MIN_YEAR] & (0x100000 >> month)) == 0) {
      return 29;
    } else {
      return 30;
    }
  }

  /**
   * 传回农历 year年闰哪个月 1-12 , 没闰传回 0
   * @param year 将要计算的年份
   * @return 传回农历 year年闰哪个月1-12, 没闰传回 0
   */
  static int leapMonth(int year) {
    return ((LUNAR_INFO[year - MIN_YEAR] & 0xF00000)) >> 20;
  }
}

测试数据:

测试数据:2020125日转公历结果为:2021117Text('${LunarCalendarUtil.lunarToSolar(2020, 12, 5, true)}'),

30、SDK升级

1、在终端中使用flutter upgrade
2、删除SDK包重新下载

31、Expanded组件不能直接嵌套LitView报错,解决办法

这样写,即可解决问题!

Row(
          children: <Widget>[
            Expanded(
              flex: 1,
              child: Container(
                height: 180,
                child: ListView(
                  children: <Widget>[
                    Container(
                      height: 85,
                      child: Image.network("https://www.itying.com/images/flutter/3.png",fit: BoxFit.cover),

                    ),
                    SizedBox(height: 10),
                    Container(
                      height: 85,
                      child: Image.network("https://www.itying.com/images/flutter/4.png",fit: BoxFit.cover),
                    )
                  ],
                )
              )
            ),

          ],
        )

32、ListView不能直接嵌套ListView解决办法

ListView(
        scrollDirection: Axis.horizontal,
        children: <Widget>[
          Container(
            width: 180,
            color: Colors.orange,
            child: ListView(
              children: <Widget>[
                Image.network("https://www.itying.com/images/flutter/1.png"),
                Text('我是一个文本')
              ],
            ),
          ),
        ],
      ),

直接套一个Container即可解决问题

32、Text的overflow属性不生效(14)

Text的overflow属性不生效(14)

33、

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Flutter 常见问题总结 的相关文章

随机推荐

  • 软件测试综述-软件开发过程

    1 软件产品构成的主要部分 1 客户需求 2 产品说明书 3 进度表 4 软件设计文档 包括 结构文档 数据流图 状态转换图 流程图 代码注释等 5 测试文档 包括 测试计划 测试用例 缺陷报告 测试工具和自动测试 质量 统计和总结 2 软
  • POJ-1416 Shredding Company(DFS)

    题目链接 点击打开链接 大致题意 公司现在要发明一种新的碎纸机 要求新的碎纸机能够把纸条上的数字切成最接近而不超过target值 比如 target的值是50 而纸条上的数字是12346 应该把数字切成四部分 分别是1 2 34 6 因为这
  • 推荐系统-基于用户的协同过滤(User-based CF)

    基于邻域的算法应该算是推荐系统中最基础的算法之一了 主要包括基于用户的协同过滤和基于物品的协同过滤 我觉得他们是最符合直觉的推荐算法了 你想想看 如果给你若干人的行为数据 你怎么去做推荐 一个就是找到和他最相似的用户 因为他们臭味相投 所以
  • SpringCloud之Eureka的报错(版本神坑)

    一 报错内容 2021 09 12 14 47 53 594 INFO 20640 freshExecutor 0 com netflix discovery DiscoveryClient Disable delta property f
  • springboot如何实现短信验证注册和短信验证码登录

    Spring Boot实现短信验证注册和短信验证码登录的步骤如下 1 集成短信服务 选择一个短信服务商 例如阿里云 腾讯云等 并集成该服务商提供的API 2 实现短信发送接口 编写一个短信发送的接口 该接口需要传入手机号并发送短信验证码到该
  • C#Socket通信基础方法知识整理

    一 IP地址操作类 1 IPAddress类 a 在该类中有一个 Parse 方法 可以把点分的十进制IP表示转化成IPAddress类 方法如下 IPAddress address IPAddress Parse 192 168 0 1
  • python sqlite3

    含数据库连接 表创建 增删改查 查看sqlite数据库的软件推荐使用sqlitestudio 下载地址 sqlitestudio SQLite文档类资源 CSDN下载 coding utf 8 乐乐感知学堂公众号 author https
  • SQL Server如何备份数据库

    一 首先把当前的数据库备份成一个文件 1 按照操作来 选择对应的数据库 确定备份文件的存储位置 点击确定 生成备份文件 2 然后可以通过该备份文件还原数据库 右键数据库点击还原文件和文件组 然后设置目标数据库的名字 如果数据库中已经存在相同
  • TSINGSEE青犀视频安防监控管理平台EasyNVR如何配置鉴权?

    视频监控汇聚平台EasyNVR是基于RTSP Onvif协议的视频平台 可支持将接入的视频流进行全平台 全终端的分发 分发的视频流包括RTSP RTMP HTTP FLV WS FLV HLS WebRTC等格式 为了满足用户的集成与二次开
  • Qt 串口类QSerialPort 使用笔记

    Qt 串口类QSerialPort 使用笔记 虽然现在大多数的家用PC机上已经不提供RS232接口了 但是由于RS232串口操作简单 通讯可靠 在工业领域中仍然有大量的应用 Qt以前的版本中 没有提供官方的对RS232串口的支持 编写串口程
  • virtual box安装Ubuntu操作系统

    在提供Ubuntu 18 10 Cosmic Cuttlefish映像的地址中有ubuntu 18 10 desktop amd64 iso和ubuntu 18 10 live server amd64 iso版本 它们是什么区别 简单的说
  • 机器学习——所有非支持向量的拉格朗日乘子一定为0

    问 SVM模型求解过程中所有非支持向量的拉格朗日乘子一定为0 答 正确 SVM模型的求解过程中 对于非支持向量的数据点 其对应的拉格朗日乘子为0 这是因为非支持向量数据点已经满足了约束条件 不需要对目标函数造成日对目标函数有贡献 简而言之
  • UDIMM、RDIMM和LRDIMM

    UDIMM RDIMM和LRDIMM UDIMM UDIMM 全称Unbuffered DIMM 即无缓冲双列直插内存模块 指地址和控制信号不经缓冲器 无需做任何时序调整 直接到达DIMM上的DRAM芯片 UDIMM由于在CPU和内存之间没
  • 基于python的Page Factory模式

    Pythium 基于 Python 的 Page Factory 设计模式测试库 类似于Java的Page Factory模式 旨在减少代码冗余 简单易用 具有高度的可扩展能力 支持以 annotation的方式定义元素 支持同一个元素多种
  • 【Unity 3D学习笔记】P&D 过河游戏智能实现

    P D 过河游戏智能帮助实现 实现状态图的自动生成 讲解图数据在程序中的表示方法 利用算法实现下一步的计算 对于过河游戏 首先需要知道其中各个状态之间的转换关系 绘制状态转移图如下 其中 P代表出发岸上的牧师 D代表出发岸上的恶魔 加号和减
  • 竞品分析该怎么做

    竞品分析 作用 知己知彼 百战不殆 为自身产品设计提供功能 可用性 关键技术等方面的参考 提高自身产品的差异化程度 为新立项的产品 拍脑袋想出来的 降低风险 如何选择竞品 行业内领先的产品 通常可以根据一些百度指数 行业排名 业务相似程度来
  • 四款Python在线模拟器

    一 菜鸟工具 地址 http c runoob com compile 9 打开的界面是酱紫的 左边是代码输入框 右边是结果输出框 特点 1 支持切换Python2 Python3版本 2 不支持常用导入模块 例如pandas等 3 运行速
  • 使用Python生成docx文档

    1 首先需要安装doxc的公共库 pip install python docx U 2 安装成功后 使用这个库的方法import docx 3 这样生成的docx内容会有汉字显示不出来 4 这样生成的docx会有乱码 需要调整字体格式添加
  • 解决linux磁盘空间不足的方法

    磁盘空间不足的解决办法 1 首先确定是否是磁盘空间不足 输入命令 df h 查看磁盘信息 很明显 Filesystem下的挂载点 dev vda1 下的50G容量已经耗尽 这时最简单的办法就是找到大且无用的文件并删除 首选就是log文件 2
  • Flutter 常见问题总结

    文章目录 1 内容简介 2 使用Column等容器包裹ListView报错的问题 3 Navigator operation requested does not include a Navigator 4 设置Container背景色 5