Flutter未知功能插件tenor_flutter的探索使用

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

Flutter未知功能插件tenor_flutter的探索使用

Tenor Flutter

Tenor Flutter Pub Package Build Status Coverage Status Tenor Dart Stars License BSD 3-Clause

tenor_flutter 是一个将 Tenor GIF 搜索 集成到 Flutter 的插件。该插件通过使用 tenor_dart 包直接与 Tenor API V2 进行通信。

目前,该插件提供了一个可定制的 UI 体验,用于从 Tenor GIF 搜索 API 中搜索和选择 GIF 或贴纸。

Tenor Flutter Demo

如果你喜欢这个插件,请给它点个星来支持我们。

使用须知

  • 要开始使用 tenor_flutter,你需要在 Tenor 注册项目并获取 API 密钥。
  • Tenor 要求使用其 API 的项目进行适当的 归因。此插件默认启用 “Powered By Tenor” 和 “Search Tenor”。你只需要其中一个即可。

获取 Tenor API v2 密钥

  1. 登录 Google Cloud Console
  2. 创建一个 新项目
  3. 进入 Google Cloud Marketplace 并找到 Tenor API
  4. 点击 Enable 以激活它
  5. 在导航菜单中,进入 APIs & Services 标签页并选择 Credentials
  6. 点击 + Create Credentials 并选择 API key
  7. 复制生成的 API 密钥
  8. 将此 API 密钥作为参数传递给 Tenor(apiKey: 'YOUR_API_KEY')

使用方法

安装

flutter pub add tenor_flutter

遇到问题?请阅读 pub.dev 的 安装页面

导入

在需要使用的 Dart 文件中导入包:

import 'package:tenor_flutter/tenor_flutter.dart';

初始化

必须传递由 Tenor 提供的有效 apiKey。强烈建议同时传递 clientKey,这将帮助你区分哪个项目正在发出请求。

final tenorClient = Tenor(apiKey: 'YOUR_API_KEY', clientKey: 'YOUR_PROJECT_NAME');

示例

更多详细的示例请参阅 example/lib/main.dart

以下是如何显示 UI 作为底部弹出框,然后打印用户的选择。如果返回 null,则表示用户在未选择 GIF 的情况下关闭了弹出框。

final tenorClient = Tenor(apiKey: 'YOUR_API_KEY', clientKey: 'YOUR_PROJECT_NAME');
final TenorResult? result = await tenorClient.showAsBottomSheet(context: context);
print(result?.media.tinyGif?.url);

不需要 UI?

如果你希望完全自定义而不依赖于任何依赖项,可以考虑使用 Tenor Dart

赞助商

Flyclops

Domino!

Flyclops 是一家独立的移动游戏工作室,专注于休闲多人游戏,包括异步回合制和实时游戏。Flyclops 的游戏已在全球范围内被数百万人玩过。

Domino! 是一款超级上瘾、节奏快速的多人多米诺游戏,适用于 iOSAndroid。这款易于学习但难以掌握的策略游戏设计精美,令人爱不释手!

下一步计划

  • 文档
  • 测试(欢迎 贡献
  • 进一步改进

贡献

如果你看到这里,那你真是太棒了!你可以通过多种方式 贡献

  • 拾取任何标记为 “good first issue” 的问题
  • 提出任何功能或增强建议
  • 报告 bug
  • 修复 bug
  • 编写和改进文档
  • 发送 Pull Request 🙏

示例代码

import 'package:flutter/material.dart';
import 'package:flutter_config/flutter_config.dart';
import 'package:tenor_flutter/tenor_flutter.dart';
import 'package:tenor_flutter_example/examples/dark_theme.dart';
import 'package:tenor_flutter_example/examples/localization.dart';

void main() async {
  // 仅用于从 .env 文件加载 API 密钥,不是必需的
  WidgetsFlutterBinding.ensureInitialized();
  await FlutterConfig.loadEnvVariables();

  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Tenor Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(),
    );
  }
}

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

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  // 替换 apiKey 为你从 Tenor 获取的 API 密钥 > https://developers.google.com/tenor/guides/quickstart
  var tenor = Tenor(apiKey: FlutterConfig.get('TENOR_API_KEY'));
  // 定义一个结果以便稍后显示
  TenorResult? selectedResult;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: const Text('Tenor Flutter Demo'),
      ),
      body: _exampleBody(),
      floatingActionButton: Row(
        mainAxisAlignment: MainAxisAlignment.end,
        children: [
          // 默认实现 tenor flutter。显示 GIF 选择器作为底部弹出框,并更新状态中的 selectedResult。
          FloatingActionButton(
            onPressed: () async {
              final result = await tenor.showAsBottomSheet(context: context);
              setState(() {
                selectedResult = result;
              });
            },
            tooltip: 'Default',
            child: const Icon(Icons.add),
          ),
        ],
      ),
    );
  }

  // 更多示例,见:https://github.com/Flyclops/tenor_flutter/tree/main/example/lib/examples
  Widget _exampleBody() {
    final selectedGif = selectedResult?.media.tinyGif ??
        selectedResult?.media.tinyGifTransparent;
    return Center(
      child: Stack(
        alignment: Alignment.center,
        children: [
          Align(
            alignment: Alignment.topCenter,
            child: Column(
              children: [
                const SizedBox(height: 8),
                const Text('Additional Examples'),
                const SizedBox(height: 8),
                Wrap(
                  alignment: WrapAlignment.center,
                  spacing: 8,
                  children: [
                    // https://github.com/Flyclops/tenor_flutter/tree/main/example/lib/examples/dark_theme.dart
                    ElevatedButton(
                      onPressed: () => push(const DarkTheme()),
                      child: const Text('Dark Theme'),
                    ),
                    // https://github.com/Flyclops/tenor_flutter/tree/main/example/lib/examples/localization.dart
                    ElevatedButton(
                      onPressed: () => push(const Localization()),
                      child: const Text('Localization'),
                    ),
                  ],
                ),
              ],
            ),
          ),
          Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              selectedResult != null && selectedGif != null
                  ? Image.network(
                      selectedGif.url,
                      width: selectedGif.dimensions.width,
                      height: selectedGif.dimensions.height,
                    )
                  : const Text('No GIF selected'),
            ],
          ),
        ],
      ),
    );
  }

  void push(Widget page) {
    Navigator.of(context).push(
      MaterialPageRoute<String>(
        builder: (BuildContext context) {
          return page;
        },
      ),
    );
  }
}

更多关于Flutter未知功能插件tenor_flutter的探索使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter未知功能插件tenor_flutter的探索使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


探索和使用Flutter中的未知功能插件tenor_flutter时,了解其核心功能和API是非常重要的。虽然具体文档和详细API信息可能有限(因为是“未知功能插件”),但通常可以通过查看插件的官方仓库、示例代码或源代码来获取关键信息。以下是一个假设性的代码案例,展示如何使用tenor_flutter插件(注意:实际API和方法可能有所不同,这里仅为示例)。

首先,确保你已经在pubspec.yaml文件中添加了tenor_flutter依赖项:

dependencies:
  flutter:
    sdk: flutter
  tenor_flutter: ^x.y.z  # 替换为实际的版本号

然后运行flutter pub get来安装依赖。

接下来,在你的Flutter项目中,你可以尝试如下方式使用tenor_flutter插件:

import 'package:flutter/material.dart';
import 'package:tenor_flutter/tenor_flutter.dart'; // 假设插件提供了这个import路径

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

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  List<GifResult> _gifs = [];
  final TenorClient _tenorClient = TenorClient(apiKey: 'YOUR_TENOR_API_KEY'); // 替换为你的Tenor API密钥

  @override
  void initState() {
    super.initState();
    _fetchGifs();
  }

  Future<void> _fetchGifs() async {
    try {
      final SearchResult searchResult = await _tenorClient.searchGifs(query: 'happy');
      setState(() {
        _gifs = searchResult.gifs;
      });
    } catch (e) {
      print('Error fetching GIFs: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Tenor Flutter Example'),
        ),
        body: GridView.builder(
          gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
            crossAxisCount: 2,
            crossAxisSpacing: 4.0,
            mainAxisSpacing: 4.0,
          ),
          itemCount: _gifs.length,
          itemBuilder: (context, index) {
            final GifResult gif = _gifs[index];
            return GestureDetector(
              onTap: () {
                // 可以在这里添加点击GIF后的处理逻辑,比如全屏显示
                print('GIF tapped: ${gif.url}');
              },
              child: Image.network(gif.url),
            );
          },
        ),
      ),
    );
  }
}

// 假设的TenorClient类和返回类型
class TenorClient {
  final String apiKey;

  TenorClient({required this.apiKey});

  Future<SearchResult> searchGifs({required String query}) async {
    // 这里应该是一个网络请求,使用dio、http等库
    // 示例代码,实际API调用和响应解析会有所不同
    final response = await http.get(
      Uri.parse('https://api.tenor.com/v1/search', {
        'q': query,
        'key': apiKey,
        'limit': '10', // 限制返回结果数量
      }),
    );

    if (response.statusCode == 200) {
      // 解析响应数据,这里假设响应数据已经被序列化为Map<String, dynamic>
      final Map<String, dynamic> data = jsonDecode(response.body);
      return SearchResult.fromJson(data);
    } else {
      throw Exception('Failed to fetch GIFs: ${response.statusCode}');
    }
  }
}

class SearchResult {
  List<GifResult> gifs;

  SearchResult({required this.gifs});

  factory SearchResult.fromJson(Map<String, dynamic> json) {
    return SearchResult(
      gifs: List<GifResult>.from(json['results'].map((x) => GifResult.fromJson(x))),
    );
  }
}

class GifResult {
  String url;

  GifResult({required this.url});

  factory GifResult.fromJson(Map<String, dynamic> json) {
    return GifResult(
      url: json['media'][0]['gif']['url'], // 假设URL的解析路径是这样的
    );
  }
}

注意

  1. 上述代码中的TenorClient类、SearchResult类和GifResult类是基于假设的API响应结构创建的。实际使用时,你需要根据tenor_flutter插件提供的API文档和响应数据结构来调整这些类。
  2. YOUR_TENOR_API_KEY需要替换为你从Tenor获取的API密钥。
  3. 网络请求部分使用了http库,你可能需要在pubspec.yaml中添加http: ^x.y.z依赖项,并运行flutter pub get来安装它。
  4. 由于tenor_flutter是一个假设的插件,上述代码可能需要根据实际插件的API进行调整。

务必查阅tenor_flutter插件的官方文档和示例代码,以确保正确使用其功能。

回到顶部