diff --git a/lib/src/widgets/raw_editor.dart b/lib/src/widgets/raw_editor.dart index 0caba63e..ce9540ab 100644 --- a/lib/src/widgets/raw_editor.dart +++ b/lib/src/widgets/raw_editor.dart @@ -254,11 +254,8 @@ class RawEditorState extends EditorState /// by changing its attribute according to [value]. void _handleCheckboxTap(int offset, bool value) { if (!widget.readOnly) { - if (value) { - widget.controller.formatText(offset, 0, Attribute.checked); - } else { - widget.controller.formatText(offset, 0, Attribute.unchecked); - } + widget.controller.formatText( + offset, 0, value ? Attribute.checked : Attribute.unchecked); } } diff --git a/lib/src/widgets/style_widgets/checkbox.dart b/lib/src/widgets/style_widgets/checkbox.dart deleted file mode 100644 index 64f36120..00000000 --- a/lib/src/widgets/style_widgets/checkbox.dart +++ /dev/null @@ -1,60 +0,0 @@ -import 'package:flutter/material.dart'; - -class QuillCheckbox extends StatelessWidget { - const QuillCheckbox({ - Key? key, - this.style, - this.width, - this.isChecked = false, - this.offset, - this.onTap, - this.uiBuilder, - }) : super(key: key); - final TextStyle? style; - final double? width; - final bool isChecked; - final int? offset; - final Function(int, bool)? onTap; - final QuillCheckboxBuilder? uiBuilder; - - void _onCheckboxClicked(bool? newValue) { - if (onTap != null && newValue != null && offset != null) { - onTap!(offset!, newValue); - } - } - - @override - Widget build(BuildContext context) { - Widget child; - if (uiBuilder != null) { - child = uiBuilder!.build( - context: context, - isChecked: isChecked, - onChanged: _onCheckboxClicked, - ); - } else { - child = Container( - alignment: AlignmentDirectional.topEnd, - width: width, - padding: const EdgeInsetsDirectional.only(end: 13), - child: GestureDetector( - onLongPress: () => _onCheckboxClicked(!isChecked), - child: Checkbox( - value: isChecked, - onChanged: _onCheckboxClicked, - ), - ), - ); - } - - return child; - } -} - -abstract class QuillCheckboxBuilder { - Widget build({ - required BuildContext context, - required bool isChecked, - required void Function(bool?) onChanged, - }); -} diff --git a/lib/src/widgets/style_widgets/checkbox_point.dart b/lib/src/widgets/style_widgets/checkbox_point.dart new file mode 100644 index 00000000..7f4bfe88 --- /dev/null +++ b/lib/src/widgets/style_widgets/checkbox_point.dart @@ -0,0 +1,78 @@ +import 'package:flutter/material.dart'; + +class CheckboxPoint extends StatefulWidget { + const CheckboxPoint({ + required this.size, + required this.value, + required this.enabled, + required this.onChanged, + this.uiBuilder, + Key? key, + }) : super(key: key); + + final double size; + final bool value; + final bool enabled; + final ValueChanged onChanged; + final QuillCheckboxBuilder? uiBuilder; + + @override + _CheckboxPointState createState() => _CheckboxPointState(); +} + +class _CheckboxPointState extends State { + @override + Widget build(BuildContext context) { + if (widget.uiBuilder != null) { + return widget.uiBuilder!.build( + context: context, + isChecked: widget.value, + onChanged: widget.onChanged, + ); + } + final theme = Theme.of(context); + final fillColor = widget.value + ? (widget.enabled + ? theme.colorScheme.primary + : theme.colorScheme.onSurface.withOpacity(0.5)) + : theme.colorScheme.surface; + final borderColor = widget.value + ? (widget.enabled + ? theme.colorScheme.primary + : theme.colorScheme.onSurface.withOpacity(0)) + : (widget.enabled + ? theme.colorScheme.onSurface.withOpacity(0.5) + : theme.colorScheme.onSurface.withOpacity(0.3)); + return Center( + child: SizedBox( + width: widget.size, + height: widget.size, + child: Material( + color: fillColor, + shape: RoundedRectangleBorder( + side: BorderSide( + color: borderColor, + ), + borderRadius: BorderRadius.circular(2), + ), + child: InkWell( + onTap: + widget.enabled ? () => widget.onChanged(!widget.value) : null, + child: widget.value + ? Icon(Icons.check, + size: widget.size, color: theme.colorScheme.onPrimary) + : null, + ), + ), + ), + ); + } +} + +abstract class QuillCheckboxBuilder { + Widget build({ + required BuildContext context, + required bool isChecked, + required ValueChanged onChanged, + }); +} diff --git a/lib/src/widgets/style_widgets/style_widgets.dart b/lib/src/widgets/style_widgets/style_widgets.dart index 2a252d43..c28606bc 100644 --- a/lib/src/widgets/style_widgets/style_widgets.dart +++ b/lib/src/widgets/style_widgets/style_widgets.dart @@ -1,3 +1,3 @@ export 'bullet_point.dart'; -export 'checkbox.dart'; +export 'checkbox_point.dart'; export 'number_point.dart'; diff --git a/lib/src/widgets/text_block.dart b/lib/src/widgets/text_block.dart index 33b1c351..fcfaa195 100644 --- a/lib/src/widgets/text_block.dart +++ b/lib/src/widgets/text_block.dart @@ -168,25 +168,20 @@ class EditableTextBlock extends StatelessWidget { } if (attrs[Attribute.list.key] == Attribute.checked) { - return QuillCheckbox( - key: UniqueKey(), - style: defaultStyles!.leading!.style, - width: 32, - isChecked: true, - offset: block.offset + line.offset, - onTap: onCheckboxTap, - uiBuilder: defaultStyles.lists!.checkboxUIBuilder, + return CheckboxPoint( + size: 14, + value: true, + enabled: !readOnly, + onChanged: (checked) => onCheckboxTap(line.documentOffset, checked), ); } if (attrs[Attribute.list.key] == Attribute.unchecked) { - return QuillCheckbox( - key: UniqueKey(), - style: defaultStyles!.leading!.style, - width: 32, - offset: block.offset + line.offset, - onTap: onCheckboxTap, - uiBuilder: defaultStyles.lists!.checkboxUIBuilder, + return CheckboxPoint( + size: 14, + value: false, + enabled: !readOnly, + onChanged: (checked) => onCheckboxTap(line.documentOffset, checked), ); } diff --git a/lib/src/widgets/text_line.dart b/lib/src/widgets/text_line.dart index d75daffd..a9e2dbc5 100644 --- a/lib/src/widgets/text_line.dart +++ b/lib/src/widgets/text_line.dart @@ -967,6 +967,17 @@ class RenderEditableTextLine extends RenderEditableBox { @override bool hitTestChildren(BoxHitTestResult result, {required Offset position}) { + if (_leading != null) { + final childParentData = _leading!.parentData as BoxParentData; + final isHit = result.addWithPaintOffset( + offset: childParentData.offset, + position: position, + hitTest: (result, transformed) { + assert(transformed == position - childParentData.offset); + return _leading!.hitTest(result, position: transformed); + }); + if (isHit) return true; + } if (_body == null) return false; final parentData = _body!.parentData as BoxParentData; return result.addWithPaintOffset(