Использование CustomPainter
Флаттера для рисования различных Image
с в Canvas
для последующего отображения на экране. Я ожидаю, что порядок глубины любых нарисованных перекрывающихся изображений будет таким, каким они были нарисованы на холсте (например, canvas.drawImage(image1,..); canvas.drawImage(image2,..); canvas.drawImage(image3,..);
отобразит три изображения на экране с image1
, появляющимися под image2
и image3
соответственно). Однако я обнаружил, что в некоторых случаях порядок отображения изображений не полностью сохраняется.
См. Пример кода ниже:
import 'dart:async';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter/services.dart' show rootBundle;
void main() => runApp(new ExampleApp());
class ExampleApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Ground Example',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: ExampleScreen(),
);
}
}
class ExampleScreen extends StatefulWidget {
final Offset initPos = Offset(0.0, 0.0);
@override
_ExampleScreenState createState() => _ExampleScreenState();
}
class _ExampleScreenState extends State<ExampleScreen> {
ui.Image _image1;
ui.Image _image2;
ui.Image _image3;
bool _prepDone;
@override
void initState() {
_prepDone = false;
super.initState();
//_draggedToOffset = widget.initPos;
}
_ExampleScreenState() {
_prepare();
}
_prepare() {
loadImage('assets/wfw_1.png').then((image1) {
_image1 = image1;
}).whenComplete(() {
loadImage('assets/wnfw_2.png').then((image2) {
_image2 = image2;
}).whenComplete(() {
loadImage('assets/wfw_1.png').then((image3) {
_image3 = image3;
}).whenComplete(() {
_prepDone = true;
_handle();
});
});
});
}
_handle() {
setState(() {});
}
@override
Widget build(BuildContext context) {
return new Container(
constraints: BoxConstraints.expand(),
color: Colors.grey,
child: new Stack(children: <Widget>[
_prepDone ? Container(child: buildPainter()) : Container()
]));
}
buildPainter() {
return Container(
child: CustomPaint(
painter: ExamplePainter(_image1, _image2, _image3),
));
}
}
class ExamplePainter extends CustomPainter {
ui.Image _image1;
ui.Image _image2;
ui.Image _image3;
Paint _paint = Paint();
ExamplePainter(this._image1, this._image2, this._image3);
@override
void paint(Canvas canvas, Size size) {
canvas.drawImage(_image1, Offset(100.0, 35.0), _paint);
canvas.drawImage(_image2, Offset(70.0, 50.0), _paint);
canvas.drawImage(_image3, Offset(40.0, 65.0), _paint);
}
@override
bool shouldRepaint(ExamplePainter oldDelegate) {
return true;
}
}
Future<ui.Image> loadImage(String assetPath) async {
ImageStream stream = new AssetImage(assetPath, bundle: rootBundle)
.resolve(ImageConfiguration.empty);
Completer<ui.Image> completer = new Completer<ui.Image>();
void listener(ImageInfo frame, bool synchronousCall) {
final ui.Image image = frame.image;
completer.complete(image);
stream.removeListener(listener);
}
stream.addListener(listener);
return completer.future;
}
Где:
image1
и image3
: wfw_1.png .
image2
- это: wnfw_2.png
На устройстве эмулятора Android моего ноутбука вывод на экран выглядит следующим образом:
визуализированный вывод
Как видно, image2
отображается поверх последнего нарисованного изображения (image3
), когда я ожидал, что оно будет отображено ниже image2
(то есть между image1
и image3
).
Единственный способ решить проблему - это либо:
Добавление фиктивного вызова drawRect(..)
между вызовами drawImage(..)
или, установив image2
s Offset.dy
в offset.dy+0.001
.
Я новичок в Dart и Flutter в целом, поэтому я не уверен, что это так: а) мой код неверен, б) мое понимание механизма рендеринга флаттера неверно, или в) ошибка в дартсе: где-то пользовательский интерфейс