您的位置:

Flutter图片详解

一、Flutter图片按钮

在Flutter中,图片按钮是一种非常常见的视觉组件。通过使用InkWell或GestureDetector包裹图片,就可以实现点击事件。同时,我们可以通过设置不同的属性来自定义按钮的样式。

GestureDetector(
  onTap: () {
    // 点击事件
  },
  child: Image.asset(
    'assets/images/button.png',
    width: 120,
    height: 60,
    fit: BoxFit.cover,
    alignment: Alignment.center,
  ),
)

二、Flutter图片加载失败显示默认图片

在网络请求或本地图片加载时,如果图片不存在或加载失败,我们可以设置一张默认图片来代替。

Image.network(
  'http://www.example.com/404.jpg',
  width: 200,
  height: 200,
  fit: BoxFit.cover,
  alignment: Alignment.center,
  errorBuilder: (BuildContext context, Object exception, StackTrace? stackTrace) {
    return Image.asset('assets/images/default.png');
  },
)

三、Flutter图片加载失败

在网络请求的图片加载时,如果网络不稳定或服务器宕机等异常情况,图片可能会加载失败。我们可以通过设置errorBuilder属性来自定义加载失败时的样式。

Image.network(
  'http://www.example.com/image.jpg',
  width: 200,
  height: 200,
  fit: BoxFit.cover,
  alignment: Alignment.center,
  errorBuilder: (BuildContext context, Object exception, StackTrace? stackTrace) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Icon(
          Icons.broken_image,
          size: 60,
          color: Colors.grey[400],
        ),
        SizedBox(height: 10),
        Text(
          '图片加载失败',
          style: TextStyle(
            color: Colors.grey[400],
            fontSize: 16,
          ),
        ),
      ],
    );
  },
)

四、Flutter图片无法铺满

在设置图片长宽时,如果图片的长宽比与容器不一致,那么图片可能无法完全铺满容器。我们可以通过调整fit属性来解决这个问题。

Image.network(
  'http://www.example.com/image.jpg',
  width: double.infinity, // 设置宽度为容器宽度
  height: 200,
  fit: BoxFit.fill, // 填充整个容器
  alignment: Alignment.center,
)

五、Flutter图片拉伸比例

拉伸比例指在填充容器时,图片长宽比是否改变。fit属性中的scaleDown和none值表示不改变比例,而cover和fill值则表示改变比例。

Image.network(
  'http://www.example.com/image.jpg',
  width: 200,
  height: 200,
  fit: BoxFit.cover,
  alignment: Alignment.center,
)

六、Flutter图片变圆角

我们可以通过使用ClipRRect组件将图片切成圆角。

ClipRRect(
  borderRadius: BorderRadius.circular(10),
  child: Image.network(
    'http://www.example.com/image.jpg',
    width: 200,
    height: 200,
    fit: BoxFit.cover,
    alignment: Alignment.center,
  ),
)

七、Flutter图片列表

在开发中,我们经常需要展示多张图片,这时我们可以使用ListView或GridView等滚动组件来实现图片列表。

GridView.builder(
  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
    crossAxisCount: 3,
    crossAxisSpacing: 10,
    mainAxisSpacing: 10,
    childAspectRatio: 1,
  ),
  itemBuilder: (BuildContext context, int index) {
    return Image.network(
      'http://www.example.com/image_$index.jpg',
      fit: BoxFit.cover,
      alignment: Alignment.center,
    );
  },
)

八、Flutter图片上传控件

在Flutter中实现图片上传控件比较简单。我们可以使用Flutter自带的ImagePicker组件来控制相册或相机。

File? _imageFile;

Future _getImageFromGallery() async {
  final pickedFile = await ImagePicker().getImage(source: ImageSource.gallery);
  setState(() {
    _imageFile = File(pickedFile!.path);
  });
}

Future
    _getImageFromCamera() async {
  final pickedFile = await ImagePicker().getImage(source: ImageSource.camera);
  setState(() {
    _imageFile = File(pickedFile!.path);
  });
}

Column(
  children: [
    ElevatedButton(
      onPressed: _getImageFromGallery,
      child: Text('从相册选择'),
    ),
    ElevatedButton(
      onPressed: _getImageFromCamera,
      child: Text('拍照上传'),
    ),
    if (_imageFile != null) Image.file(_imageFile!),
  ],
)

   
  

九、Flutter图片列表内存溢出

在展示大量图片时,由于内存限制,可能会发生内存溢出的情况。我们可以使用Flutter自带的CachedNetworkImage组件来避免内存溢出问题。

CachedNetworkImage(
  imageUrl: 'http://www.example.com/image.jpg',
  fit: BoxFit.cover,
  alignment: Alignment.center,
  placeholder: (context, url) => CircularProgressIndicator(),
  errorWidget: (context, url, error) => Icon(Icons.error),
)

十、Flutter图片视频编辑选取

在视频编辑时,我们可以使用Flutter自带的video_player和flutter_ffmpeg组件来选择视频并提取封面。

Future _pickVideoAndThumbnail() async {
  final pickedFile = await ImagePicker().getVideo(source: ImageSource.gallery);
  if (pickedFile != null) {
    final thumbnailPath = await _extractThumbnail(pickedFile.path);
    setState(() {
      _videoFile = File(pickedFile.path);
      _thumbnailFile = File(thumbnailPath);
    });
  }
}

Future
    _extractThumbnail(String videoPath) async {
  final thumbnailPath = '${(await getTemporaryDirectory()).path}/thumbnail.jpg';
  await FlutterFFmpeg().execute(
    '-i $videoPath -ss 00:00:01.000 -vframes 1 $thumbnailPath',
  );
  return thumbnailPath;
}

Column(
  children: [
    ElevatedButton(
      onPressed: _pickVideoAndThumbnail,
      child: Text('选择视频'),
    ),
    if (_thumbnailFile != null) Image.file(_thumbnailFile!),
    if (_videoFile != null) Text(_videoFile!.path),
  ],
)