import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_quill/widgets/controller.dart'; import 'package:flutter_quill/widgets/delegate.dart'; import 'package:flutter_quill/widgets/editor.dart'; class QuillField extends StatefulWidget { final QuillController controller; final FocusNode focusNode; final ScrollController scrollController; final bool scrollable; final EdgeInsetsGeometry padding; final bool autofocus; final bool showCursor; final bool readOnly; final bool enableInteractiveSelection; final double minHeight; final double maxHeight; final bool expands; final TextCapitalization textCapitalization; final Brightness keyboardAppearance; final ScrollPhysics scrollPhysics; final ValueChanged onLaunchUrl; final InputDecoration decoration; final Widget toolbar; final EmbedBuilder embedBuilder; QuillField({ Key key, @required this.controller, this.focusNode, this.scrollController, this.scrollable = true, this.padding = EdgeInsets.zero, this.autofocus = false, this.showCursor = true, this.readOnly = false, this.enableInteractiveSelection = true, this.minHeight, this.maxHeight, this.expands = false, this.textCapitalization = TextCapitalization.sentences, this.keyboardAppearance = Brightness.light, this.scrollPhysics, this.onLaunchUrl, this.decoration, this.toolbar, this.embedBuilder, }) : super(key: key); @override _QuillFieldState createState() => _QuillFieldState(); } class _QuillFieldState extends State { bool _focused; void _editorFocusChanged() { setState(() { _focused = widget.focusNode.hasFocus; }); } @override void initState() { super.initState(); _focused = widget.focusNode.hasFocus; widget.focusNode.addListener(_editorFocusChanged); } @override void didUpdateWidget(covariant QuillField oldWidget) { super.didUpdateWidget(oldWidget); if (widget.focusNode != oldWidget.focusNode) { oldWidget.focusNode.removeListener(_editorFocusChanged); widget.focusNode.addListener(_editorFocusChanged); _focused = widget.focusNode.hasFocus; } } @override Widget build(BuildContext context) { Widget child = QuillEditor( widget.controller, widget.focusNode, widget.scrollController, widget.scrollable, widget.padding, widget.autofocus, widget.showCursor, widget.readOnly, widget.enableInteractiveSelection, widget.minHeight, widget.maxHeight, widget.expands, widget.textCapitalization, widget.keyboardAppearance, widget.scrollPhysics, widget.onLaunchUrl, widget.embedBuilder, ); if (widget.toolbar != null) { child = Column( children: [ child, Visibility( child: widget.toolbar, visible: _focused, maintainSize: true, maintainAnimation: true, maintainState: true, ), ], ); } return AnimatedBuilder( animation: Listenable.merge([widget.focusNode, widget.controller]), builder: (BuildContext context, Widget child) { return InputDecorator( decoration: _getEffectiveDecoration(), isFocused: widget.focusNode.hasFocus, // TODO: Document should be considered empty of it has single empty line with no styles applied isEmpty: widget.controller.document.length == 1, child: child, ); }, child: child, ); } InputDecoration _getEffectiveDecoration() { return (widget.decoration ?? const InputDecoration()) .applyDefaults(Theme.of(context).inputDecorationTheme) .copyWith( enabled: !widget.readOnly, hintMaxLines: widget.decoration?.hintMaxLines, ); } }