您好,登录后才能下订单哦!
# Flutter实现仿微信分享功能的示例代码详解
本文将全面讲解如何使用Flutter实现仿微信的分享功能,包含UI构建、平台交互、多端适配等完整实现方案。
## 一、功能需求分析
微信分享功能主要包含以下核心要素:
1. **分享入口**:
- 右上角"..."菜单触发
- 长按内容触发
- 特定按钮点击触发
2. **分享面板UI**:
- 半透明模态弹窗
- 应用图标网格布局
- 取消按钮
3. **分享目标**:
- 微信好友
- 朋友圈
- QQ
- 微博
- 复制链接
- 更多...
4. **平台能力**:
- 调用原生分享API
- 处理分享回调
- 未安装应用处理
## 二、项目结构与依赖配置
### 1. 创建Flutter项目
```bash
flutter create wechat_share_demo
pubspec.yaml
配置:
dependencies:
flutter:
sdk: flutter
# 分享插件
share_plus: ^7.0.2
# 平台设备信息
device_info_plus: ^9.0.3
# 权限处理
permission_handler: ^10.4.0
# 图标库
font_awesome_flutter: ^10.5.0
# 路由管理
go_router: ^12.0.0
share_sheet.dart
:
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
class ShareSheet extends StatelessWidget {
final VoidCallback onCancel;
final Function(String) onShare;
const ShareSheet({
super.key,
required this.onCancel,
required this.onShare,
});
@override
Widget build(BuildContext context) {
return SafeArea(
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: const BorderRadius.vertical(top: Radius.circular(12)),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.2),
blurRadius: 10,
spreadRadius: 0,
)
],
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
_buildHeader(),
_buildPlatformGrid(),
_buildActionRow(),
_buildCancelButton(),
],
),
),
);
}
Widget _buildHeader() {
return const Padding(
padding: EdgeInsets.symmetric(vertical: 16),
child: Text(
'分享到',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.black87,
),
),
);
}
Widget _buildPlatformGrid() {
const platforms = [
{'name': '微信好友', 'icon': FontAwesomeIcons.weixin, 'color': Colors.green},
{'name': '朋友圈', 'icon': FontAwesomeIcons.users, 'color': Colors.green},
{'name': 'QQ', 'icon': FontAwesomeIcons.qq, 'color': Colors.blue},
{'name': '微博', 'icon': FontAwesomeIcons.weibo, 'color': Colors.orange},
{'name': '复制链接', 'icon': Icons.link, 'color': Colors.grey},
{'name': '更多', 'icon': Icons.more_horiz, 'color': Colors.grey},
];
return GridView.count(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
crossAxisCount: 4,
padding: const EdgeInsets.symmetric(horizontal: 16),
children: platforms.map((platform) {
return _buildPlatformItem(
platform['icon'] as IconData,
platform['name'] as String,
platform['color'] as Color,
);
}).toList(),
);
}
Widget _buildPlatformItem(IconData icon, String name, Color color) {
return GestureDetector(
onTap: () => onShare(name),
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 12),
child: Column(
children: [
Container(
width: 50,
height: 50,
decoration: BoxDecoration(
color: color.withOpacity(0.1),
shape: BoxShape.circle,
),
child: Icon(icon, color: color, size: 24),
),
const SizedBox(height: 8),
Text(
name,
style: const TextStyle(fontSize: 12),
),
],
),
),
);
}
Widget _buildActionRow() {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
child: Row(
children: [
Expanded(
child: OutlinedButton(
style: OutlinedButton.styleFrom(
foregroundColor: Colors.grey,
side: const BorderSide(color: Colors.grey),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
),
onPressed: () => onShare('收藏'),
child: const Text('收藏'),
),
),
const SizedBox(width: 12),
Expanded(
child: OutlinedButton(
style: OutlinedButton.styleFrom(
foregroundColor: Colors.grey,
side: const BorderSide(color: Colors.grey),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
onPressed: () => onShare('保存图片'),
child: const Text('保存图片'),
),
),
],
),
);
}
Widget _buildCancelButton() {
return Container(
decoration: const BoxDecoration(
border: Border(top: BorderSide(color: Colors.grey, width: 0.5)),
),
child: ListTile(
title: const Center(
child: Text(
'取消',
style: TextStyle(fontSize: 16),
),
),
onTap: onCancel,
),
);
}
}
share_service.dart
:
import 'package:device_info_plus/device_info_plus.dart';
import 'package:flutter/services.dart';
import 'package:share_plus/share_plus.dart';
class ShareService {
static Future<void> shareToWeChat(String content) async {
try {
// 检测是否安装微信
final deviceInfo = await DeviceInfoPlugin().androidInfo;
if (deviceInfo is AndroidDeviceInfo) {
// Android平台处理
const platform = MethodChannel('com.example/share');
await platform.invokeMethod('shareToWeChat', {'text': content});
} else {
// iOS平台处理
await Share.share(content, subject: '微信分享');
}
} on PlatformException catch (e) {
print('分享失败: ${e.message}');
// 处理未安装微信的情况
await Share.share(content);
}
}
static Future<void> shareToWeChatMoments(String content) async {
// 类似微信好友的实现,调用不同平台方法
}
static Future<void> shareToQQ(String content) async {
// QQ分享实现
}
static Future<void> copyLink(String link) async {
await Clipboard.setData(ClipboardData(text: link));
}
static Future<void> saveImage(String imageUrl) async {
// 图片保存实现
}
}
android/app/src/main/kotlin/com/example/wechat_share_demo/MainActivity.kt
:
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
class MainActivity: FlutterActivity() {
private val CHANNEL = "com.example/share"
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
when (call.method) {
"shareToWeChat" -> {
val text = call.argument<String>("text")
// 调用微信SDK分享
shareToWeChat(text ?: "", result)
}
else -> result.notImplemented()
}
}
}
private fun shareToWeChat(text: String, result: MethodChannel.Result) {
try {
// 实际调用微信SDK的代码
result.success(true)
} catch (e: Exception) {
result.error("UNAVLABLE", "微信未安装", null)
}
}
}
ios/Runner/AppDelegate.swift
:
import Flutter
import UIKit
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let shareChannel = FlutterMethodChannel(name: "com.example/share",
binaryMessenger: controller.binaryMessenger)
shareChannel.setMethodCallHandler({
(call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
guard call.method == "shareToWeChat" else {
result(FlutterMethodNotImplemented)
return
}
self.shareToWeChat(arguments: call.arguments, result: result)
})
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
private func shareToWeChat(arguments: Any?, result: FlutterResult) {
// 调用微信SDK分享
result(true)
}
}
main_page.dart
:
import 'package:flutter/material.dart';
import 'package:wechat_share_demo/share_sheet.dart';
import 'package:wechat_share_demo/share_service.dart';
class MainPage extends StatelessWidget {
const MainPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('微信分享示例'),
actions: [
IconButton(
icon: const Icon(Icons.share),
onPressed: () => _showShareSheet(context),
),
],
),
body: Center(
child: ElevatedButton(
child: const Text('分享内容'),
onPressed: () => _showShareSheet(context),
),
),
);
}
void _showShareSheet(BuildContext context) {
showModalBottomSheet(
context: context,
backgroundColor: Colors.transparent,
isScrollControlled: true,
builder: (context) => ShareSheet(
onCancel: () => Navigator.pop(context),
onShare: (platform) => _handleShare(platform, context),
),
);
}
Future<void> _handleShare(String platform, BuildContext context) async {
Navigator.pop(context);
const shareContent = '这是要分享的内容\nhttps://example.com';
const shareImage = 'https://example.com/image.jpg';
switch (platform) {
case '微信好友':
await ShareService.shareToWeChat(shareContent);
break;
case '朋友圈':
await ShareService.shareToWeChatMoments(shareContent);
break;
case 'QQ':
await ShareService.shareToQQ(shareContent);
break;
case '微博':
// 微博分享实现
break;
case '复制链接':
await ShareService.copyLink('https://example.com');
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('链接已复制')),
);
break;
case '保存图片':
await ShareService.saveImage(shareImage);
break;
default:
await Share.share(shareContent);
}
}
}
main.dart
:
import 'package:flutter/material.dart';
import 'package:wechat_share_demo/main_page.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: '微信分享示例',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: const MainPage(),
);
}
}
class SharePreview extends StatelessWidget {
final String title;
final String description;
final String imageUrl;
final String url;
const SharePreview({
super.key,
required this.title,
required this.description,
required this.imageUrl,
required this.url,
});
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.grey[100],
borderRadius: BorderRadius.circular(8),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
if (imageUrl.isNotEmpty)
ClipRRect(
borderRadius: BorderRadius.circular(4),
child: Image.network(
imageUrl,
height: 120,
width: double.infinity,
fit: BoxFit.cover,
),
),
const SizedBox(height: 12),
Text(
title,
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16,
),
),
const SizedBox(height: 4),
Text(
description,
style: TextStyle(
color: Colors.grey[600],
fontSize: 14,
),
),
const SizedBox(height: 8),
Text(
url,
style: TextStyle(
color: Colors.blue[400],
fontSize: 12,
),
),
],
),
);
}
}
class ShareAnalytics {
static void logShareEvent({
required String platform,
required String contentType,
required bool success,
}) {
// 实际项目中调用埋点SDK
debugPrint('''
分享事件记录:
平台: $platform
类型: $contentType
成功: $success
''');
}
}
// 使用示例
ShareAnalytics.logShareEvent(
platform: '微信好友',
contentType: '链接',
success: true,
);
class ShareLocalizations {
final Locale locale;
ShareLocalizations(this.locale);
static ShareLocalizations of(BuildContext context) {
return Localizations.of<ShareLocalizations>(context, ShareLocalizations)!;
}
static const Map<String, Map<String, String>> _localizedValues = {
'en': {
'shareTo': 'Share to',
'wechat': 'WeChat',
'moments': 'Moments',
'cancel': 'Cancel',
},
'zh': {
'shareTo': '分享到',
'wechat': '微信好友',
'moments': '朋友圈',
'cancel': '取消',
},
};
String get shareTo => _localizedValues[locale.languageCode]!['shareTo']!;
String get wechat => _localizedValues[locale.languageCode]!['wechat']!;
String get moments => _localizedValues[locale.languageCode]!['moments']!;
String get cancel => _localizedValues[locale.languageCode]!['cancel']!;
}
class OptimizedShareSheet extends StatefulWidget {
// ...参数相同
@override
State<OptimizedShareSheet> createState() => _OptimizedShareSheetState();
}
class _OptimizedShareSheetState extends State<OptimizedShareSheet> {
late final List<Map<String, dynamic>> _platforms;
@override
void initState() {
super.initState();
// 提前初始化数据,避免重复构建
_platforms = const [
{'name': '微信好友', 'icon': FontAwesomeIcons.weixin, 'color': Colors.green},
// ...其他平台数据
];
}
@override
Widget build(BuildContext context) {
return SafeArea(
child: Column(
children: [
// 使用ListView.builder优化长列表
GridView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4,
childAspectRatio: 0.8,
),
itemCount: _platforms.length,
itemBuilder: (context, index) {
final platform = _platforms[index];
return _buildPlatformItem(
platform['icon'] as IconData,
platform['name'] as String,
platform['color'] as Color,
);
},
),
// ...其他组件
],
),
);
}
}
share_sheet_test.dart
:
”`dart import ‘package:flutter/material.dart’; import ‘package:flutter_test/flutter_test.dart’; import ‘package:wechat_share_demo/share_sheet.dart’;
void main() { testWidgets(‘分享面板显示测试’, (WidgetTester tester) async { bool canceled = false; String? sharedPlatform;
await tester.pumpWidget(MaterialApp(
home: Scaffold(
body: ShareSheet(
onCancel: () => canceled = true,
onShare: (platform) => sharedPlatform = platform,
),
),
));
// 验证标题显示
expect(find.text('分享到'), finds
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。