Как добавить тень в текст в трепете?

Я искал вариант тени в TextStyle, но я не нашел. Поэтому я спрашиваю: как я могу добавить тень к тексту во флаттере? Является ли это возможным? Пример:

new Text(
"asd"
style: new TextStyle( 
//add shadow?
));

Ответ 1

Flutter теперь предоставляет способ сделать это без каких-либо обходных путей, как описано в выпуске 3402 и ответе Гэри Цяна ниже.

Хотя это пробивается в более стабильные каналы, можно подделать тень, используя BackdropFilter.

screenshot

import 'dart:ui' as ui;
import 'package:flutter/material.dart';

void main() {
  runApp(new MaterialApp(
    home: new MyApp(),
  ));
}

class ShadowText extends StatelessWidget {
  ShadowText(this.data, { this.style }) : assert(data != null);

  final String data;
  final TextStyle style;

  Widget build(BuildContext context) {
    return new ClipRect(
      child: new Stack(
        children: [
          new Positioned(
            top: 2.0,
            left: 2.0,
            child: new Text(
              data,
              style: style.copyWith(color: Colors.black.withOpacity(0.5)),
            ),
          ),
          new BackdropFilter(
            filter: new ui.ImageFilter.blur(sigmaX: 2.0, sigmaY: 2.0),
            child: new Text(data, style: style),
          ),
        ],
      ),
    );
  }
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      body: new Container(
        child: new Center(
          child: new ShadowText(
            'Hello world!',
            style: Theme.of(context).textTheme.display3,
          ),
        ),
      ),
    );
  }
}

Или, если вас не волнует размытие, просто создайте Stack с несколькими полупрозрачными Text виджетами, которые не совсем точно расположены друг над другом.

Как это:

import 'package:flutter/material.dart';

class ShadowText extends StatelessWidget {

  final String data;
  final TextStyle style;
  final TextAlign textAlign;
  final TextDirection textDirection;
  final bool softWrap;
  final TextOverflow overflow;
  final double textScaleFactor;
  final int maxLines;

  const ShadowText(this.data, {
    Key key,
    this.style,
    this.textAlign,
    this.textDirection,
    this.softWrap,
    this.overflow,
    this.textScaleFactor,
    this.maxLines,
  }) : assert(data != null);

  Widget build(BuildContext context) {
    return new ClipRect(
      child: new Stack(
        children: [
          new Positioned(
            top: 2.0,
            left: 2.0,
            child: new Text(
              data,
              style: style.copyWith(color: Colors.black.withOpacity(0.5)),
              textAlign: textAlign,
              textDirection: textDirection,
              softWrap: softWrap,
              overflow: overflow,
              textScaleFactor: textScaleFactor,
              maxLines: maxLines,
            ),
          ),
          new Text(
            data,
            style: style,
            textAlign: textAlign,
            textDirection: textDirection,
            softWrap: softWrap,
            overflow: overflow,
            textScaleFactor: textScaleFactor,
            maxLines: maxLines,
          ),
        ],
      ),
    );
  }
}

Ответ 2

Текстовые тени теперь являются свойством TextStyle с TextStyle этого коммита

Чтобы включить тени текста, убедитесь, что вы используете последнюю версию Flutter ($ flutter upgrade) и предоставьте List<Shadow> для TextStyle.shadows:

import 'dart:ui';

...

Text(
  'Hello, world!',
  style: TextStyle(
    shadows: <Shadow>[
      Shadow(
        offset: Offset(10.0, 10.0),
        blurRadius: 3.0,
        color: Color.fromARGB(255, 0, 0, 0),
      ),
      Shadow(
        offset: Offset(10.0, 10.0),
        blurRadius: 8.0,
        color: Color.fromARGB(125, 0, 0, 255),
      ),
    ],
  ),
),

...

Имейте в виду, что тени будут нарисованы в указанном порядке.

Ответ 3

В настоящее время это невозможно, но скоро это произойдет.

Вы можете следить за этой проблемой: https://github.com/flutter/flutter/issues/3402

Ответ 4

Расширяю ответ Коллина Джексона. Это будет учитывать различные свойства TextAlign.

import 'package:flutter/material.dart';

class ShadowText extends StatelessWidget {
  final String data;
  final TextStyle style;
  final TextAlign textAlign;
  final TextDirection textDirection;
  final bool softWrap;
  final TextOverflow overflow;
  final double textScaleFactor;
  final int maxLines;

  const ShadowText(
    this.data, {
    Key key,
    this.style,
    this.textAlign,
    this.textDirection,
    this.softWrap,
    this.overflow,
    this.textScaleFactor,
    this.maxLines,
  }) : assert(data != null);

  Widget build(BuildContext context) {
    AlignmentDirectional _align;
    switch (textAlign) {
      case TextAlign.justify:
      case TextAlign.center:
        _align = AlignmentDirectional.center;
        break;
      case TextAlign.end:
      case TextAlign.right:
        _align = AlignmentDirectional.centerEnd;
        break;
      case TextAlign.start:
      case TextAlign.left:
        _align = AlignmentDirectional.centerStart;
        break;
      default:
        _align = AlignmentDirectional.center;
    }
    return new ClipRect(
      child: new Stack(
        alignment: _align,
        children: [
          Text(data,
              style: style.copyWith(color: Colors.black.withOpacity(0.5)),
              textAlign: textAlign,
              textDirection: textDirection,
              softWrap: softWrap,
              overflow: overflow,
              textScaleFactor: textScaleFactor + 0.03,
              maxLines: maxLines),
          new Text(
            data,
            style: style,
            textAlign: textAlign,
            textDirection: textDirection,
            softWrap: softWrap,
            overflow: overflow,
            textScaleFactor: textScaleFactor,
            maxLines: maxLines,
          ),
        ],
      ),
    );
  }
}

Затем, когда вы захотите использовать это, просто импортируйте этот файл вверху и замените Text() на ShadowText().