Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can you return the static setKeyboardActions() or describe how to get equivalent functionality? #59

Closed
gary-c-chang opened this issue Dec 18, 2019 · 10 comments

Comments

@gary-c-chang
Copy link

I tried to upgrade to 3.1.2 from 2.1.2 but I need the equivalent of the old FormKeyboardActions.setKeyboardActions() as my logic for building the keyboard actions and my adding of the KeyboardActions widget are in different places. If there is a new way to achieve this with 3.1.2, can you please describe this in example code as I couldn't find a way to do this. Thanks.

@diegoveloper
Copy link
Owner

diegoveloper commented Dec 18, 2019 via email

@gary-c-chang
Copy link
Author

My code is structured the same way as the example code as per 2.1.2 https://pub.dev/packages/keyboard_actions/versions/2.1.2

In particular FormKeyboardActions widget is built in a separate class to where KeyboardActionsConfig is built, because my keyboard fields dynamically change depending on which type of form is being presented to the user. The example code for 2.1.2 gets around this by providing the static method FormKeyboardActions.setKeyboardActions(), which will update the previously built FormKeyboardActionsState with the update config. This is what I use to update the config. I'd just like this method to be put back. I finally got 3.1.2 working by copying the code inside FormKeyboardActions.setKeyboardActions() and putting it into my code (after renaming FormXX to XX).

The source code for 3.1.2 keyboard_actions.dart, line 70 sort of refers to this, but it seems incomplete:
/// Can be accessed statically via [] and [] to update with the latest and greatest [KeyboardActionsConfig].

3.1.2 as it currently stands doesn't allow for easy update of the config, whereas 2.1.2 did. 3.1.2 also forces the caller to define the config as soon as the KeyboardActions is created in the widget tree, whereas 2.1.2 allow the config to be defined later.

@diegoveloper
Copy link
Owner

diegoveloper commented Dec 18, 2019 via email

@gary-c-chang
Copy link
Author

That's not true, as when I build KeyboardActions, I do NOT have my config yet (see example 2.1.2 code - they are in separate classes) so my outer class does not know what keyboard actions to display yet. I need KeyboardActions at the outer level because putting it in the lower level causes sizing and layout issues. Anyway, don't bother as I have found a workaround as mentioned. Your suggestion forces the caller to build the KeyboardActions widget at the same time as the config which is not always possible for more complex use cases.

@zmGitHub
Copy link

+1

@diegoveloper
Copy link
Owner

diegoveloper commented Dec 18, 2019 via email

@gary-c-chang
Copy link
Author

gary-c-chang commented Dec 18, 2019

`
// Here is the 2.1.2 example that my actual code follows in terms of class separation.
// I have modified it to work with 3.1.2. See my comments starting GCC
// Thanks Diego

import 'package:flutter/material.dart';
import 'package:keyboard_actions/keyboard_actions.dart';

//Full screen
class ScaffoldTest extends StatelessWidget {
@OverRide
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: true,
appBar: AppBar(
title: Text("Keyboard Actions Sample"),
),
body: KeyboardActions(
config: KeyboardActionsConfig(actions: []), // GCC this was not needed in 2.1.2
child: Content(),
),
);
}
}

//Dialog

/// Displays our [FormKeyboardActions] nested in a [AlertDialog].
class DialogTest extends StatelessWidget {
@OverRide
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: true,
appBar: AppBar(
title: Text("Keyboard Actions Sample"),
),
body: Builder(builder: (context) {
return Center(
child: FlatButton(
color: Colors.blue,
child: Text('Launch dialog'),
onPressed: () => _launchInDialog(context),
),
);
}));
}

_launchInDialog(BuildContext context) {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text('Dialog test'),
content: KeyboardActions(autoScroll: true, child: Content()),
actions: [
FlatButton(
child: Text('Ok'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
}

class Content extends StatefulWidget {
@OverRide
_ContentState createState() => _ContentState();
}

class _ContentState extends State {
final FocusNode _nodeText1 = FocusNode();
final FocusNode _nodeText2 = FocusNode();
final FocusNode _nodeText3 = FocusNode();
final FocusNode _nodeText4 = FocusNode();
final FocusNode _nodeText5 = FocusNode();

/// Creates the [KeyboardActionsConfig] to hook up the fields
/// and their focus nodes to our [FormKeyboardActions].
KeyboardActionsConfig _buildConfig(BuildContext context) {
return KeyboardActionsConfig(
keyboardActionsPlatform: KeyboardActionsPlatform.ALL,
keyboardBarColor: Colors.grey[200],
nextFocus: true,
actions: [
KeyboardAction(
focusNode: _nodeText1,
),
KeyboardAction(
focusNode: _nodeText2,
closeWidget: Padding(
padding: EdgeInsets.all(8.0),
child: Icon(Icons.close),
),
),
KeyboardAction(
focusNode: _nodeText3,
onTapAction: () {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
content: Text("Custom Action"),
actions: [
FlatButton(
child: Text("OK"),
onPressed: () => Navigator.of(context).pop(),
)
],
);
});
},
),
KeyboardAction(
focusNode: _nodeText4,
displayCloseWidget: false,
),
KeyboardAction(
focusNode: _nodeText5,
closeWidget: Padding(
padding: EdgeInsets.all(5.0),
child: Text("CLOSE"),
),
),
],
);
}

@OverRide
void initState() {
// Configure keyboard actions

/**********
 * GCC Ideally the 3.1.2 library would provide this static method that was available in version 2.1.2
 KeyboardActions.setKeyboardActions(context, _buildConfig(context));
 */

// This is my workaround - just copied and slightly modified from the body of 2.1.2's FormKeyboardActions.setKeyboardActions:

final KeyboardActionstate state = context.findAncestorStateOfType<KeyboardActionstate>();

if (state == null) {
  throw FlutterError(
      'Context does not contain a FormKeyboardActions ancestor: see Scaffold.of for reference.');
}
state.setConfig(_buildConfig(context));
super.initState();

}

@OverRide
Widget build(BuildContext context) {
return Center(
child: Padding(
padding: const EdgeInsets.all(15.0),
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
TextField(
keyboardType: TextInputType.number,
focusNode: _nodeText1,
decoration: InputDecoration(
hintText: "Input Number",
),
),
TextField(
keyboardType: TextInputType.text,
focusNode: _nodeText2,
decoration: InputDecoration(
hintText: "Input Text with Custom Close Widget",
),
),
TextField(
keyboardType: TextInputType.number,
focusNode: _nodeText3,
decoration: InputDecoration(
hintText: "Input Number with Custom Action",
),
),
TextField(
keyboardType: TextInputType.text,
focusNode: _nodeText4,
decoration: InputDecoration(
hintText: "Input Text without Close Widget",
),
),
TextField(
keyboardType: TextInputType.number,
focusNode: _nodeText5,
decoration: InputDecoration(
hintText: "Input Number with Custom Close Widget",
),
),
],
),
),
),
);
}
}
`

@diegoveloper
Copy link
Owner

Why don't you remove the keyboard actions from here:

return Scaffold(
      resizeToAvoidBottomInset: true,
      appBar: AppBar(
        title: Text("Keyboard Actions Sample"),
      ),
      body:  Content(),
    );

and add it inside your Content widget.

  @override
  Widget build(BuildContext context) {
    return KeyboardActions(
      config: _buildConfig(context),
      child: Center(
        child: Padding(
          padding: const EdgeInsets.all(15.0),
          child: SingleChildScrollView(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: [
                TextField(
                  keyboardType: TextInputType.number,
                  focusNode: _nodeText1,
                  decoration: InputDecoration(
                    hintText: "Input Number",
                  ),
                ),

@gary-c-chang
Copy link
Author

As I've mentioned a few times in the thread above, I cannot do that as KeyboardActions widget at the lower level causes layout and placement issues / crashes. I've tried many different configuration of widgets (but either my form gets centered on screen rather than top aligned etc). As I've also mentioned, your solution needs separation between building the widget, and the configuration changing to handle dynamic sets of input fields.

@diegoveloper
Copy link
Owner

diegoveloper commented Dec 18, 2019 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants