You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
389 lines
11 KiB
389 lines
11 KiB
import 'package:flutter/material.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|
import '../controllers/pairing_controller.dart';
|
|
import '../../../core/widgets/common_bottom_nav.dart';
|
|
|
|
class PairingView extends GetView<PairingController> {
|
|
const PairingView({Key? key}) : super(key: key);
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
backgroundColor: Colors.grey[50],
|
|
body: SafeArea(
|
|
child: Stack(
|
|
children: [
|
|
// 主要内容
|
|
_buildMainContent(),
|
|
],
|
|
),
|
|
),
|
|
bottomNavigationBar: Opacity(
|
|
opacity: 0.5, // 保持半透明效果
|
|
child: const CommonBottomNav(currentIndex: 0),
|
|
),
|
|
);
|
|
}
|
|
|
|
// 主要内容
|
|
Widget _buildMainContent() {
|
|
return Padding(
|
|
padding: EdgeInsets.fromLTRB(24.w, 40.h, 24.w, 24.h),
|
|
child: SingleChildScrollView(
|
|
child: Column(
|
|
children: [
|
|
// 标题部分
|
|
_buildHeader(),
|
|
|
|
// 设备动画
|
|
SizedBox(height: 40.h),
|
|
_buildDeviceAnimation(),
|
|
|
|
// 搜索状态
|
|
SizedBox(height: 40.h),
|
|
_buildSearchStatus(),
|
|
|
|
// 底部按钮
|
|
SizedBox(height: 60.h),
|
|
_buildBottomButtons(),
|
|
SizedBox(height: 80.h), // 留出底部导航的空间
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
// 标题部分
|
|
Widget _buildHeader() {
|
|
return Column(
|
|
children: [
|
|
Text(
|
|
'DeepVoice',
|
|
style: TextStyle(
|
|
fontSize: 24.sp,
|
|
fontWeight: FontWeight.bold,
|
|
color: Colors.grey[800],
|
|
),
|
|
),
|
|
SizedBox(height: 8.h),
|
|
Text(
|
|
'连接世界,超越声音',
|
|
style: TextStyle(
|
|
fontSize: 14.sp,
|
|
color: Colors.grey[500],
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
// 设备动画
|
|
Widget _buildDeviceAnimation() {
|
|
return SizedBox(
|
|
width: 240.w,
|
|
height: 240.w,
|
|
child: Stack(
|
|
alignment: Alignment.center,
|
|
children: [
|
|
// 脉动动画背景
|
|
_buildPulseBackground(),
|
|
|
|
// 耳机图片
|
|
_buildHeadphoneImage(),
|
|
|
|
// 旋转加载指示器
|
|
_buildLoadingIndicator(),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
// 脉动背景
|
|
Widget _buildPulseBackground() {
|
|
return TweenAnimationBuilder<double>(
|
|
tween: Tween<double>(begin: 0.8, end: 1.1),
|
|
duration: const Duration(seconds: 2),
|
|
curve: Curves.easeInOut,
|
|
builder: (context, value, child) {
|
|
return Transform.scale(
|
|
scale: value,
|
|
child: Container(
|
|
width: 200.w,
|
|
height: 200.w,
|
|
decoration: BoxDecoration(
|
|
gradient: LinearGradient(
|
|
begin: Alignment.topLeft,
|
|
end: Alignment.bottomRight,
|
|
colors: [
|
|
Colors.blue.withOpacity(0.2),
|
|
Colors.purple.withOpacity(0.2),
|
|
],
|
|
),
|
|
shape: BoxShape.circle,
|
|
),
|
|
),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
|
|
// 耳机图片
|
|
Widget _buildHeadphoneImage() {
|
|
return Container(
|
|
width: 140.w,
|
|
height: 140.w,
|
|
decoration: BoxDecoration(
|
|
gradient: LinearGradient(
|
|
begin: Alignment.topLeft,
|
|
end: Alignment.bottomRight,
|
|
colors: [
|
|
Colors.blue,
|
|
Colors.purple,
|
|
],
|
|
),
|
|
shape: BoxShape.circle,
|
|
),
|
|
child: Icon(
|
|
Icons.headset,
|
|
size: 80.sp,
|
|
color: Colors.white,
|
|
),
|
|
);
|
|
}
|
|
|
|
// 加载指示器
|
|
Widget _buildLoadingIndicator() {
|
|
return SizedBox(
|
|
width: 180.w,
|
|
height: 180.w,
|
|
child: CircularProgressIndicator(
|
|
strokeWidth: 4.w,
|
|
valueColor: AlwaysStoppedAnimation<Color>(Colors.blue),
|
|
backgroundColor: Colors.blue.withOpacity(0.1),
|
|
),
|
|
);
|
|
}
|
|
|
|
// 搜索状态
|
|
Widget _buildSearchStatus() {
|
|
return Obx(() {
|
|
switch (controller.searchStatus) {
|
|
case SearchStatus.searching:
|
|
return Column(
|
|
children: [
|
|
Text(
|
|
'寻找设备中${controller.searchDots}',
|
|
style: TextStyle(
|
|
fontSize: 18.sp,
|
|
fontWeight: FontWeight.w600,
|
|
color: Colors.grey[800],
|
|
),
|
|
),
|
|
SizedBox(height: 8.h),
|
|
Text(
|
|
'请打开耳机充电盒,将耳机放入您的耳朵',
|
|
style: TextStyle(
|
|
fontSize: 14.sp,
|
|
color: Colors.grey[500],
|
|
),
|
|
),
|
|
],
|
|
);
|
|
case SearchStatus.found:
|
|
return Column(
|
|
children: [
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
Icon(Icons.check_circle, color: Colors.green, size: 20.sp),
|
|
SizedBox(width: 8.w),
|
|
Text(
|
|
'设备连接成功',
|
|
style: TextStyle(
|
|
fontSize: 18.sp,
|
|
fontWeight: FontWeight.w600,
|
|
color: Colors.green,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
SizedBox(height: 8.h),
|
|
Text(
|
|
'正在跳转到主页...',
|
|
style: TextStyle(
|
|
fontSize: 14.sp,
|
|
color: Colors.grey[500],
|
|
),
|
|
),
|
|
],
|
|
);
|
|
case SearchStatus.noPermission:
|
|
return Column(
|
|
children: [
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
Icon(Icons.no_encryption, color: Colors.orange, size: 20.sp),
|
|
SizedBox(width: 8.w),
|
|
Text(
|
|
'缺少必要权限',
|
|
style: TextStyle(
|
|
fontSize: 18.sp,
|
|
fontWeight: FontWeight.w600,
|
|
color: Colors.orange,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
SizedBox(height: 8.h),
|
|
Text(
|
|
controller.errorMessage,
|
|
style: TextStyle(
|
|
fontSize: 14.sp,
|
|
color: Colors.grey[600],
|
|
),
|
|
textAlign: TextAlign.center,
|
|
),
|
|
SizedBox(height: 16.h),
|
|
ElevatedButton(
|
|
onPressed: () => controller.goToAppSettings(),
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: Colors.orange,
|
|
foregroundColor: Colors.white,
|
|
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h),
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(8.r),
|
|
),
|
|
),
|
|
child: Text('打开设置'),
|
|
),
|
|
],
|
|
);
|
|
case SearchStatus.failed:
|
|
return Column(
|
|
children: [
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
Icon(Icons.error, color: Colors.red, size: 20.sp),
|
|
SizedBox(width: 8.w),
|
|
Text(
|
|
'未找到设备',
|
|
style: TextStyle(
|
|
fontSize: 18.sp,
|
|
fontWeight: FontWeight.w600,
|
|
color: Colors.red,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
SizedBox(height: 8.h),
|
|
Text(
|
|
controller.errorMessage.isEmpty ?
|
|
'请确保耳机已开机并在附近' : controller.errorMessage,
|
|
style: TextStyle(
|
|
fontSize: 14.sp,
|
|
color: Colors.grey[600],
|
|
),
|
|
textAlign: TextAlign.center,
|
|
),
|
|
],
|
|
);
|
|
case SearchStatus.needsSystemPairing:
|
|
return Column(
|
|
children: [
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
Icon(Icons.bluetooth_searching, color: Colors.blue, size: 20.sp),
|
|
SizedBox(width: 8.w),
|
|
Text(
|
|
'需要系统配对',
|
|
style: TextStyle(
|
|
fontSize: 18.sp,
|
|
fontWeight: FontWeight.w600,
|
|
color: Colors.blue,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
SizedBox(height: 8.h),
|
|
Text(
|
|
controller.errorMessage.isEmpty ?
|
|
'请在系统设置中配对您的设备' : controller.errorMessage,
|
|
style: TextStyle(
|
|
fontSize: 14.sp,
|
|
color: Colors.grey[600],
|
|
),
|
|
textAlign: TextAlign.center,
|
|
),
|
|
SizedBox(height: 16.h),
|
|
ElevatedButton(
|
|
onPressed: () => controller.openSystemBluetoothSettings(),
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: Colors.blue,
|
|
foregroundColor: Colors.white,
|
|
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h),
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(8.r),
|
|
),
|
|
),
|
|
child: Text('打开蓝牙设置'),
|
|
),
|
|
],
|
|
);
|
|
default:
|
|
return SizedBox();
|
|
}
|
|
});
|
|
}
|
|
|
|
// 底部按钮
|
|
Widget _buildBottomButtons() {
|
|
return Column(
|
|
children: [
|
|
SizedBox(
|
|
width: double.infinity,
|
|
child: ElevatedButton(
|
|
onPressed: controller.refreshSearch,
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: Colors.grey[200],
|
|
foregroundColor: Colors.grey[800],
|
|
padding: EdgeInsets.symmetric(vertical: 16.h),
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(16.r),
|
|
),
|
|
elevation: 0,
|
|
),
|
|
child: Text(
|
|
'手动连接',
|
|
style: TextStyle(
|
|
fontSize: 16.sp,
|
|
fontWeight: FontWeight.w500,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
SizedBox(height: 12.h),
|
|
SizedBox(
|
|
width: double.infinity,
|
|
child: TextButton(
|
|
onPressed: controller.skipConnecting,
|
|
style: TextButton.styleFrom(
|
|
foregroundColor: Colors.blue[600],
|
|
padding: EdgeInsets.symmetric(vertical: 12.h),
|
|
),
|
|
child: Text(
|
|
'稍后再说',
|
|
style: TextStyle(
|
|
fontSize: 16.sp,
|
|
fontWeight: FontWeight.w500,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
}
|