【Flutter】Flutter 照片墙 ( Center 组件 | Wrap 组件 | ClipRRect 组件 | Stack 组件 | Positioned 组件 | 按钮组合组件 )(三)

简介: 【Flutter】Flutter 照片墙 ( Center 组件 | Wrap 组件 | ClipRRect 组件 | Stack 组件 | Positioned 组件 | 按钮组合组件 )(三)

七、完整代码示例


完整代码示例 :


import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
void main() {
  runApp(MyApp());
}
class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: '拍照示例'),
    );
  }
}
class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;
  @override
  _MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
  /// 需要导入 dart:io 库
  /// import 'dart:io';
  File _image;
  /// 存放获取的图片集合, 初始化时为空
  List<File> _images = [];
  // 图片获取引擎
  final picker = ImagePicker();
  /// 获取摄像头图像的方法
  Future getImageFromCamera() async {
    /// 菜单按钮消失
    Navigator.pop(context);
    /// 需要导入 image_picker.dart 包
    /// import 'package:image_picker/image_picker.dart';
    final pickedFile =
    await picker.getImage(source: ImageSource.camera);
    setState(() {
      if (pickedFile != null) {
        //_image = File(pickedFile.path);
        /// 添加到图片文件集合中
        _images.add(File(pickedFile.path));
      } else {
        print('No image selected.');
      }
    });
  }
  /// 获取相册中的图像
  Future getImageFromGallery() async {
    /// 菜单按钮消失
    Navigator.pop(context);
    /// 需要导入 image_picker.dart 包
    /// import 'package:image_picker/image_picker.dart';
    final pickedFile =
    await picker.getImage(source: ImageSource.gallery);
    setState(() {
      if (pickedFile != null) {
        //_image = File(pickedFile.path);
        /// 添加到图片文件集合中
        _images.add(File(pickedFile.path));
      } else {
        print('No image selected.');
      }
    });
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Wrap(
          spacing: 5,
          runSpacing: 5,
          children:
          // 遍历 从相册选择的照片 或 相机拍摄的照片
          _images.map((file){
            // 每个照片都生成一个帧布局
            // 照片填充整个布局, 右上角放置一个关闭按钮
            return Stack(
              children: <Widget>[
                // 设置底部的大图片
                ClipRRect(
                  // 设置圆角半径 5 像素
                  borderRadius: BorderRadius.circular(5),
                  // 设置图片
                  child: Image.file(file, width: 120, height: 90, fit: BoxFit.fill,),
                ),
                // 设置右上角的关闭按钮
                Positioned(
                  // 距离右侧 5
                  right: 5,
                  // 距离顶部 5
                  top: 5,
                  // 手势检测器组件
                  child: GestureDetector(
                    // 点击事件
                    onTap: (){
                      setState(() {
                        // 从图片集合中移除该图片
                        _images.remove(file);
                      });
                    },
                    // 右上角的删除按钮
                    child: ClipOval(
                      child: Container(
                        padding: EdgeInsets.all(3),
                        // 背景装饰
                        decoration: BoxDecoration(color: Colors.black),
                        // 图标, 20 像素 , 白色 , 关闭按钮
                        child: Icon(Icons.close, size: 20, color: Colors.white,),
                      ),
                    ),
                  ),
                )
              ],
            );
            /// 注意这里要转为 List 类型 , <Widget>[]
          }).toList()
          ,
        )
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          /// 浮动按钮点击事件
          /// 点击浮动按钮 , 弹出一个菜单
          /// 菜单有两个按钮 , 分别是 拍照 / 选择图片
          showModalBottomSheet(
              context: context,
              builder: (context) {
                return Container(
                  // 设置该弹出的组件高度 200 像素
                  height: 200,
                  child: Column(
                    children: <Widget>[
                      // 拍照按钮
                      GestureDetector(
                        child: ListTile(
                          // 相机图标
                          leading: Icon(Icons.camera_alt),
                          title: Text("拍照"),
                          /// 按钮点击事件
                          onTap: (){
                            // 调用 getImage 方法 , 调出相机拍照
                            getImageFromCamera();
                          },
                        ),
                      ),
                      // 相册按钮
                      GestureDetector(
                        child: ListTile(
                          // 相册图标
                          leading: Icon(Icons.photo_library_outlined),
                          title: Text("相册"),
                          /// 按钮点击事件
                          onTap: (){
                            // 调用 getImageFromGallery 方法 , 调出相册
                            getImageFromGallery();
                          },
                        ),
                      ),
                    ],
                  ),
                );
              });
        },
        tooltip: 'Pick Image',
        child: Icon(Icons.add_a_photo),
      ),
    );
  }
  _generateImageWidgets() {
  }
}




运行效果 : 拍照获取第一个图片 , 从相册中选择第二章图片 , 然后删除第一张图片 ;




image.png




八、相关资源


参考资料 :


Flutter 官网 : https://flutter.dev/

Flutter 插件下载地址 : https://pub.dev/packages

Flutter 开发文档 : https://flutter.cn/docs ( 强烈推荐 )

官方 GitHub 地址 : https://github.com/flutter

Flutter 中文社区 : https://flutter.cn/

Flutter 实用教程 : https://flutter.cn/docs/cookbook

Flutter CodeLab : https://codelabs.flutter-io.cn/

Dart 中文文档 : https://dart.cn/

Dart 开发者官网 : https://api.dart.dev/

Flutter 中文网 ( 非官方 , 翻译的很好 ) : https://flutterchina.club/ , http://flutter.axuer.com/docs/

Flutter 相关问题 : https://flutterchina.club/faq/ ( 入门阶段推荐看一遍 )


博客源码下载 :


GitHub 地址 : https://github.com/han1202012/flutter_photo ( 随博客进度一直更新 , 有可能没有本博客的源码 )


博客源码快照 : https://download.csdn.net/download/han1202012/15978310 ( 本篇博客的源码快照 , 可以找到本博客的源码 )


目录
相关文章
|
17天前
|
容器
Flutter &&鸿蒙next中的 Stack 和 Positioned 用法详解
在 Flutter 中,Stack 和 Positioned 是创建层叠布局和灵活定位元素的常用组件。Stack 可以将多个子组件叠加在一起,允许子组件相互重叠;Positioned 用于在 Stack 内部精确控制子组件的位置。本文详细介绍了它们的基本用法、属性和应用场景,包括动画、弹出层和悬浮按钮等。
67 1
|
19天前
|
容器
深入理解 Flutter 鸿蒙版的 Stack 布局:适配屏幕与层叠样式布局
Flutter 的 Stack 布局组件允许你将多个子组件层叠在一起,实现复杂的界面效果。本文介绍了 Stack 的基本用法、核心概念(如子组件层叠、Positioned 组件和对齐属性),以及如何使用 MediaQuery 和 LayoutBuilder 实现响应式设计。通过示例展示了照片展示与文字描述、动态调整层叠布局等高级用法,帮助你构建更加精美和实用的 Flutter 应用。
107 2
|
19天前
Flutter 自定义组件继承与调用的高级使用方式
本文深入探讨了 Flutter 中自定义组件的高级使用方式,包括创建基本自定义组件、继承现有组件、使用 Mixins 和组合模式等。通过这些方法,您可以构建灵活、可重用且易于维护的 UI 组件,从而提升开发效率和代码质量。
115 1
|
19天前
|
开发工具 UED
Flutter&鸿蒙next中封装一个输入框组件
本文介绍了如何创建一个简单的Flutter播客应用。首先,通过`flutter create`命令创建项目;接着,在`lib`目录下封装一个自定义输入框组件`CustomInput`;然后,在主应用文件`main.dart`中使用该输入框组件,实现简单的UI布局和功能;最后,通过`flutter run`启动应用。本文还提供了后续扩展建议,如状态管理、网络请求和UI优化。
97 1
|
23天前
|
Dart UED
Flutter用户交互组件
Flutter用户交互组件
20 2
|
18天前
|
开发工具
Flutter&鸿蒙next中封装一个列表组件
Flutter&鸿蒙next中封装一个列表组件
32 0
|
容器
Flutter创建圆圈图标按钮
我找不到任何显示如何创建IconButton类似于的圆的示例FloatingActionButton。任何人都可以建议创建一个自定义按钮的方式/需要什么FloatingActionButton吗? 我认为RawMaterialButton更适合。
352 0
|
1月前
|
Android开发 iOS开发 容器
鸿蒙harmonyos next flutter混合开发之开发FFI plugin
鸿蒙harmonyos next flutter混合开发之开发FFI plugin
|
1月前
|
开发者
鸿蒙Flutter实战:07-混合开发
鸿蒙Flutter混合开发支持两种模式:1) 基于har包,便于主项目开发者无需关心Flutter细节,但不支持热重载;2) 基于源码依赖,利于代码维护与热重载,需配置Flutter环境。项目结构包括AppScope、flutter_module等目录,适用于不同开发需求。
74 3
|
17天前
|
传感器 开发框架 物联网
鸿蒙next选择 Flutter 开发跨平台应用的原因
鸿蒙(HarmonyOS)是华为推出的一款旨在实现多设备无缝连接的操作系统。为了实现这一目标,鸿蒙选择了 Flutter 作为主要的跨平台应用开发框架。Flutter 的跨平台能力、高性能、丰富的生态支持和与鸿蒙系统的良好兼容性,使其成为理想的选择。通过 Flutter,开发者可以高效地构建和部署多平台应用,推动鸿蒙生态的快速发展。
130 0