Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/flutter/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Flutter 如何获取父窗口中动画值的子窗口小部件大小_Flutter_Dart - Fatal编程技术网

Flutter 如何获取父窗口中动画值的子窗口小部件大小

Flutter 如何获取父窗口中动画值的子窗口小部件大小,flutter,dart,Flutter,Dart,虽然颤振正在增长,但有很多建议和“方法”。我不确定什么是正确的,因为我对这个框架真的很陌生 比如,我有以下代码(几乎没有减少): @覆盖 小部件构建(构建上下文){ 返回手势检测器( //此处需要动画值的高度 子:堆栈( 儿童:[ 定位( 左:0,, 右:0,, 底部:值, 子:列(//总高度 儿童:[ 容器(高度:60),//1 容器(高度:150),//2 集装箱(高度:200), ], ), ), ], )); } 在GestureDetector中,我正在为一些小部件动作设置动画,这取

虽然颤振正在增长,但有很多建议和“方法”。我不确定什么是正确的,因为我对这个框架真的很陌生

比如,我有以下代码(几乎没有减少):

@覆盖
小部件构建(构建上下文){
返回手势检测器(
//此处需要动画值的高度
子:堆栈(
儿童:[
定位(
左:0,,
右:0,,
底部:值,
子:列(//总高度
儿童:[
容器(高度:60),//1
容器(高度:150),//2
集装箱(高度:200),
],
),
),
],
));
}
GestureDetector
中,我正在为一些小部件动作设置动画,这取决于其子部件的不同高度

儿童
//1
//2
(以及第三个)的
高度将在开发时设置为硬编码,但是,由于有几个这样的元素和自定义小部件,我想自动获取它们。稍后,这是更好的维护,因为几乎每个小部件都有一些动画

因此,我可以使用
GlobalKey
,或者可能使用
BoxConstraints
,但是——总之——如果构建为自定义小部件,最便宜的方法是什么

结束这个问题:在
GestureDetector
中,我能够在完成初始布局和每次重建后重建

我只是不确定哪种方法是安全的,并且成本最低(代码中有好几次这些小部件)

<> > <代码> // 1 < /代码>和<代码> // 2代码>:<代码> // 1代码>代码>初始动画>代码>开始:Valuy,<代码> //5>代码>是中间停止的值,<代码> //整体高度是动画<代码>结束:< /代码>值。只是解释一下


至少:我在所有这些中都使用了
states\u rebuilder

我们只需在呈现小部件后获得其大小,除非它是常量。 我们可以使用ValueNotifier在渲染后发送子对象的大小

下面是它的完整示例

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  ValueNotifier<Size> _size = ValueNotifier<Size>(Size(0, 0));

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("example")
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            ValueListenableBuilder(
              builder: (BuildContext context, Size value, Widget child) {
                return Column(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  children: <Widget>[
                    Text('Height of the child: ${value.height}'),
                    Text('Width of the child: ${value.width}'),
                    SizeTrackingWidget(
                      child: Container(
                        height: MediaQuery.of(context).size.width*0.4,
                        width:  MediaQuery.of(context).size.width*0.3,
                        color: Colors.red
                      ),
                      sizeValueNotifier: _size,
                    )
                  ],
                );
              },
              valueListenable: _size,
              child: null,
            )
          ],
        ),
      ),
    );
  }
}


class SizeTrackingWidget extends StatefulWidget {
  Widget child;
  ValueNotifier<Size> sizeValueNotifier;
  SizeTrackingWidget({Key key, @required this.sizeValueNotifier, @required this.child}) : super(key: key);
  @override
  _SizeTrackingWidgetState createState() => _SizeTrackingWidgetState();
}

class _SizeTrackingWidgetState extends State<SizeTrackingWidget> {
  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_){
      _getSize();
    });
  }

  _getSize() {
    RenderBox renderBox = context.findRenderObject();
    widget.sizeValueNotifier.value = renderBox.size;
  }

  @override
  Widget build(BuildContext context) {
    return widget.child;
  }
}
导入“包装:颤振/材料.省道”;
void main()=>runApp(MyApp());
类MyApp扩展了无状态小部件{
//此小部件是应用程序的根。
@凌驾
小部件构建(构建上下文){
返回材料PP(
标题:“颤振演示”,
主题:主题数据(
主样本:颜色。蓝色,
),
主页:MyHomePage(),
);
}
}
类MyHomePage扩展StatefulWidget{
MyHomePage({Key}):超级(Key:Key);
@凌驾
_MyHomePageState createState()=>\u MyHomePageState();
}
类_MyHomePageState扩展状态{
ValueNotifier_size=ValueNotifier(大小(0,0));
@凌驾
小部件构建(构建上下文){
返回脚手架(
appBar:appBar(
标题:文本(“示例”)
),
正文:中(
子:列(
mainAxisAlignment:mainAxisAlignment.center,
儿童:[
ValueListenableBuilder(
生成器:(BuildContext上下文、大小值、小部件子项){
返回列(
mainAxisAlignment:mainAxisAlignment.space,
儿童:[
Text('子级的高度:${value.Height}'),
Text('子项的宽度:${value.Width}'),
SizeTrackingWidget(
子:容器(
高度:MediaQuery.of(上下文).size.width*0.4,
宽度:MediaQuery.of(context).size.width*0.3,
颜色:颜色。红色
),
sizeValueNotifier:\u大小,
)
],
);
},
valueListenable:\u大小,
child:null,
)
],
),
),
);
}
}
类SizeTrackingWidget扩展StatefulWidget{
小部件儿童;
ValueNotifier sizeValueNotifier;
SizeTrackingWidget({Key-Key,@required this.sizeValueNotifier,@required this.child}):超级(Key:Key);
@凌驾
_SizeTrackingWidgetState createState()=>\u SizeTrackingWidgetState();
}
类_SizeTrackingWidgetState扩展状态{
@凌驾
void initState(){
super.initState();
WidgetsBinding.instance.addPostFrameCallback((){
_getSize();
});
}
_getSize(){
RenderBox RenderBox=context.findenderobject();
widget.sizeValueNotifier.value=renderBox.size;
}
@凌驾
小部件构建(构建上下文){
返回widget.child;
}
}

受@Thang Mai的公认答案启发,我提出了一个类似的无状态解决方案:

class ChildSizeNotifier extends StatelessWidget {
  final ValueNotifier<Size> notifier = ValueNotifier(const Size(0, 0));
  final Widget Function(BuildContext context, Size size, Widget child) builder;
  final Widget child;
  UjChildSizeNotifier({
    Key key,
    @required this.builder,
    this.child,
  }) : super(key: key) {}

  @override
  Widget build(BuildContext context) {
    WidgetsBinding.instance.addPostFrameCallback(
      (_) {
        notifier.value = (context.findRenderObject() as RenderBox).size;
      },
    );
    return ValueListenableBuilder(
      valueListenable: notifier,
      builder: builder,
      child: child,
    );
  }
}

这听起来很有趣!非常感谢,为了更好地理解,我将执行此操作。只有当值(将在某一时间)发生更改时,此操作才会起作用?在这种情况下,我的值
heigt
是硬编码的,可能永远不会更改,但我希望通过代码获得
height
,以便于维护,而不是为所有这些值都设置几个常量。这两种情况下都适用。如果将高度设置为200,则渲染后,它还将返回等于200的高度。您应该注意,当小部件进入屏幕并呈现时,它将返回小部件的实际大小。好的,我将在接下来的几天实现它。谢谢你这也解决了一些其他的问题,所以我想把这个标记为可接受的答案。谢谢,干得真不错!
ChildSizeNotifier(
  builder: (context, size, child) {
    // size is the size of the text
    return Text(size.height > 50 ? 'big' : 'small');
  },
)