Search code examples
flutterwidgetsetstatejoystickstatefulwidget

Call a setState of a statefull widget from the stateless widget


I have a stateless widget class that has a widget whose movements need to be tracked. I cannot keep this widget inside the stateful widgets as I don't want the state of this widget to be refreshed.

I have the following code.

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
    home: new MyHomePage(),
   );
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.white,
      child: Column(
        children: <Widget>[
          Expanded(
            child: JoystickView(
              onDirectionChanged: (degree, direction) {
                //Change the state here.
              },
            ),
          ),
          Expanded(
            child: MyStateFull(),
          ),
        ],
      ),
    );
  }
}

class MyStateFull extends StatefulWidget {
  @override
  _MyStateFullState createState() => _MyStateFullState();
}

class _MyStateFullState extends State<MyStateFull> {
  double degree = 10;
  double direction = 10;

  //Call this from the stateless Widget
  void changedDirection(degree, direction) {
    setState(() {
      this.degree = degree;
      this.direction = direction;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Text(
        "The degree Moved is $degree and the direction is $direction",
        style: TextStyle(fontSize: 25, color: Colors.black),
      ),
    );
  }
}

This code produces the following output. enter image description here

I want the direction and degree values to be changed as the joystick is moved.

Thank You.


Solution

  • I tried it myself and found the solution. This can be done using streams. I will post the code just in case someone needs it in the future.

    import 'package:flutter/material.dart';
    import 'package:control_pad/control_pad.dart';
    
    class MyStateLess extends StatelessWidget {
      StreamController<List<double>> _controller = StreamController<List<double>>();
    
      GlobalKey<_MyStateFullState> statefulKey = new GlobalKey<_MyStateFullState>();
    
      @override
      Widget build(BuildContext context) {
        return Column(
          children: <Widget>[
            JoystickView(
              onDirectionChanged: (degree, direction) {
                List<double> temp = new List<double>();
                temp.add(degree);
                temp.add(direction);
                _controller.add(temp);
              },
            ),
            MyStateFull(stream: _controller.stream, key: statefulKey),
          ],
        );
      }
    }
    
    class MyStateFull extends StatefulWidget {
      final Stream<List<double>> stream;
      MyStateFull({Key key, @required this.stream}) : super(key: key);
    
      @override
      _MyStateFullState createState() => _MyStateFullState();
    }
    
    class _MyStateFullState extends State<MyStateFull> {
      double _degree = 0.0;
      double _direction = 0.0;
    
      @override
      void initState() {
        super.initState();
        widget.stream.listen((event) {
          setState(() {
            _degree = event[0];
            _direction = event[1];
          });
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return Container(
          child: Text("$_degree, $_direction"),
        );
      }
    }