Flutter圆角文本框插件rounded_text_field的使用

Flutter圆角文本框插件rounded_text_field的使用

目录

内容

功能

  • ✅ 高亮文本
  • ✅ 高亮文本框
  • ✅ 高亮文本片段

开始使用

导入包:

import 'package:rounded_text_field/rounded_text_field.dart';

用法

高亮简单文本

RoundedBackgroundText(
  'A cool text to be highlighted',
  style: const TextStyle(fontWeight: FontWeight.bold),
  backgroundColor: Colors.white,
),

多行文本也支持:

RoundedBackgroundText(
  'A cool text to be highlighted\nWith two lines or more',
  style: const TextStyle(fontWeight: FontWeight.bold),
  backgroundColor: Colors.amber,
),

高亮文本框

必须使用TextEditingController:

RoundedBackgroundTextField(
  backgroundColor: Colors.blue,
  style: const TextStyle(fontWeight: FontWeight.bold),
  textAlign: TextAlign.center,
),

文本会随着用户输入而高亮。

文本高亮会跟随文本框滚动位置。

高亮文本片段

高亮文本的一部分:

RichText(
  text: TextSpan(
    text: 'Start your text and ',
    children: [
      RoundedBackgroundTextSpan(
        text: 'highlight something',
        backgroundColor: Colors.blue,
      ),
      const TextSpan(text: ' when necessary'),
    ],
  ),
),

你可能想知道的

改变圆角半径

可以通过设置innerRadiusouterRadius来改变圆角半径:

RoundedBackgroundText(
  'A cool text to be highlighted',
  style: const TextStyle(fontWeight: FontWeight.bold),
  backgroundColor: Colors.white,
  innerRadius: 15.0,
  outerRadius: 10.0,
),

最大允许值为20.0。最小值为0.0

深入解析

这一部分详细解释了背景绘制的工作原理。

RoundedBackgroundText并没有在底层使用Text小部件。相反,它使用了一个自定义文本绘制器来在背景上绘制文本。一旦RoundedBackgroundText小部件被初始化,文本的行度量就会被计算(参见computeLineMetrics),并且当文本更改或父容器宽度变化时会重新计算。这在构建时完成,从而为用户提供流畅的体验。

为了绘制背景,会使用之前生成的行度量。每行有四个属性:

  • x - 行在大小内的水平起始位置
  • y - 行在大小内的垂直起始位置
  • width - 行的水平尺寸
  • height - 行的垂直尺寸

使用这些值,我们可以为每一行生成背景。背景从左上角到左下角再到右下角再到右上角再到左上角生成。这使得计算角落(内角或外角)变得容易。

内角和外角的半径是根据行高度(由行度量提供)和给定的innerRadiusouterRadius动态计算的。默认情况下,innerRadius10.0outerRadius10.0。为了保持正确的圆润度,这些值必须在0.0(最小值)和20.0(最大值)之间,否则绘制将超出范围。

贡献

所有贡献都欢迎!

完整示例代码

以下是一个完整的示例代码,展示了如何使用rounded_text_field插件:

import 'dart:math';

import 'package:flutter/material.dart';

import 'package:rounded_text_field/rounded_background_text.dart';

final _primaryAndAccentColors = [...Colors.primaries, ...Colors.accents];

enum _HighlightTextType { field, text, span, selectableText }

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  [@override](/user/override)
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  late final ScrollController colorsController;
  final controller = TextEditingController();

  double fontSize = 20.0;
  double innerRadius = kDefaultInnerRadius;
  double outerRadius = kDefaultOuterRadius;

  TextAlign textAlign = TextAlign.center;
  FontWeight fontWeight = FontWeight.bold;
  _HighlightTextType type = _HighlightTextType.text;

  late Color selectedColor;

  [@override](/user/override)
  void initState() {
    super.initState();

    final initialIndex = Random().nextInt(_primaryAndAccentColors.length);
    selectedColor = _primaryAndAccentColors[initialIndex];

    colorsController = ScrollController(
      initialScrollOffset: 40.0 * initialIndex,
    );
  }

  [@override](/user/override)
  void dispose() {
    controller.dispose();
    colorsController.dispose();
    super.dispose();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Rounded Background Showcase',
      theme: ThemeData(primarySwatch: Colors.blue, brightness: Brightness.dark),
      home: Scaffold(
        body: SafeArea(
          child: Column(children: [
            Material(
              child: Row(children: [
                const VerticalDivider(),
                Expanded(
                  child: DropdownButton<FontWeight>(
                    isExpanded: true,
                    value: fontWeight,
                    onChanged: (w) => setState(
                      () => fontWeight = w ?? FontWeight.normal,
                    ),
                    icon: const Icon(Icons.format_bold),
                    items: FontWeight.values.map((e) {
                      return DropdownMenuItem(
                        value: e,
                        child: Text('$e'.replaceAll('FontWeight.', '')),
                      );
                    }).toList(),
                  ),
                ),
                const VerticalDivider(),
                Expanded(
                  child: DropdownButton<TextAlign>(
                    value: textAlign,
                    onChanged: (align) => setState(
                      () => textAlign = align ?? TextAlign.center,
                    ),
                    icon: Icon(() {
                      switch (textAlign) {
                        case TextAlign.center:
                          return Icons.format_align_center;
                        case TextAlign.end:
                        case TextAlign.right:
                          return Icons.format_align_right;
                        case TextAlign.start:
                        case TextAlign.left:
                          return Icons.format_align_left;
                        default:
                          return null;
                      }
                    }()),
                    isExpanded: true,
                    items: const [
                      DropdownMenuItem(
                        value: TextAlign.start,
                        child: Text('Start'),
                      ),
                      DropdownMenuItem(
                        value: TextAlign.center,
                        child: Text('Center'),
                      ),
                      DropdownMenuItem(
                        value: TextAlign.end,
                        child: Text('End'),
                      ),
                    ],
                  ),
                ),
                const VerticalDivider(),
                Expanded(
                  child: DropdownButton<_HighlightTextType>(
                    value: type,
                    onChanged: (t) => setState(
                      () => type = t ?? _HighlightTextType.field,
                    ),
                    icon: const Icon(Icons.text_fields),
                    isExpanded: true,
                    items: const [
                      DropdownMenuItem(
                        value: _HighlightTextType.field,
                        child: Text('Field'),
                      ),
                      DropdownMenuItem(
                        value: _HighlightTextType.text,
                        child: Text('Text'),
                      ),
                      DropdownMenuItem(
                        value: _HighlightTextType.selectableText,
                        child: Text('Selectable Text'),
                      ),
                      DropdownMenuItem(
                        value: _HighlightTextType.span,
                        child: Text('Span'),
                      ),
                    ],
                  ),
                ),
                const VerticalDivider(),
              ]),
            ),
            Expanded(
              child: Padding(
                padding: const EdgeInsets.all(12.0),
                child: Center(
                  child: () {
                    final textColor = selectedColor.computeLuminance() > 0.5
                        ? Colors.black
                        : Colors.white;
                    switch (type) {
                      case _HighlightTextType.field:
                        return RoundedBackgroundTextField(
                          controller: controller,
                          backgroundColor: selectedColor,
                          textAlign: textAlign,
                          hint: 'Type your text here',
                          style: TextStyle(
                            fontSize: fontSize,
                            fontWeight: fontWeight,
                            color: textColor,
                          ),
                          innerRadius: innerRadius,
                          outerRadius: outerRadius,
                        );
                      case _HighlightTextType.text:
                        return RoundedBackgroundText(
                          '''Rounded Background Text Showcase
It handles well all font sizes and weights, as well as text alignments
Contributions are welcome!
Done with so much <3 by [@bdlukaa](/user/bdlukaa)''',
                          backgroundColor: selectedColor,
                          textAlign: textAlign,
                          style: TextStyle(
                            fontSize: fontSize,
                            fontWeight: fontWeight,
                            color: textColor,
                          ),
                          innerRadius: innerRadius,
                          outerRadius: outerRadius,
                        );
                      case _HighlightTextType.selectableText:
                        return RoundedBackgroundText.selectable(
                          '''Rounded Background Text Showcase

It handles well all font sizes and weights, as well as text alignments
Contributions are welcome!
Done with so much <3 by [@bdlukaa](/user/bdlukaa)''',
                          backgroundColor: selectedColor,
                          textAlign: textAlign,
                          style: TextStyle(
                            fontSize: fontSize,
                            fontWeight: fontWeight,
                            color: textColor,
                          ),
                          innerRadius: innerRadius,
                          outerRadius: outerRadius,
                        );
                      case _HighlightTextType.span:
                        return RichText(
                          textAlign: textAlign,
                          text: TextSpan(
                            text: 'You can use this to ',
                            style: TextStyle(
                              fontSize: fontSize,
                              fontWeight: fontWeight,
                              color: Colors.white,
                            ),
                            children: [
                              RoundedBackgroundTextSpan(
                                text: 'highlight important stuff inside a text',
                                backgroundColor: selectedColor,
                                innerRadius: innerRadius,
                                outerRadius: outerRadius,
                                textAlign: textAlign,
                                style: TextStyle(
                                  fontSize: fontSize,
                                  fontWeight: fontWeight,
                                  color: textColor,
                                ),
                              ),
                              const TextSpan(text: ' and stuff like that'),
                            ],
                          ),
                        );
                    }
                  }(),
                ),
              ),
            ),
            Row(children: [
              GestureDetector(
                onTap: () {
                  colorsController.animateTo(
                    (colorsController.position.pixels - 40),
                    duration: const Duration(milliseconds: 300),
                    curve: Curves.ease,
                  );
                },
                child: const Icon(Icons.chevron_left),
              ),
              const Spacer(),
              GestureDetector(
                onTap: () {
                  colorsController.animateTo(
                    (colorsController.position.pixels + 40),
                    duration: const Duration(milliseconds: 300),
                    curve: Curves.ease,
                  );
                },
                child: const Icon(Icons.chevron_right),
              ),
            ]),
            Material(
              child: SingleChildScrollView(
                controller: colorsController,
                padding: const EdgeInsets.only(left: 8.0, right: 8.0, top: 8.0),
                scrollDirection: Axis.horizontal,
                child: Wrap(
                  runSpacing: 10.0,
                  spacing: 10.0,
                  alignment: WrapAlignment.center,
                  children: _primaryAndAccentColors.map((color) {
                    return MouseRegion(
                      cursor: SystemMouseCursors.click,
                      child: GestureDetector(
                        onTap: () => setState(() => selectedColor = color),
                        child: AnimatedContainer(
                          duration: kThemeChangeDuration,
                          curve: Curves.bounceInOut,
                          height: 30.0,
                          width: 30.0,
                          decoration: BoxDecoration(
                            color: color,
                            borderRadius: BorderRadius.circular(2.0),
                            border: Border.all(
                              color: color.computeLuminance() > 0.5
                                  ? Colors.black
                                  : Colors.white,
                              width: 2.5,
                              style: selectedColor == color
                                  ? BorderStyle.solid
                                  : BorderStyle.none,
                            ),
                          ),
                        ),
                      ),
                    );
                  }).toList(),
                ),
              ),
            ),
            Material(
              child: Row(children: [
                Expanded(
                  child: Slider(
                    onChanged: (v) => setState(() => fontSize = v),
                    value: fontSize,
                    min: 8,
                    max: 30,
                    divisions: 30 - 8,
                    label: '${fontSize.toInt()}',
                  ),
                ),
                Expanded(
                  child: Slider(
                    onChanged: (v) => setState(() => innerRadius = v),
                    value: innerRadius,
                    min: 0,
                    max: 20,
                    label: '${innerRadius.toInt()}',
                    divisions: 20,
                  ),
                ),
                Expanded(
                  child: Slider(
                    onChanged: (v) => setState(() => outerRadius = v),
                    value: outerRadius,
                    min: 0,
                    max: 20,
                    label: '${outerRadius.toInt()}',
                    divisions: 20,
                  ),
                ),
              ]),
            ),
          ]),
        ),
      ),
    );
  }
}

更多关于Flutter圆角文本框插件rounded_text_field的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter圆角文本框插件rounded_text_field的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


rounded_text_field 是一个用于 Flutter 的插件,可以帮助你轻松地创建带有圆角的文本框。它提供了一种简单的方式来定制文本框的外观,包括圆角半径、边框颜色、背景颜色等。

以下是使用 rounded_text_field 插件的基本步骤:

1. 添加依赖

首先,你需要在 pubspec.yaml 文件中添加 rounded_text_field 插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  rounded_text_field: ^1.0.0  # 请根据实际情况使用最新版本

然后运行 flutter pub get 来获取依赖。

2. 导入插件

在需要使用 rounded_text_field 的 Dart 文件中导入插件:

import 'package:rounded_text_field/rounded_text_field.dart';

3. 使用 RoundedTextField

你可以在 UI 中使用 RoundedTextField 来创建一个带有圆角的文本框。以下是一个简单的示例:

import 'package:flutter/material.dart';
import 'package:rounded_text_field/rounded_text_field.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Rounded TextField Example'),
        ),
        body: Padding(
          padding: const EdgeInsets.all(16.0),
          child: RoundedTextField(
            borderRadius: 20.0, // 设置圆角半径
            borderColor: Colors.blue, // 设置边框颜色
            backgroundColor: Colors.grey[200], // 设置背景颜色
            hintText: 'Enter your text here', // 设置提示文本
            onChanged: (value) {
              // 处理文本变化
              print('Text changed: $value');
            },
          ),
        ),
      ),
    );
  }
}
回到顶部