Преглед на файлове

Handle user taps on the padding area around the editor

Anatoly Pulyaevskiy преди 6 години
родител
ревизия
86b30018ef

+ 1
- 1
packages/zefyr/example/ios/Podfile.lock Целия файл

25
 
25
 
26
 PODFILE CHECKSUM: 1e5af4103afd21ca5ead147d7b81d06f494f51a2
26
 PODFILE CHECKSUM: 1e5af4103afd21ca5ead147d7b81d06f494f51a2
27
 
27
 
28
-COCOAPODS: 1.5.2
28
+COCOAPODS: 1.5.3

+ 9
- 1
packages/zefyr/lib/src/widgets/editable_text.dart Целия файл

35
     @required this.imageDelegate,
35
     @required this.imageDelegate,
36
     this.autofocus: true,
36
     this.autofocus: true,
37
     this.enabled: true,
37
     this.enabled: true,
38
+    this.padding: const EdgeInsets.symmetric(horizontal: 16.0),
38
   }) : super(key: key);
39
   }) : super(key: key);
39
 
40
 
40
   final ZefyrController controller;
41
   final ZefyrController controller;
43
   final bool autofocus;
44
   final bool autofocus;
44
   final bool enabled;
45
   final bool enabled;
45
 
46
 
47
+  /// Padding around editable area.
48
+  final EdgeInsets padding;
49
+
46
   static ZefyrEditableTextScope of(BuildContext context) {
50
   static ZefyrEditableTextScope of(BuildContext context) {
47
     final ZefyrEditableTextScope result =
51
     final ZefyrEditableTextScope result =
48
         context.inheritFromWidgetOfExactType(ZefyrEditableTextScope);
52
         context.inheritFromWidgetOfExactType(ZefyrEditableTextScope);
123
     super.build(context); // See AutomaticKeepAliveState.
127
     super.build(context); // See AutomaticKeepAliveState.
124
     ZefyrEditor.of(context);
128
     ZefyrEditor.of(context);
125
 
129
 
130
+    Widget body = ListBody(children: _buildChildren(context));
131
+    if (widget.padding != null) {
132
+      body = new Padding(padding: widget.padding, child: body);
133
+    }
126
     final scrollable = SingleChildScrollView(
134
     final scrollable = SingleChildScrollView(
127
       padding: EdgeInsets.only(top: 16.0),
135
       padding: EdgeInsets.only(top: 16.0),
128
       physics: AlwaysScrollableScrollPhysics(),
136
       physics: AlwaysScrollableScrollPhysics(),
129
       controller: _scrollController,
137
       controller: _scrollController,
130
-      child: ListBody(children: _buildChildren(context)),
138
+      child: body,
131
     );
139
     );
132
 
140
 
133
     final overlay = Overlay.of(context, debugRequiredFor: widget);
141
     final overlay = Overlay.of(context, debugRequiredFor: widget);

+ 2
- 3
packages/zefyr/lib/src/widgets/editor.dart Целия файл

159
       imageDelegate: _imageDelegate,
159
       imageDelegate: _imageDelegate,
160
       autofocus: widget.autofocus,
160
       autofocus: widget.autofocus,
161
       enabled: widget.enabled,
161
       enabled: widget.enabled,
162
+      padding: widget.padding,
162
     );
163
     );
163
-    if (widget.padding != null) {
164
-      editable = new Padding(padding: widget.padding, child: editable);
165
-    }
164
+
166
     final children = <Widget>[];
165
     final children = <Widget>[];
167
     children.add(Expanded(child: editable));
166
     children.add(Expanded(child: editable));
168
     final toolbar = ZefyrToolbar(
167
     final toolbar = ZefyrToolbar(

+ 19
- 0
packages/zefyr/lib/src/widgets/render_context.dart Целия файл

94
     }, orElse: _null);
94
     }, orElse: _null);
95
   }
95
   }
96
 
96
 
97
+  /// Returns closest render box to the specified global [point].
98
+  ///
99
+  /// If [point] is inside of one of active render boxes that box is returned.
100
+  /// Otherwise this method checks if [point] is to the left or to the right
101
+  /// side of a box, e.g. if vertical offset of this point is inside of one of
102
+  /// the active boxes. If it is then that box is returned.
103
+  RenderEditableProxyBox closestBoxForGlobalPoint(Offset point) {
104
+    assert(!_disposed);
105
+    RenderEditableProxyBox box = boxForGlobalPoint(point);
106
+    if (box != null) return box;
107
+
108
+    box = _activeBoxes.firstWhere((p) {
109
+      final localPoint = p.globalToLocal(point);
110
+      return (localPoint.dy >= 0 && localPoint.dy < p.size.height);
111
+    }, orElse: _null);
112
+
113
+    return box;
114
+  }
115
+
97
   static Null _null() => null;
116
   static Null _null() => null;
98
 
117
 
99
   @override
118
   @override

+ 6
- 2
packages/zefyr/lib/src/widgets/selection.dart Целия файл

216
     HitTestResult result = new HitTestResult();
216
     HitTestResult result = new HitTestResult();
217
     WidgetsBinding.instance.hitTest(result, globalPoint);
217
     WidgetsBinding.instance.hitTest(result, globalPoint);
218
 
218
 
219
-    final box = _getEditableBox(result);
220
-    if (box == null) return;
219
+    RenderEditableProxyBox box = _getEditableBox(result);
220
+    if (box == null) {
221
+      final editable = ZefyrEditableText.of(context);
222
+      box = editable.renderContext.closestBoxForGlobalPoint(globalPoint);
223
+    }
224
+    if (box == null) return null;
221
 
225
 
222
     final localPoint = box.globalToLocal(globalPoint);
226
     final localPoint = box.globalToLocal(globalPoint);
223
     final position = box.getPositionForOffset(localPoint);
227
     final position = box.getPositionForOffset(localPoint);

+ 19
- 0
packages/zefyr/test/widgets/selection_test.dart Целия файл

33
       await editor.unfocus();
33
       await editor.unfocus();
34
       expect(editor.findSelectionHandle(), findsNothing);
34
       expect(editor.findSelectionHandle(), findsNothing);
35
     });
35
     });
36
+
37
+    testWidgets('tap outside of text area finds closest paragraph',
38
+        (tester) async {
39
+      final editor = new EditorSandBox(tester: tester);
40
+      await editor.tapEditor();
41
+      editor.controller
42
+          .updateSelection(new TextSelection.collapsed(offset: 10));
43
+      await tester.pumpAndSettle();
44
+      expect(editor.controller.selection.extentOffset, 10);
45
+
46
+      RenderEditableParagraph renderObject =
47
+          tester.firstRenderObject(find.byType(EditableRichText));
48
+      var offset = renderObject.localToGlobal(Offset.zero);
49
+      offset += Offset(-5.0, 5.0);
50
+      await tester.tapAt(offset);
51
+      await tester.pumpAndSettle();
52
+      expect(editor.controller.selection.isCollapsed, isTrue);
53
+      expect(editor.controller.selection.extentOffset, 0);
54
+    });
36
   });
55
   });
37
 }
56
 }