【问题标题】:previous child of stack widget not active堆栈小部件的前一个孩子不活动
【发布时间】:2021-09-23 23:14:56
【问题描述】:

在堆栈小部件中,我有两个子容器;每个都有一个小时候的图标。在视图中,第一个容器的子容器有一个播放图标,按下该图标应变为暂停图标,第二个容器的子容器有一个主页图标,按下该图标将变为钱包图标。

按下时播放图标不会变为暂停图标。我注意到这是因为第一个容器上有另一个小部件,它是第二个容器,它使第一个小部件的内容处于非活动状态。

如何让它活跃起来?有什么办法吗?必须有办法。

import 'package:flutter/material.dart';

void main() {
runApp(AllTests());
}

class AllTests extends StatefulWidget {
const AllTests({Key? key}) : super(key: key);

@override
_AllTestsState createState() => _AllTestsState();
}

class _AllTestsState extends State<AllTests> {
IconData home = Icons.home;
IconData play = Icons.play_circle_filled;
onHomePress() {
if (home == Icons.home) {
  home = Icons.account_balance_wallet_rounded;
} else {
  home = Icons.home;
}
}
onPlayPress() {
if (play == Icons.play_circle_filled) {
  play = Icons.pause_circle_filled_rounded;
} else {
  play = Icons.play_circle_filled;
}
}

@override
Widget build(BuildContext context) {
return MaterialApp(
  debugShowCheckedModeBanner: false,
  home: Scaffold(
    body: Column(
      mainAxisAlignment: MainAxisAlignment.center,
      crossAxisAlignment: CrossAxisAlignment.center,
      children: [
        Stack(
          overflow: Overflow.visible,
            children: [
          Positioned(
            top: 50,
            child: Container(
              height: 300,
              width: 500,
              color: Colors.pink,
              child:  IconButton(
                icon: Icon(
                  play,
                  size: 80,
                  color: Colors.black,
                ),
                onPressed: () {
                  setState(() {
                    print('hello');
                    onPlayPress();
                  });
                },
              ),
            ),
          ),
          Positioned(

            child: Padding(
              padding: const EdgeInsets.only(left: 40.0),
              child: Container(
                height: 100,
                width: 100,
                color: Colors.yellow,
                child:  IconButton(
                  icon: Icon(
                    home,
                    size: 80,
                    color: Colors.black,
                  ),
                  onPressed: () {
                    setState(() {
                      onHomePress();
                    });
                  },
                ),
              ),
            ),
          )
        ]),
      ],
    ),
  ),
);
}
}

【问题讨论】:

  • 为什么你需要第一个比图标大这么多的容器,然后另一个图标堆叠在它上面?也许张贴截图...我很难弄清楚这种安排的外观。可能有更好的方法来构建没有重叠的 UI,比如你可以将图标放在 Stack() 内的 Row() 或 Column() 中,这样它们就不会重叠吗?您可以使用 IgnorePointer() 包装小部件,但我认为这不适用于您想要做的事情。
  • 我正在构建的 UI 需要一个堆栈,一个小部件在另一个之上。而这并不是我正在做的事情,这只是一个更大项目的一小部分,所以要回答为什么第一个容器应该更大......这只是一个场景。跨度>
  • 我会尽快添加截图@Pat9RB

标签: flutter widget


【解决方案1】:

您正在使用overflow: Overflow.visible,这会导致播放按钮可见,即使它位于Stack 之外。签出以下解决该问题的代码。

import 'package:flutter/material.dart';

void main() {
  runApp(AllTests());
}

class AllTests extends StatefulWidget {
  const AllTests({Key? key}) : super(key: key);

  @override
  _AllTestsState createState() => _AllTestsState();
}

class _AllTestsState extends State<AllTests> {
  IconData home = Icons.home;
  IconData play = Icons.play_circle_filled;
  onHomePress() {
    if (home == Icons.home) {
      home = Icons.account_balance_wallet_rounded;
    } else {
      home = Icons.home;
    }
  }

  onPlayPress() {
    if (play == Icons.play_circle_filled) {
      play = Icons.pause_circle_filled_rounded;
    } else {
      play = Icons.play_circle_filled;
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Column(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            const Spacer(),
            Expanded(
              child: Stack(
//           overflow: Overflow.visible,
                children: [
                  Positioned(
                    top: 50,
                    child: Container(
                      height: 300,
                      width: 500,
                      color: Colors.pink,
                      child: IconButton(
                        icon: Icon(
                          play,
                          size: 80,
                          color: Colors.black,
                        ),
                        onPressed: () {
                          setState(() {
                            print('hello');
                            onPlayPress();
                          });
                        },
                      ),
                    ),
                  ),
                  Positioned(
                    child: Padding(
                      padding: const EdgeInsets.only(left: 40.0),
                      child: Container(
                        height: 100,
                        width: 100,
                        color: Colors.yellow,
                        child: IconButton(
                          icon: Icon(
                            home,
                            size: 80,
                            color: Colors.black,
                          ),
                          onPressed: () {
                            setState(() {
                              onHomePress();
                            });
                          },
                        ),
                      ),
                    ),
                  )
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

您还可以查看AnimatedIcon 以使用动画play_pause 按钮。

【讨论】:

  • 您的代码工作正常,按下时图标会发生变化。但主要原因是什么?如果它是溢出属性,我取消注释它以查看会发生什么,但代码仍在工作,我的意思是按下时图标会发生变化。现在我继续在自己的代码中尝试它,一旦我将溢出属性注释掉,部分容器甚至包括图标都消失了。
  • 在应用更改之前在 IDE 和模拟器上运行我的代码时,图标是否处于非活动状态?
  • 是的,当我测试您的代码时,播放图标在溢出部分处于非活动状态,问题是 Column 小部件仅占用您分配给最后一个子按钮或主页按钮的尺寸,而不是整个屏幕,因为您添加了Overflow.visible,即使播放按钮容器超出范围,它也可见但不可点击(如果您运行代码并尝试点击在范围内的播放按钮的某些部分,您会发现它是可点击的)。因此,我让Column 小部件占据了整个屏幕。
  • 并在Expanded 小部件中添加了两个按钮,这将允许Stack 占用所需的空间,添加Spacer 小部件以占用顶部的剩余空间。因为我将Stack 放在Expanded 小部件中,所以Stack 不会溢出,因此添加或删除overflow: Overflow.visible 不会有任何区别。
  • 你太棒了 :) 谢谢,成功了
【解决方案2】:

使用Stack 时提供其大小。在列中,您可以使用 SizedBox 进行包装。并且在 Widget 树上,UI 优先级是自下而上,当您的小可点击小部件超过大部件时,最后放置在堆栈子级上。

这是您的小部件。



void main() {
  runApp(AllTests());
}

class AllTests extends StatefulWidget {
  const AllTests({Key? key}) : super(key: key);

  @override
  _AllTestsState createState() => _AllTestsState();
}

class _AllTestsState extends State<AllTests> {
  IconData home = Icons.home;
  IconData play = Icons.play_circle_filled;
  onHomePress() {
    if (home == Icons.home) {
      home = Icons.account_balance_wallet_rounded;
    } else {
      home = Icons.home;
    }
  }

  onPlayPress() {
    if (play == Icons.play_circle_filled) {
      play = Icons.pause_circle_filled_rounded;
    } else {
      play = Icons.play_circle_filled;
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            SizedBox(
              height: 100 + 300 + 40,

              /// total height F
              child: Stack(
                children: [
                  Positioned(
                    top: 50,
                    child: Container(
                      height: 300,
                      width: 500,
                      color: Colors.pink,
                      child: IconButton(
                        icon: Icon(
                          play,
                          size: 80,
                          color: Colors.black,
                        ),
                        onPressed: () {
                          setState(() {
                            print('hello');
                            onPlayPress();
                          });
                        },
                      ),
                    ),
                  ),
                  Positioned(
                    top: 0,
                    child: Padding(
                      padding: const EdgeInsets.only(left: 40.0),
                      child: Container(
                        height: 100,
                        width: 100,
                        color: Colors.yellow,
                        child: IconButton(
                          icon: Icon(
                            home,
                            size: 80,
                            color: Colors.black,
                          ),
                          onPressed: () {
                            setState(() {
                              onHomePress();
                            });
                          },
                        ),
                      ),
                    ),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

【讨论】:

  • 谢谢,但我不需要你更改安排。我希望它适用于这种安排。
  • 你能测试我的小部件,它的输出和你一样吗?
  • 我已经运行了你的代码,但我注意到你改变了小部件的位置
  • UI 上的位置还是小部件树上的位置?
  • 对此感到抱歉,我想我运行的是不同的代码。您的代码正在运行,但我的仍然没有,所以我想知道您到底更改或添加了什么。单独的sizedbox?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-09
  • 2021-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-01
相关资源
最近更新 更多