Attached is a video demonstrating what I am trying to do. 3 things are noted:
1) I am trying to use the onFormFieldFocusChange to showDatePicker() and use that to update the value of the form field. There is weird behavior with the keyboard showing and hiding behind the picker though. I try and remedy this with FocusManager.instance.primaryFocus?.unfocus(); but it does not work.
2) the list box does not show a scrollbar so it is hard for users to tell there are more options.
3) The form field at the bottom of the page hides behind the keyboard when trying to type in it.
below is the minim reproducible code. anad attached are a video and the pdf used.
```
import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: true,
appBar: AppBar(
title: Text(widget.title),
),
body: Builder(
builder: (BuildContext context) {
return SfPdfViewer.asset(
'assets/test_pdf.pdf',
onFormFieldFocusChange: (details) async {
if (details.hasFocus) {
if (details.formField.name == 'test date box') {
FocusManager.instance.primaryFocus?.unfocus();
var chosen = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(1900),
lastDate: DateTime(2100),
);
(details.formField as PdfTextFormField).text =
chosen?.toString() ?? '';
} else if (details.formField.name == 'test date box2') {
var chosen = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(1900),
lastDate: DateTime(2100),
);
(details.formField as PdfTextFormField).text =
chosen?.toString() ?? '';
}
}
},
);
},
),
);
}
} ```
Also, if I add a signature to the document it glitches out. If the signature is really short it is okay but if I try a full name then the glitching occurs. See image below.
Edit I did find this post: https://github.com/syncfusion/flutter-examples/issues/792 Which goes over how it is an impeller issue with flutter. This is unfortunate as the way forward with flutter is now via Impeller as it is opt-out only now.
Does the team have any plans to adapt this to work with impeller?
Hi Jeremy Isenburg,
Currently, we are checking on the reported query and will update the further details on August 2, 2023.
Regards,
Deepika R
Hi Jeremy Isenburg,
Regarding the combo box from field does not show a scrollbar so it is hard for users to tell there are more options:
We are utilizing the PopupMenuButton widget to create the combo box form field in SfPdfViewer. On the mobile platform, the scrollbar will not be visible. This is the default behavior for PopupMenuButton.
We are currently validating the reported issue on the onFormFieldFocusChange callback, and the form field hide issue. We will provide further details on August 4, 2023.
Regards,
Deepika R
Thank you for the update!
Instead of a PopupMenuButton, could a DropdownButtonFormField be used instead? This will have the same functionality except the scrollbar will be visible.
Just to give a little more context on the onFormFieldFocusChange callback:
I have about 15 forms in my flutter app that a use fills out. There are numerous different types of data I want a use to enter, and I want to provide custom pickers (such as the showDateTime picker) to them.
These are TextFields in the PDF form and I am using the onFocusChange callback to intercept the user and show a custom picker rather than a keyboard. This works just fine, and the only issue is that the keyboard attempts to show before being dismissed bringing a poor experience for the user.
Hi Jeremy Isenburg, Thank you for providing the details. We are currently checking the onFormFieldFocusChange callback issue that occurs when displaying the datepicker or alert dialogue. We will provide more details on August 4, 2023.
Regarding the combo box form field:
Can we change the drop-down dialog for a combo box form field to look like the dialog for a list box form field? Please let us know if this meets your requirements.
Regarding the combo box form field:
Using the dialog like the list box form field is not the same. It takes a users focus away from the location in the document where the dropdown is, and it requires 3 user inputs to select an item (tap field -> tap item -> tap confirm). These two differences make it a less friendly user experience.
I have made a change to the ComboBox as shown below in the images:
This meets my requirements and is functionally the same as before, with a scrollbard.
code (Note: I did not style the button to make it sized and proportioned correctly for different button sizes and themes, but built this basic one to demonstrate my idea):
class _PdfComboBoxState extends State<PdfComboBox> {
@override
Widget build(BuildContext context) {
var newButton = DropdownButtonFormField<String>(
onChanged: widget.readOnly ? null : (value) =>
(widget.onValueChanged != null) ? widget
.onValueChanged!(value ?? '') : null,
menuMaxHeight: 300,
decoration: InputDecoration(border: InputBorder.none),
items: widget.items.map((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(
value,
style: const TextStyle(fontSize: 15),
),
);
}).toList(),
);
return Container(
decoration: const BoxDecoration(
color: Color.fromARGB(255, 221, 228, 255)
),
child: newButton,
// child: PopupMenuButton( // tooltip: '',
// constraints: const BoxConstraints(maxHeight: 300),
// itemBuilder: (BuildContext context) {
// return widget.items.map((String value) {
// return PopupMenuItem( // value: value,
// child: Text(
// value,
// style: const TextStyle(fontSize: 15),
// ),
// );
// }).toList();
// },
// enabled: !widget.readOnly,
// onSelected: widget.onValueChanged,
// child: Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children:[ // // Adjust the spacing between the icon and text
// Text(widget.selectedItem,
// style:
// TextStyle(color: Colors.black, fontSize: widget.fontSize)),
// Icon(
// Icons.arrow_drop_down_outlined,
// size: widget.bounds.height / widget.heightPercentage,
// color: Colors.black,
// ),
// ],
// ),
// ),
);
}
}
Hi Jeremy Isenburg,
Regarding onFormFieldFocusChange callback:
We have confirmed that the issue "Alert dialog or Date picker is not closed properly when invoked in the onFormFieldFocusChange callback" is a defect and logged a defect report for this issue. The fix for the same will be included in the August 22nd weekly NuGet release. Kindly use the following link to track the status:
Regarding the hiding of form fields when the keyboard is raised:
In SfPdfViewer, we use the interactive viewer widget for zooming and scrolling. We have created a simple sample without SfPdfViewer, but we are still experiencing the same issue. Consequently, we have raised a query on GitHub. We will let you know when we have the proper solution.
Regarding combo box form field:
We tried using the DropdownButtonFormField instead of the PopupMenuButton, but we are experiencing some issues with text size and alignment. Can we implement a similar design for the combo box form field, like the list box? For your reference, I have attached a screenshot of the modified combo box form field output, which can be downloaded from the attachment.
Regards,
Deepika Ravi
Regarding onFormFieldFocusChange callback:
Thanks for the update, looking forward to it!
Regarding the hiding of form fields when the keyboard is raised:
I believe this is a consequence of using a 'Positioned' Widget with the top of the screen rather than the bottom. See this example below which does properly resize the InteractiveViewer when a keyboard shows. I believe that the 'PdfTextFormFieldHelper' in SyncfusionPdfViewer is using `bottom: bounds.top / heightPercentage` to position the text field, and this should instead be based on the bottom of the screen.
Scaffold(
resizeToAvoidBottomInset: true,
body: InteractiveViewer(
boundaryMargin: const EdgeInsets.all(100.0),
minScale: 0.1,
maxScale: 1.6,
child: Stack(
children: [
Positioned(
bottom: 100,
child: Container(
color: Colors.green,
height: 50,
width: 200,
child: TextFormField(),
),
),
],
),
),
)
Regarding combo box form field:
In my PDF I have a state selector listing the 50 US states and a few of the US territories as well. From the screenshot you showed me, it appears this would take up the full screen and more. How is that experience for the user? Can it be shrunk to the same height and show only a few items at a time and scroll the rest?
I did take a look at the PdfComboBox class as well and I do think that the issues with text and alignment are just parameters that need tuning. I put together a sample here that shows an updated _PdfComboBoxState class. The contentPadding in the InputDecoration makes it so the whole box is clickable, the selectedItemBuilder makes it so that the shown selection is the same font as in the PDF, and the style parameter (with a height of 1) makes it so that the text is centered with the right size with no clipping.
class _PdfComboBoxState extends State<PdfComboBox> {
@override
Widget build(BuildContext context) {
var newButton = DropdownButtonFormField<String>(
onChanged: widget.readOnly ? null : (value) =>
(widget.onValueChanged != null) ? widget
.onValueChanged!(value ?? '') : null,
menuMaxHeight: 300,
value: widget.selectedItem,
// to show the text same size as in pdf
selectedItemBuilder: (_) =>
widget.items.map((String value) =>
Text(
value,
style: TextStyle(
fontSize: widget.fontSize ?? 14,
color: Colors.black,
),
)
).toList(),
iconEnabledColor: Colors.black,
iconDisabledColor: Colors.grey,
// current theme for text style, size of 1 to not cut off bottom of text.
style: Theme
.of(context)
.textTheme
.titleMedium
?.copyWith(fontSize: widget.fontSize ?? 14, height: 1),
decoration: InputDecoration(
border: InputBorder.none,
// resize click box to the size of field
// I am not quite sure how you are sizing the box here, but the idea is to
// pad the content so that the click area is the size of the blue area.
// This centers the text too.
contentPadding: EdgeInsets.symmetric(
vertical: false ? 0 : ((widget.bounds.height /
widget.heightPercentage)) - //+ (widget.fontSize ?? 14)) / 2 -
(widget.fontSize ?? 14),
),
// helps ro remove paddings and such
isDense: true,
),
items: widget.items.map((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value, style: const TextStyle(fontSize: 14)),
);
}).toList(),
);
return Container(
decoration: const BoxDecoration(
color: Color.fromARGB(255, 221, 228, 255)
),
child: newButton,
);
}
}
Screenshot of the resultant combo box in a PDF (the top box is a larger text, and all the others show different size boxes):
Regarding form field hide issue:
We are using InteractiveViewer to render the pdf in SfPdfViewer with constrained property set to false. Setting the constrained property false in the suggestion you have provided fails to achieve the expected behavior. In SfPdfViewer, we cannot set the 'constrained' property to true, as the PDF content would then overflow. For your reference, we have attached the output screen record of the sample we ensured, which can be downloaded from the attachment.
Regarding combo box form field:
We are checking the feasibility of changing the popup menu button to a dropdown button field in SfPdfViewer. We will provide further details on August 10, 2023.
Regarding form field hide issue:
Have you considered using the TransformationController associated with the InteractiveViewer to translate the Viewer? I think this would work. In combination with the onTap or onFocusChange of a text field, this could translate the field up, or to the center of the screen so it is visible, and back down when the editing is done. I believe this will even work when the field is at the bottom of the document where a user would not normally be a
Regarding combo box form field:
Looking forward to it!
Regarding form field hide issue:
Thank you for your suggestion.
We have checked your suggestion to translate the transform controller used in the InteractiveViewer. However, this only works with multiple-page documents in Continuous Page Layout with a vertical scroll direction.
This appears to be an issue with a design choice to use the interactive viewer with the current implementation. Is the team going to continue looking into this for a solution?
Hi Jeremy Isenburg,
Currently, it is not feasible to make changes to the design structure of the interactive viewer within SfPdfViewer. This is because essential functions such as scrolling, zooming, and panning are closely tied to the interactive viewer widget itself. We have raised the query in GitHub regarding this issue. Once we obtain a resolution, we will implement the necessary updates on our end and provide you with further information.
Regards,
Deepika R
Hi Jeremy Isenburg,
We have checked the feasibility of using `DropDownButton` instead of `PopupMenuButton` for rendering combo box form field. During our analyzation, we encountered an issue where, if an item's text is excessively long, the text gets wrapped, resulting in an unappealing appearance within the popup. It seems that this issue is with the `DropDownButton` and it can be replicated in a simple sample itself. The composition we used to replicate this issue is given below,
class ComboBoxDemo extends StatefulWidget { const ComboBoxDemo({super.key}); @override State<ComboBoxDemo> createState() => _ComboBoxDemoState(); } class _ComboBoxDemoState extends State<ComboBoxDemo> { final List<String> _items = <String>[ 'One', 'Two', 'Three', 'Four', 'Five', 'Goooooooooooooooooogle' ]; String? value; @override void initState() { value = _items[0]; super.initState(); } @override Widget build(BuildContext context) { return Scaffold( body: InteractiveViewer( constrained: false, child: Stack( children: [ SizedBox( width: 300, height: 500, ), Positioned( left: 50, top: 50, width: 75, height: 50, child: Container( decoration: const BoxDecoration( color: Color.fromARGB(255, 221, 228, 255), ), child: DropdownButton<String>( items: _items.map((String value) { return DropdownMenuItem<String>( value: value, child: Text( value, ), ); }).toList(), value: value, selectedItemBuilder: (context) { return _items.map((String value) { return Align( alignment: Alignment.centerLeft, child: Text( value, softWrap: false, ), ); }).toList(); }, isExpanded: true, underline: Container(), onChanged: (String? value) { setState(() { this.value = value; }); }, ), ), ), ], ), ), ); } } |
We will analyze further on the solution for this issue and will provide further details on August 14, 2023.
I checked how the Adobe Viewer handles this, and it will cut off the text like so:
This can be solved by giving the Text an overflow (I also set the "menuMaxHeight: 400" property):
Text(
value,
overflow: TextOverflow.ellipsis,
),
Hi Jeremy Isenburg,
We have considered your request to use the DropdownButton instead of the PopupMenuButton widget for the combo box form field. This feature enhancement will be included in our August 22nd weekly NuGet release. Kindly refer the following link for track the status of the feature,
Regards,
Deepika R
Jeremy, The issue "Alert dialog or Date picker is not closed properly when invoked in the onFormFieldFocusChange callback" has been resolved, and the fix is included in our latest weekly release. Please find the Pub.dev link below:
https://pub.dev/packages/syncfusion_flutter_pdfviewer/versions/22.2.10
We have also included your feature request for DropdownButton instead of the PopupMenuButton widget for the combo box form field. We thank you for your support and appreciate your patience in waiting for this release.
Hello,
Has there been any progress towards the interactive viewer issue mentioned above? https://www.syncfusion.com/forums/183757/attempt-to-implement-a-date-picker-and-form-field-hidden-behind-keyboard?reply=SDvPKf
Thanks
We have considered your requirement for “The focus of the TextFormField is lost when scrolling is performed, and form field is hidden in SfPdfViewer” is a defect and logged a defect report for this issue. The fix for this issue will be included in the 2023 November 28th weekly release. Kindly use the below link for track the status of the feature ,
Disclaimer: “Inclusion of this solution in the weekly release may change due to other factors including but not limited to QA checks and works reprioritization.”
The issue “The focus of the TextFormField is lost when scrolling is performed in a SfPDFViewer” has been resolved and the fix is available in our latest weekly release. Please find the package link below.
Package link: https://pub.dev/packages/syncfusion_flutter_pdfviewer/versions/23.2.5
We thank you for your support and appreciate your patience in waiting for this release. Please get in touch with us if you would require any further assistance.
Have there been any updates regarding this comment? https://www.syncfusion.com/forums/183757/attempt-to-implement-a-date-picker-and-form-field-hidden-behind-keyboard?reply=SDvPKf
Hi Jeremy Isenburg,
We built the PDF viewer widget with InteractiveViewer as the base, and we are unable to make alterations to the design at this moment.
However, we have resolved a case regarding scrolling when the text form field is focused in version 23.2.6. Could you please check your case with version 23.2.6 or later and confirm to us whether your issue is resolved?