lcuis / search_choices

Widget to let the user search through a keyword string typed on a customizable keyboard in a single or multiple choices list presented as a dropdown in a dialog box or a menu.
MIT License
51 stars 42 forks source link

SearchChoices.single Expands at first loading and then shrinks after data loaded #81

Closed 247software-vaibhav-joshi closed 2 years ago

247software-vaibhav-joshi commented 2 years ago

I am using search_choices: ^2.0.20 The issue I am facing is the SearchChoices.single Expands at first loading and then shrinks after data is loaded. Below is the screenshot of what is happening

expanded shrunk

The code for the above is

Container(
      decoration: buildBoxDecoration(),
      width: size.width * 0.6,
      child: SearchChoices.single(
        searchHint: 'Search Role',
        underline: Container(
          height: 1.0,
          color: Colors.transparent,
        ),
        displayClearIcon: false,
        items: hospRolesList?.map((HospitalRole data) {
              return DropdownMenuItem(
                value: data /*.sector*/,
                child: SizedBox(
                  width: size.width * 0.5,
                  child: Padding(
                    padding: const EdgeInsets.fromLTRB(8, 0, 5, 0.0),
                    child: Text(
                      data?.name ?? '',
                      textAlign: TextAlign.left,
                      style: TextStyle(
                        fontFamily: "Poppins",
                      ),
                    ),
                  ),
                ),
              );
            }).toList(growable: true) ??
            [],
        isCaseSensitiveSearch: false,
        value: selectedRole,
        hint: Center(
          child: Container(
            width: MediaQuery.of(context).size.width * 0.5,
            child: Padding(
              padding: const EdgeInsets.fromLTRB(8, 0, 5, 0.0),
              child: Text(
                "Role",
                textAlign: TextAlign.left,
                style: TextStyle(
                  fontFamily: "Poppins",
                ),
              ),
            ),
          ),
        ),
        selectedValueWidgetFn: (HospitalRole data) {
          return (Padding(
            padding: const EdgeInsets.all(0.0),
            child: Align(
                alignment: Alignment.centerLeft,
                child: Text(
                  data.name ?? '',
                  style: TextStyle(
                    fontSize: 16,
                    color: Colors.black,
                  ),
                )),
          ));
        },
        onChanged: (value) {
          setState(() {
            selectedRole = value;
          });
        },
        isExpanded: true,
      ),

Seeking Help regarding this. Thanks

lcuis commented 2 years ago

Hello @vaibhavjoshi247 ,

Thanks for your issue description.

Sorry, I cannot test myself right now bit I think I know what you mean.

There is a difference in presentation between the field with a selected value and without a selected value.

I believe there can be 2 ways to work around this issue untill it is solved at least for the single case.

1) Make use of the fieldPresentationFn argument.

2) Make use of the selectedValueWidgetFn argument.

Some other arguments that may help are:

Maybe the solution will be a combination of some of those.

Sorry I cannot help more at the moment.

Also, I would like a more permanent solution.

lcuis commented 2 years ago

Sorry for the delay @vaibhavjoshi247 .

I was able to reproduce your issue with the following code:

class HospitalRole {
  String name;
  HospitalRole(this.name);
  @override
  String toString() {
    return (name);
  }
}

// ...

  HospitalRole? selectedRole;

  List<HospitalRole> hospRolesList = [];

// ...

Column(
        children: [
          ElevatedButton(
              onPressed: () {
                if(hospRolesList.isEmpty){
                  hospRolesList.addAll([
                    HospitalRole("1"),
                    HospitalRole("2"),
                    HospitalRole("3"),
                  ]);
                }
                else{
                  hospRolesList.clear();
                }
                setState(() {});
              },
              child: Text("${hospRolesList.isNotEmpty?"de":""}populate")),
          Container(
            decoration: BoxDecoration(),
            // width: MediaQuery.of(context).size.width * 0.6,
            width: 300 * 0.6,
            child: SearchChoices.single(
              searchHint: 'Search Role',
              underline: Container(
                height: 1.0,
                color: Colors.transparent,
              ),
              displayClearIcon: false,
              items: hospRolesList.map((HospitalRole data) {
                return DropdownMenuItem(
                  value: data /*.sector*/,
                  child: SizedBox(
                    // width: MediaQuery.of(context).size.width * 0.5,
                    width: 300 * 0.5,
                    child: Padding(
                      padding: const EdgeInsets.fromLTRB(8, 0, 5, 0.0),
                      child: Text(
                        data.name,
                        textAlign: TextAlign.left,
                        style: TextStyle(
                          fontFamily: "Poppins",
                        ),
                      ),
                    ),
                  ),
                );
              }).toList(growable: true),
              isCaseSensitiveSearch: false,
              value: selectedRole,
              hint: Center(
                child: Container(
                  // width: MediaQuery.of(context).size.width * 0.5,
                  width: 300 * 0.5,
                  child: Padding(
                    padding: const EdgeInsets.fromLTRB(8, 0, 5, 0.0),
                    child: Text(
                      "Role",
                      textAlign: TextAlign.left,
                      style: TextStyle(
                        fontFamily: "Poppins",
                      ),
                    ),
                  ),
                ),
              ),
              selectedValueWidgetFn: (HospitalRole data) {
                return (Padding(
                  padding: const EdgeInsets.all(0.0),
                  child: Align(
                      alignment: Alignment.centerLeft,
                      child: Text(
                        data.name,
                        style: TextStyle(
                          fontSize: 16,
                          color: Colors.black,
                        ),
                      )),
                ));
              },
              onChanged: (value) {
                setState(() {
                  selectedRole = value;
                });
              },
              isExpanded: true,
            ),
          ),
        ],
      ),

// ...

I will look into this as soon as I can. This is not the issue I thought but it may be related.

lcuis commented 2 years ago

I found the reason for this.

The problematic code is this:

      final Widget? positionedHint = _enabled
          ? prepareWidget(widget.hint)
          : DropdownMenuItem<Widget>(
              child: prepareWidget(widget.disabledHint,
                      parameter: updateParentWithOptionalPop) ??
                  prepareWidget(widget.hint) ??
                  SizedBox.shrink());

The DropdownMenuItem is the cause of the additional space you experienced. We don't have this issue with the following code:

      final Widget? positionedHint = (_enabled
              ? prepareWidget(widget.hint)
              : prepareWidget(widget.disabledHint,
                      parameter: updateParentWithOptionalPop) ??
                  prepareWidget(widget.hint)) ??
          SizedBox.shrink();

Plus, this seems to fix the issue I was mentioning earlier.

I pushed it with this commit: https://github.com/lcuis/search_choices/commit/26f19fb140d8af8d95c0262e12c2b9a37d07fc8c

I just hope this doesn't break anything.

I will do more tests before I publish to pub.dev .

I will also try to integrate more fixes.

In the meanwhile, you can use the latest GitHub repository code with the following in your pubspec.yaml:

  search_choices:
    git:
      url: https://github.com/lcuis/search_choices.git
lcuis commented 2 years ago

I reworked a bit the lines corrected above as it was not working so well for other examples. I hope it will still work fine with your example. Please let me know if it is still an issue.

lcuis commented 2 years ago

Version 2.0.21 is published on pub.dev . The following now should be fine in pubspec.yaml:

  search_choices:
247software-vaibhav-joshi commented 2 years ago

Hi, @lcuis Thank you for your prompt response it is pretty helpful for us. We appreciate it.

The new improvement solved my issue but now the padding for hint remains the same (i.e. Widget appears larger and stays the same until we select an value from dropdown and then it comes to normal height). Removing hints in the widget seems normal but We don't want to remove the hint.

I am struggling to understand if I am doing something wrong. WhatsApp Image 2022-07-09 at 11 46 08 AM

shrunk

Seeking your help, Thanks

lcuis commented 2 years ago

Thanks for raising this @vaibhavjoshi247 !

I hope to have soon time to have a look.

lcuis commented 2 years ago

Hello @vaibhavjoshi247 ,

I was able to adapt the code I shared previously so that the hint looks the same way the selected value. I hope this will work fine for you as well. Sorry for the inconvenience.

      Column(
        children: [
          ElevatedButton(
              onPressed: () {
                if (hospRolesList.isEmpty) {
                  hospRolesList.addAll([
                    HospitalRole("1"),
                    HospitalRole("2"),
                    HospitalRole("3"),
                  ]);
                } else {
                  hospRolesList.clear();
                }
                setState(() {});
              },
              child: Text("${hospRolesList.isNotEmpty ? "de" : ""}populate")),
          Container(
            decoration: BoxDecoration(),
            // width: MediaQuery.of(context).size.width * 0.6,
            width: 300 * 0.6,
            child: SearchChoices.single(
              searchHint: 'Search Role',
              underline: Container(
                height: 1.0,
                color: Colors.transparent,
              ),
              displayClearIcon: false,
              items: hospRolesList.map((HospitalRole data) {
                return DropdownMenuItem(
                  value: data /*.sector*/,
                  child: SizedBox(
                    // width: MediaQuery.of(context).size.width * 0.5,
                    width: 300 * 0.5,
                    child: Padding(
                      padding: const EdgeInsets.fromLTRB(8, 0, 5, 0.0),
                      child: Text(
                        data.name,
                        textAlign: TextAlign.left,
                        style: TextStyle(
                          fontFamily: "Poppins",
                        ),
                      ),
                    ),
                  ),
                );
              }).toList(growable: true),
              isCaseSensitiveSearch: false,
              value: selectedRole,
              hint: Padding(
                padding: const EdgeInsets.all(0.0),
                child: Align(
                    alignment: Alignment.centerLeft,
                    child: Text(
                      "Role",
                      style: TextStyle(
                        fontSize: 16,
                        color: Colors.grey,
                      ),
                    )),
              ),
              selectedValueWidgetFn: (HospitalRole data) {
                return DropdownMenuItem(
                  child: (Padding(
                    padding: const EdgeInsets.all(0.0),
                    child: Align(
                        alignment: Alignment.centerLeft,
                        child: Text(
                          data.name,
                          style: TextStyle(
                            fontSize: 16,
                            color: Colors.black,
                          ),
                        )),
                  )),
                );
              },
              onChanged: (value) {
                setState(() {
                  selectedRole = value;
                });
              },
              isExpanded: true,
            ),
          ),
        ],
      )
lcuis commented 2 years ago

Closing for inactivity. Feel free to reopen if needed.