PlutoMenuItemWidget

PlutoMenuItemWidget

Example code to add custom widget to PlutoMenuBar.

·

2 min read

Example code to add custom widget to PlutoMenuBar.

One thing to note is that if a custom widget has a state change, such as the Slider in the example below, the state change must be handled by the custom widget. In the example below, if you call setState on the _MyHomePageState widget to change the Slider's value, the entire PlutoMenuBar widget will be rebuilt, which can cause the menu to close as soon as you change the Slider.

// ignore_for_file: avoid_print

import 'package:flutter/material.dart';
import 'package:pluto_menu_bar/pluto_menu_bar.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'PlutoMenuBar Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(),
    );
  }
}

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

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

class _MyHomePageState extends State<MyHomePage> {
  final TextEditingController _textEditingController = TextEditingController();

  final _SliderValue _sliderValue = _SliderValue();

  @override
  void initState() {
    super.initState();

    _textEditingController.addListener(_onChangedText);
  }

  @override
  void dispose() {
    _textEditingController.removeListener(_onChangedText);

    _textEditingController.dispose();

    super.dispose();
  }

  void _onChangedText() {
    print(_textEditingController.text);
  }

  void _onChangedSlider(double value) {
    print(value);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: PlutoMenuBar(
        mode: PlutoMenuBarMode.hover,
        menus: [
          PlutoMenuItem(
            title: 'CustomWidgets',
            children: [
              PlutoMenuItem.widget(
                widget: _TextField(controller: _textEditingController),
              ),
              PlutoMenuItem.widget(
                widget: _Slider(
                  sliderValue: _sliderValue,
                  onChanged: _onChangedSlider,
                ),
              ),
            ],
          ),
        ],
      ),
    );
  }
}

class _TextField extends StatefulWidget {
  const _TextField({required this.controller});

  final TextEditingController controller;

  @override
  State<_TextField> createState() => _TextFieldState();
}

class _TextFieldState extends State<_TextField> {
  @override
  Widget build(BuildContext context) {
    return TextField(controller: widget.controller);
  }
}

class _SliderValue {
  double value = 0;
}

class _Slider extends StatefulWidget {
  const _Slider({
    required this.sliderValue,
    this.onChanged,
  });

  final _SliderValue sliderValue;

  final void Function(double)? onChanged;

  @override
  State<_Slider> createState() => _SliderState();
}

class _SliderState extends State<_Slider> {
  @override
  Widget build(BuildContext context) {
    return Slider(
      value: widget.sliderValue.value,
      divisions: 5,
      max: 100,
      onChanged: (value) {
        setState(() {
          widget.sliderValue.value = value;
          if (widget.onChanged != null) {
            widget.onChanged!(value);
          }
        });
      },
    );
  }
}