Browse Source

修改iOS画中画

newdev_shunjiawei
tanlongsheng 11 months ago
parent
commit
7df26d3b1a
  1. 115
      lib/modules/translation/controllers/translation_controller.dart
  2. 43
      lib/modules/translation/views/translation_view.dart

115
lib/modules/translation/controllers/translation_controller.dart

@ -2,12 +2,15 @@ import 'dart:io';
import 'dart:async'; import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart'; import 'package:get_storage/get_storage.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:native_plugin/native_plugin.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart'; import 'package:permission_handler/permission_handler.dart';
import 'package:device_info_plus/device_info_plus.dart'; import 'package:device_info_plus/device_info_plus.dart';
import 'package:pip/pip.dart';
import '../../../data/services/ast_service.dart'; import '../../../data/services/ast_service.dart';
import '../../../data/services/bluetooth_manager.dart'; import '../../../data/services/bluetooth_manager.dart';
import '../../../data/services/music_manager.dart'; import '../../../data/services/music_manager.dart';
@ -49,7 +52,12 @@ class TranslationController extends GetxController with WidgetsBindingObserver {
final BleManager bleManager = Get.find<BleManager>(); final BleManager bleManager = Get.find<BleManager>();
final _musiceManager = Get.find<MusicManager>(); final _musiceManager = Get.find<MusicManager>();
late final TranslationUsageService _usageService; late final TranslationUsageService _usageService;
// 安卓悬浮窗管理器
late final FloatingWindowManager _floatingWindowManager; late final FloatingWindowManager _floatingWindowManager;
// 苹果悬浮窗管理器
late final Pip _pip;
late final NativePlugin _nativePlugin;
int _pipContentView = 0;
// ==================== 悬浮窗相关 ==================== // ==================== 悬浮窗相关 ====================
final isFloatingWindowEnabled = false.obs; // 悬浮窗状态 final isFloatingWindowEnabled = false.obs; // 悬浮窗状态
@ -135,7 +143,7 @@ class TranslationController extends GetxController with WidgetsBindingObserver {
// 底部控制栏高度 // 底部控制栏高度
double _bottomBarHeight = 0.0; double _bottomBarHeight = 0.0;
/// 初始化悬浮窗管理器 /// 初始化安卓悬浮窗管理器
void _initFloatingWindowManager() { void _initFloatingWindowManager() {
try { try {
if (!Get.isRegistered<FloatingWindowManager>()) { if (!Get.isRegistered<FloatingWindowManager>()) {
@ -148,13 +156,68 @@ class TranslationController extends GetxController with WidgetsBindingObserver {
} }
} }
/// 初始化苹果悬浮窗管理器
Future<void> initPlatformState() async {
_pip = Pip();
_nativePlugin = NativePlugin();
try {
isFloatingWindowEnabled.value = await _pip.isActived();
await _pip.registerStateChangedObserver(
PipStateChangedObserver(
onPipStateChanged: (state, error) {
isFloatingWindowEnabled.value = state == PipState.pipStateStarted;
if (state == PipState.pipStateFailed) {
_pip.dispose();
}
},
),
);
} on PlatformException {
isFloatingWindowEnabled.value = false;
}
}
/// 切换悬浮窗功能 /// 切换悬浮窗功能
Future<void> toggleFloatingWindow() async { Future<void> toggleFloatingWindow() async {
if (isFloatingWindowEnabled.value) { if (isFloatingWindowEnabled.value) {
await _disableFloatingWindow(); if (Platform.isAndroid) {
await _disableFloatingWindow();
} else if (Platform.isIOS) {
await _pip.dispose();
}
} else { } else {
await _enableFloatingWindow(); if (Platform.isAndroid) {
await _enableFloatingWindow();
} else if (Platform.isIOS) {
await _startPip();
}
}
}
Future<void> _startPip() async {
if (_pipContentView == 0) {
_pipContentView = await _nativePlugin.createPipContentView();
} }
final options = PipOptions(
autoEnterEnabled: true,
aspectRatioX: 375,
aspectRatioY: 400,
sourceRectHintLeft: 0,
sourceRectHintTop: 0,
sourceRectHintRight: 0,
sourceRectHintBottom: 0,
seamlessResizeEnabled: true,
useExternalStateMonitor: true,
externalStateMonitorInterval: 100,
contentView: _pipContentView,
preferredContentWidth: 375,
preferredContentHeight: 400,
controlStyle: 2,
);
await _pip.setup(options);
await _pip.start();
} }
/// 启用悬浮窗功能 /// 启用悬浮窗功能
@ -217,16 +280,24 @@ class TranslationController extends GetxController with WidgetsBindingObserver {
_languageManager.getChineseNameByAsrCode(item.targetLanguageCode) ?? _languageManager.getChineseNameByAsrCode(item.targetLanguageCode) ??
'unknown'; 'unknown';
final data = FloatingWindowData( if (Platform.isAndroid) {
sourceText: item.sourceText, final data = FloatingWindowData(
translatedText: item.translatedText, sourceText: item.sourceText,
sourceLanguage: sourceLanguageName, translatedText: item.translatedText,
targetLanguage: targetLanguageName, sourceLanguage: sourceLanguageName,
timestamp: item.timestamp, targetLanguage: targetLanguageName,
isIntermediate: item.isIntermediate, timestamp: item.timestamp,
); isIntermediate: item.isIntermediate,
);
await _floatingWindowManager.updateFloatingWindowContent(data); await _floatingWindowManager.updateFloatingWindowContent(data);
} else if (Platform.isIOS) {
await _nativePlugin.updatePipContentView({
'viewId': _pipContentView,
'cn': item.sourceText,
'en': item.translatedText,
'lang': '$sourceLanguageName -> $targetLanguageName',
});
}
} }
/// 更改翻译模式 /// 更改翻译模式
@ -374,8 +445,13 @@ class TranslationController extends GetxController with WidgetsBindingObserver {
_timerManager = RecordTimerController(); _timerManager = RecordTimerController();
_historyManager = TranslationHistoryManager(); _historyManager = TranslationHistoryManager();
// 初始化悬浮窗管理器 if (Platform.isAndroid) {
_initFloatingWindowManager(); // 初始化安卓悬浮窗管理器
_initFloatingWindowManager();
} else if (Platform.isIOS) {
// 初始化苹果悬浮窗管理器
initPlatformState();
}
// 预先检查权限,避免在用户交互时阻塞 // 预先检查权限,避免在用户交互时阻塞
_preCheckPermissions(); _preCheckPermissions();
@ -665,6 +741,15 @@ class TranslationController extends GetxController with WidgetsBindingObserver {
// _asrService.dispose(); // _asrService.dispose();
// _astService.dispose(); // _astService.dispose();
if (Platform.isAndroid) {
_disableFloatingWindow();
} else if (Platform.isIOS) {
_pip.dispose();
if (_pipContentView != 0) {
_nativePlugin.disposePipContentView(_pipContentView);
}
}
// 释放管理器资源 // 释放管理器资源
_timerManager.dispose(); _timerManager.dispose();
_historyManager.dispose(); _historyManager.dispose();

43
lib/modules/translation/views/translation_view.dart

@ -235,28 +235,27 @@ class TranslationView extends GetView<TranslationController> {
return Row( return Row(
children: [ children: [
// 悬浮窗切换按钮(仅在支持的模式下显示) // 悬浮窗切换按钮(仅在支持的模式下显示)
if (Platform.isAndroid) Obx(() {
Obx(() { if (controller.currentMode.value == 'call' ||
if (controller.currentMode.value == 'call' || controller.currentMode.value == 'audioVideo') {
controller.currentMode.value == 'audioVideo') { return IconButton(
return IconButton( icon: Icon(
icon: Icon( controller.isFloatingWindowEnabled.value
controller.isFloatingWindowEnabled.value ? Icons.picture_in_picture
? Icons.picture_in_picture : Icons.picture_in_picture_alt_outlined,
: Icons.picture_in_picture_alt_outlined, color: controller.isFloatingWindowEnabled.value
color: controller.isFloatingWindowEnabled.value ? Colors.blue
? Colors.blue : (isDarkMode ? Colors.white : Colors.black),
: (isDarkMode ? Colors.white : Colors.black), size: 24.sp,
size: 24.sp, ),
), onPressed: controller.toggleFloatingWindow,
onPressed: controller.toggleFloatingWindow, tooltip: controller.isFloatingWindowEnabled.value
tooltip: controller.isFloatingWindowEnabled.value ? '禁用悬浮窗'
? '禁用悬浮窗' : '启用悬浮窗',
: '启用悬浮窗', );
); }
} return const SizedBox.shrink();
return const SizedBox.shrink(); }),
}),
IconButton( IconButton(
icon: Icon( icon: Icon(
Icons.radio_button_checked, Icons.radio_button_checked,

Loading…
Cancel
Save