Flutter控件:自定义 Widget、MaterialApp、ListView

277 阅读3分钟

一、hello_flutter

先创建一个App工程,命名hello_flutter

Flutter 基础库

Flutter中做UI开发时,需要导入下面的库:

import 'package:flutter/material.dart';

iOS中的UI控件是 UIView,而Flutter中的UI控件都是widget(小部件)。

第一个 Flutter项目

iOS中开始执行视图是在window上,而Flutter中开始执行视图需要调用runApp()函数,函数中放widget控件。

示例代码:

import 'package:flutter/material.dart';

void main() {
  runApp(
    const Center( // Center 是一个widget
      child: Text( // Text 是一个widget
          'hello world',
          textDirection: TextDirection.ltr,
      ),
    )
  );
}

查看显示效果:

image.png

二、自定义 Widget

Widget 有两大类:有状态(stateful)和无状态(stateless),先创建一个无状态的示例:

import 'package:flutter/material.dart';

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

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return const Center(
      child: Text(
        'hello world !!',
        textDirection: TextDirection.ltr,
      ),
    );
  }
}
  • 调用 MyWidget 构造方法时,就会调用build函数,在 build 函数中写我们自定义的 Widget。

image.png

三、文字样式

文字样式用的是TextStyle类,示例代码如下:

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return const Center(
      child: Text(
        'hello world !!',
        textDirection: TextDirection.ltr,
        style: TextStyle(
          fontSize: 40,
          fontWeight: FontWeight.bold,
          color: Colors.red,
        ),
      ),
    );
  }
}

查看效果:

image.png

四、MaterialApp

4.1 Home

MaterialApp 也是一个 Widget,它是 stateful 类型的:

class MaterialApp extends StatefulWidget {
    ...
}

看示例代码:

import 'package:flutter/material.dart';

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

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyWidget(),
    );
  }
}

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return const Center(
      child: Text(
        'hello world !!',
        textDirection: TextDirection.ltr,
        style: TextStyle(
          fontSize: 40,
          fontWeight: FontWeight.bold,
          color: Colors.red,
        ),
      ),
    );
  }
}

查看运行效果:

image.png

  • 看运行效果只是多了一个debug的标记,和两条黄色的横线。

4.2 Scaffold

看示例代码:

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Flutter Demo'),
        ),
        body: MyWidget(),
      ),
    );
  }
}

查看运行效果:

image.png

五、初探 ListView

5.1 模型数据创建

执行操作:创建model目录 -> 创建car.dart文件:

image.png

创建Car类:

class Car {
  const Car({this.name,this.imageUrl});
  final String? name;
  final String? imageUrl;
}

并添加如下代码,给datas数组赋值:

final List<Car> datas = [
  const Car(
    name: '保时捷918 Spyder',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-7d8be6ebc4c7c95b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  const Car(
    name: '兰博基尼Aventador',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-e3bfd824f30afaac?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  const Car(
    name: '法拉利Enzo',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-a1d64cf5da2d9d99?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  const Car(
    name: 'Zenvo ST1',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-bf883b46690f93ce?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  const Car(
    name: '迈凯伦F1',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-5a7b5550a19b8342?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  const Car(
    name: '萨林S7',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-2e128d18144ad5b8?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  const Car(
    name: '科尼赛克CCR',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-01ced8f6f95219ec?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  const Car(
    name: '布加迪Chiron',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-7fc8359eb61adac0?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  const Car(
    name: '轩尼诗Venom GT',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-d332bf510d61bbc2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  const Car(
    name: '西贝尔Tuatara',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-3dd9a70b25ae6bc9?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  )
];

5.2 ListView 显示文本

main.dart中添加ListView相关代码如下:

import 'package:flutter/material.dart';
import 'model/car.dart';

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

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Home(),
    );
  }
}

class Home extends StatelessWidget {
  Widget _itemForRow(BuildContext context, int index) {
    return Text(datas[index].name!);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter Demo'),
      ),
      body: ListView.builder(
          itemBuilder: _itemForRow,
          itemCount: datas.length,
      ),
    );
  }
}

查看显示效果:

image.png

5.3 ListView 显示图片

修改_itemForRow函数,这里用了一个新控件Container

Widget _itemForRow(BuildContext context, int index) {
  return Container(
    color: Colors.white,
    margin: const EdgeInsets.all(10),
    child: Image.network(datas[index].imageUrl!),
  );
}

查看显示效果:

image.png

5.4 ListView 显示图片和文字

接下来把文字也添加进来
组件的排列有三种方式:1、横着 2、竖着 3、叠着。

先看下竖着的示例代码,修改_itemForRow函数:

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Home(),
    );
  }
}

class Home extends StatelessWidget {
  Widget _itemForRow(BuildContext context, int index) {
    return Container(
      color: Colors.white,
      margin: const EdgeInsets.all(10),
      // child: Image.network(datas[index].imageUrl!),
      child: Column(
        children: [
          Image.network(datas[index].imageUrl!),
          const SizedBox(
              height: 10
          ),
          Text(
              datas[index].name!,
              style: const TextStyle(
                fontWeight: FontWeight.w800,
                fontSize: 18.0,
                fontStyle: FontStyle.italic,
              ),
          ),
        ],
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // backgroundColor: Colors.red[100],
      appBar: AppBar(
        title: const Text('Flutter Demo'),
      ),
      body: ListView.builder(
        itemBuilder: _itemForRow,
        itemCount: datas.length,
      ),
    );
  }
}

查看显示效果:

image.png