如何在 List 小部件 Flutter 中无上下文导航

Posted

技术标签:

【中文标题】如何在 List 小部件 Flutter 中无上下文导航【英文标题】:How to navigate without context in List widget Flutter 【发布时间】:2021-12-04 00:36:47 【问题描述】:

我正在开发一个 Flutter Web 应用程序,在该应用程序中我开发了自定义导航栏,但我正在努力在导航栏项目中添加导航。我尝试在没有上下文的情况下进行导航,但不幸的是它不适用于我创建的列表。我确实尝试过创建函数并根据需要放置导航,但仍然没有运气。

import 'package:animated_text_kit/animated_text_kit.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:get/get.dart';
import 'package:shimmer/shimmer.dart';
import 'package:customweb/about.dart';

double collapsableHeight = 0.0;
Color selected = Color(0xffffffff);
Color notSelected = Color(0xafffffff);

class Nav extends StatefulWidget 
  @override
  _NavState createState() => _NavState();


class _NavState extends State<Nav> 
  @override
  Widget build(BuildContext context) 
    double width = MediaQuery.of(context).size.width;
    return SafeArea(
      child: Scaffold(
        body: Stack(
          children: [
            Align(
              alignment: Alignment.topCenter,
              child: Padding(
                  padding: EdgeInsets.only(top: 250),
                  child: Image.asset(
                    "assets/logo.png",
                    scale: 2,
                  )),
            ),
            Align(
                alignment: Alignment.bottomCenter,
                child: Padding(
                    padding: EdgeInsets.only(bottom: 120),
                    child: Text(
                      "Download now available on",
                      style: TextStyle(fontSize: 30),
                    ))),
            Align(
                alignment: Alignment.bottomCenter,
                child: Padding(
                    padding: EdgeInsets.only(right: 200, bottom: 50),
                    child: Image.asset(
                      "assets/1200px-Google_Play_Store_badge_EN.png",
                      scale: 8,
                    ))),
            Align(
                alignment: Alignment.bottomCenter,
                child: Padding(
                    padding: EdgeInsets.only(left: 200, bottom: 50),
                    child: Image.asset(
                      "assets/1200px-Download_on_the_App_Store_Badge.png",
                      scale: 8,
                    ))),
            AnimatedContainer(
              margin: EdgeInsets.only(top: 79.0),
              duration: Duration(milliseconds: 375),
              curve: Curves.ease,
              height: (width < 800.0) ? collapsableHeight : 0.0,
              width: double.infinity,
              color: Color(0xff121212),
              child: SingleChildScrollView(
                child: Column(
                  children: navBarItems,
                ),
              ),
            ),
            Container(
              color: Colors.amber,
              height: 80.0,
              padding: EdgeInsets.symmetric(horizontal: 24.0),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  AnimatedTextKit(
                    animatedTexts: [
                      FadeAnimatedText(
                        'Get It',
                        textStyle: TextStyle(fontSize: 26, color: Colors.white),
                      ),
                      FadeAnimatedText(
                        'All Amazing Stuff',
                        textStyle: TextStyle(fontSize: 22, color: Colors.white),
                      ),
                      FadeAnimatedText(
                        'One Platform',
                        textStyle: TextStyle(fontSize: 24, color: Colors.white),
                      ),
                      FadeAnimatedText(
                        'Endless Services',
                        textStyle: TextStyle(fontSize: 24, color: Colors.white),
                      ),
                      FadeAnimatedText(
                        'Available Soon',
                        textStyle: TextStyle(fontSize: 24, color: Colors.white),
                      ),
                    ],
                    onTap: () 
                      print("");
                    ,
                  ),
                  LayoutBuilder(builder: (context, constraints) 
                    if (width < 800.0) 
                      return NavBarButton(
                        onPressed: () 
                          if (collapsableHeight == 0.0) 
                            setState(() 
                              collapsableHeight = 240.0;
                            );
                           else if (collapsableHeight == 240.0) 
                            setState(() 
                              collapsableHeight = 0.0;
                            );
                          
                        ,
                      );
                     else 
                      return Row(
                        children: navBarItems,
                      );
                    
                  )
                ],
              ),
            ),
          ],
        ),
      ),
    );
  


List<Widget> navBarItems = [
  NavBarItem(
    text: 'About',
    onPressed: () 
      Get.to(AboutPage());
    ,
  ),
  NavBarItem(
    text: 'Services',
    onPressed: () 
      Get.to(AboutPage());
    ,
  ),
  NavBarItem(
    text: 'FAQ',
    onPressed: () 
      Get.to(AboutPage());
    ,
  ),
];

class NavBarItem extends StatefulWidget 
  final String text;
  final Function onPressed;

  NavBarItem(
    required this.text,
    required this.onPressed,
  );

  @override
  _NavBarItemState createState() => _NavBarItemState();


class _NavBarItemState extends State<NavBarItem> 
  Color color = notSelected;

  @override
  Widget build(BuildContext context) 
    return MouseRegion(
      onEnter: (value) 
        setState(() 
          color = selected;
        );
      ,
      onExit: (value) 
        setState(() 
          color = notSelected;
        );
      ,
      child: Material(
        color: Colors.transparent,
        child: InkWell(
          splashColor: Colors.white60,
          onTap: () ,
          child: Container(
            height: 60.0,
            alignment: Alignment.centerLeft,
            margin: EdgeInsets.symmetric(horizontal: 24.0),
            child: Text(
              widget.text,
              style: TextStyle(
                fontSize: 16.0,
                color: color,
              ),
            ),
          ),
        ),
      ),
    );
  


class NavBarButton extends StatefulWidget 
  final Function onPressed;

  NavBarButton(
    required this.onPressed,
  );

  @override
  _NavBarButtonState createState() => _NavBarButtonState();


class _NavBarButtonState extends State<NavBarButton> 
  Widget build(BuildContext context) 
    return Container(
      height: 55.0,
      width: 60.0,
      decoration: BoxDecoration(
        border: Border.all(
          color: Color(0xcfffffff),
          width: 2.0,
        ),
        borderRadius: BorderRadius.circular(15.0),
      ),
      child: Material(
        color: Colors.transparent,
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(12.0),
        ),
        child: InkWell(
          splashColor: Colors.white60,
          onTap: () 
            setState(() 
              widget.onPressed();
            );
          ,
          child: Icon(
            Icons.menu,
            size: 30.0,
            color: Color(0xcfffffff),
          ),
        ),
      ),
    );
  

我们将不胜感激任何帮助

【问题讨论】:

请修剪您的代码,以便更容易找到您的问题。请按照以下指南创建minimal reproducible example。 【参考方案1】:

您好 Asver Seb,您使用了错误的方法。我最近在 Flutter Web 上完成了一项工作,这里使用我的导航栏/标题代码来构建您正在寻找的内容,它会做得非常好。

class Header extends StatelessWidget 
  const Header(
    Key? key,
  ) : super(key: key);

  @override
  Widget build(BuildContext context) 
    return Container(
      margin: EdgeInsets.symmetric(vertical: 20, horizontal: 40),
      child: Row(
        children: <Widget>[
          Image.asset(
            'assets/images/logo.png',
            width: 50,
          ),
          SizedBox(width: 10),
          Shimmer.fromColors(
              baseColor: Colors.transparent,
              highlightColor: Colors.amber,
              child: Text(
                "Webster",
                style: TextStyle(fontSize: 32, fontWeight: FontWeight.w800),
              )),
          Spacer(),
          NavItem(
            title: 'Home',
            tapEvent: () 
              Get.to(HomeScreen());
            ,
          ),
          NavItem(
            title: 'About',
            tapEvent: () 
              Get.to(About());
            ,
          ),
          NavItem(
            title: 'FAQ',
            tapEvent: () 
              Get.to(Faq());
            ,
          ),
        ],
      ),
    );
  


class NavItem extends StatelessWidget 
  const NavItem(Key? key, required this.title, required this.tapEvent)
      : super(key: key);

  final String title;
  final GestureTapCallback tapEvent;

  @override
  Widget build(BuildContext context) 
    return InkWell(
      onTap: tapEvent,
      hoverColor: Colors.transparent,
      child: Padding(
        padding: EdgeInsets.symmetric(horizontal: 15),
        child: Text(
          title,
          style: TextStyle(fontWeight: FontWeight.w300),
        ),
      ),
    );
  

【讨论】:

效果很好,非常感谢

以上是关于如何在 List 小部件 Flutter 中无上下文导航的主要内容,如果未能解决你的问题,请参考以下文章

Flutter小部件测试中如何使用List的find.byType匹配

如何在 Flutter 的同一屏幕上沿 ListView 显示小部件?

Flutter ListView 与 List 中的小部件不会在应该更新时更新

传递正确的上下文以在flutter中构建按钮小部件

如何从 Flutter-web 中的小部件创建图像?

Flutter - 动态构建小部件