You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中使用ListView Builder组件时返回按钮失效问题

问题:添加ListView Builder后返回按钮失效

我编写了一段Flutter代码用于展示返回按钮、文本及ListView Builder组件。移除ListView Builder组件时返回按钮可正常工作,但添加该组件后返回按钮便失效,急需解决此问题。以下是页面代码:

import 'package:flutter/material.dart';
import 'package:workout_app/Screens/Components/Sign_Up_Screens/screen2.dart';

class SingleSelectListViewWithLogo extends StatefulWidget {
  final List<String> items;
  const SingleSelectListViewWithLogo({Key? key, required this.items}) : super(key: key);
  @override
  _SingleSelectListViewWithLogoState createState() =>
      _SingleSelectListViewWithLogoState();
}

class _SingleSelectListViewWithLogoState extends State<SingleSelectListViewWithLogo> {
  int? selectedIndex;

  void returnScreen(context) {
    print('returning');
    Navigator.of(context).pushReplacement(
      MaterialPageRoute(
        fullscreenDialog: true,
        builder: (context) => screen2(),
      ),
    );
  }

  bool nextValid = false;

  @override
  Widget build(BuildContext context) {
    Size size = MediaQuery.of(context).size;
    return Material(
      child: Container (
        decoration: const BoxDecoration(color: Colors.grey),
        height: size.height,
        width: double.infinity,
        child: Stack(
          children: <Widget> [
            Positioned(
              top: size.height * .06,
              left: size.width * .03,
              child: InkWell(
                onTap: () {
                  returnScreen(context);
                },
                child: Image.asset(
                  alignment: Alignment.topLeft,
                  "assets/images/back2.png",
                  width: size.width * .07,
                ),
              ),
            ),
            Positioned(
              top: size.height * .09,
              left: size.width * .4,
              child: const Text(
                style: TextStyle(fontSize: 30, color: Color.fromARGB(255, 4, 3, 3)),
                'Goals'
              )
            ),
            Positioned(
              top: size.height * .15,
              left: size.width * .07,
              child: const Text(
                style: TextStyle(fontSize: 20, color: Color.fromARGB(255, 49, 48, 48)),
                'What body type do you want to get?'
              )
            ),
            Positioned(
              top: size.height * .26,
              left: size.width * .4,
              child: const Text(
                style: TextStyle(fontSize: 15, color: Color.fromARGB(255, 33, 31, 31)),
                'Select 1'
              )
            ),
            ListView.builder(
              itemCount: widget.items.length,
              itemBuilder: (context, index) {
                return GestureDetector(
                  onTap: () {
                    setState(() {
                      selectedIndex = index;
                      nextValid = true;
                    });
                  },
                  child: Container(
                    height: size.height * .15,
                    decoration: BoxDecoration(
                      color: selectedIndex == index ? Color.fromARGB(255, 40, 188, 72) : Color.fromARGB(255, 202, 195, 195),
                      border: Border.all(
                        color: selectedIndex == index ? Color.fromARGB(255, 16, 66, 37) : Colors.transparent,
                        width: 3,
                      ),
                      borderRadius: BorderRadius.circular(10),
                    ),
                    padding: const EdgeInsets.symmetric(horizontal: 10),
                    margin: EdgeInsets.fromLTRB(16, index == 0 ? MediaQuery.of(context).size.height * 0.265 : 0, 16, 8),
                    child: Row(
                      children: [
                        Flexible(
                          child: Text(widget.items[index]),
                        )
                      ],
                    ),
                  ),
                );
              },
            ),
            Positioned(
              top: size.height * .86,
              left: size.width * .1,
              child: SizedBox(
                width: size.width * .8,
                height: size.height * .08,
                child: ElevatedButton(
                  style: ButtonStyle(                  
                    backgroundColor: MaterialStateProperty.all<Color>(!nextValid ? Color.fromRGBO(69, 75, 85, 1) : Color.fromARGB(255, 0, 147, 246)),
                  ),
                  child: const Text('Continue',
                    style: TextStyle(fontSize: 20),
                  ),
                  onPressed: () async {
                  },
                ),
              ),
            ),
          ]
        )
      )
    );
  }
}

问题原因

返回按钮失效是因为Stack布局中ListView的触摸区域覆盖了顶部的返回按钮。ListView默认会占满父容器的全部空间,且它的触摸事件优先级高于上层的Positioned元素,导致返回按钮的InkWell无法接收点击事件。

解决方案

重构布局结构,用Column替代Stack,让各组件按垂直方向排列,避免层级遮挡:

import 'package:flutter/material.dart';
import 'package:workout_app/Screens/Components/Sign_Up_Screens/screen2.dart';

class SingleSelectListViewWithLogo extends StatefulWidget {
  final List<String> items;
  const SingleSelectListViewWithLogo({Key? key, required this.items}) : super(key: key);
  @override
  _SingleSelectListViewWithLogoState createState() =>
      _SingleSelectListViewWithLogoState();
}

class _SingleSelectListViewWithLogoState extends State<SingleSelectListViewWithLogo> {
  int? selectedIndex;
  bool nextValid = false;

  void returnScreen(context) {
    print('returning');
    Navigator.of(context).pushReplacement(
      MaterialPageRoute(
        fullscreenDialog: true,
        builder: (context) => screen2(),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    Size size = MediaQuery.of(context).size;
    return Scaffold(
      backgroundColor: Colors.grey,
      body: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          // 顶部返回按钮
          Padding(
            padding: EdgeInsets.only(top: size.height * .06, left: size.width * .03),
            child: InkWell(
              onTap: () => returnScreen(context),
              child: Image.asset(
                "assets/images/back2.png",
                width: size.width * .07,
              ),
            ),
          ),
          // 标题
          Center(
            child: Padding(
              padding: EdgeInsets.only(top: size.height * .03),
              child: const Text(
                'Goals',
                style: TextStyle(fontSize: 30, color: Color.fromARGB(255, 4, 3, 3)),
              ),
            ),
          ),
          // 说明文本1
          Padding(
            padding: EdgeInsets.only(top: size.height * .06, left: size.width * .07),
            child: const Text(
              'What body type do you want to get?',
              style: TextStyle(fontSize: 20, color: Color.fromARGB(255, 49, 48, 48)),
            ),
          ),
          // 说明文本2
          Center(
            child: Padding(
              padding: EdgeInsets.only(top: size.height * .11),
              child: const Text(
                'Select 1',
                style: TextStyle(fontSize: 15, color: Color.fromARGB(255, 33, 31, 31)),
              ),
            ),
          ),
          // 中间可滚动列表
          Expanded(
            child: ListView.builder(
              padding: EdgeInsets.fromLTRB(16, size.height * .02, 16, 8),
              itemCount: widget.items.length,
              itemBuilder: (context, index) {
                return GestureDetector(
                  onTap: () {
                    setState(() {
                      selectedIndex = index;
                      nextValid = true;
                    });
                  },
                  child: Container(
                    height: size.height * .15,
                    margin: const EdgeInsets.only(bottom: 8),
                    decoration: BoxDecoration(
                      color: selectedIndex == index 
                          ? const Color.fromARGB(255, 40, 188, 72) 
                          : const Color.fromARGB(255, 202, 195, 195),
                      border: Border.all(
                        color: selectedIndex == index 
                            ? const Color.fromARGB(255, 16, 66, 37) 
                            : Colors.transparent,
                        width: 3,
                      ),
                      borderRadius: BorderRadius.circular(10),
                    ),
                    padding: const EdgeInsets.symmetric(horizontal: 10),
                    child: Align(
                      alignment: Alignment.centerLeft,
                      child: Text(widget.items[index]),
                    ),
                  ),
                );
              },
            ),
          ),
          // 底部按钮
          Padding(
            padding: EdgeInsets.only(bottom: size.height * .07, left: size.width * .1, right: size.width * .1),
            child: SizedBox(
              width: double.infinity,
              height: size.height * .08,
              child: ElevatedButton(
                style: ButtonStyle(                  
                  backgroundColor: MaterialStateProperty.all<Color>(
                    !nextValid 
                        ? const Color.fromRGBO(69, 75, 85, 1) 
                        : const Color.fromARGB(255, 0, 147, 246)
                  ),
                ),
                child: const Text(
                  'Continue',
                  style: TextStyle(fontSize: 20),
                ),
                onPressed: () async {},
              ),
            ),
          ),
        ],
      ),
    );
  }
}

修改说明

  • 用Scaffold+Column替代Stack,组件按垂直方向排列,彻底避免层级遮挡问题
  • 顶部元素通过Padding控制位置,不再依赖Positioned
  • ListView用Expanded包裹,自动占满剩余空间,不会覆盖顶部和底部元素
  • 调整了各元素的间距,保持原视觉效果

内容的提问来源于stack exchange,提问作者Promaster

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 12:25:01