Flutter自定义标签页插件flutter_custom_tabs的使用
Flutter自定义标签页插件flutter_custom_tabs的使用
简介
flutter_custom_tabs
是一个用于在移动应用程序中以自定义标签页的方式启动URL的Flutter插件。它允许您将浏览器提供的Custom Tabs体验添加到您的移动应用程序中。从2.0版本开始,该插件扩展了对启动URL的支持:
- 启动外部浏览器中的URL。
- 启动深度链接URL。
平台 | 支持版本 |
---|---|
Android | SDK 19+ |
iOS | 11.0+ |
Web | Any |
实现方式分别为:
- Android:Custom Tabs
- iOS:SFSafariViewController
- Web:url_launcher
开始使用
添加依赖
首先,在您的pubspec.yaml
文件中添加flutter_custom_tabs
作为依赖项:
dependencies:
flutter_custom_tabs: ^2.1.0
重要提示:v2.0.0包含了一些破坏性的更改,请参考migration guide进行更新。
对于Android项目,确保满足以下要求:
- Android Gradle Plugin v7.4.0及以上版本。
- Kotlin v1.7.0及以上版本。
配置如下:
// your-project/android/build.gradle
buildscript {
ext.kotlin_version = '1.7.0' // and above if explicitly depending on Kotlin.
dependencies {
classpath 'com.android.tools.build:gradle:7.4.0' // and above.
}
}
使用方法
您可以像使用url_launcher
一样启动一个网页URL,并通过指定选项来自定义外观和行为。
基本用法
import 'package:flutter/material.dart';
import 'package:flutter_custom_tabs/flutter_custom_tabs.dart';
void _launchURL(BuildContext context) async {
final theme = Theme.of(context);
try {
await launchUrl(
Uri.parse('https://flutter.dev'),
customTabsOptions: CustomTabsOptions(
colorSchemes: CustomTabsColorSchemes.defaults(
toolbarColor: theme.colorScheme.surface,
),
shareState: CustomTabsShareState.on,
urlBarHidingEnabled: true,
showTitle: true,
closeButton: CustomTabsCloseButton(
icon: CustomTabsCloseButtonIcons.back,
),
),
safariVCOptions: SafariViewControllerOptions(
preferredBarTintColor: theme.colorScheme.surface,
preferredControlTintColor: theme.colorScheme.onSurface,
barCollapsingEnabled: true,
dismissButtonStyle: SafariViewControllerDismissButtonStyle.close,
),
);
} catch (e) {
debugPrint(e.toString());
}
}
轻量级版本用法
轻量级版本适用于不需要太多自定义的用户:
import 'package:flutter/material.dart';
import 'package:flutter_custom_tabs/flutter_custom_tabs_lite.dart';
void _launchURL(BuildContext context) async {
final theme = Theme.of(context);
try {
await launchUrl(
Uri.parse('https://flutter.dev'),
options: LaunchOptions(
barColor: theme.colorScheme.surface,
onBarColor: theme.colorScheme.onSurface,
barFixingEnabled: false,
),
);
} catch (e) {
debugPrint(e.toString());
}
}
深度链接
支持启动深度链接URL(如果安装了响应深度链接的应用程序,则直接启动它;否则,启动自定义标签页):
Future<void> _launchDeepLinkURL(BuildContext context) async {
final theme = Theme.of(context);
await launchUrl(
Uri.parse('https://www.google.com/maps/@35.6908883,139.7865242,13z'),
prefersDeepLink: true,
customTabsOptions: CustomTabsOptions(
colorSchemes: CustomTabsColorSchemes.defaults(
toolbarColor: theme.colorScheme.surface,
),
),
safariVCOptions: SafariViewControllerOptions(
preferredBarTintColor: theme.colorScheme.surface,
preferredControlTintColor: theme.colorScheme.onSurface,
),
);
}
在外部浏览器中启动
默认情况下,如果没有指定平台特定选项,URL将在外部浏览器中启动:
Future<void> _launchInExternalBrowser() async {
await launchUrl(Uri.parse('https://flutter.dev'));
}
以底部弹出的形式显示
Future<void> _launchURLInBottomSheet(BuildContext context) async {
final theme = Theme.of(context);
final mediaQuery = MediaQuery.of(context);
await launchUrl(
Uri.parse('https://flutter.dev'),
customTabsOptions: CustomTabsOptions.partial(
configuration: PartialCustomTabsConfiguration(
initialHeight: mediaQuery.size.height * 0.7,
),
colorSchemes: CustomTabsColorSchemes.defaults(
toolbarColor: theme.colorScheme.surface,
),
),
safariVCOptions: SafariViewControllerOptions.pageSheet(
configuration: const SheetPresentationControllerConfiguration(
detents: {
SheetPresentationControllerDetent.large,
SheetPresentationControllerDetent.medium,
},
prefersScrollingExpandsWhenScrolledToEdge: true,
prefersGrabberVisible: true,
prefersEdgeAttachedInCompactHeight: true,
),
preferredBarTintColor: theme.colorScheme.surface,
preferredControlTintColor: theme.colorScheme.onSurface,
dismissButtonStyle: SafariViewControllerDismissButtonStyle.close,
),
);
}
优先选择默认浏览器而非Chrome
Future<void> _launchURLInDefaultBrowserOnAndroid() async {
await launchUrl(
Uri.parse('https://flutter.dev'),
customTabsOptions: CustomTabsOptions(
browser: const CustomTabsBrowserConfiguration(
prefersDefaultBrowser: true,
),
),
);
}
手动关闭Custom Tabs
Future<void> _closeCustomTabsManually() async {
await closeCustomTabs();
}
完整示例代码
以下是完整的示例代码,展示了如何在一个Flutter应用中使用flutter_custom_tabs
插件:
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_custom_tabs/flutter_custom_tabs.dart';
import 'package:flutter_custom_tabs/flutter_custom_tabs_lite.dart' as lite;
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Custom Tabs Example',
theme: ThemeData(
useMaterial3: true,
colorSchemeSeed: Colors.blue,
brightness: Brightness.light,
),
darkTheme: ThemeData(
useMaterial3: true,
colorSchemeSeed: Colors.blue,
brightness: Brightness.dark,
),
themeMode: ThemeMode.system,
home: Builder(
builder: (context) => Scaffold(
appBar: AppBar(
title: const Text('Flutter Custom Tabs Example'),
),
body: ListView(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
children: <Widget>[
FilledButton(
onPressed: () => _launchUrl(context),
child: Text(
Platform.isAndroid
? 'Show flutter.dev (Chrome)'
: 'Show flutter.dev',
),
),
if (Platform.isAndroid)
FilledButton(
onPressed: () => _launchURLInDefaultBrowserOnAndroid(context),
child:
const Text('Show flutter.dev (prefer default browser)'),
),
FilledButton(
onPressed: () => _launchUrlLite(context),
child: const Text('Show flutter.dev (lite ver)'),
),
FilledButton(
onPressed: () => _launchDeepLinkURL(context),
child: const Text('Deep link to platform maps'),
),
FilledButton(
onPressed: () => _launchUrlInBottomSheet(context),
child: const Text('Show flutter.dev in bottom sheet'),
),
FilledButton(
onPressed: () => _launchWithCustomCloseButton(context),
child: const Text('Show flutter.dev with custom close button'),
),
FilledButton(
onPressed: () => _launchWithCustomAnimation(context),
child: const Text('Show flutter.dev with custom animation'),
),
FilledButton(
onPressed: () => _launchAndCloseManually(context),
child: const Text('Show flutter.dev + close after 5 seconds'),
),
FilledButton(
onPressed: () => _launchInExternalBrowser(),
child: const Text('Show flutter.dev in external browser'),
),
],
),
),
),
);
}
}
Future<void> _launchUrl(BuildContext context) async {
final theme = Theme.of(context);
try {
await launchUrl(
Uri.parse('https://flutter.dev'),
customTabsOptions: CustomTabsOptions(
colorSchemes: CustomTabsColorSchemes.defaults(
toolbarColor: theme.colorScheme.surface,
navigationBarColor: theme.colorScheme.surface,
),
shareState: CustomTabsShareState.on,
urlBarHidingEnabled: true,
showTitle: true,
),
safariVCOptions: SafariViewControllerOptions(
preferredBarTintColor: theme.colorScheme.surface,
preferredControlTintColor: theme.colorScheme.onSurface,
barCollapsingEnabled: true,
entersReaderIfAvailable: false,
),
);
} catch (e) {
debugPrint(e.toString());
}
}
Future<void> _launchURLInDefaultBrowserOnAndroid(BuildContext context) async {
final theme = Theme.of(context);
try {
await launchUrl(
Uri.parse('https://flutter.dev'),
customTabsOptions: CustomTabsOptions(
colorSchemes: CustomTabsColorSchemes.defaults(
toolbarColor: theme.colorScheme.surface,
navigationBarColor: theme.colorScheme.surface,
),
urlBarHidingEnabled: true,
showTitle: true,
browser: const CustomTabsBrowserConfiguration(
prefersDefaultBrowser: true,
),
),
);
} catch (e) {
debugPrint(e.toString());
}
}
Future<void> _launchUrlLite(BuildContext context) async {
final theme = Theme.of(context);
try {
await lite.launchUrl(
Uri.parse('https://flutter.dev'),
options: lite.LaunchOptions(
barColor: theme.colorScheme.surface,
onBarColor: theme.colorScheme.onSurface,
barFixingEnabled: false,
),
);
} catch (e) {
debugPrint(e.toString());
}
}
Future<void> _launchDeepLinkURL(BuildContext context) async {
final theme = Theme.of(context);
final uri = Platform.isIOS
? 'https://maps.apple.com/?q=tokyo+station'
: 'https://www.google.co.jp/maps/@35.6908883,139.7865242,13.53z';
try {
await launchUrl(
Uri.parse(uri),
prefersDeepLink: true,
customTabsOptions: CustomTabsOptions(
colorSchemes: CustomTabsColorSchemes.defaults(
toolbarColor: theme.colorScheme.surface,
navigationBarColor: theme.colorScheme.surface,
),
urlBarHidingEnabled: true,
showTitle: true,
),
safariVCOptions: SafariViewControllerOptions(
preferredBarTintColor: theme.colorScheme.surface,
preferredControlTintColor: theme.colorScheme.onSurface,
barCollapsingEnabled: true,
),
);
} catch (e) {
debugPrint(e.toString());
}
}
Future<void> _launchUrlInBottomSheet(BuildContext context) async {
final theme = Theme.of(context);
final mediaQuery = MediaQuery.of(context);
try {
await launchUrl(
Uri.parse('https://flutter.dev'),
customTabsOptions: CustomTabsOptions.partial(
configuration: PartialCustomTabsConfiguration(
initialHeight: mediaQuery.size.height * 0.7,
),
colorSchemes: CustomTabsColorSchemes.defaults(
colorScheme: theme.brightness.toColorScheme(),
toolbarColor: theme.colorScheme.primary,
),
showTitle: true,
),
safariVCOptions: SafariViewControllerOptions.pageSheet(
configuration: const SheetPresentationControllerConfiguration(
detents: {
SheetPresentationControllerDetent.large,
SheetPresentationControllerDetent.medium,
},
prefersScrollingExpandsWhenScrolledToEdge: true,
prefersGrabberVisible: true,
prefersEdgeAttachedInCompactHeight: true,
preferredCornerRadius: 16.0,
),
preferredBarTintColor: theme.colorScheme.primary,
preferredControlTintColor: theme.colorScheme.onPrimary,
entersReaderIfAvailable: true,
dismissButtonStyle: SafariViewControllerDismissButtonStyle.close,
),
);
} catch (e) {
debugPrint(e.toString());
}
}
Future<void> _launchWithCustomCloseButton(BuildContext context) async {
final theme = Theme.of(context);
try {
await launchUrl(
Uri.parse('https://flutter.dev'),
customTabsOptions: CustomTabsOptions(
colorSchemes: CustomTabsColorSchemes.defaults(
toolbarColor: theme.colorScheme.surface,
),
showTitle: true,
closeButton: CustomTabsCloseButton(
icon: CustomTabsCloseButtonIcons.back,
)),
safariVCOptions: SafariViewControllerOptions(
preferredBarTintColor: theme.colorScheme.surface,
preferredControlTintColor: theme.colorScheme.onSurface,
dismissButtonStyle: SafariViewControllerDismissButtonStyle.close,
),
);
} catch (e) {
debugPrint(e.toString());
}
}
Future<void> _launchWithCustomAnimation(BuildContext context) async {
final theme = Theme.of(context);
try {
await launchUrl(
Uri.parse('https://flutter.dev'),
customTabsOptions: CustomTabsOptions(
colorSchemes: CustomTabsColorSchemes.defaults(
toolbarColor: theme.colorScheme.surface,
),
showTitle: true,
animations: CustomTabsSystemAnimations.fade(),
),
safariVCOptions: SafariViewControllerOptions(
preferredBarTintColor: theme.colorScheme.surface,
preferredControlTintColor: theme.colorScheme.onSurface,
modalPresentationStyle: ViewControllerModalPresentationStyle.automatic,
),
);
} catch (e) {
debugPrint(e.toString());
}
}
Future<void> _launchAndCloseManually(BuildContext context) async {
final theme = Theme.of(context);
try {
Timer(const Duration(seconds: 5), () {
closeCustomTabs();
});
await launchUrl(
Uri.parse('https://flutter.dev'),
customTabsOptions: CustomTabsOptions(
colorSchemes: CustomTabsColorSchemes.defaults(
toolbarColor: theme.colorScheme.surface,
),
showTitle: true,
),
safariVCOptions: SafariViewControllerOptions(
preferredBarTintColor: theme.colorScheme.surface,
preferredControlTintColor: theme.colorScheme.onSurface,
),
);
} catch (e) {
debugPrint(e.toString());
}
}
Future<void> _launchInExternalBrowser() async {
try {
await launchUrl(
Uri.parse('https://flutter.dev'),
prefersDeepLink: false,
);
} catch (e) {
debugPrint(e.toString());
}
}
以上是关于flutter_custom_tabs
插件的详细介绍和使用方法,希望对您有所帮助!
更多关于Flutter自定义标签页插件flutter_custom_tabs的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter自定义标签页插件flutter_custom_tabs的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何在Flutter项目中使用flutter_custom_tabs
插件来实现自定义标签页的示例代码。flutter_custom_tabs
插件允许你在Flutter应用中打开自定义的Chrome自定义标签页(Custom Tabs),这对于需要在应用内打开网页的场景非常有用。
首先,你需要在你的pubspec.yaml
文件中添加flutter_custom_tabs
依赖:
dependencies:
flutter:
sdk: flutter
flutter_custom_tabs: ^1.0.0 # 请确保使用最新版本
然后,运行flutter pub get
来安装依赖。
接下来,你可以在你的Flutter项目中使用这个插件。以下是一个简单的示例,展示了如何打开一个自定义标签页:
import 'package:flutter/material.dart';
import 'package:flutter_custom_tabs/flutter_custom_tabs.dart';
import 'package:url_launcher/url_launcher.dart'; // 用于检查URL是否能被打开
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Custom Tabs Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Custom Tabs Demo'),
),
body: Center(
child: ElevatedButton(
onPressed: _launchCustomTab,
child: Text('Open Custom Tab'),
),
),
);
}
Future<void> _launchCustomTab() async {
// 定义要打开的URL
final url = 'https://flutter.dev';
// 检查URL是否可以被打开
if (await canLaunch(url)) {
// 使用FlutterCustomTabsPlugin打开自定义标签页
// 这里可以传递一些自定义选项,比如工具栏颜色、动作按钮等
try {
await FlutterCustomTabsPlugin.withNewEngine(url)
.setCustomTabsOptions(
CustomTabsOptions(
toolbarColor: Colors.blue.withOpacity(0.9),
enableUrlBarHiding: true,
showPageTitle: true,
// 添加自定义动作按钮(可选)
actionButton: CustomTabsActionButton(
icon: BitmapFactory.decodeResource(
Resources(),
android.R.drawable.ic_menu_share,
),
description: "Share",
pendingIntent: PendingIntent.getBroadcast(
// 你需要在这里提供合适的Context和Intent
// 由于这是一个Flutter示例,这里省略了具体实现
null,
0,
Intent(),
0
),
),
// 更多自定义选项...
)
)
.launch();
} catch (e) {
// 处理异常
print("Failed to launch URL: $e");
}
} else {
// 如果无法打开URL,显示错误消息
throw UnsupportedError('Could not launch $url');
}
}
}
注意:
-
在上面的代码中,
CustomTabsActionButton
和PendingIntent
等Android特有的实现需要一些Android原生代码的支持,这超出了Flutter的纯粹范围。为了简化示例,这些部分被省略了。在实际应用中,你可能需要在你的Android原生代码中实现这些功能,并通过平台通道与Flutter进行通信。 -
由于
flutter_custom_tabs
插件在iOS上通常使用Safari View Controller,因此许多自定义选项(如工具栏颜色)在iOS上可能不适用。 -
确保你的AndroidManifest.xml和iOS配置允许打开外部链接。
-
在实际项目中,请根据你的需求调整URL和自定义选项。
希望这个示例能帮助你在Flutter项目中成功使用flutter_custom_tabs
插件!