dart 如何在Flutter中打开DropdownSearch小部件时隐藏AppBar返回按钮?

zqdjd7g9  于 2023-07-31  发布在  Flutter
关注(0)|答案(1)|浏览(182)

我正在用Flutter开发一个应用程序,其中有一个DropdownSearch小部件和一个带有后退按钮的AppBar。我希望在下拉菜单打开时隐藏后退按钮,并在下拉菜单关闭时再次显示。
我试图通过使用FocusNode并向其添加一个侦听器来实现这一点。当DropdownSearch被聚焦(打开)时,我将showBackButton变量设置为false,当DropdownSearch失去聚焦(关闭)时,我将showBackButton设置回trueFocusNode随后被传递给DropdownSearch小工具。
下面是代码片段:

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});
  @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;
  bool showBackButton = true;
}

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 GetBuilder<QuestionnaireController>(builder: (controller) {
      return Scaffold(
        appBar: AppBar(
          leading: controller.showBackButton ? BackButton() : null,
          // Use the new variable to control the visibility of the back button
          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}) {
    final controller = Get.find<QuestionnaireController>();

    // Initialize FocusNode and add a listener
    FocusNode _dropdownFocusNode = FocusNode();
    _dropdownFocusNode.addListener(() {
      if (_dropdownFocusNode.hasFocus) {
        // Dropdown is opened
        setState(() {
          print("user opened the drop down");
          controller.showBackButton = false;
          controller.update();
        });
      } else {
        // Dropdown is closed
        setState(() {
          print("user closed the drop down");
          controller.showBackButton = true;
          controller.update();
        });
      }
    });

    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.bottomSheet(
        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,
              ),
            ),
            suffixIcon: IconButton(
              icon: Icon(Icons.clear),
              onPressed: () {
                controller.choices.clear();
              },
            ),
          ),
          style: TextStyle(color: Colors.black),
          autofocus: true,
          focusNode: _dropdownFocusNode,
        ),
        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(),
        );
      },
    );
  }
}

字符串
showBackButton变量在GetxController中定义,用于控制后退按钮的可见性。当它的值改变时,我调用update()来重建使用showBackButton的小部件。
但是,此解决方案并不能按预期工作。当下拉式清单开启时,上一页按钮不会隐藏。

的数据
如何在DropdownSearch小工具打开时隐藏AppBar后退按钮?如果你能帮忙的话,我会很感激的。

wa7juj8i

wa7juj8i1#

首先,当你使用Getx时,不要使用setState
然后让你的showBackButton值可以被来自Getx的.obs观察到。
然后使用Getx提供的Obx小部件 Package 您的AppBar
像这样使用Obx小部件中的变量

controller.showBackButton.value ? BackButton() : null

字符串
另外,请检查您的变量是否正在更新。

相关问题