Flutter:当按钮被按下时更改容器的高度。

3
这里的问题是在按下按钮更改funArg值后,Container没有重新绘制自身,这应该会改变其高度,因为它被用于计算中。
以下是代码:
以下是main.dart:
import 'package:flutter/material.dart';
import 'package:sqaure/ui/fun.dart';

Widget rect0;


String rectArg = "20";


class Home extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return new HomeState();
  }
}

class HomeState extends State<Home> {
  var list = ["20", "15"];

  Widget funTest() {
    setState(() {
      rectArg = list[1];
      rect0 = new Plate(rectArg);
    });
  }


  //final Color primaryColor = Colors.red;

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("rect"),
        backgroundColor: Colors.red,
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.start,
        children: <Widget>[
          new Container(
            alignment: Alignment.topCenter,
            color: Colors.white,
            height: 245.0,
            child: new Stack(
              children: <Widget>[
                Center(
                  child: Padding(
                    padding: const EdgeInsets.only(left: 55.0),
                    child: Row(
                      children: <Widget>[
                        //plates
                        rect0 = new Plate(rectArg),
                      ],
                    ),
                  ),
                )
              ],
            ),
          ),
          new RaisedButton(onPressed: () {
            funTest();
            debugPrint(rectArg);
          })
        ],
      ),
    );
  }
}

这里是 fun.dart:

import 'package:flutter/material.dart';

class Plate extends StatefulWidget {
  final String funArg2;
  @override
  State<StatefulWidget> createState() {
    return new PlateState(funArg2);
  }
[enter image description here][1]
  Plate(this.funArg2);
}

class PlateState extends State<Plate> {
  String funArg;
  @override
  Widget build(BuildContext context) {
    return Padding(
        padding: const EdgeInsets.all(3.0),
        child: Container(
          alignment: Alignment.center,
          color: Colors.redAccent,
          height:  funArg !=  "" ? (9.33 * double.parse(funArg) + 45) : 0.0,
          width: 29.0,
          child: new Text(
            funArg,
            style: new TextStyle(
              color: Colors.white,
              fontWeight: FontWeight.w600,
              fontSize: funArg.length > 4
                  ? 10.0
                  : funArg.length > 3 ? 14.0 : 19.0,
            ),
          ),
        ));
  }

  PlateState(this.funArg);
}

正如你所看到的,容器的高度是由内部的子文本决定的。

截图

谢谢。


1
你没有调用setState,因为funArg被修改了。是吗? - dazza5000
不,我不会,请问您能教我如何做吗? - ViralCode
当funArg改变时,您需要调用setState并更新本地变量值。您可以在此处查看示例:https://github.com/dazza5000/austin-feeds-me-flutter/blob/master/lib/views/event_map_view.dart#L40 - dazza5000
1个回答

3
这是您代码的一个修复和注释版。请仔细阅读注释!
主要问题是您将Plate定义为有状态小部件,并将rectArg存储在状态中!PlateState仅被初始化一次,直到您离开屏幕时,它才不会重新创建当父小部件被重建时!
实际上,Plate没有任何内部状态,所以它应该是StatelessWidget。您应该始终优先考虑StatelessWidget。理解为什么对于Flutter开发是至关重要的!
import 'package:flutter/material.dart';

main() => runApp(MaterialApp(home: Home()));

class Home extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return new HomeState();
  }
}

// this seems to be a constant, so can put it outside of the class
// or alternatively inside, with "static const" modifier
const list = ["20", "15"];

class HomeState extends State<Home> {
  // stateful variables (things that change over time)
  // must be inside of your state class
  String rectArg = "20";

  // we can return void here!
  void funTest() {
    setState(() {
      // state is modified here. this triggers a rebuild/redraw
      // that means the build function is called again
      // note that we are only the storing the string value, NOT a widget!
      rectArg = list[1];
    });
  }

  // this is called every time you setState
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("rect"),
        backgroundColor: Colors.red,
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.start,
        children: <Widget>[
          new Container(
            alignment: Alignment.topCenter,
            color: Colors.white,
            height: 245.0,
            child: new Stack(
              children: <Widget>[
                Center(
                  child: Padding(
                    padding: const EdgeInsets.only(left: 55.0),
                    child: Row(
                      children: <Widget>[
                        // DO NOT SET VARIABLES FROM THE BUILD METHOD!
                        // this is bad:
                        // rect0 = new Plate(rectArg),
                        Plate(
                          funArg: rectArg,
                        ),
                      ],
                    ),
                  ),
                )
              ],
            ),
          ),
          new RaisedButton(onPressed: () {
            funTest();
            debugPrint(rectArg);
          })
        ],
      ),
    );
  }
}

// Plate is actually a StatelessWidget because it is not interactive and holds no internal state
// All the data (funArg) is passed in from the parent ==> StatelessWidget
// Always prefer stateless widgets!
// That means the widget is completely rebuilt every time the build() method is called in HomeState
class Plate extends StatelessWidget {
  // Use named constructor parameters and call the super constructor!
  // you can auto-generate the constructor with Android Studio
  const Plate({Key key, this.funArg}) : super(key: key);

  final String funArg;

  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(3.0),
      child: Container(
        alignment: Alignment.center,
        color: Colors.redAccent,
        height: funArg != "" ? (9.33 * double.parse(funArg) + 45) : 0.0,
        width: 29.0,
        child: new Text(
          funArg,
          style: new TextStyle(
            color: Colors.white,
            fontWeight: FontWeight.w600,
            fontSize: funArg.length > 4 ? 10.0 : funArg.length > 3 ? 14.0 : 19.0,
          ),
        ),
      ),
    );
  }
}

如果您需要一个具有内部状态的 StatefulWidget,并且还由父部件设置构造参数(这很常见):在您的 Statebuild 方法内,使用 widget 属性来访问 widget 的最终字段:

class ColoredCheckbox extends StatefulWidget {
  const ColoredCheckbox({Key key, this.color}) : super(key: key);

  // this is passed in from the parent, can change when the parent is rebuilt
  final Color color;

  @override
  State<StatefulWidget> createState() => ColoredCheckboxState();
}

class ColoredCheckboxState extends State<ColoredCheckbox> {
  // this is internal state, kept even when the parent is rebuilt
  bool checked = false;

  // build is called when:
  // - you call setState from this widget
  // - when the parent widget is rebuilt
  @override
  Widget build(BuildContext context) {
    return RaisedButton(
      child: Text(checked ? 'X' : '0'),
      // use "widget" to access the fields passed in from the parent
      color: widget.color,
      onPressed: () {
        // always call setState when changing internal state
        setState(() {
          checked = !checked;
        });
      },
    );
  }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接