@@ -296,33 +296,91 @@ class _ContentInput extends StatelessWidget {
296
296
// clip the 8th line, where the height matches the spec of 178 logical
297
297
// pixels. The partial line hints that the content input is scrollable.
298
298
maxHeight: topPadding + contentLineHeight * 7 + contentLineHeight * 0.727 ),
299
- child: ClipRect (
300
- child: ComposeAutocomplete (
301
- narrow: narrow,
302
- controller: controller,
303
- focusNode: focusNode,
304
- fieldViewBuilder: (context) => TextField (
299
+ child: ClipRect (
300
+ child: ComposeAutocomplete (
301
+ narrow: narrow,
305
302
controller: controller,
306
303
focusNode: focusNode,
307
- // `contentPadding` causes the text to be clipped while leaving
308
- // a gap to the top border, because it shrinks the size of the
309
- // body of `TextField`. Overriding this gives us full control
310
- // over the clipping behavior with the `ConstrainedBox`.
311
- clipBehavior: Clip .none,
312
- minLines: 2 ,
313
- maxLines: null ,
314
- textCapitalization: TextCapitalization .sentences,
315
- style: TextStyle (
316
- fontSize: 17 ,
317
- height: (contentLineHeight / 17 ),
318
- color: designVariables.textInput),
319
- decoration: InputDecoration (
320
- isDense: true ,
321
- border: InputBorder .none,
322
- contentPadding: const EdgeInsets .only (top: topPadding),
323
- hintText: hintText,
324
- hintStyle: TextStyle (
325
- color: designVariables.textInput.withValues (alpha: 0.5 )))))));
304
+ fieldViewBuilder: (context) => _ShadowBox (
305
+ color: designVariables.bgComposeBox,
306
+ child: TextField (
307
+ controller: controller,
308
+ focusNode: focusNode,
309
+ // `contentPadding` causes the text to be clipped while leaving
310
+ // a gap to the top border, because it shrinks the size of the
311
+ // body of `TextField`. Overriding this gives us full control
312
+ // over the clipping behavior with the `ConstrainedBox`.
313
+ clipBehavior: Clip .none,
314
+ minLines: 2 ,
315
+ maxLines: null ,
316
+ textCapitalization: TextCapitalization .sentences,
317
+ style: TextStyle (
318
+ fontSize: 17 ,
319
+ height: (contentLineHeight / 17 ),
320
+ color: designVariables.textInput),
321
+ decoration: InputDecoration (
322
+ isDense: true ,
323
+ border: InputBorder .none,
324
+ contentPadding: const EdgeInsets .only (top: topPadding),
325
+ hintText: hintText,
326
+ hintStyle: TextStyle (
327
+ color: designVariables.textInput.withValues (alpha: 0.5 ))))))));
328
+ }
329
+ }
330
+
331
+ /// Overlay inset shadows on the child from all scrollable directions.
332
+ class _ShadowBox extends StatefulWidget {
333
+ const _ShadowBox ({required this .color, required this .child});
334
+
335
+ final Color color;
336
+ final Widget child;
337
+
338
+ @override
339
+ State <_ShadowBox > createState () => _ShadowBoxState ();
340
+ }
341
+
342
+ class _ShadowBoxState extends State <_ShadowBox > {
343
+ bool showTopShadow = false ; bool showBottomShadow = false ;
344
+ bool showLeftShadow = false ; bool showRightShadow = false ;
345
+
346
+ bool handleScroll (ScrollNotification notification) {
347
+ final metrics = notification.metrics;
348
+ setState (() {
349
+ switch (metrics.axisDirection) {
350
+ case AxisDirection .up:
351
+ case AxisDirection .down:
352
+ showTopShadow = metrics.extentBefore != 0 ;
353
+ showBottomShadow = metrics.extentAfter != 0 ;
354
+ case AxisDirection .right:
355
+ case AxisDirection .left:
356
+ showLeftShadow = metrics.extentBefore != 0 ;
357
+ showRightShadow = metrics.extentAfter != 0 ;
358
+ }
359
+ });
360
+ return false ;
361
+ }
362
+
363
+ @override
364
+ Widget build (BuildContext context) {
365
+ BoxDecoration shadowFrom (AlignmentGeometry begin) =>
366
+ BoxDecoration (gradient: LinearGradient (begin: begin, end: - begin,
367
+ colors: [widget.color, widget.color.withValues (alpha: 0 )]));
368
+
369
+ return NotificationListener <ScrollNotification >(
370
+ onNotification: handleScroll,
371
+ child: Stack (
372
+ children: [
373
+ widget.child,
374
+ if (showTopShadow) Positioned (top: 0 , left: 0 , right: 0 ,
375
+ child: Container (height: 8 , decoration: shadowFrom (Alignment .topCenter))),
376
+ if (showBottomShadow) Positioned (bottom: 0 , left: 0 , right: 0 ,
377
+ child: Container (height: 8 , decoration: shadowFrom (Alignment .bottomCenter))),
378
+ if (showLeftShadow) Positioned (left: 0 , top: 0 , bottom: 0 ,
379
+ child: Container (width: 8 , decoration: shadowFrom (Alignment .centerLeft))),
380
+ if (showRightShadow) Positioned (right: 0 , top: 0 , bottom: 0 ,
381
+ child: Container (width: 8 , decoration: shadowFrom (Alignment .centerRight))),
382
+ ],
383
+ ));
326
384
}
327
385
}
328
386
0 commit comments