skip to Main Content

I tried to create a button in the AppBar that displays a PopUpMenu if you press it. In the PopUpMenu there schould be several boxes with text next to them that you can check.

I tried creating a column in which I first display a title and then a CheckBoxListTile, but I couldn’t check the CheckBox.
This is my code:

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:mynotes/constants/routes.dart';
import 'package:mynotes/enums/menu_action.dart';
import 'package:mynotes/extensions/buildcontext/loc.dart';
import 'package:mynotes/services/auth/auth_service.dart';
import 'package:mynotes/services/auth/bloc/auth_bloc.dart';
import 'package:mynotes/services/auth/bloc/auth_event.dart';
import 'package:mynotes/services/cloud/cloud_note.dart';
import 'package:mynotes/services/cloud/firebase_cloud_storage.dart';
import 'package:mynotes/utilities/dialogs/logout_dialog.dart';
import 'package:mynotes/views/notes/notes_list_view.dart';
import 'package:flutter_bloc/flutter_bloc.dart' show ReadContext;

extension Count<T extends Iterable> on Stream<T> {
  Stream<int> get getLength => map((event) => event.length);
}

class NotesView extends StatefulWidget {
  const NotesView({Key? key}) : super(key: key);

  @override
  _NotesViewState createState() => _NotesViewState();
}

class _NotesViewState extends State<NotesView> {
  late final FirebaseCloudStorage _notesService;
  String get userId => AuthService.firebase().currentUser!.id;
  bool isInputVisible = false;
  TextEditingController _textEditingController = TextEditingController();
  String searchResult = 'Nachhilfe';
  late final RawKeyboard _rawKeyboard;
  List<String> selectedFilters = [];
  late bool? isChecked1;

  @override
  void initState() {
    _notesService = FirebaseCloudStorage();
    _textEditingController = TextEditingController();
    _setupTextControllerListener();
    _rawKeyboard = RawKeyboard.instance;
    _rawKeyboard.addListener(_onKeyEvent);
    isChecked1 = false;
    super.initState();
  }

  void _textControllerListener() async {
    final suche = _textEditingController.text;
  }

  void _onKeyEvent(RawKeyEvent event) {
    if (event is RawKeyDownEvent &&
        event.logicalKey == LogicalKeyboardKey.enter) {
      searchResult = _textEditingController.text;
      setState(() {
        isInputVisible = false;
      });

      print(searchResult);
    }
  }

  void _setupTextControllerListener() {
    _textEditingController.removeListener(_textControllerListener);
    _textEditingController.addListener(_textControllerListener);
  }

  @override
  void dispose() {
    _textEditingController.dispose();
    _rawKeyboard.removeListener(_onKeyEvent);

    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: StreamBuilder(
          stream: _notesService.allNotes(searchResult).getLength,
          builder: (context, AsyncSnapshot<int> snapshot) {
            if (snapshot.hasData) {
              final noteCount = snapshot.data ?? 0;
              final text = context.loc.notes_title(noteCount);
              return Text(text);
            } else {
              return const Text('');
            }
          },
        ),
        actions: [
          PopupMenuButton<int>(
            icon: Icon(Icons.filter_list),
            itemBuilder: (BuildContext context) {
              return <PopupMenuEntry<int>>[
                PopupMenuItem<int>(
                  value: 0,
                  child: Container(
                      padding: const EdgeInsets.symmetric(
                          vertical: 8.0, horizontal: 12.0),
                      child: Column(
                        children: [
                          const Text(
                            'Select Filters',
                            style: TextStyle(
                              fontWeight: FontWeight.bold,
                              fontSize: 16.0,
                            ),
                          ),
                          CheckboxListTile(
                            title: const Text('Bogenhausen'),
                            controlAffinity: ListTileControlAffinity.leading,
                            value: isChecked1,
                            onChanged: (bool? newValue) {
                              setState(() {
                                isChecked1 = newValue;
                              });
                            },
                            activeColor: Colors.greenAccent,
                            checkColor: Colors.black,
                          ),
                        ],
                      )),
                ),
              ];
            },
          ),
          IconButton(
            icon: const Icon(Icons.search),
            onPressed: () {
              setState(() {
                isInputVisible = !isInputVisible;
              });
            },
          ),
          Visibility(
            visible: isInputVisible,
            child: Container(
              width: 200,
              child: Padding(
                padding: const EdgeInsets.all(5.0),
                child: TextField(
                  controller: _textEditingController,
                  decoration: const InputDecoration(
                    hintText: 'search',
                    border: OutlineInputBorder(),
                  ),
                ),
              ),
            ),
          ),
          IconButton(
            onPressed: () {
              Navigator.of(context).pushNamed(createOrUpdateNoteRoute);
            },
            icon: const Icon(Icons.add),
          ),
          PopupMenuButton<MenuAction>(
            onSelected: (value) async {
              switch (value) {
                case MenuAction.logout:
                  final shouldLogout = await showLogOutDialog(context);
                  if (shouldLogout) {
                    context.read<AuthBloc>().add(
                          const AuthEventLogOut(),
                        );
                  }
              }
            },
            itemBuilder: (context) {
              return [
                PopupMenuItem<MenuAction>(
                  value: MenuAction.logout,
                  child: Text(context.loc.logout_button),
                ),
              ];
            },
          )
        ],
      ),
      body: StreamBuilder(
        stream: _notesService.allNotes(searchResult),
        builder: (context, snapshot) {
          switch (snapshot.connectionState) {
            case ConnectionState.waiting:
            case ConnectionState.active:
              if (snapshot.hasData) {
                final allNotes = snapshot.data as Iterable<CloudNote>;
                final sortedNotes = sortNotes(allNotes, searchResult);
                return NotesListView(
                  notes: sortedNotes,
                  onDeleteNote: (note) async {
                    await _notesService.deleteNote(documentId: note.documentId);
                  },
                  onTap: (note) {
                    Navigator.of(context).pushNamed(
                      showNotesRoute,
                      arguments: note.documentId,
                    );
                  },
                );
              } else {
                return const CircularProgressIndicator();
              }
            default:
              return const CircularProgressIndicator();
          }
        },
      ),
    );
  }
}

Iterable<CloudNote> sortNotes(Iterable<CloudNote> notes, String searchResult) {
  final List<CloudNote> specificValueNotes = [];
  final List<CloudNote> otherNotes = [];
  final hi = searchResult;

  for (final note in notes) {
    if (note.textJob == hi || note.textJob == 'Nachhilfe') {
      specificValueNotes.add(note);
    } else {
      otherNotes.add(note);
    }
  }

  return [...specificValueNotes, ...otherNotes];
}

List<String> selectedFilters = [];
void _handleFilterSelection(String filter) {
  if (selectedFilters.contains(filter)) {
    selectedFilters.remove(filter);
  } else {
    selectedFilters.add(filter);
  }
}

2

Answers


  1. To ensure that the PopupMenuItem gets refreshed, you need to wrap it with a StatefulBuilder.

    Here’s how you can do it:

    PopupMenuItem<int>(
      value: 0,
      child: StatefulBuilder(
        builder: (context, innerSetState) {
          return Container(
              padding: ...,
              child: Column(
                children: [
                  ...,
                  CheckboxListTile(
                    ...,
                    value: isChecked1,
                    onChanged: (bool? newValue) {
                      innerSetState(() {
                        isChecked1 = newValue;
                      });
                      setState(() {
                        isChecked1 = newValue;
                      });
                    },
                    ...,
                  ),
                ],
              ));
        }
      ),
    ),
    

    To update the states of both _NotesViewState and the PopupMenuItem, you’ll need to call setState for each specific context.

    Login or Signup to reply.
  2. import 'package:flutter/material.dart';
    
    void main() {
    runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
       );
      }
     }
    
    class MyHomePage extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Checkable PopupMenu'),
      ),
      body: Center(
        child: Text('Click the button to show the PopupMenu'),
      ),
      floatingActionButton: PopupMenuButton<String>(
        onSelected: (String result) {
          print('Selected: $result');
        },
        itemBuilder: (BuildContext context) => <PopupMenuEntry<String>>[
          PopupMenuItem<String>(
            value: 'option1',
            child: CheckboxListTile(
              title: Text('Option 1'),
              value: false, // Initial value of checkbox
              onChanged: (bool? value) {
                // Handle checkbox state changes
                print('Option 1 checked: $value');
              },
            ),
          ),
          PopupMenuItem<String>(
            value: 'option2',
            child: CheckboxListTile(
              title: Text('Option 2'),
              value: false, // Initial value of checkbox
              onChanged: (bool? value) {
                // Handle checkbox state changes
                print('Option 2 checked: $value');
              },
            ),
          ),
          PopupMenuItem<String>(
            value: 'option3',
            child: CheckboxListTile(
              title: Text('Option 3'),
              value: false, // Initial value of checkbox
              onChanged: (bool? value) {
                // Handle checkbox state changes
                print('Option 3 checked: $value');
              },
            ),
          ),
        ],
      ),
    );
      }
     }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search