Flutter控件之文本Text封装

Flutter控件之基类Widget封装

上篇文章,我们简单针对Widget做了一个基类封装,拓展出了很多常见又易用的属性,比如宽高,内外边距等等,很方便的为接下来的各个基础组件的封装,提供极大的便利,在上篇文章中,诉说了BaseWidget可以单独使用,也可以让别的组件继承使用,目的就是为了拓展,而本篇文章就是基于上篇,我们拓展一下Text组件。

本篇文章的内容大概如下:

1、实际的效果一览

2、Text相关属性分析

3、源码和具体使用

4、相关总结

一、实际的效果一览

文本Text比较简单,除了基类BaseWidget所提供的属性之外,又简单的扩展了部分属性,比如图文和富文本,都是系统原生的提供的,做了简单的封装。

二、Text相关属性分析

关于文本的属性,为什么要去继承BaseWidget,也就是上篇封装的基类,一个重要的原因就是,拓展文本的点击,内外边距和相关背景等属性,方便在实际的开发中进行调用。

文本所提供的常见属性,如文字的大小,颜色等,我们可以原封不动的抛出去,毕竟这都是基本的属性,我们没必要再一一自己实现,为了更好的符合实际的开发需要,比如富文本,带有Icon等等,我们尽量也拓展一下。

自定义的文本属性相对不是很多,大致如下,这些属性,还是那句话,需要根据实际的需求和业务,我们选择性进行使用。

属性

类型

概述

text

String

文本内容

style

TextStyle

文本样式

leftIcon

String

左边的图片

leftIconWidth

double

左边的图片宽度

leftIconHeight

double

左边的图片高度

iconMarginRight

double

图片距离右边的文字距离

rightIcon

String

右边的图片

rightIconWidth

double

右边的图片宽度

rightIconHeight

double

右边的图片高度

iconMarginLeft

double

图片距离左边的文字距离

topIcon

String

上边的图片

topIconWidth

double

上边的图片宽度

topIconHeight

double

上边的图片高度

iconMarginBottom

double

图片距离下边的文字距离

bottomIcon

String

下边的图片

bottomIconWidth

double

下边的图片宽度

bottomIconHeight

double

下边的图片高度

iconMarginTop

double

图片距离上边的文字距离

mainAxisAlignment

MainAxisAlignment

文字的相对父位置

textOverflow

TextOverflow

文字溢出方式

textAlign

TextAlign

文字位置

maxLines

int

最大行数

richList

List<TextRichBean>

富文本数据

onRichClick

Function(int, TextRichBean)

富文本点击事件

三、源码和具体使用

源码相对比较简单,毕竟都是系统的Api,无非就是做了一个简单的封装,首先是继承了BaseWidget,实现了getWidget方法,这个很重要,因为所有的组件效果,都是从这个方法里进行渲染的。

关于这个Text类,需要注意是,如果你想把基类的属性拓展出去,那么就可以在构造方法里进行super一下,具体需要拓展哪些,完全按实际的业务去走,并不是所有的属性都需要拓展。

相关注释已经标记,大家可以直接使用。

自定义文本源码

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

import '../../base/base_widget.dart';
import '../../data/bean/text_rich_bean.dart';

///AUTHOR:AbnerMing
///DATE:2023/5/19
///INTRODUCE:文本控件 Text

class VipText extends BaseWidget {
  final String text; //文本内容
  final TextStyle? style; //文本样式
  final String? leftIcon; //左边的图片
  final double? leftIconWidth; //左边的图片宽度
  final double? leftIconHeight; //左边的图片高度
  final double? iconMarginRight; //图片距离右边的文字距离
  final String? rightIcon; //右边的图片
  final double? rightIconWidth; //右边的图片宽度
  final double? rightIconHeight; //右边的图片高度
  final double? iconMarginLeft; //图片距离左边的文字距离
  final String? topIcon; //上边的图片
  final double? topIconWidth; //上边的图片宽度
  final double? topIconHeight; //上边的图片高度
  final double? iconMarginBottom; //图片距离下边的文字距离
  final String? bottomIcon; //下边的图片
  final double? bottomIconWidth; //下边的图片宽度
  final double? bottomIconHeight; //下边的图片高度
  final double? iconMarginTop; //图片距离上边的文字距离
  final MainAxisAlignment? mainAxisAlignment; //文字的位置
  final TextOverflow? textOverflow; //文字溢出方式
  final TextAlign? textAlign;//文字位置
  final int? maxLines;//最大行数
  final List<TextRichBean>? richList; //富文本数据
  final Function(int, TextRichBean)? onRichClick; //富文本点击事件

  const VipText(this.text,
      {super.key,
      this.style,
      this.leftIcon,
      this.leftIconWidth = 22,
      this.leftIconHeight = 22,
      this.iconMarginRight = 0,
      this.rightIcon,
      this.rightIconWidth = 22,
      this.rightIconHeight = 22,
      this.iconMarginLeft = 0,
      this.topIcon,
      this.topIconWidth = 22,
      this.topIconHeight = 22,
      this.iconMarginBottom = 0,
      this.bottomIcon,
      this.bottomIconWidth = 22,
      this.bottomIconHeight = 22,
      this.iconMarginTop = 0,
      this.mainAxisAlignment = MainAxisAlignment.center,
      this.textOverflow,
      this.textAlign,
      this.maxLines,
      this.richList,
      this.onRichClick,
      super.width,
      super.height,
      super.margin,
      super.marginLeft,
      super.marginTop,
      super.marginRight,
      super.marginBottom,
      super.padding,
      super.paddingLeft,
      super.paddingTop,
      super.paddingRight,
      super.paddingBottom,
      super.backgroundColor,
      super.strokeWidth,
      super.strokeColor,
      super.solidColor,
      super.radius,
      super.isCircle,
      super.leftTopRadius,
      super.rightTopRadius,
      super.leftBottomRadius,
      super.rightBottomRadius,
      super.childWidget,
      super.alignment,
      super.onClick,
      super.onDoubleClick,
      super.onLongPress});

  /*
  * 返回图片的组件
  * */
  Widget getImageWidget(String icon, double width, double height) {
    if (icon.contains("http")) {
      return Image.network(icon, width: width, height: height);
    } else {
      return Image.asset(icon, width: width, height: height);
    }
  }

  @override
  Widget getWidget(BuildContext context) {
    List<Widget> widgets = [];
    //左边的Icon
    if (leftIcon != null) {
      widgets.add(getImageWidget(leftIcon!, leftIconWidth!, leftIconHeight!));
    }
    //水平中间的文字
    if (leftIcon != null || rightIcon != null) {
      widgets.add(Container(
        margin: EdgeInsets.only(left: iconMarginRight!, right: iconMarginLeft!),
        child: getTextWidget(),
      ));
    }

    //右边的Icon
    if (rightIcon != null) {
      widgets
          .add(getImageWidget(rightIcon!, rightIconWidth!, rightIconHeight!));
    }

    if (widgets.isNotEmpty) {
      return Row(
        mainAxisAlignment: mainAxisAlignment!,
        children: widgets,
      );
    }

    //上边的icon
    if (topIcon != null) {
      widgets.add(getImageWidget(topIcon!, topIconWidth!, topIconHeight!));
    }
    //垂直中间的文字
    if (topIcon != null || bottomIcon != null) {
      widgets.add(Container(
        margin: EdgeInsets.only(top: iconMarginBottom!, bottom: iconMarginTop!),
        child: getTextWidget(),
      ));
    }
    //下面的icon
    if (bottomIcon != null) {
      widgets.add(
          getImageWidget(bottomIcon!, bottomIconWidth!, bottomIconHeight!));
    }
    if (widgets.isNotEmpty) {
      return Column(
        mainAxisAlignment: mainAxisAlignment!,
        children: widgets,
      );
    }

    //富文本
    if (richList != null && richList!.isNotEmpty) {
      List<TextSpan> list = [];
      for (var a = 0; a < richList!.length; a++) {
        var richBean = richList![a];
        var textSpan = TextSpan(
            text: richBean.text,
            recognizer: TapGestureRecognizer()
              ..onTap = () {
                //点击事件
                if (onRichClick != null) {
                  onRichClick!(a, richBean);
                }
              },
            style: TextStyle(
                fontSize: richBean.textSize, color: richBean.textColor));
        list.add(textSpan);
      }
      //富文本
      return Text.rich(TextSpan(children: list));
    }
    return getTextWidget();
  }

  Widget getTextWidget() {
    return Text(
      text,
      overflow: textOverflow,
      textAlign: textAlign,
      maxLines: maxLines,
      style: style,
    );
  }
}

TextRichBean

用于富文本数据渲染

import 'package:flutter/material.dart';

///AUTHOR:AbnerMing
///DATE:2023/5/19
///INTRODUCE:文本控件之富文本对象

class TextRichBean {
  String? text; //文字
  Color? textColor; //文字颜色
  double? textSize; //文字大小
  String? link; //文字链接
  TextRichBean({this.text, this.textColor, this.textSize, this.link});
}

具体使用

简单的就可以如下使用,需要什么属性,直接书写即可,比如内外边距,点击事件等等。

 VipText("普通文字", marginTop: 10, onClick: () {
   print("普通文字");
 })

所有使用方式案例(可直接复制使用)

import 'package:flutter/material.dart';

import '../../data/bean/text_rich_bean.dart';
import '../widget/vip_text.dart';

///AUTHOR:AbnerMing
///DATE:2023/5/19
///INTRODUCE:文本Text效果

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

  @override
  State<StatefulWidget> createState() => _TextPageState();
}

class _TextPageState extends State<TextPage> {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        VipText("普通文字", marginTop: 10, onClick: () {
          print("普通文字");
        }),
        VipText("加粗文字",
            marginTop: 10,
            style: const TextStyle(fontWeight: FontWeight.bold), onClick: () {
          print("加粗文字");
        }),
        VipText("倾斜文字",
            marginTop: 10,
            style: const TextStyle(fontStyle: FontStyle.italic), onClick: () {
          print("倾斜文字");
        }),
        VipText("文字背景颜色", marginTop: 10, backgroundColor: Colors.red,
            onClick: () {
          print("文字背景颜色");
        }),
        VipText("文字圆角背景",
            marginTop: 10,
            radius: 10,
            solidColor: Colors.red,
            padding: 3, onClick: () {
          print("文字圆角背景");
        }),
        VipText("文字圆角框背景",
            marginTop: 10,
            radius: 10,
            strokeColor: Colors.red,
            padding: 3, onClick: () {
          print("文字圆角框背景");
        }),
        VipText("圆",
            marginTop: 10,
            isCircle: true,
            solidColor: Colors.cyan,
            padding: 8, onClick: () {
          print("圆");
        }),
        VipText("下划线文字",
            marginTop: 10,
            style: const TextStyle(decoration: TextDecoration.underline),
            onClick: () {
          print("下划线文字");
        }),
        VipText("下划波浪线文字",
            marginTop: 10,
            style: const TextStyle(
              decoration: TextDecoration.underline,
              decorationStyle: TextDecorationStyle.wavy,
            ), onClick: () {
          print("下划波浪线文字");
        }),
        VipText("删除线文字",
            marginTop: 10,
            style: const TextStyle(decoration: TextDecoration.lineThrough),
            onClick: () {
          print("删除线文字");
        }),
        ShaderMask(
          shaderCallback: (Rect bounds) {
            return const LinearGradient(
              colors: [Colors.red, Colors.blue],
            ).createShader(Offset.zero & bounds.size);
          },
          child: VipText(
            '文字设置渐变色',
            marginTop: 10,
            style: const TextStyle(
              fontSize: 16,
              color: Colors.white,
              fontWeight: FontWeight.bold,
            ),
            onClick: () {
              print("文字设置渐变色");
            },
          ),
        ),
        VipText("改变颜色",
            style: const TextStyle(color: Colors.red),
            marginTop: 10, onClick: () {
          print("改变颜色");
        }),
        VipText("左边带有Icon",
            marginTop: 10,
            //可以是网络图片或assets图片
            leftIcon: "https://www.vipandroid.cn/ming/image/gan.png",
            iconMarginRight: 10, onClick: () {
          print("左边带有Icon");
        }),
        VipText("右边带有Icon",
            marginTop: 10,
            //可以是网络图片或assets图片
            rightIcon: "https://www.vipandroid.cn/ming/image/gan.png",
            iconMarginLeft: 10, onClick: () {
          print("左边带有Icon");
        }),
        VipText("左右边都带有Icon",
            marginTop: 10,
            //可以是网络图片或assets图片
            leftIcon: "https://www.vipandroid.cn/ming/image/gan.png",
            rightIcon: "https://www.vipandroid.cn/ming/image/gan.png",
            iconMarginRight: 10,
            iconMarginLeft: 10, onClick: () {
          print("左右边都带有Icon");
        }),
        VipText("上边带有Icon",
            marginTop: 10,
            strokeColor: Colors.red,
            //可以是网络图片或assets图片
            topIcon: "https://www.vipandroid.cn/ming/image/gan.png",
            onClick: () {
          print("上边带有Icon");
        }),
        VipText("下边带有Icon",
            strokeColor: Colors.red,
            marginTop: 10,
            //可以是网络图片或assets图片
            bottomIcon: "https://www.vipandroid.cn/ming/image/gan.png",
            onClick: () {
          print("下边带有Icon");
        }),
        VipText(
          "超出的文字展示省略号,不妨我们就简单测试一下,看看是否能实现,再多打些文字看看吧,马上就够了,不着急哈,再输入一点",
          textOverflow: TextOverflow.ellipsis,
          marginLeft: 10,
          marginRight: 10,
          maxLines: 2,
          marginTop: 10,
          onClick: () {
            print("超出文字点击");
          },
        ),
        VipText("富文本设置", richList: [
          TextRichBean(text: "我已经阅读并同意"),
          TextRichBean(text: "《用户服务协议》", textColor: Colors.red),
          TextRichBean(text: "和"),
          TextRichBean(text: "《用户隐私政策》", textColor: Colors.red)
        ], onRichClick: (position, richBean) {
          //富文本点击事件
          print(richBean.text);
        }, marginTop: 10)
      ],
    );
  }
}

四、相关总结

关于子类需要拓展父类的哪些属性,这个需要结合实际的项目和需求而定,而关于自定义组件的命名,也需要根据公司而定,好了老铁们,一个简单的文本组件就介绍到这里,希望可以帮助到大家。

猜你喜欢

转载自blog.csdn.net/ming_147/article/details/130772005