Added keyboard checks
This commit is contained in:
@@ -77,249 +77,260 @@ class _CreateGameViewState extends State<CreateGameView> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return CupertinoPageScaffold(
|
return PopScope(
|
||||||
resizeToAvoidBottomInset: false,
|
canPop: false,
|
||||||
navigationBar: CupertinoNavigationBar(
|
onPopInvokedWithResult: (bool didPop, dynamic result) async {
|
||||||
previousPageTitle: AppLocalizations.of(context).games,
|
if (!didPop) {
|
||||||
middle: Text(AppLocalizations.of(context).new_game),
|
await _keyboardDelay();
|
||||||
),
|
if (context.mounted) Navigator.pop(context);
|
||||||
child: SafeArea(
|
}
|
||||||
child: SingleChildScrollView(
|
},
|
||||||
child: Column(
|
child: CupertinoPageScaffold(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
resizeToAvoidBottomInset: false,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
navigationBar: CupertinoNavigationBar(
|
||||||
children: [
|
previousPageTitle: AppLocalizations.of(context).games,
|
||||||
Padding(
|
middle: Text(AppLocalizations.of(context).new_game),
|
||||||
padding: const EdgeInsets.fromLTRB(10, 10, 0, 0),
|
),
|
||||||
child: Text(
|
child: SafeArea(
|
||||||
AppLocalizations.of(context).game,
|
child: SingleChildScrollView(
|
||||||
style: CustomTheme.rowTitle,
|
child: Column(
|
||||||
),
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
),
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
Padding(
|
children: [
|
||||||
padding: const EdgeInsets.fromLTRB(15, 10, 10, 0),
|
Padding(
|
||||||
child: CupertinoTextField(
|
padding: const EdgeInsets.fromLTRB(10, 10, 0, 0),
|
||||||
decoration: const BoxDecoration(),
|
child: Text(
|
||||||
maxLength: 20,
|
AppLocalizations.of(context).game,
|
||||||
prefix: Text(AppLocalizations.of(context).name),
|
style: CustomTheme.rowTitle,
|
||||||
textAlign: TextAlign.right,
|
),
|
||||||
placeholder: AppLocalizations.of(context).game_title,
|
|
||||||
controller: _gameTitleTextController,
|
|
||||||
onSubmitted: (_) {
|
|
||||||
_playerNameFocusNodes.isNotEmpty
|
|
||||||
? _playerNameFocusNodes[0].requestFocus()
|
|
||||||
: FocusScope.of(context).unfocus();
|
|
||||||
},
|
|
||||||
textInputAction: _playerNameFocusNodes.isNotEmpty
|
|
||||||
? TextInputAction.next
|
|
||||||
: TextInputAction.done,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.fromLTRB(15, 10, 10, 0),
|
|
||||||
child: CupertinoTextField(
|
|
||||||
decoration: const BoxDecoration(),
|
|
||||||
readOnly: true,
|
|
||||||
prefix: Text(AppLocalizations.of(context).mode),
|
|
||||||
suffix: Row(
|
|
||||||
children: [
|
|
||||||
_getDisplayedGameMode(),
|
|
||||||
const SizedBox(width: 3),
|
|
||||||
const CupertinoListTileChevron(),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
onTap: () async {
|
Padding(
|
||||||
final selectedMode = await Navigator.push(
|
padding: const EdgeInsets.fromLTRB(15, 10, 10, 0),
|
||||||
context,
|
child: CupertinoTextField(
|
||||||
CupertinoPageRoute(
|
decoration: const BoxDecoration(),
|
||||||
builder: (context) => ModeSelectionMenu(
|
maxLength: 20,
|
||||||
pointLimit: ConfigService.getPointLimit(),
|
prefix: Text(AppLocalizations.of(context).name),
|
||||||
showDeselection: false,
|
textAlign: TextAlign.right,
|
||||||
),
|
placeholder: AppLocalizations.of(context).game_title,
|
||||||
),
|
controller: _gameTitleTextController,
|
||||||
);
|
onSubmitted: (_) {
|
||||||
|
_playerNameFocusNodes.isNotEmpty
|
||||||
setState(() {
|
? _playerNameFocusNodes[0].requestFocus()
|
||||||
gameMode = selectedMode ?? gameMode;
|
: FocusScope.of(context).unfocus();
|
||||||
});
|
},
|
||||||
},
|
textInputAction: _playerNameFocusNodes.isNotEmpty
|
||||||
),
|
? TextInputAction.next
|
||||||
),
|
: TextInputAction.done,
|
||||||
Padding(
|
),
|
||||||
padding: const EdgeInsets.fromLTRB(10, 10, 0, 0),
|
),
|
||||||
child: Text(
|
Padding(
|
||||||
AppLocalizations.of(context).players,
|
padding: const EdgeInsets.fromLTRB(15, 10, 10, 0),
|
||||||
style: CustomTheme.rowTitle,
|
child: CupertinoTextField(
|
||||||
),
|
decoration: const BoxDecoration(),
|
||||||
),
|
readOnly: true,
|
||||||
ReorderableListView.builder(
|
prefix: Text(AppLocalizations.of(context).mode),
|
||||||
shrinkWrap: true,
|
suffix: Row(
|
||||||
physics: const BouncingScrollPhysics(),
|
|
||||||
padding: const EdgeInsets.all(8),
|
|
||||||
itemCount: _playerNameTextControllers.length,
|
|
||||||
onReorder: (oldIndex, newIndex) {
|
|
||||||
setState(() {
|
|
||||||
if (oldIndex < _playerNameTextControllers.length &&
|
|
||||||
newIndex <= _playerNameTextControllers.length) {
|
|
||||||
if (newIndex > oldIndex) newIndex--;
|
|
||||||
final item =
|
|
||||||
_playerNameTextControllers.removeAt(oldIndex);
|
|
||||||
_playerNameTextControllers.insert(newIndex, item);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
return Padding(
|
|
||||||
key: ValueKey(index),
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
children: [
|
||||||
CupertinoButton(
|
_getDisplayedGameMode(),
|
||||||
padding: EdgeInsets.zero,
|
const SizedBox(width: 3),
|
||||||
child: Icon(
|
const CupertinoListTileChevron(),
|
||||||
CupertinoIcons.minus_circle_fill,
|
|
||||||
color: CustomTheme.red,
|
|
||||||
size: 25,
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
setState(() {
|
|
||||||
_playerNameTextControllers[index].dispose();
|
|
||||||
_playerNameTextControllers.removeAt(index);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: CupertinoTextField(
|
|
||||||
controller: _playerNameTextControllers[index],
|
|
||||||
focusNode: _playerNameFocusNodes[index],
|
|
||||||
maxLength: 12,
|
|
||||||
placeholder:
|
|
||||||
'${AppLocalizations.of(context).player} ${index + 1}',
|
|
||||||
padding: const EdgeInsets.all(12),
|
|
||||||
decoration: const BoxDecoration(),
|
|
||||||
textInputAction:
|
|
||||||
index + 1 < _playerNameTextControllers.length
|
|
||||||
? TextInputAction.next
|
|
||||||
: TextInputAction.done,
|
|
||||||
onSubmitted: (_) {
|
|
||||||
if (index + 1 < _playerNameFocusNodes.length) {
|
|
||||||
_playerNameFocusNodes[index + 1]
|
|
||||||
.requestFocus();
|
|
||||||
} else {
|
|
||||||
FocusScope.of(context).unfocus();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
AnimatedOpacity(
|
|
||||||
opacity: _playerNameTextControllers.length > 1
|
|
||||||
? 1.0
|
|
||||||
: 0.0,
|
|
||||||
duration: const Duration(
|
|
||||||
milliseconds: Constants.kFadeInDuration),
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.only(right: 8.0),
|
|
||||||
child: ReorderableDragStartListener(
|
|
||||||
index: index,
|
|
||||||
child: const Icon(
|
|
||||||
CupertinoIcons.line_horizontal_3,
|
|
||||||
color: CupertinoColors.systemGrey,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
onTap: () async {
|
||||||
}),
|
await _keyboardDelay();
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.fromLTRB(8, 0, 8, 50),
|
if (context.mounted) {
|
||||||
child: Stack(
|
final selectedMode = await Navigator.push(
|
||||||
children: [
|
context,
|
||||||
Row(
|
CupertinoPageRoute(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
builder: (context) => ModeSelectionMenu(
|
||||||
children: [
|
pointLimit: ConfigService.getPointLimit(),
|
||||||
CupertinoButton(
|
showDeselection: false,
|
||||||
padding: EdgeInsets.zero,
|
),
|
||||||
onPressed: null,
|
),
|
||||||
child: Icon(
|
);
|
||||||
CupertinoIcons.plus_circle_fill,
|
|
||||||
color: CustomTheme.primaryColor,
|
setState(() {
|
||||||
size: 25,
|
gameMode = selectedMode ?? gameMode;
|
||||||
),
|
});
|
||||||
),
|
}
|
||||||
],
|
},
|
||||||
),
|
),
|
||||||
Center(
|
),
|
||||||
child: CupertinoButton(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 0),
|
padding: const EdgeInsets.fromLTRB(10, 10, 0, 0),
|
||||||
child: Row(
|
child: Text(
|
||||||
|
AppLocalizations.of(context).players,
|
||||||
|
style: CustomTheme.rowTitle,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ReorderableListView.builder(
|
||||||
|
shrinkWrap: true,
|
||||||
|
physics: const BouncingScrollPhysics(),
|
||||||
|
padding: const EdgeInsets.all(8),
|
||||||
|
itemCount: _playerNameTextControllers.length,
|
||||||
|
onReorder: (oldIndex, newIndex) {
|
||||||
|
setState(() {
|
||||||
|
if (oldIndex < _playerNameTextControllers.length &&
|
||||||
|
newIndex <= _playerNameTextControllers.length) {
|
||||||
|
if (newIndex > oldIndex) newIndex--;
|
||||||
|
final item =
|
||||||
|
_playerNameTextControllers.removeAt(oldIndex);
|
||||||
|
_playerNameTextControllers.insert(newIndex, item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
return Padding(
|
||||||
|
key: ValueKey(index),
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
CupertinoButton(
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
child: Icon(
|
||||||
|
CupertinoIcons.minus_circle_fill,
|
||||||
|
color: CustomTheme.red,
|
||||||
|
size: 25,
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
setState(() {
|
||||||
|
_playerNameTextControllers[index].dispose();
|
||||||
|
_playerNameTextControllers.removeAt(index);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: CupertinoTextField(
|
||||||
|
controller: _playerNameTextControllers[index],
|
||||||
|
focusNode: _playerNameFocusNodes[index],
|
||||||
|
maxLength: 12,
|
||||||
|
placeholder:
|
||||||
|
'${AppLocalizations.of(context).player} ${index + 1}',
|
||||||
|
padding: const EdgeInsets.all(12),
|
||||||
|
decoration: const BoxDecoration(),
|
||||||
|
textInputAction: index + 1 <
|
||||||
|
_playerNameTextControllers.length
|
||||||
|
? TextInputAction.next
|
||||||
|
: TextInputAction.done,
|
||||||
|
onSubmitted: (_) {
|
||||||
|
if (index + 1 <
|
||||||
|
_playerNameFocusNodes.length) {
|
||||||
|
_playerNameFocusNodes[index + 1]
|
||||||
|
.requestFocus();
|
||||||
|
} else {
|
||||||
|
FocusScope.of(context).unfocus();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
AnimatedOpacity(
|
||||||
|
opacity: _playerNameTextControllers.length > 1
|
||||||
|
? 1.0
|
||||||
|
: 0.0,
|
||||||
|
duration: const Duration(
|
||||||
|
milliseconds: Constants.kFadeInDuration),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 8.0),
|
||||||
|
child: ReorderableDragStartListener(
|
||||||
|
index: index,
|
||||||
|
child: const Icon(
|
||||||
|
CupertinoIcons.line_horizontal_3,
|
||||||
|
color: CupertinoColors.systemGrey,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(8, 0, 8, 50),
|
||||||
|
child: Stack(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
CupertinoButton(
|
||||||
child: Center(
|
padding: EdgeInsets.zero,
|
||||||
child: Text(
|
onPressed: null,
|
||||||
AppLocalizations.of(context).add_player,
|
child: Icon(
|
||||||
style: TextStyle(
|
CupertinoIcons.plus_circle_fill,
|
||||||
color: CustomTheme.primaryColor),
|
color: CustomTheme.primaryColor,
|
||||||
),
|
size: 25,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
onPressed: () {
|
Center(
|
||||||
if (_playerNameTextControllers.length < maxPlayers) {
|
child: CupertinoButton(
|
||||||
setState(() {
|
padding: const EdgeInsets.symmetric(horizontal: 0),
|
||||||
_playerNameTextControllers
|
child: Row(
|
||||||
.add(TextEditingController());
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
_playerNameFocusNodes.add(FocusNode());
|
children: [
|
||||||
});
|
Expanded(
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
child: Center(
|
||||||
_playerNameFocusNodes.last.requestFocus();
|
child: Text(
|
||||||
});
|
AppLocalizations.of(context).add_player,
|
||||||
} else {
|
style: TextStyle(
|
||||||
_showFeedbackDialog(CreateStatus.maxPlayers);
|
color: CustomTheme.primaryColor),
|
||||||
}
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
if (_playerNameTextControllers.length <
|
||||||
|
maxPlayers) {
|
||||||
|
setState(() {
|
||||||
|
_playerNameTextControllers
|
||||||
|
.add(TextEditingController());
|
||||||
|
_playerNameFocusNodes.add(FocusNode());
|
||||||
|
});
|
||||||
|
WidgetsBinding.instance
|
||||||
|
.addPostFrameCallback((_) {
|
||||||
|
_playerNameFocusNodes.last.requestFocus();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
_showFeedbackDialog(CreateStatus.maxPlayers);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(0, 0, 0, 50),
|
||||||
|
child: Center(
|
||||||
|
child: CustomButton(
|
||||||
|
child: Text(
|
||||||
|
AppLocalizations.of(context).create_game,
|
||||||
|
style: TextStyle(
|
||||||
|
color: CustomTheme.primaryColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onPressed: () async {
|
||||||
|
await _keyboardDelay();
|
||||||
|
_checkAllGameAttributes();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.fromLTRB(0, 0, 0, 50),
|
|
||||||
child: Center(
|
|
||||||
child: CustomButton(
|
|
||||||
child: Text(
|
|
||||||
AppLocalizations.of(context).create_game,
|
|
||||||
style: TextStyle(
|
|
||||||
color: CustomTheme.primaryColor,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
FocusScope.of(context).unfocus();
|
|
||||||
Future.delayed(
|
|
||||||
const Duration(
|
|
||||||
milliseconds: Constants.kKeyboardDelay), () {
|
|
||||||
_checkAllGameAttributes();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
KeyboardVisibilityBuilder(builder: (context, visible) {
|
||||||
|
if (visible) {
|
||||||
|
return SizedBox(
|
||||||
|
height: MediaQuery.of(context).viewInsets.bottom *
|
||||||
|
keyboardHeightAdjustmentFactor,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return const SizedBox.shrink();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
],
|
||||||
),
|
),
|
||||||
KeyboardVisibilityBuilder(builder: (context, visible) {
|
))));
|
||||||
if (visible) {
|
|
||||||
return SizedBox(
|
|
||||||
height: MediaQuery.of(context).viewInsets.bottom *
|
|
||||||
keyboardHeightAdjustmentFactor,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return const SizedBox.shrink();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a widget that displays the currently selected game mode in the View.
|
/// Returns a widget that displays the currently selected game mode in the View.
|
||||||
@@ -460,8 +471,18 @@ class _CreateGameViewState extends State<CreateGameView> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _keyboardDelay() async {
|
||||||
|
if (!KeyboardVisibilityController().isVisible) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
FocusScope.of(context).unfocus();
|
||||||
|
await Future.delayed(
|
||||||
|
const Duration(milliseconds: Constants.kKeyboardDelay), () {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
Future<void> dispose() async {
|
||||||
_gameTitleTextController.dispose();
|
_gameTitleTextController.dispose();
|
||||||
for (var controller in _playerNameTextControllers) {
|
for (var controller in _playerNameTextControllers) {
|
||||||
controller.dispose();
|
controller.dispose();
|
||||||
|
|||||||
Reference in New Issue
Block a user