'How to set controller and focusnode in custom TextField - Flutter

I'm trying to create my custom TextField widget with a dropdown list. I want to give it arguments of controller and focusnode. I don't want them to be required, but if they are not, I can't set them for Controller() and FocusNode(). And I can't have them with null value cause I already work with them inside the class. I'm not sure how to do this. Here is what I have:

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

class DropdownText extends StatefulWidget {
  final TextEditingController controller;
  final FocusNode focusNode;

  const DropdownText({Key key, this.controller, this.focusNode}) : super(key: key);
  @override
  _DropdownTextState createState() => _DropdownTextState();
}

class _DropdownTextState extends State<DropdownText> {

  bool _show = false;

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

    widget.focusNode.addListener(listener);
  }

  void listener(){
    if(widget.focusNode.hasFocus){
      setState(() {
        _show = true;
      });
    }else{
      setState(() {
        _show = false;
      });
    }
  }

}

And I already work with the text of my TextField (using the controller.text) inside this class when someone touches one of the options for changing whats written on it. Is there any way for me to give the user of my widget access for the controller and the focusNode just as TextField does?

PS: English is not my first language and I'm starting to programm with OOP with flutter.



Solution 1:[1]

You can use two separate objects in _DropdownTextState and initialize them in initState().

Checkout out below code.

class _DropdownTextState extends State<DropdownText> {
  TextEditingController _controller;
  FocusNode _focusNode;

  bool _show = false;

  @override
  void initState() {
    super.initState();
    if (widget.controller != null)
      _controller = widget.controller;
    else
      _controller = TextEditingController();
    if (widget.focusNode != null)
      _focusNode = widget.focusNode;
    else
      _focusNode = FocusNode();

    _focusNode.addListener(listener);
  }

  @override
  void dispose() {
    super.dispose();
    _controller?.dispose();
    _focusNode?.dispose();
  }

  void listener() {
    if (widget.focusNode.hasFocus) {
      setState(() {
        _show = true;
      });
    } else {
      setState(() {
        _show = false;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return TextField(
      focusNode: _focusNode,
      controller: _controller,
    );
  }
}

Hope it helps :)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Ajay Kumar