Flutter 基础-下

news2024/11/15 10:37:21

一、shared_preferences

  • shared_preferences 是一个本地数据缓存库(类似 AsyncStorage)
    • https://pub.dev/packages/shared_preferences
  • 使用步骤
    • 在 pubsepc.yaml 中添加 shared_preferences 依赖
    • 安装依赖(pub get | flutter packages get | VS Code 中保存配置,自动下载
    • 引入import ‘package:shared_preferences/shared_preferences.dart’;
    • 使用 SharedPreferences prefs = await SharedPreferences.getInstance();

shared_preferences - 操作

    • setString(key, value)
    • remove(key) | clear()
    • 更改就是重新设置数据setString(key, value)
    • getString(key)
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

class Home extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("shared_preferences"),
        leading: Icon(Icons.menu),
        actions: [
          Icon(Icons.settings)
        ],
        elevation: 0.0,
        centerTitle: true,
      ),
      body: SharedPreferencesDemo()
    );
  }
}

class SharedPreferencesDemo extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Container(
      width: double.infinity,
      child: Column(
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          ElevatedButton(
            onPressed: _incrementCounter, 
            child: Text('递增')
          ),
          ElevatedButton(
            onPressed: _decrementCounter, 
            child: Text('递减')
          ),
          ElevatedButton(
            onPressed: _removeCounter, 
            child: Text('删除')
          ),
          ElevatedButton(
            onPressed: _addMyContent, 
            child: Text('设置字符串')
          ),
          ElevatedButton(
            onPressed: _getMyContent, 
            child: Text('获取字符串')
          ),
          ElevatedButton(
            onPressed: _clearContent, 
            child: Text('清空')
          ),
        ],
      )
    );
  }

  _incrementCounter() async {
    // 获取保存实例
    SharedPreferences prefs = await SharedPreferences.getInstance();
    int counter = (prefs.getInt('counter') ?? 0) + 1;
    print('Pressed $counter times.');
    await prefs.setInt('counter', counter);
  }

  _decrementCounter() async {
    // 获取保存实例
    SharedPreferences prefs = await SharedPreferences.getInstance();
    int counter = prefs.getInt('counter') ?? 0;
    if (counter > 0) {
      counter--;
    }
    print('Pressed $counter times.');
    await prefs.setInt('counter', counter);
  }

  _removeCounter() async {
    // 获取保存实例
    SharedPreferences prefs = await SharedPreferences.getInstance();
    await prefs.remove('counter');
    int counter = (prefs.getInt('counter') ?? 0) + 1;
    print('Pressed $counter times.');
  }

  _addMyContent() async {
    // 获取保存实例
    SharedPreferences prefs = await SharedPreferences.getInstance();
    await prefs.setString('hi', 'Hello World');
    String content = prefs.getString('hi') ?? "";
    print('设置字符串的内容是 $content');
  }

  _getMyContent() async {
    // 获取保存实例
    SharedPreferences prefs = await SharedPreferences.getInstance();
    String content = prefs.getString('hi') ?? "";
    print('获取字符串的内容是 $content');
  }

  _clearContent() async {
    // 获取保存实例
    SharedPreferences prefs = await SharedPreferences.getInstance();
    await prefs.clear();
  }
}

在这里插入图片描述

二、StatefulWidget

在这里插入图片描述
StatefulWidget

  • Flutter 中的组件,按状态划分
    • StatelessWidget (无状态组件)
    • StatefulWidget(状态组件)
  • 按状态作用域划分
    • 组件内私有状态(StatefulWidget)
    • 跨组件状态共享(InheritedWidget、 Provider)
    • 全局状态(Redux | fish-redux、Mobx…
  • 状态组件的组成
    • StatefulWidget(组件本身不可变 - @immutable)
    • State(将变化的状态放到 State 中维护)
import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("StatefulWidget"),
        leading: Icon(Icons.menu),
        actions: [
          Icon(Icons.settings)
        ],
        elevation: 0.0,
        centerTitle: true,
      ),
      body: MyState()
    );
  }
}

class MyState extends StatefulWidget {
  
  _MyStateState createState() => _MyStateState();
}

class _MyStateState extends State<MyState> {
  int _num = 0;

  void _increment() {
    setState(() {
      _num++;
    });
  }

  void _decrement() {
    setState(() {
      _num--;
    });
  }

  
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        children: [
          ElevatedButton(
            onPressed: _decrement, 
            child: Text('-')
          ),
          Padding(
            padding: EdgeInsets.all(20),
            child: Text('$_num')
          ),
          ElevatedButton(
            onPressed: _increment, 
            child: Icon(Icons.add)
          )
        ],
      )
    );
  }
}

在这里插入图片描述

三、DataTable

  • DataTable 是 Flutter 中的表格
    • columns (声明表头列表)
      • DataColumn (表头单元格)
  • rows (声明数据列表)
    • DataRow (一行数据)
      • DataCell (数据单元格)
  • 其他属性

在这里插入图片描述

import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("DataTable"),
        leading: Icon(Icons.menu),
        actions: [
          Icon(Icons.settings)
        ],
        elevation: 0.0,
        centerTitle: true,
      ),
      body: UserList()
    );
  }
}

class User {
  String name;
  int age;
  bool selected;

  User(this.name, this.age, {this.selected = false});
}

class UserList extends StatefulWidget {
  UserList({Key key}) : super(key: key);

  
  _UserListState createState() => _UserListState();
}

class _UserListState extends State<UserList> {
  List<User> data = [
    User('张三', 18),
    User('张三丰', 218, selected: true),
    User('张翠山', 30),
    User('张无忌', 60),
  ];

  var _sortAscending = true;

  List _getUserRows() {
    List<DataRow> dataRows = [];
    for (int i = 0; i < data.length; i++) {
      dataRows.add(
        DataRow(
          selected: data[i].selected,
          onSelectChanged: (selected) {
            setState(() {
              data[i].selected = selected;
            });
          },
          cells: [
            DataCell(Text('${data[i].name}')),
            DataCell(Text('${data[i].age}')),
            DataCell(Text('男')),
            DataCell(Text('---')),
          ]
        )
      );
    }

    return dataRows;
  }

  
  Widget build(BuildContext context) {
    return Container(
      child: SingleChildScrollView(
        scrollDirection: Axis.horizontal,
        child: DataTable(
          sortColumnIndex: 1,
          sortAscending: _sortAscending,
          dataRowHeight: 100,
          horizontalMargin: 20,
          columnSpacing: 100,
          columns: [
            DataColumn(label: Text('姓名')),
            DataColumn(
              label: Text('年龄'),
              numeric: true,
              onSort: (int columnIndex, bool asscending) {
                setState(() {
                  _sortAscending = asscending;
                  if (asscending) {
                    data.sort((a, b) => a.age.compareTo(b.age));
                  } else {
                    data.sort((a, b) => b.age.compareTo(a.age));
                  }
                });
              }
            ),
            DataColumn(label: Text('性别')),
            DataColumn(label: Text('简介')),
          ], 
          rows: _getUserRows(),
          // [
          //   DataRow(
          //     cells: [
          //       DataCell(Text('张三')),
          //       DataCell(Text('18')),
          //       DataCell(Text('男')),
          //       DataCell(Text('一个男人')),
          //     ]
          //   ),
          //   DataRow(
          //     cells: [
          //       DataCell(Text('张三')),
          //       DataCell(Text('18')),
          //       DataCell(Text('男')),
          //       DataCell(Text('一个男人')),
          //     ]
          //   ),
          //   DataRow(
          //     cells: [
          //       DataCell(Text('张三')),
          //       DataCell(Text('18')),
          //       DataCell(Text('男')),
          //       DataCell(Text('一个男人')),
          //     ]
          //   )
          // ]
        )
      ),
    );
  }
}

在这里插入图片描述

四、InheritedWidget

  • What:提供了沿树向下,共享数据的功能
    • 即子组件可以获取父组件(InheritedWidget的子类)的数据
  • Why:
    • 依赖构造函数传递数据的方式不能满足业务需求
    • 所以,需要一个新的,更好的跨组件数据传输方案
  • How:
    • BuildContext.dependOnInheritedWidgetOfExactType()
import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("InheritedWidget"),
        leading: Icon(Icons.menu),
        actions: [
          Icon(Icons.settings)
        ],
        elevation: 0.0,
        centerTitle: true,
      ),
      body: MyState()
    );
  }
}

class MyState extends StatefulWidget {
  
  _MyStateState createState() => _MyStateState();
}

class _MyStateState extends State<MyState> {
  int _num = 0;

  void _increment() {
    setState(() {
      _num++;
    });
  }

  void _decrement() {
    setState(() {
      _num--;
    });
  }

  
  Widget build(BuildContext context) {
    return ShareDataWidget(
      num: _num,
      child: Center(
        child: Column(
          children: [
            ElevatedButton(
              onPressed: _decrement, 
              child: Text('-')
            ),
            Padding(
              padding: EdgeInsets.all(20),
              // child: Text('$_num')
              // 跨组件访问数据
              child: MyCounter(),
            ),
            ElevatedButton(
              onPressed: _increment, 
              child: Icon(Icons.add)
            )
          ],
        )
      ),
    );
  }
}

class MyCounter extends StatefulWidget {
  MyCounter({Key key}) : super(key: key);

  
  _MyCounterState createState() => _MyCounterState();
}

class _MyCounterState extends State<MyCounter> {
  
  Widget build(BuildContext context) {
    // 使用 InheritedWidget 中的共享数据
    return Text(ShareDataWidget.of(context).num.toString());
  }
}

// 数据共享组件
class ShareDataWidget extends InheritedWidget {
  final int num;
  final Widget child;

  ShareDataWidget({Key key, this.child,  this.num}) : super(key: key, child: child);

  static ShareDataWidget of(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType<ShareDataWidget>();
  }

  
  bool updateShouldNotify(ShareDataWidget oldWidget) {
    return true;
  }
}

五、生命周期

  • initState() 组件对象插入到元素树中时
  • didChangeDependencies() 当前状态对象的依赖改变时
  • build() 组件渲染时
  • setState() 组件对象的内部状态变更时
  • didUpdateWidget() 组件配置更新时
  • deactivate() 组件对象在元素树中暂时移除时
  • dispose() 组件对象在元素树中永远移除时
import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Life Cycle"),
        leading: Icon(Icons.menu),
        actions: [
          Icon(Icons.settings)
        ],
        elevation: 0.0,
        centerTitle: true,
      ),
      body: MyState()
    );
  }
}

class MyState extends StatefulWidget {
  
  // _MyStateState createState() => _MyStateState();
  _MyStateState createState() {
    print('create state');
    return _MyStateState();
  }
}

class _MyStateState extends State<MyState> {
  int _num;

  
  void initState() {
    // TODO: implement initState
    super.initState();
    print('init state');
    _num = 1;
  }

  
  void didChangeDependencies() {
    // TODO: implement didChangeDependencies
    super.didChangeDependencies();
    print('didChangeDependencies');
  }

  
  void didUpdateWidget(covariant MyState oldWidget) {
    // TODO: implement didUpdateWidget
    super.didUpdateWidget(oldWidget);
    print('didUpdateWidget');
  }

  
  void deactivate() {
    // TODO: implement deactivate
    super.deactivate();
    print('deactivate');
  }

  
  void dispose() {
    // TODO: implement dispose
    super.dispose();
    print('dispose');
  }

  void _increment() {
    setState(() {
      print('setState');
      _num++;
    });
  }

  void _decrement() {
    setState(() {
      print('setState');
      _num--;
    });
  }

  
  Widget build(BuildContext context) {
    print('build');
    return Center(
      child: Column(
        children: [
          ElevatedButton(
            onPressed: _decrement, 
            child: Text('-')
          ),
          Padding(
            padding: EdgeInsets.all(20),
            child: Text('$_num')
          ),
          ElevatedButton(
            onPressed: _increment, 
            child: Icon(Icons.add)
          )
        ],
      )
    );
  }
}

六、Provider

  • Provider 是对 InheritedWidget 的封装
    • https://pub.dev/packages/provider
  • 优点:
    • 简化资源的分配与处置
    • 懒加载

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

class Home extends StatelessWidget {
  
  Widget build(BuildContext context) {
    // 2. 创建 Provider (注册数据模型)
    return ChangeNotifierProvider(
      create: (BuildContext context) => new LikesModel(),
      child: Scaffold(
        appBar: AppBar(
          title: Text("Provider"),
          leading: Icon(Icons.menu),
          actions: [
            Icon(Icons.settings)
          ],
          elevation: 0.0,
          centerTitle: true,
        ),
        body: MyHomePage()
      ),
    );
  }
}

// 1. 创建数据模型
class LikesModel extends ChangeNotifier {
  int _counter = 0;

  int get counter => _counter;

  incrementCounter() {
    // 累加
    _counter++;

    // 通过 UI 更新
    notifyListeners();
  }
}

class MyHomePage extends StatelessWidget {
  const MyHomePage({Key key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return Container(
      width: double.infinity,
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          // 3. 在子组件中使用数据模型
          Text(
            '${context.watch<LikesModel>().counter}'
          ),
          TextButton(
            // 3. 在子组件中使用数据模型
            onPressed: Provider.of<LikesModel>(context).incrementCounter, 
            child: Icon(Icons.thumb_up)
          )
        ],
      ),
    );
  }
}

七、匿名路由

路由简介

  • Route
    • 一个路由是一个屏幕或页面的抽象
  • Navigator
    • 管理路由的组件。Navigator 可以通过路由入栈和出栈来实现页面之间的跳转
    • 常用属性:
      • initialRoute:初始路由,即默认页面
      • onGenerateRoute: 动态路由(根据规则,匹配动态路由
      • onUnknownRoute: 未知路由,也就是 404
      • routes: 路由集合

匿名路由

  • Navigator
  • push (跳转到指定组件)
Navigator.push(
context,
MaterialPageRoute(builder: (context) => 组件名称())
  • pop (回退)
 Navigator.pop(context)
import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("匿名路由"),
        leading: Icon(Icons.menu),
        actions: [
          Icon(Icons.settings)
        ],
        elevation: 0.0,
        centerTitle: true,
      ),
      body: HomePage()
    );
  }
}

class HomePage extends StatelessWidget {
  const HomePage({Key key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return Container(
      child: Center(
        child: ElevatedButton(
          onPressed: () {
            return Navigator.push(
              context, 
              MaterialPageRoute(builder: (context) => Product())
            );
          }, 
          child: Text('跳转到商品页面'),
        )
      ),
    );
  }
}

class Product extends StatelessWidget {
  const Product({Key key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("商品页面"),
        leading: Icon(Icons.menu),
        actions: [
          Icon(Icons.settings)
        ],
        elevation: 0.0,
        centerTitle: true,
      ),
      body: Container(
        child: Center(
          child: ElevatedButton(
            onPressed: () => Navigator.pop(context), 
            child: Text('返回')
          )
        ),
      ),
    );
  }
}

八、命名路由

  • 声明路由

    • routes 路由表(Map 类型)
    • initialRoute(初始路由)
    • onUnknownRoute(未知路由-404)
  • 跳转到命名路由

    • Navigator.pushNamed(context,‘路由名称");

    在这里插入图片描述
    main.dart

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

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Flutter Demo",
      home: Home(),
      // 声明命名路由
       routes: {
         'home': (context) => Home(),
         'product': (context) => Product(),
         'productDetail': (context) => ProductDetail(),
       },
      initialRoute: 'home',
      theme: CustomTheme.lightTheme,
      darkTheme: CustomTheme.darkTheme,

      debugShowCheckedModeBanner: false,
      // 国际化
      localizationsDelegates: [
        // 本地化代理
        CustomLocalizations.delegate,
        GlobalMaterialLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
      ],
      supportedLocales: [
        const Locale('en', 'US'), // 美国英语
        const Locale('zh', 'CN'), // 简体中文
      ],
      localeResolutionCallback: (locale, supportedLocales) {
        print('deviceLocale: $locale');
        print('languageCode: ${locale.languageCode}');
        print('countryCode: ${locale.countryCode}');
        for (var supportedLocale in supportedLocales) {
          if (supportedLocale.languageCode == locale.languageCode 
          && supportedLocale.countryCode == locale.countryCode) {
            return supportedLocale;
          }
        }

        return supportedLocales.first;
      },
    );
  }

_namedRoute.dart

import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("首页"),
        leading: Icon(Icons.menu),
        actions: [
          Icon(Icons.settings)
        ],
        elevation: 0.0,
        centerTitle: true,
      ),
      body: Center(
        child: Column(
          children: [
            ElevatedButton(
              onPressed: () => Navigator.pushNamed(context, 'product'), 
              child: Text('跳转'),
            ),
            ElevatedButton(
              onPressed: () => Navigator.pushNamed(context, 'user'), 
              child: Text('未知路由'),
            ),
          ],
        ),
      ),
    );
  }
}

class Product extends StatelessWidget {
  const Product({Key key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("商品页"),
        leading: Icon(Icons.menu),
        actions: [
          Icon(Icons.settings)
        ],
        elevation: 0.0,
        centerTitle: true,
      ),
      body: Center(
        child: Column(
          children: [
            ElevatedButton(
              onPressed: () => Navigator.pop(context), 
              child: Text('返回'),
            )
          ],
        ),
      ),
    );
  }
}

class UnknowPage extends StatelessWidget {
  const UnknowPage({Key key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("404"),
        leading: Icon(Icons.menu),
        actions: [
          Icon(Icons.settings)
        ],
        elevation: 0.0,
        centerTitle: true,
      ),
      body: Center(
        child: Column(
          children: [
            ElevatedButton(
              onPressed: () => Navigator.pop(context), 
              child: Text('返回'),
            )
          ],
        ),
      ),
    );
  }
}

九、动态路由

  • 动态路由是指,通过onGenerateRoute属性指定的路由

main.dart
在这里插入图片描述

import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("首页"),
        leading: Icon(Icons.menu),
        actions: [
          Icon(Icons.settings)
        ],
        elevation: 0.0,
        centerTitle: true,
      ),
      body: Center(
        child: Column(
          children: [
            ElevatedButton(
              onPressed: () => Navigator.pushNamed(context, '/product'), 
              child: Text('跳转'),
            ),
            ElevatedButton(
              onPressed: () => Navigator.pushNamed(context, '/product/1'), 
              child: Text('商品1'),
            ),
            ElevatedButton(
              onPressed: () => Navigator.pushNamed(context, '/product/2'), 
              child: Text('商品2'),
            ),
            ElevatedButton(
              onPressed: () => Navigator.pushNamed(context, 'user'), 
              child: Text('未知路由'),
            ),
          ],
        ),
      ),
    );
  }
}

class Product extends StatelessWidget {
  const Product({Key key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("商品页"),
        leading: Icon(Icons.menu),
        actions: [
          Icon(Icons.settings)
        ],
        elevation: 0.0,
        centerTitle: true,
      ),
      body: Center(
        child: Column(
          children: [
            ElevatedButton(
              onPressed: () => Navigator.pop(context), 
              child: Text('返回'),
            )
          ],
        ),
      ),
    );
  }
}

class ProductDetail extends StatelessWidget {
  // product/1
  final String id;

  const ProductDetail({Key key, this.id}) : super(key: key);

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("商品详情页"),
        leading: Icon(Icons.menu),
        actions: [
          Icon(Icons.settings)
        ],
        elevation: 0.0,
        centerTitle: true,
      ),
      body: Center(
        child: Column(
          children: [
            Text('当前商品的id是:'+this.id),
            ElevatedButton(
              onPressed: () => Navigator.pop(context), 
              child: Text('返回'),
            )
          ],
        ),
      ),
    );
  }
}

class UnknowPage extends StatelessWidget {
  const UnknowPage({Key key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("404"),
        leading: Icon(Icons.menu),
        actions: [
          Icon(Icons.settings)
        ],
        elevation: 0.0,
        centerTitle: true,
      ),
      body: Center(
        child: Column(
          children: [
            ElevatedButton(
              onPressed: () => Navigator.pop(context), 
              child: Text('返回'),
            )
          ],
        ),
      ),
    );
  }
}

十、路由传参-匿名路由

  • 路由中声明参数

    • Navigator.push
      在这里插入图片描述
  • 组件中接收参数

路由传参-命名路由

  • 路由中声明参数
    • Navigator.pushNamed(context, routename, {arguments})
  • 组件中接收参数
    • ModalRoute.of(context).settings.arguments
      在这里插入图片描述

十一、Drawer 导航

  • Scaffold
    • drawer (左侧抽屉菜单)
    • endDrawer (右侧抽屉菜单)
  • UserAccountsDrawerHeader
    • 抽屉菜单头部组件
  • AboutListTile
    • 关于弹窗

在这里插入图片描述

import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Drawer"),
        leading: Icon(Icons.menu),
        actions: [
          Icon(Icons.settings)
        ],
        elevation: 0.0,
        centerTitle: true,
      ),
      body: HomePage(),
      drawer: DrawerList(),
      endDrawer: DrawerList(),
    );
  }
}

class HomePage extends StatelessWidget {
  const HomePage({Key key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return Container(
      child: Center(
        child: Text('Home'),
      ),
    );
  }
}

class DrawerList extends StatelessWidget {
  const DrawerList({Key key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return Drawer(
      child: ListView(
        padding: EdgeInsets.all(0),
        children: [
          UserAccountsDrawerHeader(
            accountName: Text('初六'),
            accountEmail: Text('whoicliu@163.com'),
            decoration: BoxDecoration(
              image: DecorationImage(
                image: AssetImage('images/bg1.jpg'),
                fit: BoxFit.cover,
              )
            ),
            currentAccountPicture: CircleAvatar(
              backgroundImage: AssetImage('images/flutter.jpg'),
            ),
          ),
          ListTile(
            leading: Icon(Icons.settings),
            title: Text('设置'),
            trailing: Icon(Icons.arrow_forward_ios),
          ),
          Divider(thickness: 2,),
          ListTile(
            leading: Icon(Icons.account_balance),
            title: Text('余额'),
            trailing: Icon(Icons.arrow_forward_ios),
          ),
          Divider(thickness: 2,),
          ListTile(
            leading: Icon(Icons.person),
            title: Text('我的'),
            trailing: Icon(Icons.arrow_forward_ios),
          ),
          Divider(thickness: 2,),
          ListTile(
            leading: Icon(Icons.person),
            title: Text('回退'),
            onTap: () => Navigator.pop(context),
            trailing: Icon(Icons.arrow_forward_ios),
          ),
          AboutListTile(
            child: Text('关于'),
            applicationName: "你的应用名称",
            applicationVersion: "1.0.0",
            icon: CircleAvatar(
              child: Text('aaa')
            ),
            applicationLegalese: "应用法律条例",
            aboutBoxChildren: [
              Text('条例一:xxxx'),
              Text('条例二:xxxx'),
            ],
            applicationIcon: Image.asset(
              'images/flutter.jpg',
              width: 50,
              height: 50,
            )
          ),
          // Text('Drawer')
        ]
      ),
    );
  }
}

十二、BottomNavigationBar 导航

  • items
    • 包含导航(BottomNavigationBarltem)的列表
  • currentIndex
    • 当前导航索引
  • type
    • 导航类型(BottomNavigationBarType)
  • onTap()
    • 导航的点击事件(一般会更新导航索引)
import 'package:flutter/material.dart';

class Home extends StatefulWidget {
  Home({Key key}) : super(key: key);

  
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
  final List<BottomNavigationBarItem> bottomNavItems = [
    BottomNavigationBarItem(
      backgroundColor: Colors.blue,
      icon: Icon(Icons.home),
      label: '首页',
    ),
    BottomNavigationBarItem(
      backgroundColor: Colors.green,
      icon: Icon(Icons.message),
      label: '消息',
    ),
    BottomNavigationBarItem(
      backgroundColor: Colors.amber,
      icon: Icon(Icons.shopping_cart),
      label: '购物车',
    ),
    BottomNavigationBarItem(
      backgroundColor: Colors.red,
      icon: Icon(Icons.person),
      label: '我',
    ),
  ];

  final pages = [
    Center(
      child: Text("Home", style: TextStyle(fontSize: 50)),
    ),
    Center(
      child: Text("Message", style: TextStyle(fontSize: 50)),
    ),
    Center(
      child: Text("Cart", style: TextStyle(fontSize: 50)),
    ),
    Center(
      child: Text("Profile", style: TextStyle(fontSize: 50)),
    ),
  ];

  int currentIndex;

  
  void initState() {
    // TODO: implement initState
    super.initState();
    currentIndex = 0;
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("底部导航"),
        leading: Icon(Icons.menu),
        actions: [
          Icon(Icons.settings)
        ],
        elevation: 0.0,
        centerTitle: true,
      ),
      bottomNavigationBar: BottomNavigationBar(
        items: bottomNavItems,
        currentIndex: currentIndex,
        type: BottomNavigationBarType.fixed,
        // type: BottomNavigationBarType.shifting,
        onTap: (index) {
          _changePage(index);
        }
      ),
      body: pages[currentIndex],
    );
  }

  void _changePage(int index) {
    if (index != currentIndex) {
      setState(() {
        currentIndex = index;
      });
    }
  }
}

在这里插入图片描述

十三、Tab 导航

  • DefaultTabController (整个Tab导航的容器)
    • length (声明导航数量)
    • child(指定子组件)
  • TabBar (导航菜单)
    • tabs (导航菜单数组)
  • TabBarView (导航页面)
    • children (多个导航页面内容)
import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  // 菜单数组
  final List<Widget> _tabs = [
    Tab(text: "首页", icon: Icon(Icons.home)),
    Tab(text: "添加", icon: Icon(Icons.add)),
    Tab(text: "搜索", icon: Icon(Icons.search)),
  ];

  // 页面数组
  final List<Widget> _tabViews = [
    Icon(Icons.home, size: 120, color: Colors.red),
    Icon(Icons.add, size: 120, color: Colors.green),
    Icon(Icons.search, size: 120, color: Colors.black),
  ];

  
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: _tabs.length, 
      child: Scaffold(
        appBar: AppBar(
          title: Text("Tab"),
          leading: Icon(Icons.menu),
          actions: [
            Icon(Icons.settings)
          ],
          elevation: 0.0,
          centerTitle: true,
          bottom: TabBar(
            tabs: _tabs,
            labelColor: Colors.yellow,
            unselectedLabelColor: Colors.black45,
            indicatorSize: TabBarIndicatorSize.tab,
            indicatorColor: Colors.yellow,
            indicatorWeight: 10,
          ),
        ),
        body: TabBarView(
          children: _tabViews
        ),
        bottomNavigationBar: TabBar(
          tabs: _tabs,
          labelColor: Colors.blue,
          unselectedLabelColor: Colors.black45,
        ),
      ),
    );
  }
}

在这里插入图片描述

十四、表单-Switch

  • value(开关的值,一般与状态字段绑定)
    • onChanged(开关状态变更时调用)
    • activeColor (开关开启时的圆圈颜色)
    • activeTrackColor (开关开启时的轨道颜色)
    • inactiveThumbColor (开关关闭时的圆圈颜色)
    • inactiveTrackColor (开关关闭时的轨道颜色)
  • CupertinoSwitch (iOS风格的开关)
    • import ‘package:flutter/cupertino.dart’;

在这里插入图片描述

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

class Home extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Switch"),
        leading: Icon(Icons.menu),
        actions: [
          Icon(Icons.settings)
        ],
        elevation: 0.0,
        centerTitle: true,
      ),
      body: SwitchDemo()
    );
  }
}

class SwitchDemo extends StatefulWidget {
  SwitchDemo({Key key}) : super(key: key);

  
  _SwitchDemoState createState() => _SwitchDemoState();
}

class _SwitchDemoState extends State<SwitchDemo> {
  bool _switchValue = false;

  
  Widget build(BuildContext context) {
    return Container(
       child: ListView(
         children: [
           ListTile(
             leading: Switch(
               value: _switchValue,
               onChanged: (bool val) {
                 setState(() {
                   _switchValue = val;
                 });
               },
               activeColor: Colors.orange,
               activeTrackColor: Colors.pink,
               inactiveTrackColor: Colors.grey,
               inactiveThumbColor: Colors.blue[100],
             ),
             title: Text("当前的状态是: ${_switchValue == true ? "选中" : "未选中"}"),
           ),
           ListTile(
             leading: CupertinoSwitch(
               value: _switchValue, 
               onChanged: (bool val) {
                 setState(() {
                   _switchValue = val;
                 });
               },
               activeColor: Colors.red,
               trackColor: Colors.yellow,
             ),
             title: Text('iOS 风格的 Switch'),
           )
         ]
       ),
    );
  }
}

在这里插入图片描述

十五、表单-Checkbox

  • value(复选框的值)
    • onChanged (复选框状态更改时调用)
    • activeColor (选中时,复选框背景的颜色)
    • checkColor(选中时,复选框中对号的颜色)
  • CheckboxListTile
    • title (标题)
    • subtitle (子标题)
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';

class Home extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Checkbox"),
        leading: Icon(Icons.menu),
        actions: [
          Icon(Icons.settings)
        ],
        elevation: 0.0,
        centerTitle: true,
      ),
      body: CheckboxDemo()
    );
  }
}

class CheckboxDemo extends StatefulWidget {
  CheckboxDemo({Key key}) : super(key: key);

  
  _CheckboxDemoState createState() => _CheckboxDemoState();
}

class _CheckboxDemoState extends State<CheckboxDemo> {
  bool _male = true;
  bool _female = false;
  bool _transgender = true;
  bool _value1 = true;
  bool _value2 = false;

  
  Widget build(BuildContext context) {
    return Column(
       children: [
         ListTile(
           leading: Checkbox(
             value: this._male,
             onChanged: (bool value) {
               setState(() {
                 this._male = value;
               });
             },
           ),
           title: Text('男'),
         ),
         ListTile(
           leading: Checkbox(
             value: this._female,
             onChanged: (bool value) {
               setState(() {
                 this._female = value;
               });
             },
           ),
           title: Text('女'),
         ),
         ListTile(
           leading: Checkbox(
             value: this._transgender,
             onChanged: (bool value) {
               setState(() {
                 this._transgender = value;
               });
             },
             activeColor: Colors.pink,
             checkColor: Colors.yellow,
           ),
           title: Text('人妖'),
         ),
         CheckboxListTile(
           secondary: Icon(Icons.settings, size: 50),
           value: this._value1, 
           onChanged: (bool value) {
            setState(() {
              this._value1 = value;
            });
           },
           title: Text('1:00 叫我起床'),
           subtitle: Text('太困了,起不来'),
           activeColor: Colors.green,
           checkColor: Colors.green,
           selected: this._value1,
         ),
         CheckboxListTile(
           secondary: Icon(Icons.settings, size: 50),
           value: this._value2, 
           onChanged: (bool value) {
            setState(() {
              this._value2 = value;
            });
           },
           title: Text('2:00 叫我起床'),
           subtitle: Text('这还差不多'),
         ),
       ],
    );
  }
}

在这里插入图片描述

十六、表单-TextField

  • autofocus(是否获取焦点)
  • keyboardType (键盘类型)
  • obscureText (设置为密码框)
  • decoration (样式修饰)
  • onChanged (内容更改时自动调用-value)
  • labelText (标题)
  • hintText(提示文字-placeholder)
  • maxLines (显示行数-文本域)
import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("TextField"),
        leading: Icon(Icons.menu),
        actions: [
          Icon(Icons.settings)
        ],
        elevation: 0.0,
        centerTitle: true,
      ),
      body: TextFieldDemo()
    );
  }
}

class TextFieldDemo extends StatefulWidget {
  TextFieldDemo({Key key}) : super(key: key);

  
  _TextFieldDemoState createState() => _TextFieldDemoState();
}

class _TextFieldDemoState extends State<TextFieldDemo> {
  String phone;
  String password;
  String description;

  _register() {
    print(phone);
    print(password);
    print(description);
  }

  
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.all(20),
       child: Column(
         children: [
           TextField(
             autofocus: true,
             keyboardType: TextInputType.phone,
             decoration: InputDecoration(
               prefixIcon: Icon(Icons.mobile_screen_share),
               // 获取焦点时,高亮的边框样式
               focusedBorder: UnderlineInputBorder(
                 borderSide: BorderSide(
                   color: Colors.green,
                 )
               ),
               // 默认边框样式
               enabledBorder: UnderlineInputBorder(
                 borderSide: BorderSide(
                   color: Colors.yellow,
                 )
               ),
               labelText: "手机号",
               hintText: "请输入手机号",
               hintStyle: TextStyle(
                 color: Colors.green,
                 fontSize: 14,
               ),
             ),
             maxLength: 11,
             onChanged: (value) {
               setState(() {
                 phone = value;
               });
             },
           ),
           TextField(
             obscureText: true,
             keyboardType: TextInputType.text,
             decoration: InputDecoration(
               prefixIcon: Icon(Icons.code_outlined),
               // 获取焦点时,高亮的边框样式
               focusedBorder: UnderlineInputBorder(
                 borderSide: BorderSide(
                   color: Colors.green,
                 )
               ),
               // 默认边框样式
               enabledBorder: UnderlineInputBorder(
                 borderSide: BorderSide(
                   color: Colors.yellow,
                 )
               ),
               labelText: "密码",
               hintText: "请输入密码",
               hintStyle: TextStyle(
                 color: Colors.green,
                 fontSize: 14,
               ),
             ),
             onChanged: (value) {
               setState(() {
                 password = value;
               });
             },
           ),
           TextField(
             maxLines: 5,
             keyboardType: TextInputType.text,
             decoration: InputDecoration(
               prefixIcon: Icon(Icons.person),
               // 获取焦点时,高亮的边框样式
               focusedBorder: UnderlineInputBorder(
                 borderSide: BorderSide(
                   color: Colors.green,
                 )
               ),
               // 默认边框样式
               enabledBorder: UnderlineInputBorder(
                 borderSide: BorderSide(
                   color: Colors.yellow,
                 )
               ),
               labelText: "简介",
               hintText: "请介绍一下自己",
               hintStyle: TextStyle(
                 color: Colors.green,
                 fontSize: 14,
               ),
             ),
             onChanged: (value) {
               setState(() {
                 description = value;
               });
             },
           ),
         
           // 声明按钮
           Container(
             width: double.infinity,
             child: ElevatedButton(
              onPressed: () {
                _register();
              }, 
              child: Text('提交'),
            ),
           )
         ],
       ),
    );
  }
}

在这里插入图片描述

十七、表单-日历

  • CalendarDatePicker (日历选择器)
    • initialCalendarMode
      • DatePickerMode.day
      • DatePickerMode.year
  • showDatePicker (日期选择器)
    • initialDatePickerMode (year | day)
    • initialEntryMode (calendar | input)
  • showTimePicker (时间选择器)
    在这里插入图片描述
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';

class Home extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Calendar'),
        centerTitle: true,
        elevation: 0.0,
        leading: Icon(Icons.menu),
        actions: [
          Icon(Icons.search)
        ],
        backgroundColor: Colors.blue,
      ),
      body: CalendarDemo(),
    );
  }
}

class CalendarDemo extends StatefulWidget {
  CalendarDemo({Key key}) : super(key: key);

  
  _CalendarDemoState createState() => _CalendarDemoState();
}

class _CalendarDemoState extends State<CalendarDemo> {
  
  Widget build(BuildContext context) {
    return Container(
       child: ListView(
        padding: EdgeInsets.all(15),
        children: [
          _showDatePicker(context),
          _showDatePickerForYear(context),
          _showDatePickerForInput(context),
          _showDatePickerForTheme(context),
          _showTimePicker(context),

          Text("CalendarDatePicker day"),
          SizedBox(height: 30),
          _calendarDatePicker(DatePickerMode.day),
          SizedBox(height: 30),
          Text("CalendarDatePicker year"),
          SizedBox(height: 30),
          _calendarDatePicker(DatePickerMode.year),
          SizedBox(height: 30),
          Text("_cupertinoTimePicker - hms"),
          SizedBox(height: 30),
          _cupertinoTimePicker(CupertinoTimerPickerMode.hms),
          SizedBox(height: 30),
          Text("_cupertinoTimePicker - hm"),
          SizedBox(height: 30),
          _cupertinoTimePicker(CupertinoTimerPickerMode.hm),
          SizedBox(height: 30),
          Text("_cupertinoTimePicker - ms"),
          SizedBox(height: 30),
          _cupertinoTimePicker(CupertinoTimerPickerMode.ms),
          SizedBox(height: 30),
          Text("CupertinoDatePicker - time"),
          SizedBox(height: 30),
          _cupertinoDatePicker(CupertinoDatePickerMode.time),
          SizedBox(height: 30),
          Text("CupertinoDatePicker - dateAndTime"),
          SizedBox(height: 30),
          _cupertinoDatePicker(CupertinoDatePickerMode.dateAndTime),
          SizedBox(height: 30),
          Text("CupertinoDatePicker - date"),
          SizedBox(height: 30),
          _cupertinoDatePicker(CupertinoDatePickerMode.date),
        ],
      ),
    );
  }

  ElevatedButton _showDatePicker(context) {
    return ElevatedButton(
      child: Text("showDatePicker"),
      onPressed: () {
        showDatePicker(
          context: context,
          initialDatePickerMode: DatePickerMode.day, // 日期选择模式,默认为天数选择
          initialDate: DateTime.now(), // 初始化选中日期
          firstDate: DateTime(2020, 6), // 开始日期
          lastDate: DateTime(2021, 6), // 结束日期
          initialEntryMode: DatePickerEntryMode.calendar, // 日历弹框样式

          currentDate: DateTime.now(), // 当前日期
          helpText: "日期选择器", // 左上方提示
          cancelText: "取消",  // 取消按钮文案
          confirmText: "确定",  // 确认按钮文案

          errorFormatText: "errorFormatText",  // 格式错误提示
          errorInvalidText: "errorInvalidText",  // 输入不在 first 与 last 之间日期提示
          fieldLabelText: "fieldLabelText",  // 输入框上方提示
          fieldHintText: "fieldHintText",  // 输入框为空时内部提示
          useRootNavigator: true, // 是否为根导航器
          // 设置不可选日期
          selectableDayPredicate: (dayTime) {
            if (dayTime == DateTime(2021, 1, 15)) {
              return false;
            }
            return true;
          }
        );
      },
    );
  }

  ElevatedButton _showDatePickerForYear(context) {
    return ElevatedButton(
      child: Text("showDatePicker - YearMode"),
      onPressed: (){
        showDatePicker(
          context: context,
          initialDatePickerMode: DatePickerMode.year, // 日期选择模式,默认为天数选择
          initialEntryMode: DatePickerEntryMode.calendar, // 日历弹框样式
          initialDate: DateTime.now(), // 初始化选中日期
          firstDate: DateTime(2015, 6), // 开始日期
          lastDate: DateTime(2025, 6), // 结束日期
          currentDate: DateTime.now(), // 当前日期
          helpText: "年份选择器", // 左上方提示
          cancelText: "取消", // 取消按钮文案
          confirmText: "确认", // 确认按钮文案
        );
      },
    );
  }

  ElevatedButton _showDatePickerForInput(context) {
    return ElevatedButton(
      child: Text("showDatePicker - InputMode"),
      onPressed: (){
        showDatePicker(
            context: context,
            initialEntryMode: DatePickerEntryMode.input,  // 日历弹框样式
            initialDate: DateTime.now(), // 初始化选中日期
            firstDate: DateTime(2020, 6), // 开始日期
            lastDate: DateTime(2021, 6), // 结束日期
            textDirection: TextDirection.rtl, // 文字方向

            currentDate: DateTime(2020, 10, 20), // 当前日期
            helpText: "helpText", // 左上方提示
            cancelText: "cancelText", // 取消按钮文案
            confirmText: "confirmText", // 确认按钮文案

            errorFormatText: "errorFormatText",  // 格式错误提示
            errorInvalidText: "errorInvalidText",  // 输入不在 first 与 last 之间日期提示

            fieldLabelText: "fieldLabelText",  // 输入框上方提示
            fieldHintText: "fieldHintText",  // 输入框为空时内部提示

            // initialDatePickerMode: DatePickerMode.day, // 日期选择模式,默认为天数选择
            useRootNavigator: true, // 是否为根导航器
            // 设置不可选日期,这里将 2020-10-15,2020-10-16,2020-10-17 三天设置不可选
            selectableDayPredicate: (dayTime){
              if (dayTime == DateTime(2020, 10, 15) || dayTime == DateTime(2020, 10, 16) || dayTime == DateTime(2020, 10, 17)) {
                return false;
              }
              return true;
            }
        );
      },
    );
  }

  ElevatedButton _showDatePickerForTheme(context) {
    return ElevatedButton(
      child: Text("showDatePicker - InputMode"),
      onPressed: (){
        showDatePicker(
          context: context,
          builder: (context, child) {
            return Theme(
              data: ThemeData(
                cardColor: Colors.red,
                brightness: Brightness.dark,
              ),
              child: child,
            );
          },
          initialDatePickerMode: DatePickerMode.year, // 日期选择模式,默认为天数选择
          initialDate: DateTime.now(), // 初始化选中日期
          firstDate: DateTime(2018, 6),  // 开始日期
          lastDate: DateTime(2025, 6),  // 结束日期
          currentDate: DateTime(2020, 10, 20),  // 当前日期
          helpText: "helpText", // 左上方提示
          cancelText: "cancelText",  // 取消按钮文案
          confirmText: "confirmText",  // 确认按钮文案
        );
      },
    );
  }

  ElevatedButton _showTimePicker(context) {
    return ElevatedButton(
      child: Text("showTimePicker - InputMode"),
      onPressed: (){
        showTimePicker(
          context: context,
          initialTime: TimeOfDay(hour: 10, minute: 30),
          initialEntryMode: TimePickerEntryMode.input,
          helpText: "时间选择器",
          cancelText: "取消",
          confirmText: "确定"
        );
      },
    );
  }

  CalendarDatePicker _calendarDatePicker(DatePickerMode mode) {
    return CalendarDatePicker(
      initialCalendarMode: mode, // 日期选择样式
      initialDate: DateTime.now(), // 初始化选中日期~
      currentDate: DateTime.now(), // 当前日期~
      firstDate: DateTime(2010, 9, 10),  // 开始日期
      lastDate: DateTime(2030, 9, 10),  // 结束日期
      
      // 选中日期改变回调函数
      onDateChanged: (dateTime){
        print("选择日期 $dateTime");
      },
      // 月份改变回调函数
      onDisplayedMonthChanged: (dateTime){
        print("选择月份 $dateTime");
      },
      // 筛选日期可不可点回调函数
      selectableDayPredicate: (dayTime) {
        if (dayTime == DateTime(2021, 1, 15)) {
          return false;
        }
        return true;
      }
    );
  }

  CupertinoTimerPicker _cupertinoTimePicker(CupertinoTimerPickerMode mode) {
    return CupertinoTimerPicker(
      mode: mode, // 展示模式,默认为 hms
      initialTimerDuration: Duration(hours: 5, minutes: 10), // 默认选中时间
      minuteInterval: 10, // 分钟间隔
      secondInterval: 10, // 秒间隔
      alignment: Alignment.center, // 对齐方式
      backgroundColor: Colors.amber[200], // 背景颜色
      // 滑动后,每次改变回调函数
      onTimerDurationChanged: (dayTime){
        print("选中时间 $dayTime");
      },
    );
  }

  Container _cupertinoDatePicker(CupertinoDatePickerMode mode) {
    return Container(
      height: 300,
      child: CupertinoDatePicker(
        mode: mode, // 展示模式, 默认为 dateAndTime
        initialDateTime: DateTime(2020, 10, 10), // 默认选中日期
        minimumDate: DateTime(2010, 10, 10), // 最小可选日期
        maximumDate: DateTime(2021, 10, 10), // 最大可选日期
        minuteInterval: 10, // 分钟间隔
        use24hFormat: true, // 是否采用24小时制
        backgroundColor: Colors.greenAccent[200], // 背景色
        onDateTimeChanged: (dayTime) {
          print("选择日期时间 $dayTime");
        },
      ),
    );
  }
}

十八、表单-Form

  • 使用步骤
    • 创建表单 Form,并以 GlobalKey 作为唯一性标识
    • 添加带验证逻辑的 TextFormField 到 Form 中
    • 创建按钮以验证和提交表单
  • Form (表单容器)
    • key (GlobalKey)
    • child (子组件)
  • TextFormField (输入框)
    • 与 TextField 的区别:必须在 Form 内使用 & 带有验证器
    • validator (验证器)
import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Form"),
        leading: Icon(Icons.menu),
        actions: [
          Icon(Icons.settings)
        ],
        elevation: 0.0,
        centerTitle: true,
      ),
      body: FormDemo()
    );
  }
}

class FormDemo extends StatefulWidget {
  FormDemo({Key key}) : super(key: key);

  
  _FormDemoState createState() => _FormDemoState();
}

class _FormDemoState extends State<FormDemo> {
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();

  
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.all(20),
      child: Column(
        children: [
          Form(
            key: _formKey,
            child: Column(
              children: [
                TextFormField(
                  decoration: InputDecoration(
                    hintText: '手机号'
                  ),
                  validator: (value) {
                    RegExp reg = new RegExp(r'^\d{11}$');
                    if (!reg.hasMatch(value)) {
                      return '手机号非法111';
                    }
                    return null;
                  }
                )
              ],
            )
          ),
          Row(
            children: [
              Expanded(
                child: ElevatedButton(
                  onPressed: () {
                    if (_formKey.currentState.validate()) {
                      print('提交成功');
                    }
                  }, 
                  child: Text('提交'),
                )
              )
            ],
          )
        ],
      ),
    );
  }
}

在这里插入图片描述

十九、表单-Form

  • Form (表单容器)
    • 创建表单唯一键:final GlobalKey_formKey = GlobalKey();
    • 验证表单: _formKey.currentState.validate()
    • 提交表单:_formKey.currentState.ve()
    • 重置表单: _formKey.currentState.reset()
  • TextFormField (输入框)
    • validator(验证器)
    • obscureText (密码框)
    • onSaved
      • 设定表单字段的值
      • 在表单的方法之后执行
import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Form"),
        leading: Icon(Icons.menu),
        actions: [
          Icon(Icons.settings)
        ],
        elevation: 0.0,
        centerTitle: true,
      ),
      body: FormDemo()
    );
  }
}

class FormDemo extends StatefulWidget {
  FormDemo({Key key}) : super(key: key);

  
  _FormDemoState createState() => _FormDemoState();
}

class _FormDemoState extends State<FormDemo> {
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  String _phone;
  String _password;

  
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.all(20),
      child: Column(
        children: [
          Form(
            key: _formKey,
            child: Column(
              children: [
                TextFormField(
                  decoration: InputDecoration(
                    hintText: '手机号'
                  ),
                  validator: (value) {
                    RegExp reg = new RegExp(r'^\d{11}$');
                    if (!reg.hasMatch(value)) {
                      return '手机号非法111';
                    }
                    return null;
                  },
                  onSaved: (value) {
                    print('_phone onSaved');
                    _phone = value;
                  },
                ),
                TextFormField(
                  obscureText: true,
                  decoration: InputDecoration(
                    hintText: '密码'
                  ),
                  validator: (value) {
                    return value.length < 6 ? "密码长度不够": null;
                  },
                  onSaved: (value) {
                    print('_password onSaved');
                    _password = value;
                  },
                )
              ],
            )
          ),
          Row(
            children: [
              Expanded(
                child: ElevatedButton(
                  onPressed: () {
                    if (_formKey.currentState.validate()) {
                      print('提交成功');
                      // 提交表单
                      print('_formKey.currentState.save() - Before');
                      _formKey.currentState.save();
                      print('_formKey.currentState.save() - After');
                      print(_phone);
                      print(_password);
                    }
                  }, 
                  child: Text('提交'),
                )
              ),
              SizedBox(
                width: 20,
              ),
              Expanded(
                child: ElevatedButton(
                  onPressed: () {
                    _formKey.currentState.reset();
                  }, 
                  child: Text('重置'),
                )
              )
            ],
          )
        ],
      ),
    );
  }
}

二十、动画

  • Why
    • UI 界面设计合理的动画,可以让用户觉得更加流畅、直观,可以极大提高和改善用户体验。
  • What (实现原理)
    • 动画就是动起来的画面
    • 视觉暂留:画面经视神经传入大脑后,不会立即消失(会存留一段时间)
    • 帧(Frame):单个的画面,在学术上叫帧。
    • 每秒中展示的帧数简称fps (Frame per Second)

动画分类

  • 补间(Tween)动画
    • 在补间动画中我们定义开始点和结束点、时间线以及定义转换时间和速度曲线。然后由系统计算,从开始点运动到结束点。从而形成动画效果
    • 例如:透明度从 0 到 1,颜色值从 0 到 255
  • 拟物动画
    • 拟物动画是对真实世界的行为进行建模,使动画效果类似于现实中的物理效果。
    • 例如:弹簧,阻尼,重力,抛物线等。

动画-Animation

  • Animation,是 Flutter 动画库中的一个核心类。它包含动画的值和状态两个属性,定义了动画的一系列监听函数。
    • 监听值:
      • addListener
      • removeListener
    • 监听状态:
      • addStatusListener
      • removeStatusListener

动画状态

  • AnimationStatus.dismissed
    • 动画初始状
  • AnimationStatus.completed
    • 动画结束状
  • AnimationStatus.forward
    • 动画处在从开始到结束的运行状态
  • AnimationStatus.reverse
    • 动画处在从结束到开始的运行状态

动画-AnimationController

  • AnimationController (动画控制器)
    • 在指定时间内,将组件属性值由初始值演变到终止值。从而形成动画效果。
  • AnimationController 参数
    • duration (动画的执行时间)
    • reverseDuration (动画反向执行时间)
    • lowerBound =0.0 (动画最小值)
    • upperBound =1.0 (动画最大值)
    • value(动画初始值,默认是 lowerBound)
    • vsync(TickerProvider 类型的对象,用来创建 Ticker 对象)

动画-AnimationController

  • 当创建一个 AnimationController 时,需要传递一个 vsync 参数
    • vsync 的作用是:防止屏幕外动画(动画页面切换到后台时)消耗不必要的资源
    • 通过将 SingleTickerProviderStateMixin 添加到类定义中,可以将 stateful 对象作为vsync 的值。
  • AnimationController 具有控制动画的方法:
    • forward()可以正向执行动画
    • reverse()可以反向执行动画
    • dispose()用来释放动画资源(在不使用时需要调用该方法,否则会造成资源泄露)
    • stop()用来停止动画运行

动画-Tween

  • 简介
    • AnimationController 动画生成值的默认区间是 0.0 到 1.0,如果希望使用不同的区间,或不同的数据类型,需要使用Tween (补间动画)
    • Tween 的唯一职责就是定义从输入范围到输出范围的映射。
    • 例如:颜色区间是 0到 255
  • Tween
    • Tween(begin: 起始值,end: 终止值);
    • ColorTween(begin: Colors.withe, end: Colors.black);

动画-CurvedAnimation

  • 简介
    • 动画执行的速度有多种(匀速、先快后慢或先慢后快)这里的速度称为动画曲线CurvedAnimation 的目的是为 AnimationController 添加动画曲线
  • 组件
    • CurvedAnimation(parent: controller, curve: Curves.easeln)
    • parent (动画控制器对象)
    • curve(正向执行的动画曲线)
    • reverseCurve (反向执行的动画曲线)
  • Curves
    • 动画曲线: https://api.flutter.dev/flutter/animation/Curves-class.html

动画-步骤

  • 创建动画控制器
    • controller = AnimationController(duration, vsync)
  • 创建动画
    • 动画曲线(CurvedAnimation)
    • 补间动画(Tween)
  • 监听动画
    • addListener() // 监听动画生成值addStatusListener() //监听动画状态执行动画
    • controller.forward()// 正向执行
    • controller.reverse()// 反向执行
import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Animation"),
        leading: Icon(Icons.menu),
        actions: [
          Icon(Icons.settings)
        ],
        elevation: 0.0,
        centerTitle: true,
      ),
      body: AnimationDemo()
    );
  }
}

class AnimationDemo extends StatefulWidget {
  AnimationDemo({Key key}) : super(key: key);

  
  _AnimationDemoState createState() => _AnimationDemoState();
}

class _AnimationDemoState extends State<AnimationDemo> with SingleTickerProviderStateMixin {
  AnimationController controller;
  Animation animation;

  
  void initState() {
    // TODO: implement initState
    super.initState();

    // 1.创建 AnimationController
    controller = AnimationController(
      duration: Duration(milliseconds: 400),
      vsync: this
    );

    // 2.1 声明动画曲线
    animation = CurvedAnimation(parent: controller, curve: Curves.bounceIn);

    // 2.2 设置动画值的范围
    animation = Tween(begin: 50.0, end: 400.0).animate(controller);

    // 3. 监听动画
    animation.addListener(() {
      print(animation.value);
      setState(() {
        
      });
    });

    // 4. 执行动画
    // controller.forward();
  }

  
  Widget build(BuildContext context) {
    return Center(
       child: Column(
         children: [
           ElevatedButton(
             onPressed: () {
               controller.forward();
             }, 
             child: Text('放大')
           ),
           ElevatedButton(
             onPressed: () {
               controller.reverse();
             }, 
             child: Text('缩小')
           ),
           ElevatedButton(
             onPressed: () {
               animation.addStatusListener((status) {
                 if (status == AnimationStatus.completed) {
                   // 反向执行动画
                   controller.reverse();
                 } else if (status == AnimationStatus.dismissed) {
                   // 正向执行动画
                   controller.forward();
                 }
               });
               controller.forward();
             }, 
             child: Text('重复')
           ),
           ElevatedButton(
             onPressed: () {
               controller.stop();
             }, 
             child: Text('停止')
           ),
           Icon(
             Icons.favorite,
             color: Colors.red,
             size: animation.value
           ),
           Opacity(
             opacity: controller.value,
             child: Text('Hello World')
           )
         ],
       ),
    );
  }

  
  void dispose() {
    // TODO: implement dispose
    super.dispose();
    controller.dispose();
  }
}

在这里插入图片描述
交织动画

  • What?
    • 交织动画是由多个单一动画叠加而成复杂动画
    • 例如:组件变化可能涉及高度、宽度、颜色、透明度、位置等等
    • 需要给每个动画设置时间间隔(Interval)
  • Transform (对组件进行矩阵变换)
    • 平移:Transform.translate()
    • 旋转: Transform.rotate
    • 缩放:Transform.scale()

在这里插入图片描述

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

class Home extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Stagger Animation"),
        leading: Icon(Icons.menu),
        actions: [
          Icon(Icons.settings)
        ],
        elevation: 0.0,
        centerTitle: true,
      ),
      body: AnimationDemo()
    );
  }
}

class AnimationDemo extends StatefulWidget {
  AnimationDemo({Key key}) : super(key: key);

  
  _AnimationDemoState createState() => _AnimationDemoState();
}

class _AnimationDemoState extends State<AnimationDemo> with SingleTickerProviderStateMixin {
  AnimationController controller;
  Animation animation;
  Animation sizeAnimation;
  Animation colorAnimation;
  Animation rotationAnimation;

  
  void initState() {
    // TODO: implement initState
    super.initState();

    // 1. 创建 AnimationController
    controller = AnimationController(
      duration: Duration(seconds: 3),
      vsync: this,
    );

    // 2. 创建动画
    animation = CurvedAnimation(
      parent: controller, 
      curve: Interval(0.0, 0.5)
    )..addListener(() {
      setState(() {
        
      });
      });

    // 3. 让动画反复运行
    animation.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        // 反向执行动画
        controller.reverse();
      } else if (status == AnimationStatus.dismissed) {
        // 正向执行动画
        controller.forward();
      }
    });

    // 4. 设置其他动画
    sizeAnimation = Tween(begin: 0.0, end: 200.0).animate(animation);
    colorAnimation = ColorTween(begin: Colors.yellow, end: Colors.red)
      .animate(CurvedAnimation(
        parent: controller, 
        curve: Interval(0.5, 0.8, curve: Curves.bounceIn)
      ))
      ..addListener(() { 
        setState(() {
          
        });
      });

    rotationAnimation = Tween(begin: 0.0, end: 2*pi).animate(
      CurvedAnimation(
        parent: controller, 
        curve: Interval(0.8, 1.0, curve: Curves.easeIn)
      )
    );
  }

  
  Widget build(BuildContext context) {
    return Center(
       child: Column(
         children: [
           ElevatedButton(
             onPressed: () {
              //  animation.addStatusListener((status) {
              //    if (status == AnimationStatus.completed) {
              //      // 反向执行动画
              //      controller.reverse();
              //    } else if (status == AnimationStatus.dismissed) {
              //      // 正向执行动画
              //      controller.forward();
              //    }
              //  });
               controller.forward();
             }, 
             child: Text('重复')
           ),
           ElevatedButton(
             onPressed: () {
               controller.stop();
             }, 
             child: Text('停止')
           ),
Opacity(
  opacity: controller.value,
  child: Transform.rotate(
    angle: rotationAnimation.value,
    child: Container(
      width: sizeAnimation.value,
      height: sizeAnimation.value,
      color: colorAnimation.value
    )
  )
)
         ],
       ),
    );
  }

  
  void dispose() {
    // TODO: implement dispose
    super.dispose();
    controller.dispose();
  }
}

二十一、Hero 动画

  • Hero 动画用来实现跨页面的动画效果
    • 在不同页面中,声明一个共享组件(Hero)
    • 由于共享组件在不同页面中的位置、外观等不同,路由切换时,形成动画效果
  • 如何实现
    • 在页面 A 中定义起始 Hero 组件(source hero),声明 tag
    • 在页面 B 中定义目标 Hero 组件(destination hero),绑定相同的 tag
    • 页面跳转时,通过 Navigator,传递 tag
  • Hero 组件
    • tag(路由切换时,共享组件的标记)
    • child (声明子组件)
import 'package:flutter/material.dart';
import 'ImageDetail.dart';

class Home extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Hero Animation"),
        leading: Icon(Icons.menu),
        actions: [
          Icon(Icons.settings)
        ],
        elevation: 0.0,
        centerTitle: true,
      ),
      body: HeroAnimation()
    );
  }
}

class HeroAnimation extends StatelessWidget {
  const HeroAnimation({Key key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.symmetric(vertical: 20),
      child: GridView.extent(
        maxCrossAxisExtent: 200.0,
        mainAxisSpacing: 20,
        children: List.generate(20, (index) {
          String imageURL = "https://picsum.photos/id/$index/300/400";
          return GestureDetector(
            onTap: () {
              Navigator.push(context, MaterialPageRoute(builder: (BuildContext ctx) {
                return ImageDetail(imageURL);
              }));
            },
            child: Hero(
              tag: imageURL, 
              child: Image.network(imageURL)
            )
          );
        })
      ),
    );
  }
}
import 'package:flutter/material.dart';

class ImageDetail extends StatelessWidget {
  final String imageURL;
  ImageDetail(this.imageURL);

  
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.black,
      body: Center(
        child: GestureDetector(
          onTap: () {
            // 调回去
            Navigator.pop(context);
          },
          child: Hero(
            tag: imageURL, 
            child: Image.network(
              imageURL,
              width: double.infinity,
              fit: BoxFit.cover
            )
          )
        )
      )
    );
  }
}

在这里插入图片描述

二十二、多语言(国际化)

  • 国际化(internationalization 简称 i18n)
    • 终端(手机)系统语言切换时, Flutter应用的跟随切换,
  • 内容
    • 组件(Widget)国际化
      • 例如:日历,弹窗等常用组件的国际化
    • 文本国际化(包括文本的顺序)
      • 自定义文本的国际化

多语言(国际化)-组件

  • 在 pubspec.yaml 中引入 flutter_localizations
    • 安装包: flutter pub get (VS Code 中保存自动安装)
  • 设置 MaterialApp
    • import ‘package:flutter_localizations/flutter_localizations.dart’;
    • localizationsDelegates(指定哪些组件需要进行国际化)
    • supportedlocales(指定要支持哪些语言)

在这里插入图片描述

在这里插入图片描述
多语言(国际化) -文本

  • 创建本地化类
    • CustomLocalizations
  • 创建本地化类的代理
    • CustomLocalizationsDelegate extends LocalizationsDelegate
      • isSupported(当前本地化,是否在有效的语言范围内
      • shouldReload(本地化重新构建时,是否调用 load 方法,加载本地化资源)
      • load(语言发生变更时,加载对应的本地化资源)
  • 使用本地化类
    • CustomLocalizations.delegate
      在这里插入图片描述
      在这里插入图片描述
      多语言(国际化)- 文本- 加载语言包
  • 检测当前语言
    • localeResolutionCallback
      • locale. languageCode(语言代码,例如:en、zh)
      • locale.countryCode(国家代码,例如:US,CN)
        在这里插入图片描述
  • 设置语言包
    • 创建语言文件
    • 在 pubspec.yaml 中配置语言资源
  • 异步加载语言包
    • 在 CustomLocalizations 中,添加 loadJSON() 方法
    • 在 CustomLocalizationsDelegate 中,调用 CustomLocalizations 的 loadJSON() 方法

在这里插入图片描述
在这里插入图片描述

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

class CustomLocalizations {
  final Locale locale;

  CustomLocalizations(this.locale);

  // static Map<String, Map<String, String>> _localizedValues = {
    // "en": {
    //   "title": "Home",
    //   "greet": "Hello",
    // },
  //   "zh": {
  //     "title": "首页",
  //     "greet": "你好",
  //   },
  // };

  Map<String, String> _localizedValues;

  Future<bool> loadJSON() async {
    String jsonString = await rootBundle.loadString('lang/${locale.languageCode}.json');
    Map<String, dynamic> jsonMap = json.decode(jsonString);

    _localizedValues = jsonMap.map((key, value) {
      return MapEntry(key, value.toString());
    });

    return true;
  }

  String t(String key) {
    // _localizedValues['zh']['title']
    // return _localizedValues[locale.languageCode][key];
    return _localizedValues[key];
  }

  static CustomLocalizations of(BuildContext context) {
    return Localizations.of(context, CustomLocalizations);
  }

  static CustomLocalizationsDelegate delegate = CustomLocalizationsDelegate();
}

class CustomLocalizationsDelegate extends LocalizationsDelegate<CustomLocalizations> {
  
  bool isSupported(Locale locale) {
    return ["en", "zh"].contains(locale.languageCode);
  }

  
  Future<CustomLocalizations> load(Locale locale) async {
    // return SynchronousFuture(CustomLocalizations(locale));
    CustomLocalizations localizations = CustomLocalizations(locale);
    await localizations.loadJSON();
    return localizations;
  }

  
  bool shouldReload(covariant LocalizationsDelegate<CustomLocalizations> old) {
    return false;
  }
}

二十三、多主题

  • 主题(UI风格、样式、皮肤)
  • 主题风格可通过 theme 来定义,从而实现整个 App 风格的统一
  • 一旦设置了主题,那么应用程序中的某些 Widget, 就会直接使用主题的样式
    组件
    ThemeData
    Brightness (Brightness.light | Brightness.dark)
    primaryColor | accentColor
    buttonTheme | cardTheme | iconTheme | textTheme
    Theme (声明局部主题)
    Theme.of(context) 获取上下文中的主题信息

多主题-适配终端

  • 声明不同的主题
    • CustomTheme
  • 使用主题import ‘CustomTheme.dart’;
    • theme: CustomTheme.lightTheme,
    • darkTheme: CustomTheme.darkTheme,
    • theme: ThemeData.light(),
    • darkTheme: ThemeData.dark(),
  • 查看效果
    • 模拟器中切换主题,Flutter 应用中查看效果

在这里插入图片描述

import 'package:flutter/material.dart';

class CustomTheme {
  // 公共样式
  static const double _CardBorderWidth = 20;
  static const double _CardElevation = 20;

  // 高亮主题
  static final ThemeData lightTheme = ThemeData(
    primaryColor: Colors.red,
    cardTheme: CardTheme(
      color: Colors.red[100],
      shape: Border.all(width: _CardBorderWidth, color: Colors.red),
      elevation: _CardElevation,
    )
  );

  // 黑暗主题
  static final ThemeData darkTheme = ThemeData(
    primaryColor: Colors.grey,
    cardTheme: CardTheme(
      color: Colors.grey[100],
      shape: Border.all(width: _CardBorderWidth, color: Colors.black45),
      elevation: _CardElevation,
    )
  );
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/176865.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Git使用Merge和Rebase区别及心得技巧

git rebase命令常常因为江湖上关于它是一种Git魔法命令的名声而导致Git新手对它敬而远之&#xff0c;但是事实上如果一个团队能够正确使用的话&#xff0c;它确实可以让生活变得更简单。在这篇文章中我们会比较git rebase和经常与之相提并论的git merge命令&#xff0c;并且在真…

【回望2022,走向2023】一个双非二本非科班的学生的旅途

目录 1.自我介绍 2.高考与暑假 梦想 幻灭 决心 暑假 3.大一上学期 4.奋进之路 5.展望未来 1.自我介绍 我是一个双非本科的大一学生&#xff0c;在2023年的新春之际&#xff0c;借着CSDN的这次年度总结活动&#xff0c;来好好回顾一下&#xff0c;2022这个平凡却又不乏…

css 2D转换

文章目录一、什么是2D转换二、rotate() 方法&#xff08;旋转&#xff09;三、translate() 方法&#xff08;位移&#xff09;四、scale() 方法&#xff08;缩放&#xff09;五、skew() 方法 &#xff08;倾斜&#xff09;一、什么是2D转换 在二维空间下对元素进行移动、缩放、…

面试官问我有没有分布式系统开发经验,我一脸懵圈…

目录 从单块系统说起团队越来越大&#xff0c;业务越来越复杂分布式出现&#xff1a;庞大系统分而治之分布式系统所带来的技术问题一句话总结&#xff1a;什么是分布式系统设计和开发经验补充说明&#xff1a;中间件系统及大数据系统 前言 现在有很多Java技术方向的同学在找工…

深度学习网络---YOLO系列

深度学习网络—YOLO yolov1&#xff08;仅适用一个卷积神经网络端到端地实现检测物体的目的&#xff09; 首先将输入图片resize到448448&#xff0c;然后送入CNN网络&#xff0c;最后处理预测的结果得到检测的目标&#xff1b;yolov1的具体思想是将全图划分为SS的格子&#xf…

结构型模式-外观模式

1.概述 有些人可能炒过股票&#xff0c;但其实大部分人都不太懂&#xff0c;这种没有足够了解证券知识的情况下做股票是很容易亏钱的&#xff0c;刚开始炒股肯定都会想&#xff0c;如果有个懂行的帮帮手就好&#xff0c;其实基金就是个好帮手&#xff0c;支付宝里就有许多的基…

智能的本质不是数据算法算力和知识

编者按&#xff1a;人机之间未解决的大部分问题不是统计问题&#xff0c;而是统计概率分布外的问题。人是自然的&#xff0c;又不是自然的&#xff0c;还是社会的&#xff0c;人类和机器都可以作为认知的载体&#xff0c;但认知的性质是不同的&#xff0c;一个是生命的认知&…

GA6-BGSM/GPRS模块介绍

GA6-BGSM/GPRS模块简介GA6-B是一个4频的GSM/GPRS模块&#xff0c;工作的频段为&#xff1a;EGSM 900MHz、 GSM850MHz和DCS1800, PCS1900。GA6-B支持GPRS multi-slot class 10/ class 8&#xff08;可选&#xff09;和 GPRS 编码格式CS-1, CS-2, CS-3 and CS-4。模块的尺寸只有2…

SelectPdf for .NET 22.0 Crack

SelectPdf for .NET 是一个专业的 PDF 库&#xff0c;可用于创建、编写、编辑、处理和读取 PDF 文件&#xff0c;而无需在 .NET 应用程序中使用任何外部依赖项。使用此 .NET PDF 库&#xff0c;您可以实现丰富的功能&#xff0c;从头开始创建 PDF 文件或完全通过 C#/VB.NET 处理…

python数据结构——栈、队列

python数据结构——栈、队列、树和算法栈栈的操作队列单端队列操作双端队列操作链表或者顺序表的使用场景&#xff1a; 当数据需要后进先出&#xff0c;来构建栈或者先进先出&#xff0c;构建队列时 栈或者队列之内的数据可以以顺序表或者链表的方式进行存储 python内置的数据…

Python基础学习 -- 模块与包

1、模块每一个py文件都可以理解为一个模块&#xff0c;模块可以增加项目的可读性2、新建一个名为算数.py文件&#xff0c;代码内容如下&#xff1a;print("算数模块被加载&#xff01;") def 加法(a,b):print(ab)3、新建一个main.py文件&#xff0c;调用模块的内容第…

Vue TypeScript 使用eval函数的坑

正常情况下&#xff0c;项目里不会用eval函数&#xff0c;但是万一要调用一个全局的js库&#xff0c;就需要用eval做些骚操作&#xff0c;这个时候编译会提示&#xff1a; is strongly discouraged as it poses security risks and may cause issues with minification. 警告是…

Java多线程(二)——ReentrantLock源码解析(补充1——从AQS中唤醒的线程)

ReentrantLock源码解析&#xff08;补充1&#xff09; 上一章仅介绍了 ReentrantLock 的常用方法以及公平锁、非公平锁的实现。这里对上一章做一些补充。主要是&#xff1a; AQS 中阻塞的线程被唤醒后的执行流程 &#xff08;本篇讲述&#xff09; 可打断的锁 lock.lockInter…

【QT5.9】与MFC对比学习笔记-感悟篇2【2023.01.23】

是对QT的分析&#xff0c;不仅局限于QT。 二者区别 天下文章一大抄&#xff0c;技术也一样。MFC是对Windows系统API进行的封装&#xff0c;是以视类与文档类为核心的框架设计。微软20年前就已经把MVC玩的很6了&#xff0c;还有控件、动态库等等技术都是微软爸爸先搞出来的。若…

Kubernetes:认识 K8s开源 Web/桌面 客户端工具 Headlamp

写在前面 分享一个 k8s 客户端开源项目 Headlamp 给小伙伴博文内容涉及&#xff1a; Headlamp 桌面/集群 Web 端安装启动导入集群简单查看集群信息 理解不足小伙伴帮忙指正 我所渴求的&#xff0c;無非是將心中脫穎語出的本性付諸生活&#xff0c;為何竟如此艱難呢 ------赫尔曼…

第八层:模板

文章目录前情回顾模板模板的概念模板的特点模板分类函数模板作用语法函数模板的使用注意事项普通函数和函数模板的区别普通函数和函数模板的调用规则优先调用普通函数空模板强调函数模板函数模板可以发生重载函数模板产生更好的匹配时模板的局限性类模板作用语法类模板实例化对…

Redis在秒杀场景的作用

秒杀业务特点&#xff1a;限时限量&#xff0c;业务系统要处理瞬时高并发请求&#xff0c;Redis是必需品。 秒杀可分成秒杀前、秒杀中和秒杀后三阶段&#xff0c;每个阶段的请求处理需求不同&#xff0c;Redis具体在秒杀场景的哪个环节起到作用呢&#xff1f; 1 秒杀负载特征…

Java-数据结构-二叉树<三>

承接上文&#xff1a; Java-数据结构-二叉树&#xff1c;一&#xff1e; Java-数据结构-二叉树&#xff1c;二&#xff1e; 一. 二叉树的简单介绍 见Java-数据结构-二叉树&#xff1c;一&#xff1e; 二. 二叉树的典型代码实现 见Java-数据结构-二叉树&#xff1c;一&#x…

4. RNN网络架构解读|词向量模型|模型整体框架|训练数据构建|CBOW和Skip-gram模型|负采样方案

文章目录RNN网络架构解读词向量模型模型整体框架训练数据构建CBOW和Skip-gram模型负采样方案RNN网络架构解读 递归神经网络实际上就是普通的神经网络的部分进行修改更新&#xff1a;实际上常用于时间序列的更新。或者就是自然处理中 X序列代表着时间序列&#xff0c;x0是一个时…

linux入门---云服务器购买和登陆

目录标题云服务器选择云服务器购买xshell下载如何登陆云服务器Linux的新建与删除新建删除云服务器选择 学习linux的时候云服务器是一个非常重要的工具&#xff0c;那么我们在购买云服务器的时候有很多选择比如说&#xff1a;华为云&#xff0c;腾讯云&#xff0c;阿里云等等&a…