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

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

How to hide the AppBar back button when a DropdownSearch widget is open in Flutter?

问题

以下是您要翻译的代码部分:

// 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();
    });
  }
});
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),
),

如果需要进一步帮助,请告诉我。

英文:

I am developing an application in Flutter where I have a DropdownSearch widget and an AppBar with a back button. I want the back button to be hidden when the dropdown is opened and shown again when the dropdown is closed.

I attempted to achieve this by using a FocusNode and adding a listener to it. When the DropdownSearch is focused (opened), I set a showBackButton variable to false, and when the DropdownSearch loses focus (is closed), I set showBackButton back to true. The FocusNode is then passed to the DropdownSearch widget.

Here's the code snippet:

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(),
        );
      },
    );
  }
}

The showBackButton variable is defined in a GetxController and is used to control the visibility of the back button. When its value is changed, I call update() to rebuild the widgets that use showBackButton.

However, this solution does not work as expected. The back button does not hide when the dropdown is opened.
如何在Flutter中打开DropdownSearch小部件时隐藏AppBar返回按钮?

How can I hide the AppBar back button when the DropdownSearch widget is open? Any help would be appreciated.

答案1

得分: 1

首先,当你使用Getx时,请不要使用setState

然后,通过在变量后面加上.obs来使你的showBackButton值可观察。

接着,用Getx提供的Obx小部件包裹你的AppBar

Obx小部件内部像这样使用变量:

controller.showBackButton.value ? BackButton() : null

另外,请检查一下你的变量是否在更新。

英文:

Bro 1st of all don't use setState when you are using Getx.

And then make your showBackButton value observable by .obs from Getx.

and then wrap your AppBar with the Obx widget provided by Getx.

use the variable inside the Obx widget like this

controller.showBackButton.value ? BackButton() : null

Also, please check whether your variable is updating or not.

huangapple
  • 本文由 发表于 2023年7月23日 16:03:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/76747212.html
匿名

发表评论

匿名网友

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

确定