如何将Flutter中的DropdownSearch小部件移动到屏幕顶部,位于键盘上方?

huangapple go评论83阅读模式
英文:

How to move the DropdownSearch widget to the top of the screen above the keyboard in Flutter?

问题

以下是您要翻译的内容:

"I have a Flutter app where I'm using the dropdown_search package to implement a multi-select dropdown. The problem I'm facing is that when the keyboard is active, it covers the "Ok" button at the bottom of the dropdown. I want the dropdown to move to the top of the screen and show the "Ok" button above the keyboard so that the user doesn't have to manually scroll to reach it.

I've tried wrapping the DropdownSearch widget with a SingleChildScrollView but it doesn't seem to work. The dropdown still remains at the bottom of the screen, and the keyboard covers the "Ok" button.

Here's my code:

import 'package:flutter/material.dart';
import 'package:dropdown_search/dropdown_search.dart';
import 'package:get/get.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      title: 'MultiSelectDropDown',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'MultiSelectDropDown'),
      initialBinding: QuestionnaireBinding(),
    );
  }
}

class QuestionnaireBinding extends Bindings {
  @override
  void dependencies() {
    Get.lazyPut<QuestionnaireController>(() => QuestionnaireController());
  }
}

class QuestionnaireController extends GetxController
    with GetSingleTickerProviderStateMixin {
    RxList<String> choices = <String>[].obs;
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this title});
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final dropdownSearchTheme = ThemeData(
      colorScheme: const ColorScheme(
        primary: Color(0xFF485946),
        onPrimary: Colors.white,
        secondary: Colors.black,
        onSecondary: Colors.deepOrange,
        error: Colors.transparent,
        onError: Colors.transparent,
        background: Colors.transparent,
        onBackground: Colors.black,
        brightness: Brightness.light,
        onSurface: Colors.black,
        surface: Colors.white,
      ));

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: SingleChildScrollView(
        child: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            children: [
              const Text(
                'Let\'s start choosing',
                textAlign: TextAlign.center,
              ),
              const SizedBox(
                height: 30,
              ),
              Theme(
                data: dropdownSearchTheme,
                child: _buildDropdownSearch(
                  context,
                  Get.find<QuestionnaireController>().choices,
                  dropdownCustomBuilder: _customChoice,
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

  Widget _buildDropdownSearch(
      BuildContext context,
      RxList<String> selectedChoice,
      {Widget Function(BuildContext, List<String>)? dropdownCustomBuilder}) {
    return DropdownSearch<String>.multiSelection(
      selectedItems: selectedChoice,
      items: ["choice1", "choice2", "choice3", "choice4", "choice5", "choice6", "choice7", "choice8", "choice9", "choice10", "choice11"],
      dropdownDecoratorProps: DropDownDecoratorProps(
          dropdownSearchDecoration: InputDecoration(
            hintText: 'pickChoice',
            hintStyle: TextStyle(color: Colors.black),
            border: OutlineInputBorder(
              borderRadius: BorderRadius.circular(8.0),
              borderSide: BorderSide(
                color: Colors.grey,
              ),
            ),
          )),
      dropdownBuilder: dropdownCustomBuilder,
      popupProps: PopupPropsMultiSelection.modalBottomSheet(
        modalBottomSheetProps: ModalBottomSheetProps(
          padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
        ),
        searchFieldProps: TextFieldProps(
          padding: EdgeInsets.symmetric(vertical: 10, horizontal: 20),
          decoration: InputDecoration(
            hintText: 'Search for choice',
            hintStyle: TextStyle(color: Colors.black),
            border: OutlineInputBorder(
              borderRadius: BorderRadius.circular(8.0),
              borderSide: BorderSide(
                color: Colors.grey,
              ),
            ),
          ),
          style: TextStyle(color: Colors.black),
          autofocus: true,
          focusNode: FocusNode(canRequestFocus: true),
        ),
        showSearchBox: true,
        showSelectedItems: true,
        isFilterOnline: false,
        onItemAdded: (selectedItems, addedItem) {
          selectedChoice.add(addedItem);
        },
        onItemRemoved: (selectedItems, removedItem) {
          selectedChoice.remove(removedItem);
        },
      ),
    );
  }

  Widget _customChoice(BuildContext context, List<String> selectedItems) {
    final controller = Get.find<QuestionnaireController>();
    return GetBuilder<QuestionnaireController>(
      initState: (_) {},
      builder: (_) {
        if (selectedItems.isEmpty) {
          return Text("Pick a choice");
        }
        return Wrap(
          spacing: 2,
          runSpacing: -10,
          children: selectedItems.map((e) {
            return Chip(
              backgroundColor: Colors.lightGreen,
              label: Text(
                e.toString().trim(),
              ),
              onDeleted: () {
                selectedItems.remove(e.toString().trim());
                controller.choices.remove(e.toString().trim());
              },
            );
          }).toList(),
        );
      },
    );
  }
}

希望这能帮助您解决移动下拉列表以在键盘上方显示“Ok”按钮的问题。

英文:

I have a Flutter app where I'm using the dropdown_search package to implement a multi-select dropdown. The problem I'm facing is that when the keyboard is active, it covers the "Ok" button at the bottom of the dropdown. I want the dropdown to move to the top of the screen and show the "Ok" button above the keyboard so that the user doesn't have to manually scroll to reach it.

I've tried wrapping the DropdownSearch widget with a SingleChildScrollView but it doesn't seem to work. The dropdown still remains at the bottom of the screen, and the keyboard covers the "Ok" button.

Here's my code:

import &#39;package:flutter/material.dart&#39;;
import &#39;package:dropdown_search/dropdown_search.dart&#39;;
import &#39;package:get/get.dart&#39;;
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: &#39;MultiSelectDropDown&#39;,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: &#39;MUltiSelectDropDown&#39;),
initialBinding: QuestionnaireBinding(),
);
}
}
class QuestionnaireBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut&lt;QuestionnaireController&gt;(() =&gt; QuestionnaireController());
}
}
class QuestionnaireController extends GetxController
with GetSingleTickerProviderStateMixin {
RxList&lt;String&gt; choices = &lt;String&gt;[].obs;
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State&lt;MyHomePage&gt; createState() =&gt; _MyHomePageState();
}
class _MyHomePageState extends State&lt;MyHomePage&gt; {
final dropdownSearchTheme = ThemeData(
colorScheme: const ColorScheme(
primary: Color(0xFF485946),
onPrimary: Colors.white,
secondary: Colors.black,
onSecondary: Colors.deepOrange,
error: Colors.transparent,
onError: Colors.transparent,
background: Colors.transparent,
onBackground: Colors.black,
brightness: Brightness.light,
onSurface: Colors.black,
surface: Colors.white,
));
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
const Text(
&#39;Let\&#39;s start choosing&#39;,
textAlign: TextAlign.center,
),
const SizedBox(
height: 30,
),
Theme(
data: dropdownSearchTheme,
child: _buildDropdownSearch(
context,
Get.find&lt;QuestionnaireController&gt;().choices,
dropdownCustomBuilder: _customChoice,
),
),
],
),
),
),
);
}
Widget _buildDropdownSearch(
BuildContext context,
RxList&lt;String&gt; selectedChoice,
{Widget Function(BuildContext, List&lt;String&gt;)? dropdownCustomBuilder}) {
return DropdownSearch&lt;String&gt;.multiSelection(
selectedItems: selectedChoice,
items: [&quot;choice1&quot;, &quot;choice2&quot;, &quot;choice3&quot;, &quot;choice4&quot;, &quot;choice5&quot;, &quot;choice6&quot;, &quot;choice7&quot;, &quot;choice8&quot;, &quot;choice9&quot;, &quot;choice10&quot;, &quot;choice11&quot;],
dropdownDecoratorProps: DropDownDecoratorProps(
dropdownSearchDecoration: InputDecoration(
hintText: &#39;pickChoice&#39;,
hintStyle: TextStyle(color: Colors.black),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide(
color: Colors.grey,
),
),
)),
dropdownBuilder: dropdownCustomBuilder,
popupProps: PopupPropsMultiSelection.modalBottomSheet(
modalBottomSheetProps: ModalBottomSheetProps(
padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
),
searchFieldProps: TextFieldProps(
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 20),
decoration: InputDecoration(
hintText: &#39;Search for choice&#39;,
hintStyle: TextStyle(color: Colors.black),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide(
color: Colors.grey,
),
),
),
style: TextStyle(color: Colors.black),
autofocus: true,
focusNode: FocusNode(canRequestFocus: true),
),
showSearchBox: true,
showSelectedItems: true,
isFilterOnline: false,
onItemAdded: (selectedItems, addedItem) {
selectedChoice.add(addedItem);
},
onItemRemoved: (selectedItems, removedItem) {
selectedChoice.remove(removedItem);
},
),
);
}
Widget _customChoice(BuildContext context, List&lt;String&gt; selectedItems) {
final controller = Get.find&lt;QuestionnaireController&gt;();
return GetBuilder&lt;QuestionnaireController&gt;(
initState: (_) {},
builder: (_) {
if (selectedItems.isEmpty) {
return Text(&quot;Pick a choice&quot;);
}
return Wrap(
spacing: 2,
runSpacing: -10,
children: selectedItems.map((e) {
return Chip(
backgroundColor: Colors.lightGreen,
label: Text(
e.toString().trim(),
),
onDeleted: () {
selectedItems.remove(e.toString().trim());
controller.choices.remove(e.toString().trim());
},
);
}).toList(),
);
},
);
}
}

如何将Flutter中的DropdownSearch小部件移动到屏幕顶部,位于键盘上方?

I would appreciate any help or suggestions on how to achieve the desired behavior of moving the dropdown to the top of the screen and showing the "Ok" button above the keyboard.

答案1

得分: 1

可以通过将 PopupPropsMultiSelection.modalBottomSheet 替换为 PopupPropsMultiSelection.bottomSheet 来简单实现。

英文:

It can simply achieve by replacing

PopupPropsMultiSelection.modalBottomSheet

to

PopupPropsMultiSelection.bottomSheet

huangapple
  • 本文由 发表于 2023年7月20日 17:22:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/76728430.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定