Flutter控件之文本Text封装

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

上篇文章,我们简单针对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:文本控件 TextclassVipTextextendsBaseWidget {
finalStringtext; //文本内容finalTextStyle?style; //文本样式finalString?leftIcon; //左边的图片finaldouble?leftIconWidth; //左边的图片宽度finaldouble?leftIconHeight; //左边的图片高度finaldouble?iconMarginRight; //图片距离右边的文字距离finalString?rightIcon; //右边的图片finaldouble?rightIconWidth; //右边的图片宽度finaldouble?rightIconHeight; //右边的图片高度finaldouble?iconMarginLeft; //图片距离左边的文字距离finalString?topIcon; //上边的图片finaldouble?topIconWidth; //上边的图片宽度finaldouble?topIconHeight; //上边的图片高度finaldouble?iconMarginBottom; //图片距离下边的文字距离finalString?bottomIcon; //下边的图片finaldouble?bottomIconWidth; //下边的图片宽度finaldouble?bottomIconHeight; //下边的图片高度finaldouble?iconMarginTop; //图片距离上边的文字距离finalMainAxisAlignment?mainAxisAlignment; //文字的位置finalTextOverflow?textOverflow; //文字溢出方式finalTextAlign?textAlign;//文字位置finalint?maxLines;//最大行数finalList<TextRichBean>?richList; //富文本数据finalFunction(int, TextRichBean)?onRichClick; //富文本点击事件constVipText(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});
/** 返回图片的组件* */WidgetgetImageWidget(Stringicon, doublewidth, doubleheight) {
if (icon.contains("http")) {
returnImage.network(icon, width: width, height: height);
    } else {
returnImage.asset(icon, width: width, height: height);
    }
  }
@overrideWidgetgetWidget(BuildContextcontext) {
List<Widget>widgets= [];
//左边的Iconif (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(),
      ));
    }
//右边的Iconif (rightIcon!=null) {
widgets          .add(getImageWidget(rightIcon!, rightIconWidth!, rightIconHeight!));
    }
if (widgets.isNotEmpty) {
returnRow(
mainAxisAlignment: mainAxisAlignment!,
children: widgets,
      );
    }
//上边的iconif (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(),
      ));
    }
//下面的iconif (bottomIcon!=null) {
widgets.add(
getImageWidget(bottomIcon!, bottomIconWidth!, bottomIconHeight!));
    }
if (widgets.isNotEmpty) {
returnColumn(
mainAxisAlignment: mainAxisAlignment!,
children: widgets,
      );
    }
//富文本if (richList!=null&&richList!.isNotEmpty) {
List<TextSpan>list= [];
for (vara=0; a<richList!.length; a++) {
varrichBean=richList![a];
vartextSpan=TextSpan(
text: richBean.text,
recognizer: TapGestureRecognizer()
              ..onTap= () {
//点击事件if (onRichClick!=null) {
onRichClick!(a, richBean);
                }
              },
style: TextStyle(
fontSize: richBean.textSize, color: richBean.textColor));
list.add(textSpan);
      }
//富文本returnText.rich(TextSpan(children: list));
    }
returngetTextWidget();
  }
WidgetgetTextWidget() {
returnText(
text,
overflow: textOverflow,
textAlign: textAlign,
maxLines: maxLines,
style: style,
    );
  }
}


TextRichBean


用于富文本数据渲染


import'package:flutter/material.dart';
///AUTHOR:AbnerMing///DATE:2023/5/19///INTRODUCE:文本控件之富文本对象classTextRichBean {
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效果classTextPageextendsStatefulWidget {
constTextPage({super.key});
@overrideState<StatefulWidget>createState() =>_TextPageState();
}
class_TextPageStateextendsState<TextPage> {
@overrideWidgetbuild(BuildContextcontext) {
returnColumn(
children: [
VipText("普通文字", marginTop: 10, onClick: () {
print("普通文字");
        }),
VipText("加粗文字",
marginTop: 10,
style: constTextStyle(fontWeight: FontWeight.bold), onClick: () {
print("加粗文字");
        }),
VipText("倾斜文字",
marginTop: 10,
style: constTextStyle(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: constTextStyle(decoration: TextDecoration.underline),
onClick: () {
print("下划线文字");
        }),
VipText("下划波浪线文字",
marginTop: 10,
style: constTextStyle(
decoration: TextDecoration.underline,
decorationStyle: TextDecorationStyle.wavy,
            ), onClick: () {
print("下划波浪线文字");
        }),
VipText("删除线文字",
marginTop: 10,
style: constTextStyle(decoration: TextDecoration.lineThrough),
onClick: () {
print("删除线文字");
        }),
ShaderMask(
shaderCallback: (Rectbounds) {
returnconstLinearGradient(
colors: [Colors.red, Colors.blue],
            ).createShader(Offset.zero&bounds.size);
          },
child: VipText(
'文字设置渐变色',
marginTop: 10,
style: constTextStyle(
fontSize: 16,
color: Colors.white,
fontWeight: FontWeight.bold,
            ),
onClick: () {
print("文字设置渐变色");
            },
          ),
        ),
VipText("改变颜色",
style: constTextStyle(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)
      ],
    );
  }
}

四、相关总结

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

相关文章
|
4月前
Flutter 组件(二)文本 与 输入框组件
Flutter 组件(二)文本 与 输入框组件
70 0
|
7月前
|
缓存 Java 开发工具
Flutter的文本、图片和按钮使用
Flutter的文本、图片和按钮使用
65 0
|
10月前
|
Android开发 iOS开发 容器
Flutter控件封装之轮播图Banner
Flutter中实现轮播图的方式有很多种,比如使用三方flutter_swiper,card_swiper等等,使用这些三方,可以很快很方便的实现一个轮播图展示,基本上也能满足我们日常的开发需求,如果说,想要一些定制化的操作,那么就不得不去更改源码或者自己自定义一个,自己定义的话,Flutter中提供了原生组件PageView,可以使用它很方便的来实现一个轮播图。
188 0
|
5月前
Flutter StatefulWidget传递数据,多级控件传递数据
Flutter StatefulWidget传递数据,多级控件传递数据 在Flutter中,StatefulWidget可以通过构造函数将数据传递给其子控件,这种方式适用于一些简单的场景。但是,当存在多级嵌套控件时,将数据从祖先传递到后代可能会变得困难。在这种情况下,可以使用Flutter提供的InheritedWidget类来传递数据。
|
10月前
|
API Android开发
Flutter控件封装之视频进度条
视频控制器,三方所提供的样式,有时很难满足我们的需求,对于此情况,我们不得不在此基础上自行封装,今天所分享的文章就是一个很简单的控制器封装案例,包含了基本的播放暂停,全屏和退出全屏,以及时间和进度的展示,封装了事件回调以及各个属性的控制,基本上可以满足大部分的业务需求,即便不满足,大家也可以在此基础之上拓展。
135 0
|
10月前
|
Android开发 UED
Flutter控件之Tab选项卡封装
Tab选项卡,这是一个非常常见且权重很高的一个组件,随便打开一个App,比如掘金,如下图,首页顶部就是一个Tab选项卡,这个功能可以说,几乎每个App都会存在。
169 0
|
10月前
|
存储 Android开发
Flutter控件之图片Image封装
Flutter中偏偏原生的控件,少了很多需要又常用的属性,比如宽高,比如内外边距,又比如点击事件,如果不采取封装,视图的结构会一层嵌套一层,徒增很多的冗余代码,所以,为了简洁代码,还有为了拓展原生组件没有的属性,就不得不进行一次简单的封装,使其在调用的时候,可以很方便的实现某些功能。
|
10月前
|
API Android开发 容器
Flutter控件之基类Widget封装
基类的Widget主要确定以下几个方面,第一就是,自定义一个抽象类还是非抽象类,第二、继承方式,采取有状态还是无状态,第三、关于组件的点击方式,如何进行实现。
105 0
|
11月前
|
容器
Flutter的ClipRRect控件介绍
ClipRRect(Rounded Rectangle Clip)是Flutter中的一个控件,用于将其子控件剪裁为圆角矩形形状。
|
11月前
|
容器