Flutter链接预览插件flutter_link_preview的使用

发布于 1周前 作者 wuwangju 来自 Flutter

Flutter链接预览插件flutter_link_preview的使用

这是一个用于预览URL内容的插件。它可以帮助开发者在应用中快速预览网页内容。

特殊功能

  • 使用多进程解析网页,避免阻塞主线程。
  • 支持内容缓存和过期机制,以更快地返回结果。
  • 更好的容错性,多种方式查找图标、标题、描述和图片。
  • 对GBK编码有更好的支持,避免乱码。
  • 优化了大文件的抓取性能。
  • 支持第二跳认证(带Cookies)。
  • 支持GIF、视频等内容捕获。
  • 支持自定义构建器。

开始使用

首先,确保已经将flutter_link_preview添加到项目的pubspec.yaml文件中:

dependencies:
  flutter_link_preview: ^1.0.0

然后,导入并使用该插件:

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

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

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'Flutter Demo',
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key key}) : super(key: key);

  [@override](/user/override)
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  TextEditingController _controller;

  [@override](/user/override)
  void initState() {
    _controller = TextEditingController(text: "https://github.com");
    super.initState();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Padding(
          padding: const EdgeInsets.all(15),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              TextField(controller: _controller),
              FlutterLinkPreview(
                key: ValueKey(_controller.value.text),
                url: _controller.value.text,
                titleStyle: const TextStyle(
                  color: Colors.blue,
                  fontWeight: FontWeight.bold,
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

运行后效果如下:

自定义渲染

可以使用builder属性来自定义预览内容的样式:

Widget _buildCustomLinkPreview(BuildContext context) {
  return FlutterLinkPreview(
    key: ValueKey("${_controller.value.text}211"),
    url: _controller.value.text,
    builder: (info) {
      if (info == null) return const SizedBox();
      if (info is WebImageInfo) {
        return CachedNetworkImage(
          imageUrl: info.image,
          fit: BoxFit.contain,
        );
      }

      final WebInfo webInfo = info;
      if (!WebAnalyzer.isNotEmpty(webInfo.title)) return const SizedBox();
      return Container(
        decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(10),
          color: const Color(0xFFF0F1F2),
        ),
        padding: const EdgeInsets.all(10),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            Row(
              children: <Widget>[
                CachedNetworkImage(
                  imageUrl: webInfo.icon ?? "",
                  imageBuilder: (context, imageProvider) {
                    return Image(
                      image: imageProvider,
                      fit: BoxFit.contain,
                      width: 30,
                      height: 30,
                      errorBuilder: (context, error, stackTrace) {
                        return const Icon(Icons.link);
                      },
                    );
                  },
                ),
                const SizedBox(width: 8),
                Expanded(
                  child: Text(
                    webInfo.title,
                    overflow: TextOverflow.ellipsis,
                  ),
                ),
              ],
            ),
            if (WebAnalyzer.isNotEmpty(webInfo.description)) ...[
              const SizedBox(height: 8),
              Text(
                webInfo.description,
                maxLines: 5,
                overflow: TextOverflow.ellipsis,
              ),
            ],
            if (WebAnalyzer.isNotEmpty(webInfo.image)) ...[
              const SizedBox(height: 8),
              CachedNetworkImage(
                imageUrl: webInfo.image,
                fit: BoxFit.contain,
              ),
            ]
          ],
        ),
      );
    },
  );
}

效果如下:

示例代码

完整的示例代码可以在以下链接找到: 点击这里查看详细示例

完整代码如下:

import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_link_preview/flutter_link_preview.dart';

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

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'Flutter Demo',
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key key}) : super(key: key);

  [@override](/user/override)
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  TextEditingController _controller;
  int _index = -1;
  final List<String> _urls = [
    "https://mp.weixin.qq.com/s/qj7gkU-Pbdcdn3zO6ZQxqg",
    "https://mp.weixin.qq.com/s/43GznPLxi5i3yOdvrlr1JQ",
    "https://m.tb.cn/h.VFcZsnK?sm=34cd13",
    "http://world.people.com.cn/n1/2020/0805/c1002-31811808.html",
    // 其他URL...
  ];

  [@override](/user/override)
  void initState() {
    _controller = TextEditingController(
        text:
            "https://www.bilibili.com/video/BV1F64y1c7hd?spm_id_from=333.851.b_7265706f7274466972737431.12");
    super.initState();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Padding(
          padding: const EdgeInsets.all(15),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              TextField(controller: _controller),
              Row(
                children: <Widget>[
                  RaisedButton(
                    onPressed: () {
                      setState(() {});
                    },
                    child: const Text("get"),
                  ),
                  const SizedBox(width: 15),
                  RaisedButton(
                    onPressed: () {
                      _index++;
                      if (_index >= _urls.length) _index = 0;
                      _controller.text = _urls[_index];
                      setState(() {});
                    },
                    child: const Text("next"),
                  ),
                  const SizedBox(width: 15),
                  RaisedButton(
                    onPressed: () {
                      _controller.clear();
                    },
                    child: const Text("clear"),
                  ),
                ],
              ),
              const SizedBox(height: 15),
              FlutterLinkPreview(
                key: ValueKey(_controller.value.text),
                url: _controller.value.text,
                titleStyle: const TextStyle(
                  color: Colors.blue,
                  fontWeight: FontWeight.bold,
                ),
              ),
              const SizedBox(height: 50),
              const Text("Custom Builder", style: TextStyle(fontSize: 20)),
              const Divider(),
              _buildCustomLinkPreview(context),
            ],
          ),
        ),
      ),
    );
  }

  Widget _buildCustomLinkPreview(BuildContext context) {
    return FlutterLinkPreview(
      key: ValueKey("${_controller.value.text}211"),
      url: _controller.value.text,
      builder: (info) {
        if (info == null) return const SizedBox();
        if (info is WebImageInfo) {
          return CachedNetworkImage(
            imageUrl: info.image,
            fit: BoxFit.contain,
          );
        }

        final WebInfo webInfo = info;
        if (!WebAnalyzer.isNotEmpty(webInfo.title)) return const SizedBox();
        return Container(
          decoration: BoxDecoration(
            borderRadius: BorderRadius.circular(10),
            color: const Color(0xFFF0F1F2),
          ),
          padding: const EdgeInsets.all(10),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              Row(
                children: <Widget>[
                  CachedNetworkImage(
                    imageUrl: webInfo.icon ?? "",
                    imageBuilder: (context, imageProvider) {
                      return Image(
                        image: imageProvider,
                        fit: BoxFit.contain,
                        width: 30,
                        height: 30,
                        errorBuilder: (context, error, stackTrace) {
                          return const Icon(Icons.link);
                        },
                      );
                    },
                  ),
                  const SizedBox(width: 8),
                  Expanded(
                    child: Text(
                      webInfo.title,
                      overflow: TextOverflow.ellipsis,
                    ),
                  ),
                ],
              ),
              if (WebAnalyzer.isNotEmpty(webInfo.description)) ...[
                const SizedBox(height: 8),
                Text(
                  webInfo.description,
                  maxLines: 5,
                  overflow: TextOverflow.ellipsis,
                ),
              ],
              if (WebAnalyzer.isNotEmpty(webInfo.image)) ...[
                const SizedBox(height: 8),
                CachedNetworkImage(
                  imageUrl: webInfo.image,
                  fit: BoxFit.contain,
                ),
              ]
            ],
          ),
        );
      },
    );
  }
}

更多关于Flutter链接预览插件flutter_link_preview的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter链接预览插件flutter_link_preview的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


flutter_link_preview 是一个用于在 Flutter 应用中显示链接预览的插件。它可以解析给定的 URL,并显示该链接的标题、描述、图片等信息。以下是如何在 Flutter 项目中使用 flutter_link_preview 的基本步骤:

1. 添加依赖

首先,在你的 pubspec.yaml 文件中添加 flutter_link_preview 依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_link_preview: ^1.0.0+3

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

2. 导入包

在你的 Dart 文件中导入 flutter_link_preview 包:

import 'package:flutter_link_preview/flutter_link_preview.dart';

3. 使用 flutter_link_preview

你可以使用 FlutterLinkPreview 小部件来显示链接预览。以下是一个简单的示例:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Link Preview Example'),
        ),
        body: Center(
          child: FlutterLinkPreview(
            url: 'https://flutter.dev', // 替换为你想要预览的链接
          ),
        ),
      ),
    );
  }
}

4. 自定义预览样式

FlutterLinkPreview 提供了一些可选的参数来自定义预览的样式。例如:

  • titleStyle: 用于自定义标题的样式。
  • bodyStyle: 用于自定义描述的样式。
  • showMultimedia: 控制是否显示多媒体内容(如图片)。
  • placeholderWidget: 在链接预览加载时显示的占位符小部件。
FlutterLinkPreview(
  url: 'https://flutter.dev',
  titleStyle: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
  bodyStyle: TextStyle(fontSize: 14, color: Colors.grey),
  showMultimedia: true,
  placeholderWidget: CircularProgressIndicator(),
)

5. 处理错误

flutter_link_preview 还提供了 onError 回调,用于处理链接预览加载失败的情况:

FlutterLinkPreview(
  url: 'https://invalid-url.com',
  onError: (error) {
    print('Error loading link preview: $error');
  },
)
回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!