You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中如何检测TextField输入的URL并实时显示预览?

Flutter实时检测TextField中URL并展示预览的实现思路

思路一:实时输入监听+正则提取URL+自定义预览组件

核心是通过TextField的输入回调触发URL检测,再渲染预览UI:

  1. 利用TextField的onChanged回调监听文本变化,每次输入时用正则匹配提取URL
  2. 常用URL正则示例:r'https?://(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)'
  3. 用Uri.tryParse验证提取到的URL合法性,避免无效链接
  4. 渲染预览组件:可以用WebView直接加载URL,或自定义卡片展示网页元信息(需配合html包解析网页的title、description、缩略图meta标签)

代码示例:

String _inputText = '';
String? _detectedUrl;

@override
Widget build(BuildContext context) {
  return Column(
    children: [
      TextField(
        onChanged: (text) {
          setState(() {
            _inputText = text;
            final urlRegex = RegExp(r'https?://(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)');
            final match = urlRegex.firstMatch(_inputText);
            _detectedUrl = match?.group(0);
          });
        },
        decoration: const InputDecoration(hintText: '输入内容...'),
        maxLines: 3,
      ),
      if (_detectedUrl != null && Uri.tryParse(_detectedUrl!)?.hasAbsolutePath == true)
        Container(
          margin: const EdgeInsets.only(top: 16),
          height: 200,
          child: WebView(
            initialUrl: _detectedUrl,
            javascriptMode: JavascriptMode.unrestricted,
          ),
        ),
    ],
  );
}

思路二:使用第三方富文本编辑器组件

借助成熟的富文本库快速实现URL检测与预览,这类组件通常内置URL识别逻辑:

  • 推荐组件:flutter_quill、zefyr
  • 优势:无需手动写正则和监听,支持自动将输入的URL转为可点击链接,部分组件支持自定义预览卡片样式
  • 示例(flutter_quill):
QuillController _controller = QuillController.basic();

@override
Widget build(BuildContext context) {
  return Column(
    children: [
      QuillToolbar.basic(controller: _controller),
      Expanded(
        child: QuillEditor(
          controller: _controller,
          readOnly: false,
          autoFocus: false,
          expands: false,
          padding: EdgeInsets.zero,
          customStyles: DefaultStyles(
            link: const TextStyle(color: Colors.blue, decoration: TextDecoration.underline),
          ),
        ),
      ),
      // 额外提取URL展示独立预览:监听document变化提取URL
    ],
  );
}

思路三:自定义TextEditingController封装检测逻辑

将URL检测逻辑封装到自定义控制器中,实现业务逻辑与UI分离,方便复用:

  1. 继承TextEditingController,重写textChanged方法实现URL检测
  2. 通过回调将检测到的URL传递给UI层

代码示例:

class UrlDetectingController extends TextEditingController {
  final ValueChanged<String?> onUrlDetected;

  UrlDetectingController({required this.onUrlDetected});

  @override
  void textChanged() {
    super.textChanged();
    final urlRegex = RegExp(r'https?://(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)');
    final match = urlRegex.firstMatch(text);
    onUrlDetected(match?.group(0));
  }
}

// 使用时
UrlDetectingController _controller = UrlDetectingController(
  onUrlDetected: (url) {
    setState(() => _detectedUrl = url);
  },
);

思路四:结合Linkify组件实现点击预览

用linkify包将文本中的URL转为可点击链接,再扩展点击事件触发预览:

  1. 用Linkify渲染输入文本,自动识别并高亮URL
  2. 给链接添加点击事件,点击时弹出预览弹窗或加载预览组件
  3. 可选:实时提取最新URL,自动展示预览卡片

代码示例:

String _inputText = '';
String? _currentUrl;

@override
Widget build(BuildContext context) {
  return Column(
    children: [
      TextField(
        onChanged: (text) {
          setState(() {
            _inputText = text;
            final urlRegex = RegExp(r'https?://(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)');
            _currentUrl = urlRegex.firstMatch(text)?.group(0);
          });
        },
        decoration: const InputDecoration(hintText: '输入内容...'),
        maxLines: 3,
      ),
      Padding(
        padding: const EdgeInsets.all(8.0),
        child: Linkify(
          text: _inputText,
          onOpen: (link) => _showUrlPreview(context, link.url),
          linkStyle: const TextStyle(color: Colors.blue),
        ),
      ),
    ],
  );
}

void _showUrlPreview(BuildContext context, String url) {
  showDialog(
    context: context,
    builder: (ctx) => Dialog(
      child: SizedBox(
        height: 300,
        width: double.maxFinite,
        child: WebView(initialUrl: url, javascriptMode: JavascriptMode.unrestricted),
      ),
    ),
  );
}

内容的提问来源于stack exchange,提问作者Yogesh Chawla

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 21:40:21