Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/dart/3.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

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
Dart 通过其他小部件为小部件约束提供绝对位置_Dart_Flutter - Fatal编程技术网

Dart 通过其他小部件为小部件约束提供绝对位置

Dart 通过其他小部件为小部件约束提供绝对位置,dart,flutter,Dart,Flutter,我试图给出一个小部件在小部件树的最下面的绝对位置。因为它位于小部件树的下方,所以很可能存在由其祖先设置的某些布局约束。我正在寻找一些可以忽略这些约束,只使用绝对坐标的东西 如果解释令人困惑,我画了一个代表我想要的结果的小方案: 我尝试使用堆栈来执行此操作,但这使得在绝对坐标中传递非常困难,即使使用定位的,因为设置属性left:0.0将使用相对于祖先的相对坐标。因此,将其设置为零并不一定意味着小部件将位于屏幕的左上角。 我也尝试过使用覆盖,但结果与堆栈实现几乎相同 在Flatter中,推荐的方法

我试图给出一个小部件在小部件树的最下面的绝对位置。因为它位于小部件树的下方,所以很可能存在由其祖先设置的某些布局约束。我正在寻找一些可以忽略这些约束,只使用绝对坐标的东西

如果解释令人困惑,我画了一个代表我想要的结果的小方案:

我尝试使用
堆栈来执行此操作,但这使得在绝对坐标中传递非常困难,即使使用
定位的
,因为设置属性
left:0.0
将使用相对于祖先的相对坐标。因此,将其设置为零并不一定意味着小部件将位于屏幕的左上角。
我也尝试过使用
覆盖
,但结果与
堆栈
实现几乎相同


在Flatter中,推荐的方法是什么?

我将描述两种方法,但我不会提供代码或示例,因为我不认为以可复制粘贴的方式发布这一点一定是个好主意-我同意@Remi的评论,即如果你需要在应用程序中执行此操作,有一个很好的机会,应用程序可以重构,以避免它。然而,有一种方法可以做到这一点——尽管需要警告,但它可能会导致一些问题,例如触摸事件(尽管我认为有一些方法可以绕过它——请参阅起点)。既然你还没有真正解释你想要这个做什么,我想这不是你需要的

我会鼓励你寻找其他的方法来做你想做的事情,并询问你是否愿意帮助找出更好的方法

总之,关于好东西=p:


方法#1-使用现有覆盖:

实际上,我自己也使用过这种方法来实现一个模式加载指示器,我希望在推送下面的页面之间保持该指示器,并且可以从应用程序中的任何位置调用该指示器,而无需在其上方的树中设置任何小部件。这是一个非常具体的用例,尽管我认为它证明了这种用法的合理性

基本上,您希望使用覆盖,但不是创建自己的覆盖(与您正在处理的小部件大小相同),而是希望使用现有的覆盖。如果你正在使用MaterialApp、WidgetApp,甚至只是应用程序中的某个导航器,那么你已经有了一个几乎可以肯定与屏幕大小相同的覆盖。如果你有多个覆盖层,你想得到一个在顶部,因为这是最有可能覆盖整个屏幕

要访问它,可以使用
overlystate rootOverlay=context.rootAncestorStateOfType(consttypematcher())
来获取根覆盖(您可能希望断言它确实找到了一个)

一旦你有权访问它,你就可以创建一个覆盖入口来构建你的小部件,然后调用
rootOverlay.insert(…)
来添加它。覆盖入口生成的项目将从左上角定位到屏幕范围,只要覆盖本身覆盖整个屏幕(您可以自己进行偏移)。您还需要确保在某个时候删除(…)
,这意味着保留对OverlayEntry的引用。我个人会创建一个名为OverlayInsertionManager的类,或者一些跟踪overlay条目并进行插入/删除的类


方法#2-使用您自己的小部件

如果你只是在自己的应用程序中做这件事,我会认为这样做稍微干净些,尽管可能还不是一个好主意。p> 基本上,你想做的是在你的应用程序中创建一个有状态的小部件——比任何会占用屏幕空间的东西都重要。这在理论上可能意味着高于您的MaterialApp/WidgetApp/etc,尽管如果您使用WidgetApp提供的主题/文本方向性/etc,这可能会给您带来问题。我认为您可以使用将小部件放置在需要的位置。为了方便起见,我们将其命名为
PageOverlay
(使用相应的
PageOverlayState

在您的小部件中,您将有一个静态的
of
方法,如下所示(这些方法在Flatter的源代码中随处可见,或多或少是一种惯例):

的静态页面覆盖系统状态(BuildContext上下文){
final pageOverlyState结果=context.ancestorStateOfType(const TypeMatcher());
断言(){
如果(结果==null){
抛出新错误(
'未找到覆盖小部件。\n'
);
}
返回true;
}());
返回结果;
}
在PageOverlyState中,您将有一个类似于
WidgetBuilder\u OverlyBuilder
的变量,通常为空,还有一个类似于
set OverlyBuilder(WidgetBuilder OverlyBuilder)=>setState(()=>\u OverlyBuilder=OverlyBuilder)的方法/设置器;

在PageOverlyState的生成器中,您将创建一个堆栈;第一个子项将是传递到
WidgetApp.builder
MaterialApp.builder
中的子项。只有当OverlyBuilder不为null时,您才会创建第二个子项;如果它不为null,则第二个子项应该类似于
new builder(生成器:_overlybuilder)


您可能需要做一些适当调整堆栈大小的工作(例如,将其放在展开的文件或其他文件中)。

您看过Positioned吗?@EricvanderToorn我看过,但要定位
就要有“real”绝对坐标,你需要
堆栈
你使用它来达到顶层,不是吗?@EricvanderToorn和“真实”绝对坐标,我的意思是,如果堆栈位于屏幕中心的一个框内,那么坐标0.0,0.0将不会是屏幕的左上方
static PageOverlayState of(BuildContext context) {
  final PageOverlayState result = context.ancestorStateOfType(const TypeMatcher<PageOverlayState>());
  assert(() {
    if (result == null) {
      throw new FlutterError(
          'No Overlay widget found.\n'
      );
    }
    return true;
  }());
  return result;
}