Flutter技术学习

时间:2024-10-15 07:23:21

以下内容更适用于 不拘泥于教程学习,而是从简单项目入手的初学者。

在开始第一个项目之前,我们先要了解 两个概念。

Widget 和 属性

  • Widget 是用户界面的基本构建块,可以是任何 UI 元素。
  • 属性 是 widget 类中定义的变量,用于配置和定制 widget 的外观和行为。
  • 当你创建一个 widget 时,可以通过构造函数传递参数来设置这些属性,从而定制 widget 的表现。
  • Widget包含属性

UI 元素:Text、Image、Container、Column、AppBar 、布局等等

外观:颜色、大小、形状等等

行为:点击事件、动画、数据更新等等

vscode创建默认项目(这里默认前置工作都已经准备好了)

1. Hellow world

替换lib\main.dart

import 'package:flutter/material.dart';

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

// 定义无状态组件
class MyApp extends StatelessWidget{
  const MyApp({super.key});

  @override
  Widget build(BuildContext context){
    return MaterialApp(
      // 初始标题
      title: 'Welcome to flutter',
      // 初始页面
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Welcome to flutter'),
        ),
        // 居中   一个子widget
        body: const Center(
          child: Text(
          'Hellow World', 
          // 字体样式
          style: TextStyle(
            // 字体颜色
            color: Colors.green,
          )),
        ),
        // 垂直排列 多个子widget
        // body: Column(
        //   // 只能定义一个children属性 可包含 一个wedget或者wedget列表
        //   children: [
        //     const Text("Hello World"),
        //     Image.network("https://gd-hbimg.huaban.com/88b49ee5dc63c49f26d984a71ce061729f27070c3124c-jZyeMc_fw1200webp",fit: BoxFit.cover),
        //     const Center(
        //       child: Text("Hello world"),
        //     ),
        //   ],
          
        // ),
      ),
    );
  }
}

flutter run 命令运行 

2. 使用依赖包(package) 

包管理:https://pub.dev/

 打开包管理网站 搜索 english_words 

替换lib\main.dart   终端运行  flutter packages get  获取依赖包 

import 'package:flutter/material.dart';
// 引入 英文单词 包
import 'package:english_words/english_words.dart';

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

// 定义无状态组件
class MyApp extends StatelessWidget{
  
  const MyApp({super.key});
  

  @override
  Widget build(BuildContext context){
    
    return MaterialApp(
      // 初始标题
      title: 'Welcome to flutter',
      // 初始页面
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Welcome to flutter'),
        ),
        // 居中   一个子widget
        body: Center(
          child: Text(
          generateWordPairs().take(10).map((pair) => pair.asPascalCase).join('\n'), 
          // 字体样式
          style: TextStyle(
            // 字体颜色
            color: Colors.green,
          )),
        ),
      ),
    );
  }
}

保存 终端 输入r  热重载运行 

3. 使用有状态的部件(Stateful widget) 

替换lib\main.dart

import 'package:flutter/material.dart';

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

// 定义有状态组件

class MyApp extends StatefulWidget{
  @override
  _MyAppState createState() => _MyAppState();

}

// 管理组件状态
class _MyAppState extends State<MyApp>{
  // 初始化变量
  int _counter = 0;

  // 定义一个方法
  void _incrementCounter(){
    // 触发组件更新
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '计数器',
      home: Scaffold(
      appBar: AppBar(
        title: const Text("计数器"),
      ),
      body: Center(
        child: Text(
          // 状态改变时自动更新
          '你点击了 $_counter 次'
        ),
      ),
      // 浮动动作按钮
      floatingActionButton: FloatingActionButton(
        // 按钮被按下时调用 _incrementCounter方法
        onPressed: _incrementCounter,
        // 按钮的提示文本
        tooltip: "Increment",  
        // 按钮上的图标
        child: const Icon(Icons.add),
      ),
    )
    );
  }
}

保存 终端 输入r  热重载运行 

4. 创建一个无限滚动的 ListView  

替换lib\main.dart

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

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

// 无状态组件
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '无限滚动列表',
      // 主页为 RandomWords 组件
      home: RandomWords(),
    );
  }
}

// RandomWords 类  有状态组件
class RandomWords extends StatefulWidget {
  @override
  _RandomWordsState createState() => _RandomWordsState();
}

//  _RandomWordsState 组件,是RandomWords的状态
class _RandomWordsState extends State<RandomWords> {
  //  final声明的变量,引用是不可变的,也就是不可重新赋值;内容是可变的,也就是可向列表内容添加或删除

  // 声明列表并指定集合中元素的类型为WordPair
  final _suggestions = <WordPair>[];
  // 常量 设置字体样式
  final _biggerFont = const TextStyle(fontSize: 18.0);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('无限滚动列表'),
      ),
      //  body部分单独抽出,避免嵌套过多 
      body: _buildSuggestions(),
    );
  }

  Widget _buildSuggestions(){
    // 构建无限滚动列表。滑动时触发
    return ListView.builder(
      // 内边距
      padding: const EdgeInsets.all(16.0),
      // 回调函数,用于生成每个列表项
      itemBuilder: (context,i){
        print('当前索引:$i');
        // 如果是奇数 返回分割线
        if(i.isOdd) return const Divider();

        //  i 除以 2, 并向下取整
        final index = i ~/ 2;

        print('当前实际单词对数量:$index');
        if(index >= _suggestions.length){
          _suggestions.addAll(generateWordPairs().take(10));
        }
        print('列表内容:$_suggestions');
        return _buildRow(_suggestions[index]);
      }
    );
  }

  Widget _buildRow(WordPair pair){
    return ListTile(
      title: Text(
        // 将两个单词组合成PascalCase 格式的字符串
        pair.asPascalCase,
        style: _biggerFont,
      ),
    );
  }
}

保存 终端 输入r  热重载运行  

 

5. 添加交互