如何在 Flutter 中使用 setState 更改一个按钮被选中时的颜色,并取消选中其他按钮?

问题描述 投票:0回答:1

我想使用

setState
将按钮的颜色更改为单击时的蓝色,并将其他按钮更改为灰色以显示它们未被选中。我也希望它能改变按钮下方页面的内容。

这是目前的样子。默认情况下,表视图按钮处于选中状态,热图处于未选中状态。在这种情况下,按钮下方的“表格视图”文本会在选择“表格视图”按钮时显示。

代码如下:

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

  @override
  State<MusclesPane> createState() => _MusclesPaneState();
}

class _MusclesPaneState extends State<MusclesPane> {
  EdgeInsets padding = const EdgeInsets.all(25);
  Widget pageSection = const MusclesTableView();
  bool tableViewIsActive = true;
  bool heatmapDiagramIsActive = false;

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Row(
          mainAxisAlignment: MainAxisAlignment.end,
          children: [
            InkWell(
                onTap: () => {
                      setState(() {
                        pageSection = const MusclesTableView();

                        tableViewIsActive = true;
                        heatmapDiagramIsActive = false;
                      })
                    },
                child: ViewTypeButton(
                    title: "Table view", isActive: tableViewIsActive)),
            InkWell(
                onTap: () => {
                      setState(() {
                        pageSection = const MusclesHeatmapDiagram();

                        heatmapDiagramIsActive = true;
                        tableViewIsActive = false;
                      })
                    },
                child: ViewTypeButton(
                    title: "Heatmap diagram",
                    isActive: heatmapDiagramIsActive)),
          ],
        ),
        Padding(padding: padding, child: pageSection),
      ],
    );
  }
}

class ViewTypeButton extends StatelessWidget {
  const ViewTypeButton({Key? key, required this.title, required this.isActive})
      : super(key: key);
  final String title;
  final bool isActive;

  @override
  Widget build(BuildContext context) {
    return Container(
        margin: const EdgeInsets.symmetric(horizontal: 4.0),
        child: ElevatedButton(
            onPressed: () {},
            style: ElevatedButton.styleFrom(
                primary: isActive ? Colors.blue : Colors.grey),
            child: Text(title)));
  }
}

当我点击热图按钮时,没有任何反应。同样在 setState 函数中,我尝试使用

print(heatmapDiagramIsActive)
print(tableViewIsActive)
来检查变量是否发生变化,但没有任何输出,所以我不确定变量是否在变化。

我在想这可能是由于变量的范围。我尝试将

tableViewIsActive
heatmapDiagramIsActive
变量移到课堂之外;我也尝试将它们移动到 build() 函数下,但这并没有解决问题。

任何帮助将不胜感激 - 我现在已经多次回到这个问题,但我仍然坚持下去。另外,如果有任何我可以改进的 Flutter 实践,例如命名约定或任何重构建议,请告诉我,因为我是 Flutter 的新手。

flutter dart scope setstate state-management
1个回答
0
投票

正如我在评论中提到的,堆叠

InkWell
ElevatedButton
使得
ElevatedButton
正在接收输入但
InkWell
不是。您可以通过将回调函数传递给
ElevatedButton
并在点击按钮时调用该函数来解决这个问题:

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

  @override
  State<MusclesPane> createState() => _MusclesPaneState();
}

class _MusclesPaneState extends State<MusclesPane> {
  EdgeInsets padding = const EdgeInsets.all(25);
  Widget pageSection = const MusclesTableView();
  bool tableViewIsActive = true;
  bool heatmapDiagramIsActive = false;

  selectTableView() {
    setState(() {
      pageSection = const MusclesTableView();
      tableViewIsActive = true;
      heatmapDiagramIsActive = false;
    });
  }

  selectHeatMapView() {
    setState(() {
      pageSection = const MusclesHeatMapDiagram();
      tableViewIsActive = false;
      heatmapDiagramIsActive = true;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        const SizedBox(height: 90),
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ViewTypeButton(
              title: "Table view",
              isActive: tableViewIsActive,
              callback: selectTableView,
            ),
            ViewTypeButton(
              title: "HeatMapDiagram",
              isActive: heatmapDiagramIsActive,
              callback: selectHeatMapView,
            ),
          ],
        ),
        Padding(padding: padding, child: pageSection),
      ],
    );
  }
}

class ViewTypeButton extends StatelessWidget {
  const ViewTypeButton(
      {Key? key,
      required this.title,
      required this.isActive,
      required this.callback})
      : super(key: key);
  final String title;
  final bool isActive;
  final Function callback;

  @override
  Widget build(BuildContext context) {
    return Container(
        margin: const EdgeInsets.symmetric(horizontal: 4.0),
        child: ElevatedButton(
            onPressed: () => callback(),
            style: ElevatedButton.styleFrom(
                backgroundColor: isActive ? Colors.blue : Colors.grey),
            child: Text(title)));
  }
}

ElevatedButton
里面已经有
InkWell
,所以再多一个是多余的。

在设计方面,当您只有几样东西可供选择时,为每个按钮使用布尔值很简单。然而,如果你想扩展到拥有更多按钮,你可以使用一个整数作为键来确定一个按钮是否被激活。您可以根据需要扩展到任意数量的按钮,而无需创建无穷无尽的布尔变量。

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

  @override
  State<MusclesPane> createState() => _MusclesPaneState();
}

class _MusclesPaneState extends State<MusclesPane> {
  EdgeInsets padding = const EdgeInsets.all(25);
  Widget pageSection = const MusclesTableView();
  int selected = 0;

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        const SizedBox(height: 90),
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            ElevatedButton(
                onPressed: () => setState(() {
                      selected = 0;
                      pageSection = const MusclesTableView();
                    }),
                style: ElevatedButton.styleFrom(
                    backgroundColor: selected == 0 ? Colors.blue : Colors.grey),
                child: const Text("Table view")),
            ElevatedButton(
                onPressed: () => setState(() {
                      selected = 1;
                      pageSection = const MusclesHeatmapDiagram();
                    }),
                style: ElevatedButton.styleFrom(
                    backgroundColor: selected == 1 ? Colors.blue : Colors.grey),
                child: const Text("Heatmap diagram")),
          ],
        ),
        Padding(padding: padding, child: pageSection),
      ],
    );
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.