[英]Flutter (camera) does not refresh Photo Preview
我正在使用 Flutter + 相机 package 创建照片并在预览中显示。 在预览中,用户可以决定是否要保留/使用这张照片,或者是否要重复拍摄。
问题:
重复照片时,预览页面显示与第一次尝试时相同的图像。 使用图像(将其发送到 API)时,用户将被重定向到发起相机调用的页面。 但即使在那里 - 再做一次时,旧的预览还是可见的。
启动页面(我们称之为“StartPage”)
SizedBox(
width: double.infinity,
child: IconButton(
icon: const Icon(Icons.camera_alt_outlined),
iconSize: 80,
color: Colors.grey,
onPressed: () async {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PhotoPage()))
.then((value) => setState(() {}));
},
),
)
PhotoPage 显示实时摄像头图像(一切正常,API 呼叫有效)
class PhotoPage extends StatefulWidget {
@override
_PhotoPageState createState() => _PhotoPageState();
}
class _PhotoPageState extends State<PhotoPage> {
CameraController? cameraController;
List? cameras;
int? selectedCameraIndex;
String? imgPath;
Future initCamera(CameraDescription cameraDescription) async {
if (cameraController != null) {
await cameraController!.dispose();
}
cameraController =
CameraController(cameraDescription, ResolutionPreset.veryHigh);
cameraController!.addListener(() {
if (mounted) {
setState(() {});
}
});
if (cameraController!.value.hasError) {
print('Camera Error ${cameraController!.value.errorDescription}');
}
try {
await cameraController!.initialize();
} catch (e) {
showCameraException(e);
}
if (mounted) {
setState(() {});
}
}
Widget cameraPreview() {
if (cameraController == null || !cameraController!.value.isInitialized) {
return Text(
'Loading',
style: TextStyle(
color: Colors.white, fontSize: 20.0, fontWeight: FontWeight.bold),
);
}
return AspectRatio(
aspectRatio: cameraController!.value.aspectRatio,
child: CameraPreview(cameraController!),
);
}
Widget cameraControl(context) {
return Stack(
children: <Widget>[
Align(
alignment: Alignment.centerRight,
child: FloatingActionButton.extended(
icon: Icon(Icons.camera),
label: Text(''),
backgroundColor: Colors.green,
onPressed: () {
onCapture(context);
}))
],
//),
);
}
onCapture(context) async {
try {
var p = await getTemporaryDirectory();
var name = 'test';
var path = "${p.path}/$name.png";
XFile image = await cameraController!.takePicture();
image.saveTo(path);
await cameraController!.takePicture().then((value) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PreviewScreen(
imgPath: path,
fileName: "$name.png",
key: UniqueKey(),
))).then((value) => setState(() {}));
});
} catch (e) {
showCameraException(e);
}
}
@override
void initState() {
// TODO: implement initState
super.initState();
SystemChrome.setPreferredOrientations([
DeviceOrientation.landscapeRight,
]);
availableCameras().then((value) {
cameras = value;
if (cameras!.length > 0) {
setState(() {
selectedCameraIndex = 0;
});
initCamera(cameras![selectedCameraIndex!]).then((value) {});
} else {
print('No camera available');
}
}).catchError((e) {
print('Error : ${e.code}');
});
}
@override
dispose() {
SystemChrome.setPreferredOrientations([
DeviceOrientation.landscapeRight,
]);
imgPath = '';
cameraController!.dispose();
PaintingBinding.instance!.imageCache!.clear();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
body: Stack(children: <Widget>[
CameraPreview(cameraController!),
Align(
alignment: Alignment.bottomCenter,
child: Image(
image: new AssetImage(
"assets/layer.png",
),
)),
Align(
alignment: Alignment.bottomCenter,
child: Text(
"Please hold the phone in Landscape mode",
textAlign: TextAlign.center,
textScaleFactor: 1.3,
style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
).tr(),
),
cameraControl(context),
]),
);
}
showCameraException(e) {
String errorText = 'Error ${e.code} \nError message: ${e.description}';
}
}
所以我将图像的路径推送到 PreviewScreen:
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PreviewScreen(
imgPath: path,
fileName: "$name.png",
key: UniqueKey(),
))).then((value) => setState(() {}));
});
我的 PreviewScreen 如下所示:
class PreviewScreen extends StatefulWidget {
String? imgPath;
String? fileName;
PreviewScreen(
{required this.imgPath, required this.fileName, required Key key})
: super(key: key);
@override
_PreviewScreenState createState() => _PreviewScreenState();
}
final SaveController controller = Get.put(SaveController());
class _PreviewScreenState extends State<PreviewScreen> {
/* @override
void initState() {
super.initState();
} */
@override
void dispose() {
SaveController().dispose();
_PreviewScreenState().dispose();
PaintingBinding.instance!.imageCache!.clear();
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
//child: Stack(
//crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Row(children: [
Expanded(
flex: 2,
child: Image.file(
File(widget.imgPath!),
fit: BoxFit.cover,
),
)
]),
Align(
alignment: Alignment.bottomLeft,
child: FloatingActionButton.extended(
icon: Icon(Icons.repeat_outlined),
label: Text('Repeat').tr(),
backgroundColor: Colors.red,
onPressed: () {
widget.imgPath = '';
setState(() {});
Navigator.pop(context);
}
//Get.back();
),
),
Align(
alignment: Alignment.bottomRight,
child: FloatingActionButton.extended(
icon: Icon(Icons.check_circle_outline_sharp),
label: Text('Confirm').tr(),
backgroundColor: Colors.green,
onPressed: () {
SystemServices.savePhoto(widget.imgPath!)
.then((value) => setState(() {}));
},
),
),
],
),
);
}
Future getBytes() async {
Uint8List bytes = File(widget.imgPath!).readAsBytesSync();
// print(ByteData.view(buffer))
return ByteData.view(bytes.buffer);
}
}
“重复”功能如下所示:
onPressed: () {
widget.imgPath = '';
setState(() {});
Navigator.pop(context);
}
不幸的是,我真的不知道了。 据我所见(我是Flutter的初学者),state被清除,变量为空。
有人可以告诉我,为什么 PreviewScreen 中的照片保持不变? 我究竟做错了什么?
非常感谢,我真的很感激任何提示。
看起来,这是解决该问题的方法:
@override
void initState() {
imageCache!.clear();
imageCache!.clearLiveImages();
super.initState();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.