Изменение размера холста
Итак, я пытаюсь создать приложение для рисования и хочу иметь холст определенного размера, скажем, 80% всего экрана, но у меня возникают некоторые проблемы.
Вот мои фрагменты кода для функциональности рисования:
Drawing_page.dart
import 'dart:async';
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:drawing_app/drawn_line.dart';
import 'package:drawing_app/sketcher.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:image_gallery_saver/image_gallery_saver.dart';
class DrawingPage extends StatefulWidget {
@override
_DrawingPageState createState() => _DrawingPageState();
}
class _DrawingPageState extends State<DrawingPage> {
GlobalKey _globalKey = new GlobalKey();
List<DrawnLine?> lines = <DrawnLine>[];
DrawnLine? line;
Color selectedColor = Colors.black;
double selectedWidth = 5.0;
bool absorb = false;
StreamController<List<DrawnLine?>> linesStreamController =
StreamController<List<DrawnLine?>>.broadcast();
StreamController<DrawnLine?> currentLineStreamController =
StreamController<DrawnLine?>.broadcast();
Future<void> save() async {
try {
RenderRepaintBoundary boundary = _globalKey.currentContext!
.findRenderObject() as RenderRepaintBoundary;
ui.Image image = await boundary.toImage();
ByteData byteData = await (image.toByteData(
format: ui.ImageByteFormat.png) as FutureOr<ByteData>);
Uint8List pngBytes = byteData.buffer.asUint8List();
var saved = await ImageGallerySaver.saveImage(
pngBytes,
quality: 100,
name: DateTime.now().toIso8601String() + ".png",
isReturnImagePathOfIOS: true,
);
print(saved);
} catch (e) {
print(e);
}
}
Future<void> clear() async {
setState(() {
lines = [];
line = null;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[200],
body: Center(
child: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Stack(
children: [
Center(
child: Container(
color: Colors.yellow[200],
width: MediaQuery.of(context).size.width * 0.7,
height: MediaQuery.of(context).size.height * 0.7,
child: Stack(
children: [
buildAllPaths(context),
buildCurrentPath(context),
],
),
),
),
buildStrokeToolbar(),
buildColorToolbar(),
],
),
),
),
);
}
Widget buildCurrentPath(BuildContext context) {
return AbsorbPointer(
absorbing: absorb,
child: Container(
width: MediaQuery.of(context).size.width * 0.8,
height: MediaQuery.of(context).size.height * 0.8,
child: GestureDetector(
onPanStart: onPanStart,
onPanUpdate: onPanUpdate,
onPanEnd: onPanEnd,
child: RepaintBoundary(
child: StreamBuilder<DrawnLine?>(
stream: currentLineStreamController.stream,
builder: (context, snapshot) {
return CustomPaint(
painter: Sketcher(
lines: [line],
),
);
},
),
),
),
),
);
}
Widget buildAllPaths(BuildContext context) {
return Container(
width: MediaQuery.of(context).size.width * 0.8,
height: MediaQuery.of(context).size.height * 0.8,
child: RepaintBoundary(
key: _globalKey,
child: StreamBuilder<List<DrawnLine?>>(
stream: linesStreamController.stream,
builder: (context, snapshot) {
return CustomPaint(
painter: Sketcher(
lines: lines,
),
);
},
),
),
);
}
void onPanStart(DragStartDetails details) {
RenderBox box = context.findRenderObject() as RenderBox;
// Offset point = box.globalToLocal(details.globalPosition);
Offset point = box.globalToLocal(details.localPosition);
line = DrawnLine([point], selectedColor, selectedWidth);
}
void onPanUpdate(DragUpdateDetails details) {
RenderBox box = context.findRenderObject() as RenderBox;
// Offset point = box.globalToLocal(details.globalPosition);
Offset point = box.globalToLocal(details.localPosition);
List<Offset> path = List.from(line!.path)..add(point);
line = DrawnLine(path, selectedColor, selectedWidth);
currentLineStreamController.add(line);
}
void onPanEnd(DragEndDetails details) {
lines = List.from(lines)..add(line);
linesStreamController.add(lines);
}
Widget buildStrokeToolbar() {
return Positioned(
bottom: 100.0,
right: 10.0,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: [
buildStrokeButton(5.0),
buildStrokeButton(10.0),
buildStrokeButton(15.0),
],
),
);
}
Widget buildStrokeButton(double strokeWidth) {
return GestureDetector(
onTap: () {
setState(() {
selectedWidth = strokeWidth;
});
},
child: Padding(
padding: const EdgeInsets.all(4.0),
child: Container(
width: strokeWidth * 2,
height: strokeWidth * 2,
decoration: BoxDecoration(
color: selectedColor, borderRadius: BorderRadius.circular(50.0)),
),
),
);
}
Widget buildColorToolbar() {
return Positioned(
top: 40.0,
right: 10.0,
child: Container(
decoration: BoxDecoration(
// color: Colors.black26,
color: Colors.transparent,
borderRadius: BorderRadius.circular(45),
),
child: Padding(
padding: const EdgeInsets.all(5.0),
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: [
!absorb
? IconButton(
onPressed: () {
setState(() {
absorb = true;
});
},
icon: Icon(Icons.edit),
)
: IconButton(
onPressed: () {
setState(() {
absorb = false;
});
},
icon: Icon(Icons.edit_off),
),
buildClearButton(),
Divider(
height: 10.0,
),
buildSaveButton(),
Divider(
height: 20.0,
),
buildColorButton(Colors.red),
buildColorButton(Colors.blueAccent),
buildColorButton(Colors.deepOrange),
buildColorButton(Colors.green),
buildColorButton(Colors.lightBlue),
buildColorButton(Colors.black),
buildColorButton(Colors.white),
],
),
),
),
),
);
}
Widget buildColorButton(Color color) {
return Padding(
padding: const EdgeInsets.all(4.0),
child: FloatingActionButton(
mini: true,
backgroundColor: color,
child: Container(),
onPressed: () {
setState(() {
selectedColor = color;
});
},
),
);
}
Widget buildSaveButton() {
return GestureDetector(
onTap: save,
child: CircleAvatar(
child: Icon(
Icons.save,
size: 20.0,
color: Colors.white,
),
),
);
}
Widget buildClearButton() {
return GestureDetector(
onTap: clear,
child: CircleAvatar(
child: Icon(
Icons.create,
size: 20.0,
color: Colors.white,
),
),
);
}
}
Скетчер.дротик
import 'dart:ui';
import 'package:drawing_app/drawn_line.dart';
import 'package:flutter/material.dart';
class Sketcher extends CustomPainter {
final List<DrawnLine?>? lines;
Sketcher({this.lines});
@override
void paint(Canvas canvas, Size size) {
Paint paint = Paint()
..color = Colors.redAccent
..strokeCap = StrokeCap.round
..strokeWidth = 5.0;
// Rect rect = Rect.fromLTWH(0, 0, size.width, size.height);
// canvas.drawRect(rect, paint);
// canvas.clipRect(rect,);
for (int i = 0; i < lines!.length; ++i) {
if (lines![i] == null) continue;
for (int j = 0; j < lines![i]!.path.length - 1; ++j) {
if (lines![i]!.path[j] != null && lines![i]!.path[j + 1] != null) {
paint.color = lines![i]!.color;
paint.strokeWidth = lines![i]!.width;
canvas.drawLine(lines![i]!.path[j], lines![i]!.path[j + 1], paint);
}
}
}
}
@override
bool shouldRepaint(Sketcher oldDelegate) {
return true;
}
}
DrawnLine.dart
import 'package:flutter/material.dart';
class DrawnLine {
final List<Offset> path;
final Color color;
final double width;
DrawnLine(this.path, this.color, this.width);
}
Насколько мне известно, размер холста будет зависеть от родительского виджета, тогда почему я не могу ограничить размер холста. Я хочу разрешить пользователю рисовать только в контейнере, но я могу рисовать весь каркас, я не понимаю, что пошло не так, и поэтому любая форма помощи будет оценена.