styled_text.dart 3.72 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
2 3 4 5 6
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/material.dart';

7
typedef _TextTransformer = Widget Function(String name, String text);
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

// From https://en.wikiquote.org/wiki/2001:_A_Space_Odyssey_(film)
const String _kDialogText = '''
Dave: Open the pod bay doors, please, HAL. Open the pod bay doors, please, HAL. Hello, HAL. Do you read me? Hello, HAL. Do you read me? Do you read me, HAL?
HAL: Affirmative, Dave. I read you.
Dave: Open the pod bay doors, HAL.
HAL: I'm sorry, Dave. I'm afraid I can't do that.
Dave: What's the problem?
HAL: I think you know what the problem is just as well as I do.
Dave: What are you talking about, HAL?
HAL: This mission is too important for me to allow you to jeopardize it.''';

// [["Dave", "Open the pod bay..."] ...]
final List<List<String>> _kNameLines = _kDialogText
  .split('\n')
23
  .map<List<String>>((String line) => line.split(':'))
24 25
  .toList();

26 27
final TextStyle _kDaveStyle = TextStyle(color: Colors.indigo.shade400, height: 1.8);
final TextStyle _kHalStyle = TextStyle(color: Colors.red.shade400, fontFamily: 'monospace');
28 29
const TextStyle _kBold = TextStyle(fontWeight: FontWeight.bold);
const TextStyle _kUnderline = TextStyle(
30
  decoration: TextDecoration.underline,
31
  decorationColor: Color(0xFF000000),
32
  decorationStyle: TextDecorationStyle.wavy,
33 34 35
);

Widget toStyledText(String name, String text) {
36
  final TextStyle lineStyle = (name == 'Dave') ? _kDaveStyle : _kHalStyle;
37 38 39
  return RichText(
    key: Key(text),
    text: TextSpan(
Adam Barth's avatar
Adam Barth committed
40 41
      style: lineStyle,
      children: <TextSpan>[
42
        TextSpan(
Adam Barth's avatar
Adam Barth committed
43 44
          style: _kBold,
          children: <TextSpan>[
45
            TextSpan(
Adam Barth's avatar
Adam Barth committed
46
              style: _kUnderline,
47
              text: name,
Adam Barth's avatar
Adam Barth committed
48
            ),
49 50
            const TextSpan(text: ':'),
          ],
Adam Barth's avatar
Adam Barth committed
51
        ),
52 53 54
        TextSpan(text: text),
      ],
    ),
55 56 57
  );
}

58
Widget toPlainText(String name, String text) => Text(name + ':' + text);
59

60
class SpeakerSeparator extends StatelessWidget {
61
  @override
62
  Widget build(BuildContext context) {
63
    return Container(
64
      constraints: const BoxConstraints.expand(height: 0.0),
65
      margin: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 64.0),
66
      decoration: const BoxDecoration(
67 68
        border: Border(
          bottom: BorderSide(color: Color.fromARGB(24, 0, 0, 0))
69
        )
70
      ),
71 72 73 74
    );
  }
}

75
class StyledTextDemo extends StatefulWidget {
76
  @override
77
  _StyledTextDemoState createState() => _StyledTextDemoState();
78 79 80
}

class _StyledTextDemoState extends State<StyledTextDemo> {
81
  @override
82 83 84 85 86
  void initState() {
    super.initState();
    _toText = toStyledText;
  }

87
  _TextTransformer _toText;
88 89 90 91 92 93 94

  void _handleTap() {
    setState(() {
      _toText = (_toText == toPlainText) ? toStyledText : toPlainText;
    });
  }

95
  @override
96
  Widget build(BuildContext context) {
97
    return GestureDetector(
98
      onTap: _handleTap,
99
      child: Container(
100
        padding: const EdgeInsets.symmetric(horizontal: 8.0),
101
        child: Column(
102
          mainAxisAlignment: MainAxisAlignment.center,
103
          crossAxisAlignment: CrossAxisAlignment.start,
104 105 106 107 108 109 110
          children: _kNameLines
            .map<Widget>((List<String> nameAndText) => _toText(nameAndText[0], nameAndText[1]))
            .expand((Widget line) => <Widget>[
              line,
              SpeakerSeparator(),
            ])
            .toList()..removeLast(),
111 112
        ),
      ),
113 114 115 116 117
    );
  }
}

void main() {
118 119 120 121
  runApp(MaterialApp(
    theme: ThemeData.light(),
    home: Scaffold(
      appBar: AppBar(
122
        title: const Text('Hal and Dave'),
123
      ),
124
      body: Material(
125
        color: Colors.grey.shade50,
126 127 128
        child: StyledTextDemo(),
      ),
    ),
129 130
  ));
}