Search code examples
flutterfocustextfield

Flutter: Change button color on TextField focus


I have a text field and a separate button, I want to change the button's color when the text field focuses.

Naively, I would like to write: FlatButton(..., backgroundColor: myFocusNode.hasFocus ? Colors.red : Colors.green). This, of course, does not work as the Button doesn't get notified about the focus change. Alternatively, I tried to add a Listener to myFocusNode, but if I try to call setState inside it in order to rebuild the button, the text field loses it's focus again.

I modified the sample code from the respective cookbook to illustrate, you can copy the code below and paste and run to see what I mean. How can i make the button turn red when clicking the text field?

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Text Field Focus',
      home: MyCustomForm(),
    );
  }
}

// Define a custom Form widget.
class MyCustomForm extends StatefulWidget {
  @override
  _MyCustomFormState createState() => _MyCustomFormState();
}

// Define a corresponding State class.
// This class holds data related to the form.
class _MyCustomFormState extends State<MyCustomForm> {
  // Define the focus node. To manage the lifecycle, create the FocusNode in
  // the initState method, and clean it up in the dispose method.
  FocusNode myFocusNode;

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

    myFocusNode = FocusNode();
  }

  @override
  void dispose() {
    // Clean up the focus node when the Form is disposed.
    myFocusNode.dispose();

    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Text Field Focus'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            // The first text field is focused on as soon as the app starts.
            TextField(
              autofocus: true,
            ),
            // The second text field is focused on when a user taps the
            // FloatingActionButton.
            TextField(
              focusNode: myFocusNode,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        // When the button is pressed,
        // give focus to the text field using myFocusNode.
        onPressed: () => myFocusNode.requestFocus(),
        tooltip: 'Focus Second Text Field',
        backgroundColor: myFocusNode.hasFocus ? Colors.red : Colors.green,
        child: Icon(Icons.edit),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

Solution

  • Please check the below code , i have use the Focus widget for it, it has the onFocusChange which will indicate the TextField is selected or not

    import 'package:flutter/cupertino.dart';
    import 'package:flutter/material.dart';
    import 'package:flutter/rendering.dart';
    import 'package:flutterlearningapp/colors.dart';
    
    class HomeScreen extends StatefulWidget {
      @override
      State<StatefulWidget> createState() {
        // TODO: implement createState
        return _HomeScreen();
      }
    }
    
    class _HomeScreen extends State<HomeScreen> {
      bool isTextFiledFocus = false;
    
      @override
      void initState() {
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: "Demo",
          home: Scaffold(
            appBar: AppBar(
              title: Text("List"),
            ),
            body: Container(
              margin: EdgeInsets.all(20.0),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: <Widget>[
                  Focus(
                    child: TextFormField(
                      textInputAction: TextInputAction.next,
                      decoration: InputDecoration(labelText: "Input 1"),
                    ),
                    onFocusChange: (hasFocus) {
                      setState(() {
                        isTextFiledFocus = hasFocus;
                      });
                    },
                  ),
    
                  TextFormField(
                    textInputAction: TextInputAction.next,
                    decoration: InputDecoration(labelText: "Input 1"),
                  ),
                  RaisedButton(
                    color: isTextFiledFocus ? Colors.pink : Colors.blue,
                    child: Text("Ok"),
                    onPressed: () {
                      print("I am clicked");
                    },
                  )
                ],
              ),
            ),
          ),
        );
      }
    }
    

    And check the below output of it
    enter image description here