flutter: Support screen recording (Experimental)
This commit is contained in:
parent
2989407d31
commit
2b157caba7
|
@ -200,6 +200,30 @@
|
|||
"@startNewGame": {
|
||||
"description": "Start new game"
|
||||
},
|
||||
"startRecording": "Starte die Aufnahme",
|
||||
"@startRecording": {
|
||||
"description": "Start recording"
|
||||
},
|
||||
"recording": "Aufzeichnung...",
|
||||
"@recording": {
|
||||
"description": "Recording..."
|
||||
},
|
||||
"stopRecording": "Höre auf, aufzunehmen",
|
||||
"@stopRecording": {
|
||||
"description": "Stop recording"
|
||||
},
|
||||
"showRecording": "Aufnahme anzeigen",
|
||||
"@showRecording": {
|
||||
"description": "Show recording"
|
||||
},
|
||||
"noRecording": "Kein Aufnehmen.",
|
||||
"@noRecording": {
|
||||
"description": "No recording."
|
||||
},
|
||||
"pleaseWait": "Warten Sie mal...",
|
||||
"@pleaseWait": {
|
||||
"description": "Please wait..."
|
||||
},
|
||||
"restartGame": "Spiel neu beginnen?",
|
||||
"@restartGame": {
|
||||
"description": "Restart current Game?"
|
||||
|
@ -935,5 +959,9 @@
|
|||
"more": "Mehr",
|
||||
"@more": {
|
||||
"description": "More"
|
||||
},
|
||||
"experimental": "Dies ist eine experimentelle Funktion.",
|
||||
"@experimental": {
|
||||
"description": "Dies ist eine experimentelle Funktion."
|
||||
}
|
||||
}
|
||||
|
|
|
@ -200,6 +200,30 @@
|
|||
"@startNewGame": {
|
||||
"description": "Start new game"
|
||||
},
|
||||
"startRecording": "Start recording",
|
||||
"@startRecording": {
|
||||
"description": "Start recording"
|
||||
},
|
||||
"recording": "Recording...",
|
||||
"@recording": {
|
||||
"description": "Recording..."
|
||||
},
|
||||
"stopRecording": "Stop recording",
|
||||
"@stopRecording": {
|
||||
"description": "Stop recording"
|
||||
},
|
||||
"showRecording": "Show recording",
|
||||
"@showRecording": {
|
||||
"description": "Show recording"
|
||||
},
|
||||
"noRecording": "No recording.",
|
||||
"@noRecording": {
|
||||
"description": "No recording."
|
||||
},
|
||||
"pleaseWait": "Please wait...",
|
||||
"@pleaseWait": {
|
||||
"description": "Please wait..."
|
||||
},
|
||||
"restartGame": "Restart current Game?",
|
||||
"@restartGame": {
|
||||
"description": "Restart current Game?"
|
||||
|
@ -935,5 +959,9 @@
|
|||
"more": "More",
|
||||
"@more": {
|
||||
"description": "More"
|
||||
},
|
||||
"experimental": "This is an experimental feature.",
|
||||
"@experimental": {
|
||||
"description": "This is an experimental feature."
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,6 +50,12 @@
|
|||
"thinking": "对方思考中...",
|
||||
"newGame": "新局",
|
||||
"startNewGame": "开始新局",
|
||||
"startRecording": "开始录制",
|
||||
"recording": "录制中...",
|
||||
"stopRecording": "停止录制",
|
||||
"showRecording": "回放录制",
|
||||
"noRecording": "没有可回放的",
|
||||
"pleaseWait": "请稍候...",
|
||||
"restartGame": "重新开局?",
|
||||
"restart": "重开局",
|
||||
"gameStarted": "游戏开始 请落子",
|
||||
|
@ -233,5 +239,6 @@
|
|||
"atEnd": "已经到底了",
|
||||
"tapBackAgainToLeave": "再次按返回键退出应用",
|
||||
"environmentVariables": "环境变量",
|
||||
"more": "更多"
|
||||
"more": "更多",
|
||||
"experimental": "此仍属实验性功能。"
|
||||
}
|
|
@ -17,6 +17,7 @@
|
|||
*/
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
@ -32,6 +33,7 @@ import 'package:sanmill/mill/types.dart';
|
|||
import 'package:sanmill/services/audios.dart';
|
||||
import 'package:sanmill/style/app_theme.dart';
|
||||
import 'package:sanmill/widgets/game_settings_page.dart';
|
||||
import 'package:screen_recorder/screen_recorder.dart';
|
||||
import 'package:stack_trace/stack_trace.dart';
|
||||
|
||||
import 'board.dart';
|
||||
|
@ -58,6 +60,10 @@ class _GamePageState extends State<GamePage> with RouteAware {
|
|||
bool isReady = false;
|
||||
bool isGoingToHistory = false;
|
||||
late Timer timer;
|
||||
ScreenRecorderController screenRecorderController = ScreenRecorderController(
|
||||
pixelRatio: 1.0,
|
||||
skipFramesBetweenCaptures: 0,
|
||||
);
|
||||
final String tag = "[game_page]";
|
||||
|
||||
@override
|
||||
|
@ -479,6 +485,75 @@ class _GamePageState extends State<GamePage> with RouteAware {
|
|||
}
|
||||
}
|
||||
|
||||
onStartRecordingButtonPressed() async {
|
||||
Navigator.of(context).pop();
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: true,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text(
|
||||
S.of(context).appName,
|
||||
style: TextStyle(color: AppTheme.dialogTitleColor),
|
||||
),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
S.of(context).experimental,
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
child: Text(S.of(context).ok),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
screenRecorderController.start();
|
||||
showSnackBar(
|
||||
S.of(context).recording,
|
||||
duration: Duration(seconds: 1 << 31),
|
||||
);
|
||||
}
|
||||
|
||||
onStopRecordingButtonPressed() async {
|
||||
Navigator.of(context).pop();
|
||||
screenRecorderController.stop();
|
||||
showSnackBar(
|
||||
S.of(context).stopRecording,
|
||||
duration: Duration(seconds: 2),
|
||||
);
|
||||
}
|
||||
|
||||
onShowRecordingButtonPressed() async {
|
||||
Navigator.of(context).pop();
|
||||
showSnackBar(
|
||||
S.of(context).pleaseWait,
|
||||
duration: Duration(seconds: 1 << 31),
|
||||
);
|
||||
var gif = await screenRecorderController.export();
|
||||
ScaffoldMessenger.of(context).hideCurrentSnackBar();
|
||||
if (gif == null) {
|
||||
showSnackBar(S.of(context).noRecording);
|
||||
return;
|
||||
}
|
||||
|
||||
var image = Image.memory(
|
||||
Uint8List.fromList(gif),
|
||||
);
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(backgroundColor: Colors.black, content: image);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
onAutoReplayButtonPressed() async {
|
||||
Navigator.of(context).pop();
|
||||
|
||||
|
@ -487,8 +562,9 @@ class _GamePageState extends State<GamePage> with RouteAware {
|
|||
}
|
||||
|
||||
onGameButtonPressed() {
|
||||
showDialog(
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
backgroundColor: Colors.transparent,
|
||||
builder: (BuildContext context) {
|
||||
return SimpleDialog(
|
||||
backgroundColor: Colors.transparent,
|
||||
|
@ -501,6 +577,33 @@ class _GamePageState extends State<GamePage> with RouteAware {
|
|||
),
|
||||
onPressed: onStartNewGameButtonPressed,
|
||||
),
|
||||
SizedBox(height: AppTheme.sizedBoxHeight),
|
||||
SimpleDialogOption(
|
||||
child: Text(
|
||||
S.of(context).startRecording,
|
||||
style: AppTheme.simpleDialogOptionTextStyle,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
onPressed: onStartRecordingButtonPressed,
|
||||
),
|
||||
SizedBox(height: AppTheme.sizedBoxHeight),
|
||||
SimpleDialogOption(
|
||||
child: Text(
|
||||
S.of(context).stopRecording,
|
||||
style: AppTheme.simpleDialogOptionTextStyle,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
onPressed: onStopRecordingButtonPressed,
|
||||
),
|
||||
SizedBox(height: AppTheme.sizedBoxHeight),
|
||||
SimpleDialogOption(
|
||||
child: Text(
|
||||
S.of(context).showRecording,
|
||||
style: AppTheme.simpleDialogOptionTextStyle,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
onPressed: onShowRecordingButtonPressed,
|
||||
),
|
||||
/*
|
||||
SizedBox(height: AppTheme.sizedBoxHeight),
|
||||
SimpleDialogOption(
|
||||
|
@ -1002,10 +1105,13 @@ class _GamePageState extends State<GamePage> with RouteAware {
|
|||
);
|
||||
}
|
||||
|
||||
void showSnackBar(String message) {
|
||||
void showSnackBar(String message,
|
||||
{Duration duration = const Duration(milliseconds: 4000)}) {
|
||||
ScaffoldMessenger.of(context).hideCurrentSnackBar();
|
||||
ScaffoldMessenger.of(context)
|
||||
.showSnackBar(SnackBar(content: Text(message)));
|
||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
|
||||
content: Text(message),
|
||||
duration: duration,
|
||||
));
|
||||
}
|
||||
|
||||
String getInfoText() {
|
||||
|
@ -1160,7 +1266,16 @@ class _GamePageState extends State<GamePage> with RouteAware {
|
|||
|
||||
return Scaffold(
|
||||
backgroundColor: Color(Config.darkBackgroundColor),
|
||||
body: Column(children: <Widget>[header, board, toolbar]),
|
||||
body: Column(children: <Widget>[
|
||||
header,
|
||||
ScreenRecorder(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
height: MediaQuery.of(context).size.width,
|
||||
controller: screenRecorderController,
|
||||
child: board,
|
||||
),
|
||||
toolbar
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ dependencies:
|
|||
device_info_plus_platform_interface: ^1.0.1
|
||||
devicelocale: ^0.4.1
|
||||
double_back_to_close_app: ^2.0.1
|
||||
screen_recorder: ^0.0.2
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
Loading…
Reference in New Issue