Flutter健身锻炼管理插件workout的使用
Flutter健身锻炼管理插件workout的使用
workout简介
workout
插件可以帮助你在Flutter应用程序中启动健身锻炼会话,并从Wear OS和Tizen设备获取实时健康数据。此外,它还可以在iOS上启动watchOS应用。
入门指南
Wear OS
目前Health Services for Wear OS处于测试阶段。为了使用此插件,你需要确保满足以下条件:
- 在
android/app/build.gradle
文件中设置minSdkVersion 30
- 修改
android/app/src/main/AndroidManifest.xml
文件,添加必要的权限:
<!-- Required for heart rate -->
<uses-permission android:name="android.permission.BODY_SENSORS" />
<!-- Required for calories, steps, distance, speed -->
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
<!-- Required to use location to estimate distance, speed -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
Tizen
此插件要求Tizen 4.0或更高版本。需要对tizen/tizen-manifest.xml
进行如下修改:
<manifest api-version="4.0" ...>
<privileges>
<privilege>http://tizen.org/privilege/healthinfo</privilege>
</privileges>
<feature name="http://tizen.org/feature/sensor.heart_rate_monitor">true</feature>
<feature name="http://tizen.org/feature/sensor.pedometer">true</feature>
</manifest>
iOS
虽然Flutter不能直接运行在watchOS上,但可以通过iOS启动watch应用。要使这一功能正常工作,需确保:
- 手机和手表应用都具有
HealthKit
权限。 - 手表应用启用了
Workout Processing
后台模式。
支持的数据类型
Feature | Wear OS | Tizen |
---|---|---|
心率 | Yes | Yes |
卡路里 | Yes | Yes |
步数 | Yes | Yes |
速度 | Yes | Yes |
距离 | Yes | Yes |
示例代码
以下是完整的示例demo,演示如何使用workout
插件创建一个简单的健身锻炼应用:
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:wear_plus/wear_plus.dart';
import 'package:workout/workout.dart';
void main() {
runApp(Platform.isIOS ? const MyIosApp() : const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final workout = Workout();
final exerciseType = ExerciseType.walking;
final features = [
WorkoutFeature.heartRate,
WorkoutFeature.calories,
WorkoutFeature.steps,
WorkoutFeature.distance,
WorkoutFeature.speed,
];
final enableGps = true;
double heartRate = 0;
double calories = 0;
double steps = 0;
double distance = 0;
double speed = 0;
bool started = false;
_MyAppState() {
workout.stream.listen((event) {
debugPrint('${event.feature}: ${event.value} (${event.timestamp})');
switch (event.feature) {
case WorkoutFeature.unknown:
return;
case WorkoutFeature.heartRate:
setState(() {
heartRate = event.value;
});
case WorkoutFeature.calories:
setState(() {
calories = event.value;
});
case WorkoutFeature.steps:
setState(() {
steps = event.value;
});
case WorkoutFeature.distance:
setState(() {
distance = event.value;
});
case WorkoutFeature.speed:
setState(() {
speed = event.value;
});
}
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: Colors.black),
home: AmbientMode(
builder: (context, mode, child) => child!,
child: Scaffold(
body: Center(
child: Column(
children: [
const Spacer(),
Text('Heart rate: $heartRate'),
Text('Calories: ${calories.toStringAsFixed(2)}'),
Text('Steps: $steps'),
Text('Distance: ${distance.toStringAsFixed(2)}'),
Text('Speed: ${speed.toStringAsFixed(2)}'),
const Spacer(),
TextButton(
onPressed: toggleExerciseState,
child: Text(started ? 'Stop' : 'Start'),
),
],
),
),
),
),
);
}
void toggleExerciseState() async {
if (started) {
await workout.stop();
} else {
final supportedExerciseTypes = await workout.getSupportedExerciseTypes();
debugPrint('Supported exercise types: ${supportedExerciseTypes.length}');
final result = await workout.start(
exerciseType: exerciseType,
features: features,
enableGps: enableGps,
);
if (result.unsupportedFeatures.isNotEmpty) {
debugPrint('Unsupported features: ${result.unsupportedFeatures}');
} else {
debugPrint('All requested features supported');
}
}
setState(() => started = !started);
}
}
class MyIosApp extends StatefulWidget {
const MyIosApp({super.key});
@override
State<StatefulWidget> createState() => _MyIosAppState();
}
class _MyIosAppState extends State<MyIosApp> {
final workout = Workout();
var exerciseType = ExerciseType.workout;
var locationType = WorkoutLocationType.indoor;
var swimmingLocationType = WorkoutSwimmingLocationType.pool;
var lapLength = 25.0;
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: SafeArea(
child: ListView(
padding: const EdgeInsets.all(16),
children: [
DropdownButton<ExerciseType>(
value: exerciseType,
onChanged: (value) => setState(() => exerciseType = value!),
items: ExerciseType.values
.map((e) => DropdownMenuItem(value: e, child: Text(e.name)))
.toList(),
),
DropdownButton<WorkoutLocationType>(
value: locationType,
onChanged: (value) => setState(() => locationType = value!),
items: WorkoutLocationType.values
.map((e) => DropdownMenuItem(value: e, child: Text(e.name)))
.toList(),
),
DropdownButton<WorkoutSwimmingLocationType>(
value: swimmingLocationType,
onChanged: (value) =>
setState(() => swimmingLocationType = value!),
items: WorkoutSwimmingLocationType.values
.map((e) => DropdownMenuItem(value: e, child: Text(e.name)))
.toList(),
),
TextField(
decoration: const InputDecoration(labelText: 'Lap length'),
keyboardType: TextInputType.number,
onChanged: (value) =>
setState(() => lapLength = double.parse(value)),
),
ElevatedButton(
onPressed: start,
child: const Text('Start Apple Watch app'),
),
],
),
),
),
);
}
void start() {
workout.start(
exerciseType: exerciseType,
features: [],
locationType: locationType,
swimmingLocationType: swimmingLocationType,
lapLength: lapLength,
);
}
}
通过以上代码,你可以创建一个简单的Flutter应用来管理健身锻炼,并从连接的可穿戴设备获取实时健康数据。希望这个例子能帮助你更好地理解和使用workout
插件!
更多关于Flutter健身锻炼管理插件workout的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter健身锻炼管理插件workout的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,关于Flutter中的workout
插件(需要注意的是,Flutter社区和官方库中并没有一个直接名为workout
的广泛认可的标准插件,但我将假设你指的是一个健身锻炼管理相关的自定义或第三方插件,或者是一个概念性的需求),下面是一个如何集成和使用一个假设的健身锻炼管理插件的示例代码案例。这个示例将涵盖初始化插件、创建锻炼计划、记录锻炼数据等核心功能。
1. 添加依赖
首先,假设这个插件在pub.dev
上可用,你需要在pubspec.yaml
文件中添加依赖:
dependencies:
flutter:
sdk: flutter
workout_manager: ^1.0.0 # 假设插件名为workout_manager,版本号根据实际情况填写
然后运行flutter pub get
来安装依赖。
2. 初始化插件
在你的主应用文件(通常是main.dart
)中,初始化插件:
import 'package:flutter/material.dart';
import 'package:workout_manager/workout_manager.dart'; // 假设插件的import路径
void main() {
WidgetsFlutterBinding.ensureInitialized();
// 初始化插件(如果有初始化方法)
WorkoutManager.instance.initialize();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Fitness Tracker',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: HomeScreen(),
);
}
}
3. 创建锻炼计划
接下来,你可以创建一个页面来添加锻炼计划。假设插件提供了Workout
和Exercise
类来表示锻炼和单个练习:
import 'package:flutter/material.dart';
import 'package:workout_manager/workout_manager.dart';
class CreateWorkoutScreen extends StatefulWidget {
@override
_CreateWorkoutScreenState createState() => _CreateWorkoutScreenState();
}
class _CreateWorkoutScreenState extends State<CreateWorkoutScreen> {
final TextEditingController _workoutNameController = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Create Workout'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: <Widget>[
TextField(
controller: _workoutNameController,
decoration: InputDecoration(labelText: 'Workout Name'),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () async {
// 创建练习(假设Exercise有一个构造函数接受名称和持续时间)
List<Exercise> exercises = [
Exercise('Squats', Duration(minutes: 3, seconds: 0)),
Exercise('Push-ups', Duration(minutes: 2, seconds: 0)),
];
// 创建锻炼(假设Workout有一个构造函数接受名称和练习列表)
Workout workout = Workout(_workoutNameController.text, exercises);
// 保存锻炼到数据库或本地存储(根据插件提供的API)
await WorkoutManager.instance.saveWorkout(workout);
// 返回到前一个屏幕或显示成功消息
Navigator.pop(context);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Workout created successfully!')),
);
},
child: Text('Create Workout'),
),
],
),
),
);
}
}
4. 显示锻炼计划
最后,你可以创建一个页面来显示已保存的锻炼计划:
import 'package:flutter/material.dart';
import 'package:workout_manager/workout_manager.dart';
class WorkoutListScreen extends StatefulWidget {
@override
_WorkoutListScreenState createState() => _WorkoutListScreenState();
}
class _WorkoutListScreenState extends State<WorkoutListScreen> {
List<Workout> _workouts = [];
@override
void initState() {
super.initState();
// 从数据库或本地存储加载锻炼计划
_loadWorkouts();
}
Future<void> _loadWorkouts() async {
_workouts = await WorkoutManager.instance.loadWorkouts();
setState(() {});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('My Workouts'),
),
body: _workouts.isEmpty
? Center(child: Text('No workouts found.'))
: ListView.builder(
itemCount: _workouts.length,
itemBuilder: (context, index) {
Workout workout = _workouts[index];
return ListTile(
title: Text(workout.name),
subtitle: Text('${workout.exercises.length} exercises'),
trailing: Icon(Icons.arrow_forward),
onTap: () {
// 导航到锻炼详情页面
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => WorkoutDetailScreen(workout: workout),
),
);
},
);
},
),
);
}
}
class WorkoutDetailScreen extends StatelessWidget {
final Workout workout;
WorkoutDetailScreen({required this.workout});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(workout.name),
),
body: ListView.builder(
itemCount: workout.exercises.length,
itemBuilder: (context, index) {
Exercise exercise = workout.exercises[index];
return ListTile(
title: Text(exercise.name),
subtitle: Text('Duration: ${exercise.duration}'),
);
},
),
);
}
}
总结
以上代码示例展示了如何在Flutter应用中集成和使用一个假设的健身锻炼管理插件。请注意,实际的插件API可能会有所不同,因此你需要参考插件的官方文档来调整代码。如果插件不存在,你可能需要自己实现这些功能,包括数据模型、持久化存储和用户界面。