Flutter报错:命名参数'image'未定义,求助相机图片替换代码位置
问题描述
我需要代码帮助,不清楚该在scan_screen.dart的哪个位置放置image: DecorationImage(image: FileImage(imageFile!)代码。我跟着《Pick Images from Gallery and Camera in Flutter (Quality Compression)》教程,想用相机拍摄的图片替换imgRectangle2362,但遇到Flutter报错:The named parameter 'image' isn't defined。
相关代码
scan_screen.dart
import 'dart:io'; import 'controller/scan_controller.dart'; import 'package:flutter/material.dart'; import 'package:grabbit/core/app_export.dart'; import 'package:image_picker/image_picker.dart'; import 'package:grabbit/widgets/custom_button.dart'; class ScanScreen extends StatefulWidget { const ScanScreen({Key? key}) : super(key: key); @override State<ScanScreen> createState() => _ScanScreenState(); } class _ScanScreenState extends State<ScanScreen> { File? imageFile; @override Widget build(BuildContext context) { return SafeArea( child: Scaffold( backgroundColor: ColorConstant.whiteA700, body: Container( width: size.width, child: SingleChildScrollView( child: Container( child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.end, children: [ Container( height: getVerticalSize(434.00), width: getHorizontalSize(326.00), margin: getMargin(left: 17, top: 135, right: 17), child: Stack( alignment: Alignment.topCenter, children: [ Align( alignment: Alignment.center, child: Container( height: getVerticalSize(434.00), width: getHorizontalSize(325.00), margin: getMargin(left: 1), child: Card( clipBehavior: Clip.antiAlias, elevation: 0, margin: EdgeInsets.all(0), color: ColorConstant.bluegray100, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(getHorizontalSize(15.00)), ), child: Stack( children: [ Align( alignment: Alignment.bottomCenter, child: Padding( padding: getPadding(left: 121, top: 27, right: 121, bottom: 27), child: CommonImageView( imagePath: ImageConstant.imgCameraicon, height: getVerticalSize(77.00), width: getHorizontalSize(82.00), ), ), ), ], ), ), ), ), Align( alignment: Alignment.topCenter, child: Padding( padding: getPadding(top: 26, right: 1, bottom: 26), child: CommonImageView( image: DecorationImage( image: FileImage(imageFile!), fit: BoxFit.cover ), imagePath: ImageConstant.imgRectangle2362, height: getVerticalSize(281.00), width: getHorizontalSize(325.00), ), ), ), ], ), ), CustomButton( width: 267, text: "Next", margin: getMargin(left: 17, top: 135, right: 17, bottom: 20), ), ], ), ), ), ), ), ); } onTapImgCameraicon() async { await PermissionManager.askForPermission(Permission.camera); await PermissionManager.askForPermission(Permission.storage); List<String?>? imageList = []; //TODO: Permission - use imageList for using selected images await FileManager().showModelSheetForImage(getImages: (value) async { imageList = value; }); } void getImage({required ImageSource source}) async { final file = await ImagePicker().pickImage( source: source, maxWidth: 640, maxHeight: 480, imageQuality: 70 //0 - 100 ); if (file?.path != null) { setState(() { imageFile = File(file!.path); }); } } } void onTap() { Get.toNamed(AppRoutes.homepageScreen); }
common_image_view.dart
// ignore_for_file: must_be_immutable import 'dart:io'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; class CommonImageView extends StatelessWidget { ///[url] is required parameter for fetching network image String? url; String? imagePath; String? svgPath; File? file; double? height; double? width; final BoxFit fit; final String placeHolder; ///a [CommonNetworkImageView] it can be used for showing any network images /// it will shows the placeholder image if image is not found on network CommonImageView({ this.url, this.imagePath, this.svgPath, this.file, this.height, this.width, this.fit = BoxFit.fill, this.placeHolder = 'assets/images/image_not_found.png', }); @override Widget build(BuildContext context) { return _buildImageView(); } Widget _buildImageView() { if (svgPath != null && svgPath!.isNotEmpty) { return Container( height: height, width: width, child: SvgPicture.asset( svgPath!, height: height, width: width, fit: fit, ), ); } else if (file != null && file!.path.isNotEmpty) { return Image.file( file!, height: height, width: width, fit: fit, ); } else if (url != null && url!.isNotEmpty) { return CachedNetworkImage( height: height, width: width, fit: fit, imageUrl: url!, placeholder: (context, url) => Container( height: 30, width: 30, child: LinearProgressIndicator( color: Colors.grey.shade200, backgroundColor: Colors.grey.shade100, ), ), errorWidget: (context, url, error) => Image.asset( placeHolder, height: height, width: width, fit: fit, ), ); } else if (imagePath != null && imagePath!.isNotEmpty) { return Image.asset( imagePath!, height: height, width: width, fit: fit, ); } return SizedBox(); } }
错误原因
你错误地给自定义组件CommonImageView传入了image参数,但该组件的构造函数并没有这个参数。CommonImageView是通过file参数来接收本地文件图片的,你混淆了它和Flutter原生DecorationImage的用法,导致参数不匹配报错。
解决方案
1. 修正CommonImageView调用逻辑
修改scan_screen.dart中顶部的CommonImageView代码,根据imageFile是否为空切换显示内容:
Align( alignment: Alignment.topCenter, child: Padding( padding: getPadding(top: 26, right: 1, bottom: 26), child: CommonImageView( // 有拍摄图片时传入file参数 file: imageFile, // 无图片时显示默认图 imagePath: imageFile == null ? ImageConstant.imgRectangle2362 : null, height: getVerticalSize(281.00), width: getHorizontalSize(325.00), ), ), ),
2. 给相机图标添加拍照触发事件
让底部的相机图标点击后调用getImage方法打开相机:
Align( alignment: Alignment.bottomCenter, child: Padding( padding: getPadding(left: 121, top: 27, right: 121, bottom: 27), child: GestureDetector( onTap: () => getImage(source: ImageSource.camera), child: CommonImageView( imagePath: ImageConstant.imgCameraicon, height: getVerticalSize(77.00), width: getHorizontalSize(82.00), ), ), ), ),
3. 完整修改后的scan_screen.dart代码
import 'dart:io'; import 'controller/scan_controller.dart'; import 'package:flutter/material.dart'; import 'package:grabbit/core/app_export.dart'; import 'package:image_picker/image_picker.dart'; import 'package:grabbit/widgets/custom_button.dart'; class ScanScreen extends StatefulWidget { const ScanScreen({Key? key}) : super(key: key); @override State<ScanScreen> createState() => _ScanScreenState(); } class _ScanScreenState extends State<ScanScreen> { File? imageFile; @override Widget build(BuildContext context) { return SafeArea( child: Scaffold( backgroundColor: ColorConstant.whiteA700, body: Container( width: size.width, child: SingleChildScrollView( child: Container( child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.end, children: [ Container( height: getVerticalSize(434.00), width: getHorizontalSize(326.00), margin: getMargin(left: 17, top: 135, right: 17), child: Stack( alignment: Alignment.topCenter, children: [ Align( alignment: Alignment.center, child: Container( height: getVerticalSize(434.00), width: getHorizontalSize(325.00), margin: getMargin(left: 1), child: Card( clipBehavior: Clip.antiAlias, elevation: 0, margin: EdgeInsets.all(0), color: ColorConstant.bluegray100, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(getHorizontalSize(15.00)), ), child: Stack( children: [ Align( alignment: Alignment.bottomCenter, child: Padding( padding: getPadding(left: 121, top: 27, right: 121, bottom: 27), child: GestureDetector( onTap: () => getImage(source: ImageSource.camera), child: CommonImageView( imagePath: ImageConstant.imgCameraicon, height: getVerticalSize(77.00), width: getHorizontalSize(82.00), ), ), ), ), ], ), ), ), ), Align( alignment: Alignment.topCenter, child: Padding( padding: getPadding(top: 26, right: 1, bottom: 26), child: CommonImageView( file: imageFile, imagePath: imageFile == null ? ImageConstant.imgRectangle2362 : null, height: getVerticalSize(281.00), width: getHorizontalSize(325.00), ), ), ), ], ), ), CustomButton( width: 267, text: "Next", margin: getMargin(left: 17, top: 135, right: 17, bottom: 20), ), ], ), ), ), ), ), ); } void getImage({required ImageSource source}) async { final file = await ImagePicker().pickImage( source: source, maxWidth: 640, maxHeight: 480, imageQuality: 70 //0 - 100 ); if (file?.path != null) { setState(() { imageFile = File(file!.path); }); } } } void onTap() { Get.toNamed(AppRoutes.homepageScreen); }
说明
- 修改后,当用户点击相机图标拍摄图片,
imageFile会被赋值并触发UI刷新,CommonImageView会自动切换为显示拍摄的图片; - 没有拍摄图片时,依然显示默认的
imgRectangle2362; - 移除了无用的
onTapImgCameraicon方法,直接使用getImage方法实现相机调用逻辑。
内容的提问来源于stack exchange,提问作者John Michael Tan
相关产品推荐
相关产品推荐

