当前位置: 首页 > news >正文

南阳网站建设制作价格asp.net 网站开发项目

南阳网站建设制作价格,asp.net 网站开发项目,wordpress积分插件,装网要多少钱Flutter 代码如何实现一个带有富文本显示和交互的页面。 前置知识点学习 RealRichText RealRichText 和 ImageSpan 不是 Flutter 框架中内置的组件#xff0c;而是自定义的组件或来自第三方库。这些组件的实现可以提供比标准 RichText 更丰富的功能#xff0c;比如在富文本…Flutter 代码如何实现一个带有富文本显示和交互的页面。 前置知识点学习 RealRichText RealRichText 和 ImageSpan 不是 Flutter 框架中内置的组件而是自定义的组件或来自第三方库。这些组件的实现可以提供比标准 RichText 更丰富的功能比如在富文本中插入图片、处理点击事件等。由于这些组件在标准 Flutter 中不存在我将解释如何可能实现类似的功能。 TextSpan TextSpan 是 Flutter 中用于构建富文本的基本组件之一。它允许你在同一个文本组件中混合和匹配不同的文本样式和手势识别功能。TextSpan 通常与 RichText 组件一起使用以显示复杂的文本布局。 TextSpan 的基本结构 TextSpan 是一个不可变的、递归的数据结构可以包含其他 TextSpan从而允许嵌套不同的文本样式。 TextSpan({TextStyle? style,String? text,ListInlineSpan? children,GestureRecognizer? recognizer,String? semanticsLabel, }) 关键属性 style: 指定文本的样式例如字体大小、颜色、粗细等。 类型为 TextStyle。 text: 要显示的文本字符串。 text 和 children 之间是互斥的如果需要在一个 TextSpan 中显示多个文本片段通常使用 children。 children: 一个 InlineSpan通常为 TextSpan的列表用于嵌套子文本。 允许创建复杂的文本结构如不同样式的文本段落。 recognizer: 用于处理文本的手势识别例如点击事件。 通常使用 TapGestureRecognizer 来处理点击事件。 semanticsLabel: 为文本提供一个可供屏幕阅读器使用的标签帮助无障碍访问。 使用示例 下面是一个简单的例子展示如何使用 TextSpan 来创建一个包含多种样式和交互的文本。 import package:flutter/gestures.dart; import package:flutter/material.dart;class RichTextExample extends StatelessWidget {const RichTextExample({super.key});overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text(Rich Text Example)),body: Center(child: RichText(text: TextSpan(text: Hello ,style: const TextStyle(color: Colors.black, fontSize: 18),children: TextSpan[const TextSpan(text: bold, style: TextStyle(fontWeight: FontWeight.bold)),const TextSpan(text: and ,),const TextSpan(text: italic,style: TextStyle(fontStyle: FontStyle.italic),),TextSpan(text: clickable ,style: const TextStyle(color: Colors.blue),recognizer: TapGestureRecognizer()..onTap () {ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text(Clickable text clicked!)),);},),const TextSpan(text: text.,),],),),),);} }ImageSpan ImageSpan 是一种在富文本中嵌入图片的技术。在 Flutter 中虽然没有直接提供一个名为 ImageSpan 的组件但你可以通过使用 WidgetSpan 来实现类似的功能。WidgetSpan 允许你在 RichText 中插入任意的 Flutter 小部件包括图片。 使用 WidgetSpan 实现 ImageSpan 的功能 WidgetSpan 是 InlineSpan 的子类可以在 TextSpan 列表中使用来嵌入小部件。通过这种方式你可以在文本段落中插入图片或者其他小部件。 示例代码 import package:flutter/material.dart;class RichTextWithImageExample extends StatelessWidget {const RichTextWithImageExample({super.key});overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text(Rich Text with Image Example)),body: Center(child: RichText(text: TextSpan(style: const TextStyle(color: Colors.black, fontSize: 18),children: InlineSpan[const TextSpan(text: This is an example of ),WidgetSpan(child: Image.asset(static/demo.png,width: 24,height: 24,)),const TextSpan(text: in a rich text widget.),]),),),);} }解释 RichText 和 TextSpan: RichText 用于显示复杂的文本布局TextSpan 用于定义文本的样式和内容。 WidgetSpan: WidgetSpan 可以嵌入任何小部件。在这个例子中它用于插入一个图片。 child 属性接受一个 Widget这里使用 Image.asset 来加载本地图片。 图片资源: 确保图片路径正确并在 pubspec.yaml 中声明图片资源。 例如 flutter:assets:- assets/demo.png 使用场景 图文混排: 当需要在同一个文本段落中展示图片和文本比如图标、表情符号或其他装饰性元素。 动态内容: 在文章或聊天应用中以富文本形式展示内容图片作为内嵌元素。 自定义格式: 创建带有图片的复杂格式文本比如新闻应用中的插图或注释。 通过 WidgetSpan你可以在 Flutter 的文本组件中灵活地插入图片和其他小部件实现更复杂的文本布局和丰富的用户界面体验。 TapGestureRecognizer TapGestureRecognizer 是 Flutter 中用于检测点击手势的一个手势识别器。它通常用于处理文本中的点击事件特别是在 TextSpan 中使得文本中的某些部分可以响应用户的点击操作。 基本使用 TapGestureRecognizer 是 GestureRecognizer 的一个子类它专门用于处理点击tap事件。通常情况下它与 RichText 和 TextSpan 结合使用以实现文本的可点击功能。 如何使用 TapGestureRecognizer 以下是一个简单示例展示如何在 TextSpan 中使用 TapGestureRecognizer使得文本的一部分可以被点击并响应事件 import package:flutter/gestures.dart; import package:flutter/material.dart; class TapGestureExample extends StatelessWidget {const TapGestureExample({super.key});overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text(Tap Gesture Recognizer Example)),body: Center(child: RichText(text: TextSpan(text: Click ,style: const TextStyle(color: Colors.black, fontSize: 18),children: TextSpan[TextSpan(text: here,style: const TextStyle(color: Colors.blue, decoration: TextDecoration.underline),recognizer: TapGestureRecognizer()..onTap () {ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text(Text clicked!)),);},),const TextSpan(text: to see the effect.,),],),),),);} } 解释 RichText 和 TextSpan: RichText 用于显示富文本。通过 TextSpan你可以定义不同的文本样式和内容。 TapGestureRecognizer: 创建一个 TapGestureRecognizer 实例并将其分配给 TextSpan 的 recognizer 属性。 使用 ..onTap级联操作符来定义 onTap 回调函数当用户点击该文本时调用。 响应点击: 在 onTap 回调中使用 ScaffoldMessenger 显示一个 SnackBar以反馈用户的点击操作。 注意事项 释放资源: 如果在有状态的小部件中使用 TapGestureRecognizer请确保在 dispose 方法中调用 dispose 方法来释放手势识别器以避免内存泄漏。 多手势识别: TapGestureRecognizer 可以与其他类型的手势识别器一起使用。使用 GestureDetector 可以创建更复杂的手势识别场景。 用户体验: 确保可点击的文本有视觉上的提示如颜色变化或下划线以便用户能够清楚地识别哪些文本是可交互的。 通过 TapGestureRecognizer你可以为文本添加交互功能使得应用的用户界面更加动态和响应用户操作。 富文本代码实现学习 import package:flutter/gestures.dart; import package:flutter/material.dart; import package:gsy_flutter_demo/widget/rich/real_rich_text.dart;class RichTextDemoPage extends StatefulWidget {const RichTextDemoPage({super.key});override_RichTextDemoState createState() _RichTextDemoState(); }class _RichTextDemoState extends StateRichTextDemoPage {overrideWidget build(BuildContext mainContext) {return Scaffold(appBar: AppBar(title: const Text(RichTextDemoPage),),body: Container(margin: const EdgeInsets.all(10),child: Builder(builder: (context) {return Center(child: RealRichText([TextSpan(text: A Text Link,style: const TextStyle(color: Colors.red, fontSize: 14),recognizer: TapGestureRecognizer()..onTap () {show(context, Link Clicked.);},),ImageSpan(const AssetImage(static/demo.png),imageWidth: 24,imageHeight: 24,),ImageSpan(const AssetImage(static/demo.png),imageWidth: 24,imageHeight: 24,margin: const EdgeInsets.symmetric(horizontal: 10)),const TextSpan(text: 哈哈哈,style: TextStyle(color: Colors.yellow, fontSize: 14),),TextSpan(text: Somebody,style: const TextStyle(color: Colors.black,fontSize: 14,fontWeight: FontWeight.bold),recognizer: TapGestureRecognizer()..onTap () {show(context, Link Clicked.);},),TextSpan(text: #RealRichText# ,style: const TextStyle(color: Colors.blue, fontSize: 14),recognizer: TapGestureRecognizer()..onTap () {show(context, Link Clicked.);},),const TextSpan(text: showing a bigger image,style: TextStyle(color: Colors.black, fontSize: 14),),ImageSpan(const AssetImage(static/demo.png),imageWidth: 24,imageHeight: 24,margin: const EdgeInsets.symmetric(horizontal: 5)),const TextSpan(text: and seems working perfect……,style: TextStyle(color: Colors.black, fontSize: 14),),]),);}),),);}show(context, text) {ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(text),action: SnackBarAction(label: ACTION,onPressed: () {ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text(You pressed snackbar\s action.),));},),));} }三方flutter库中的富文本实现源码 import dart:ui as ui show Image;import package:flutter/material.dart; import package:flutter/rendering.dart;/// According to the related Flutter Issues(#2022) , /// Inline-Image-In-Text is a long-time(2 years) missing feature since RichText(or the underlying Paragraph) does only support pure text. /// But we can solve this problem in a simple/tricky way: /// /// 1. Regarde the images as a particular blank TextSpan, /// convert images width and height to textspans letterSpacing and fontSize. /// the origin paragraph will do the layout operation and leave the desired image space for us. /// 2. Override the paint function /// calculate the right offset via the getOffsetForCaret() api to draw the image over the space. /// /// The only thing you have to do is converting your origin text to a TextSpan/ImageSpan List first. /// /// {tool sample} /// /// dart /// RealRichText([ /// TextSpan( /// text: showing a bigger image, /// style: TextStyle(color: Colors.black, fontSize: 14), /// ), /// ImageSpan( /// AssetImage(packages/real_rich_text/images/emoji_10.png), /// width: 40, /// height: 40, /// ), /// TextSpan( /// text: and seems working perfect……, /// style: TextStyle(color: Colors.black, fontSize: 14), /// ), /// ]) /// /// {end-tool} /// class RealRichText extends Text {final ListTextSpan textSpanList;const RealRichText(this.textSpanList, {super.key,TextStyle? style,TextAlign textAlign TextAlign.start,TextDirection? textDirection,bool softWrap true,TextOverflow overflow TextOverflow.clip,TextScaler? textScaler,int? maxLines,Locale? locale,}) : super(,style: style,textAlign: textAlign,textDirection: textDirection,softWrap: softWrap,overflow: overflow,textScaler: textScaler,maxLines: maxLines,locale: locale);ListTextSpan extractAllNestedChildren(TextSpan textSpan) {if (textSpan.children null || textSpan.children!.isEmpty) {return [textSpan];}ListTextSpan childrenSpan [];for (var child in textSpan.children!) {childrenSpan.addAll(extractAllNestedChildren(child as TextSpan));}return childrenSpan;}overrideWidget build(BuildContext context) {final DefaultTextStyle defaultTextStyle DefaultTextStyle.of(context);TextStyle? effectiveTextStyle style;if (style null || style!.inherit) {effectiveTextStyle defaultTextStyle.style.merge(style);}if (MediaQuery.boldTextOf(context)) {effectiveTextStyle effectiveTextStyle!.merge(const TextStyle(fontWeight: FontWeight.bold));}TextSpan textSpan TextSpan(style: effectiveTextStyle,text: ,children: extractAllNestedChildren(TextSpan(style: effectiveTextStyle,text: ,children: textSpanList,)));// pass the context to ImageSpan to create a ImageConfigurationfor (var f in textSpan.children!) {if (f is ImageSpan) {f.updateImageConfiguration(context);}}Widget result _RichTextWrapper(textAlign: textAlign ?? defaultTextStyle.textAlign ?? TextAlign.start,textDirection: textDirection,// RichText uses Directionality.of to obtain a default if this is null.locale: locale,// RichText uses Localizations.localeOf to obtain a default if this is nullsoftWrap: softWrap ?? defaultTextStyle.softWrap,overflow: overflow ?? defaultTextStyle.overflow,textScaler: textScaler ?? MediaQuery.textScalerOf(context),maxLines: maxLines ?? defaultTextStyle.maxLines,text: textSpan);if (semanticsLabel ! null) {result Semantics(textDirection: textDirection,label: semanticsLabel,child: ExcludeSemantics(child: result,));}return result;} }/// Since flutter engine does not support inline-image for now, we have to support this feature via a tricky solution: /// convert image to a particular TextSpan whose text always be \u200B(a zero-width-space). /// set letterSpacing by the required image width /// set fontSize by the required image height class ImageSpan extends TextSpan {final double imageWidth;final double imageHeight;final EdgeInsets? margin;final ImageProvider imageProvider;final ImageResolver imageResolver;ImageSpan(this.imageProvider, {this.imageWidth 14.0,this.imageHeight 14.0,this.margin,super.recognizer,}) : imageResolver ImageResolver(imageProvider),super(style: TextStyle(color: Colors.transparent,letterSpacing:imageWidth (margin null ? 0 : margin.horizontal),height: 1,fontSize: (imageHeight / 1.15) (margin null ? 0 : margin.vertical)),text: \u200B,children: []);void updateImageConfiguration(BuildContext context) {imageResolver.updateImageConfiguration(context, imageWidth, imageHeight);}double get width imageWidth (margin null ? 0 : margin!.horizontal);double get height imageHeight (margin null ? 0 : margin!.vertical); }typedef ImageResolverListener void Function(ImageInfo imageInfo, bool synchronousCall);class ImageResolver {final ImageProvider imageProvider;ImageStream? _imageStream;ImageConfiguration? _imageConfiguration;ui.Image? image;ImageResolverListener? _listener;ImageResolver(this.imageProvider);/// set the ImageConfiguration from outsidevoid updateImageConfiguration(BuildContext context, double width, double height) {_imageConfiguration createLocalImageConfiguration(context,size: Size(width, height),);}ImageStreamListener? imageStreamListener;void resolve(ImageResolverListener listener) {assert(_imageConfiguration ! null);final ImageStream? oldImageStream _imageStream;_imageStream imageProvider.resolve(_imageConfiguration!);assert(_imageStream ! null);_listener listener;if (_imageStream!.key ! oldImageStream?.key) {if (imageStreamListener ! null) {oldImageStream?.removeListener(imageStreamListener!);}imageStreamListener ?? ImageStreamListener(_handleImageChanged);_imageStream!.addListener(imageStreamListener!);}}void _handleImageChanged(ImageInfo imageInfo, bool synchronousCall) {image imageInfo.image;_listener?.call(imageInfo, synchronousCall);}void addListening() {if (_listener ! null) {imageStreamListener ?? ImageStreamListener(_handleImageChanged);_imageStream?.addListener(imageStreamListener!);}}void stopListening() {if (imageStreamListener ! null) {_imageStream?.removeListener(imageStreamListener!);}} }/// Just a subclass of RichText for overriding createRenderObject /// to return a [_RealRichRenderParagraph] object /// /// No more special purpose. class _RichTextWrapper extends RichText {_RichTextWrapper({required TextSpan super.text,super.textAlign,super.textDirection,super.softWrap,super.overflow,super.textScaler,super.maxLines,super.locale,}) : assert(maxLines null || maxLines 0);overrideRenderParagraph createRenderObject(BuildContext context) {assert(textDirection ! null || debugCheckHasDirectionality(context));return _RealRichRenderParagraph(text as TextSpan,textAlign: textAlign,textDirection: textDirection ?? Directionality.of(context),softWrap: softWrap,overflow: overflow,textScaler: textScaler,maxLines: maxLines,locale: locale ?? Localizations.localeOf(context),);} }/// paint the image on the top of those ImageSpans blank space class _RealRichRenderParagraph extends RenderParagraph {_RealRichRenderParagraph(TextSpan super.text,{required super.textAlign,required super.textDirection,required super.softWrap,required super.overflow,required super.textScaler,super.maxLines,super.locale});overridevoid paint(PaintingContext context, Offset offset) {super.paint(context, offset);// Here it is!paintImageSpan(context, offset);}overridevoid attach(covariant Object owner) {super.attach(owner as PipelineOwner);for (var textSpan in (text as TextSpan).children!) {if (textSpan is ImageSpan) {textSpan.imageResolver.addListening();}}}overridevoid detach() {super.detach();for (var textSpan in (text as TextSpan).children!) {if (textSpan is ImageSpan) {textSpan.imageResolver.stopListening();}}}overridevoid performLayout() {super.performLayout();debugPrint(size $size);}/// this method draws inline-image over blank text space.void paintImageSpan(PaintingContext context, Offset offset) {final Canvas canvas context.canvas;final Rect bounds offset size;debugPrint(_RealRichRenderParagraph offset$offset bounds$bounds);canvas.save();int textOffset 0;for (TextSpan textSpanin (text as TextSpan).children as IterableTextSpan) {if (textSpan is ImageSpan) {// this is the top-center point of the ImageSpanOffset offsetForCaret getOffsetForCaret(TextPosition(offset: textOffset),bounds,);// found this is a overflowed image. ignore itif (textOffset ! 0 offsetForCaret.dx 0 offsetForCaret.dy 0) {return;}// this is the top-left point of the ImageSpan.// Usually, offsetForCaret indicates the top-center offset// except the first text which is always (0, 0)Offset topLeftOffset Offset(offset.dx offsetForCaret.dx -(textOffset 0 ? 0 : textSpan.width / 2),offset.dy offsetForCaret.dy);debugPrint(_RealRichRenderParagraph ImageSpan, textOffset $textOffset, offsetForCaret$offsetForCaret, topLeftOffset$topLeftOffset);// if image is not ready: wait for async ImageInfoif (textSpan.imageResolver.image null) {textSpan.imageResolver.resolve((imageInfo, synchronousCall) {if (synchronousCall) {paintImage(canvas: canvas,rect: topLeftOffset Size(textSpan.width, textSpan.height),image: textSpan.imageResolver.image!,fit: BoxFit.scaleDown,alignment: Alignment.center);} else {if (owner null || !owner!.debugDoingPaint) {markNeedsPaint();}}});textOffset textSpan.toPlainText().length;continue;}// else: just paint it. bottomCenter Alignment seems better...paintImage(canvas: canvas,rect: topLeftOffset Size(textSpan.width, textSpan.height),image: textSpan.imageResolver.image!,fit: BoxFit.scaleDown,alignment: Alignment.center);}textOffset textSpan.toPlainText().length;}canvas.restore();} }
http://www.w-s-a.com/news/447927/

相关文章:

  • 建设购物网站要求cnzz数据统计
  • 深圳自适应网站建设价格广东网站建设软件
  • 网页设计介绍北京网站自己做彩票网站
  • 最牛论坛网站app生成链接
  • 用jsp做的网站源代码网站优化说明
  • 网站建设公司名字甘肃省和住房建设厅网站
  • 做外贸网站需要什么卡网站建设公司怎样
  • 网站关键词密度怎么计算的中文版wordpress
  • asp网站建设教程如何在线上推广自己的产品
  • 电脑网站你懂我意思正能量济南网站建设公司熊掌号
  • 杂志社网站建设萧山区网站建设
  • 电商网站前端制作分工网站怎做百度代码统计
  • 免费的html大作业网站网站开发心得500字
  • 临时工找工作网站做美缝帮别人做非法网站
  • 深圳网站建设 设计创公司新昌网站开发
  • 唐山教育平台网站建设上海装修网官网
  • 一个公司做多个网站什么行业愿意做网站
  • 成都龙泉建设网站免费域名app官方下载
  • xss网站怎么搭建如何用wordpress站群
  • 怎样做网站外链supercell账号注册网站
  • 阿里巴巴网站是用什么技术做的哪些网站做推广比较好
  • 做网站go和python手机如何创网站
  • 网站开发进修网站做301将重定向到新域名
  • 公司网站开发费用账务处理ucenter wordpress
  • 六站合一的优势少儿编程机构
  • 软件开发与网站开发学做美食网站哪个好
  • 网站搜索 收录优化百度推广页面投放
  • 响应式网站的优点浙江省网站域名备案
  • 网站安全 扫描深圳被点名批评
  • 在哪个网站可以一对一做汉教网站优化策略