Flutter,为什么新的窗口小部件没有显示?

时间:2019-02-14 17:12:00

标签: flutter dropdown setstate

下面附有代码。 如何创建具有不同颜色的Shape的新小部件, 从下拉菜单中选择,通过按灰色按钮(COLOR CHANGE), 根据下拉菜单中选择的内容? 顶部的Container在这里无事可做,只是一个占位符。

我已经对其进行了测试,没有Widgets MySquare,MyRound和MyRectangle仅根据下拉选择更改颜色,并且可以正常工作。但是,使用其他窗口小部件类MySquare,MyRound和MyRectangle似乎不会重绘新的窗口小部件。

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

class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: MyTrial(strShape: 'ROUND'));
  }
}

class MyTrial extends StatefulWidget{
  final String strShape;

  MyTrial({this.strShape});

  @override
  MyTrialState createState() {
    return new MyTrialState();
  }
}

class MyTrialState extends State<MyTrial> {
  List<String> listShapes;
  String strShapeSelected;

  Widget widgetType;

  @override
  void initState() {
    super.initState();
    listShapes = ['SQUARE', 'ROUND','RECTANGLE'];
    strShapeSelected = widget.strShape;

    widgetType = _myGetShape('ROUND');
  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(title: Text('Change\nColor'),
        actions: <Widget>[
          /// button to change color
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 10.0),
            child: GestureDetector(onTap: () {
              _myChangeShapeColor(strShapeSelected);
              setState(() {});
              //print('Gesture $strShapeSelected');
            },
              child: new Container(
                child: new Center(
                    child: new Padding(
                      padding: const EdgeInsets.all(5.0),
                      child: new Text('COLOR\nCHANGE',textAlign: TextAlign.center,),
                    )),
                decoration: new BoxDecoration(
                    color: Colors.blueGrey, shape: BoxShape.circle),
              ),
            ),
          ),
          /// drop down list
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 10.0),
            child: DropdownButton<String>(
                items: listShapes.map((String value) {
                  return new DropdownMenuItem(
                    child: new Text('$value'),
                    value: value,
                  );
                }).toList(),
                value: strShapeSelected,
                onChanged: (String newValue) {
                  setState(() {
                    strShapeSelected = newValue;
                  });
                  widgetType = _myGetShape(strShapeSelected);
                }),
          )
        ],),
      body: Column(
        children: <Widget>[
          /// place holder
          Padding(
            padding: const EdgeInsets.all(10.0),
            child: Container(
              height: 80.0, color: Colors.teal,),
          ),
          /// shape widget
          /// changed by drop-down
          Center(child: widgetType),
        ],
      ),
    );
  }

  Widget _myGetShape(String newValue) {
    Widget newShape;
    switch(newValue){
      case 'SQUARE':
        newShape = MySquare(myColor: Colors.brown,);
        break;
      case 'ROUND':
        newShape = MyRound(myColor: Colors.green,);
        break;
      case 'RECTANGLE':
        newShape = MyRectangle(myColor: Colors.blue,);
        break;
    }
    return newShape;
  }

  void _myChangeShapeColor(String strNewShape) {
    switch(strNewShape){
      case 'SQUARE':
        widgetType = MySquare(myColor: Colors.amber,);
        break;
      case 'ROUND':
        widgetType = MyRound(myColor: Colors.lightGreenAccent,);
        break;
      case 'RECTANGLE':
        widgetType = MyRectangle(myColor: Colors.purple,);
        break;
    }
    setState(() {});
  }
}

/// SQUARE
class MySquare extends StatefulWidget{
  final Color myColor;

  MySquare({this.myColor});

  @override
  MySquareState createState() {
    return new MySquareState();
  }
}

class MySquareState extends State<MySquare> {
  Color newColor;

  @override
  void initState() {
    newColor = widget.myColor;
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Container(child: Center(
        child: Text('SQUARE',style: TextStyle(fontSize: 15.0))),
      color: newColor,
      width: 120.0,height: 120.0,);
  }
}

/// ROUND
class MyRound extends StatefulWidget{
  final Color myColor;

  MyRound({this.myColor});

  @override
  MyRoundState createState() {
    return new MyRoundState();
  }
}

class MyRoundState extends State<MyRound> {
  Color newColor;

  @override
  void initState() {
    newColor = widget.myColor;
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Container(child: Center(
        child: Text('ROUND',style: TextStyle(fontSize: 15.0))),
      decoration: BoxDecoration(color: newColor,
          shape: BoxShape.circle),
      width: 120.0,height: 120.0,);
  }
}

/// RECTANGLE
class MyRectangle extends StatefulWidget{
  final Color myColor;

  MyRectangle({this.myColor});

  @override
  MyRectangleState createState() {
    return new MyRectangleState();
  }
}

class MyRectangleState extends State<MyRectangle> {
  Color newColor;

  @override
  void initState() {
    newColor = widget.myColor;
    super.initState();
  }
  @override
  Widget build(BuildContext context) {
    return Container(child: Center(
        child: Text('RECTANGLE',style: TextStyle(fontSize: 15.0))),
      color: newColor,
      width: 200.0,height: 120.0,);
  }
}

1 个答案:

答案 0 :(得分:1)

您需要在MySquare,MyRound & MyRectangle中转换-StatelessWidget类。其余代码保持不变,并且可以按预期工作。

现在您将其命名为StatefulWidget-因此它们一旦初始化便保持状态。因此不会改变颜色。

   /// SQUARE
    class MySquare extends StatelessWidget {
      final Color myColor;
      MySquare({this.myColor});

      @override
      Widget build(BuildContext context) {
        return Container(
          child: Center(child: Text('SQUARE', style: TextStyle(fontSize: 15.0))),
          color: myColor,
          width: 120.0,
          height: 120.0,
        );
      }
    }

与矩形和圆形相同。

更新

如果要将其保留为StatefulWidget。然后,您需要使用-didUpdateWidget方法。

 class MySquareState extends State<MySquare> {
      Color newColor;

      @override
      void initState() {
        newColor = widget.myColor;
        super.initState();
      }

      @override
      void didUpdateWidget(MySquare oldWidget) {
        super.didUpdateWidget(oldWidget);
        print('Called');
        newColor = widget.myColor;
      }

      @override
      Widget build(BuildContext context) {
        return Container(child: Center(
            child: Text('SQUARE',style: TextStyle(fontSize: 15.0))),
          color: newColor,
          width: 120.0,height: 120.0,);
      }
    }