Изменение размера холста

Итак, я пытаюсь создать приложение для рисования и хочу иметь холст определенного размера, скажем, 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);
}

Насколько мне известно, размер холста будет зависеть от родительского виджета, тогда почему я не могу ограничить размер холста. Я хочу разрешить пользователю рисовать только в контейнере, но я могу рисовать весь каркас, я не понимаю, что пошло не так, и поэтому любая форма помощи будет оценена.

0 ответов

Другие вопросы по тегам