首页 > 解决方案 > 在绘制小部件树之前如何使用其他小部件的大小?[示例]

问题描述

这通过一个简单的示例显示了其他帖子中讨论的所有 3 个案例。 如何在构建阶段使用其他小部件的约束和大小

笔记:

  1. 我知道这很奇怪

  2. 我知道如果使用不当,这可能会创建从未绘制过的布局

  3. 仅阅读约束是不够的,因为有时约束不存在(例如在这种特殊情况下)

目标: 在 0 次重新构建(或 1 次构建)而不是 2 次重新构建后,让屏幕上绘制的内容稳定下来

当前进程:

  1. 构建 1构建 1
  2. 构建 2构建 2
  3. 构建 3构建 3

when ("automaticReBuilding" == true) => 系统会根据依赖的数量自动重建自身(这由你决定)[自动重建多次运行构建函数的事实是造成我提到的口吃问题的原因到现在和以前的帖子]

when ("automaticReBuilding" == false) => 系统等待你手动重建东西

//------------------------------------------------ --代码开始

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

//Desired Behavior on FIRST build (It should not take 3)
//CASE 1 (parent uses child size) : eye.width = vane.width * 10
//CASE 2 (child uses parent size) : pupil.width = iris.width / 2
//CASE 3: (child uses sibling size) : iris.width = vane.width * 5

//Desired Sizes (can be read from Render Tree in Flutter Inspector) [in original config of 4 letters]
//vane = 30
//pupil = 75
//iris = 150
//eye = 300

//NOTE: that vane width (aka size) is not determined until we see what is inside of it

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new StateFull();
  }
}

class StateFull extends StatefulWidget {
  @override
  _StateFullState createState() => new _StateFullState();
}

var vaneKey = new GlobalKey();
var vaneWidth;
var irisKey = new GlobalKey();
var irisWidth;

class _StateFullState extends State<StateFull> {

  //NOTE: change this to either run the rebuild in one shot or slowly see the progression
  bool automaticReBuilding = false;
  //NOTE: this starts here because the first build method isn't technically a rebuild
  int timesReBuilt = -1;
  //NOTE: this is set MANUALLY given the dependencies between your widgets
  //In this particular case C relies on B which relies on A
  //so (first) I get the size of A, (second) I use the size of A to get B, (third) i use the size of B to get C
  //which comes down to 3 rebuilds
  int requiredBuildsPerChange = 3;
  int timesBuilt = 0;

  rebuild(){
    setState(() {

    });
  }

  rebuildAsync() async{
    await Future.delayed(Duration.zero);
    setState(() {

    });
  }

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {

    timesReBuilt++;

    if(automaticReBuilding){
      timesBuilt++;
      print("build #" + timesBuilt.toString());
      if(timesBuilt < requiredBuildsPerChange)
        rebuildAsync();
      else
        timesBuilt = 0;
    }

    var complexWidget = complexRelationshipWidget();

    return new MaterialApp(
      title: '3 Cases Test',
      home: new Scaffold(
        backgroundColor: Colors.brown,
        body: new Stack(
          children: <Widget>[
            new Align(
              alignment: Alignment.center,
              child: complexWidget,
            ),
            new Container(
              padding: EdgeInsets.all(16.0),
              alignment: Alignment.bottomRight,
              child: new RaisedButton(
                onPressed: () => (automaticReBuilding == false) ? rebuild() : null,
                child: new Column(
                  mainAxisSize: MainAxisSize.min,
                  children: <Widget>[
                    Icon(Icons.update),
                    new Text("Manual ReBuilds\nOR\nAutomatic Frame Stutter\n$timesReBuilt", textAlign: TextAlign.center,),
                  ],
                ),
              ),
            ),
          ],
        )
      ),
    );
  }

  Container complexRelationshipWidget() {

    vaneWidth = vaneKey?.currentContext?.findRenderObject()?.semanticBounds?.size?.width;
    irisWidth = irisKey?.currentContext?.findRenderObject()?.semanticBounds?.size?.width;

    return new Container( //-----EYE-----
        decoration: BoxDecoration(shape: BoxShape.circle, color: Colors.white),
        width: vaneWidth == null ? null : vaneWidth * 10,
        alignment: Alignment.center,
        child: new Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            new Container( //-----VANE-----
              key: vaneKey,
              color: Colors.red,
              child: new Text("vane"),
            ),
            new Container( //-----IRIS-----
              key: irisKey,
              decoration: BoxDecoration(shape: BoxShape.circle, color: Colors.blue),
              width: vaneWidth == null ? null : vaneWidth * 5,
              alignment: Alignment.center,
              child: new Container( //-----PUPIL
                decoration: BoxDecoration(shape: BoxShape.circle, color: Colors.black),
                width: irisWidth == null ? null : irisWidth / 2,
              ),
            ),
          ],
        )
    );
  }
}

//------------------------------------------------ --代码结束

标签: flutterflutter-layout

解决方案


推荐阅读