【问题标题】:Is it possible to implement widgets using list in flutter?是否可以在颤动中使用列表实现小部件?
【发布时间】:2021-02-16 13:56:16
【问题描述】:

我正在创建一个 Journal 移动应用程序,它可以作为查看杂志和每日新闻更新的媒介。这是我的第一个颤振项目,我对颤振完全陌生。如果我说错了什么或没有提供足够的信息,请原谅我。

我使用来自 github 的代码作为我的应用程序的主页,并进行了一些更改以满足我的需求。现在在我的代码中,主页由一个侧边菜单栏组成,这个栏由 4 个按钮组成,即 HomeMy ProfilePremium常见问题解答。侧面菜单栏的GlobalKeys 使用名称为_keys 的列表调用,该列表的类型为GlobalKey。我尝试将列表_keys的数据类型更改为Widget,然后调用类的相应Widgets。但随后弹出两个错误。

没有为类 'Widget' 定义 getter 'currentContext'。

参数类型“Widget”不能分配给参数类型“GlobalKey”。

现在我希望列表_keys 的类型为Widget,以便我调用它的相应小部件主页我的个人资料PremiumFAQ 从它的每个类中,以便我查看相应的页面。或者,如果不可能,我很想知道一个替代方案让它开始工作。

以下是我的应用程序的代码。

import 'dart:math' as math;

import 'package:flutter/scheduler.dart';
import 'package:google_signin_example/google%20sign%20in/logged_in_widget.dart';
import 'package:google_signin_example/main app/lib/ui_3/TravelBean.dart';
import 'package:google_signin_example/main app/lib/ui_3/magazine/screens/home_screen.dart';
import 'package:google_signin_example/main%20app/lib/ui_3/FAQ/faq.dart';
import 'package:google_signin_example/main%20app/lib/ui_3/Newspaper%20and%20Kiddos/lib_kiddos/main.dart';
import 'package:google_signin_example/main%20app/lib/ui_3/Newspaper%20and%20Kiddos/lib_news/main.dart';
import 'package:google_signin_example/main%20app/lib/ui_3/premium/premium.dart';
import 'package:google_signin_example/widget/sign_up_widget.dart';

import 'detail_page.dart';

class HomePage1 extends StatefulWidget {
  @override
  _HomePage1State createState() => _HomePage1State();
}

class _HomePage1State extends State<HomePage1> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      body: Container(
        child: Row(
          children: <Widget>[
            LeftWidget(),
            Expanded(
              child: RightWidget(),
            )
          ],
        ),
      ),
    );
  }
}

class LeftWidget extends StatefulWidget {
  @override
  _LeftWidgetState createState() => _LeftWidgetState();
}

class _LeftWidgetState extends State<LeftWidget> with TickerProviderStateMixin {
  List<String> _list = ["Home", "My profile", "Premium", "FAQ"];

  List <Widget> _keys = [                  
    HomePage1(),                           //These are the widgets from different classes.
    LoggedInWidget(),
    premium(),
    faq(),
    /*GlobalKey(),                         //This was available before I made the changes. 
    GlobalKey(),
    GlobalKey(),
    GlobalKey()*/
  ];

  int checkIndex = 0;

  Offset checkedPositionOffset = Offset(0, 0);
  Offset lastCheckOffset = Offset(0, 0);

  Offset animationOffset = Offset(0, 0);
  Animation _animation;
  AnimationController _animationController;

  @override
  void initState() {
    checkIndex = _list.length - 1;
    super.initState();

    SchedulerBinding.instance.endOfFrame.then((value) {
      calcuteCheckOffset();
      addAnimation();
    });
  }

  void calcuteCheckOffset() {

    lastCheckOffset = checkedPositionOffset;
    RenderBox renderBox = _keys[checkIndex].currentContext.findRenderObject();   //This is where the first error occurs.
    Offset widgetOffset = renderBox.localToGlobal(Offset(0, 0));
    Size widgetSise = renderBox.size;
    checkedPositionOffset = Offset(widgetOffset.dx + widgetSise.width,
        widgetOffset.dy + widgetSise.height);
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Stack(
        children: <Widget>[
          Container(
            width: 50,
            decoration: BoxDecoration(
              color: Color(0xff000000),
              borderRadius: BorderRadius.circular(30),
            ),
            child: Column(
              children: _buildList(),
            ),
          ),
          Positioned(
            top: animationOffset.dy,
            left: animationOffset.dx,
            child: CustomPaint(
              painter: CheckPointPainter(Offset(10, 0)),
            ),
          )
        ],
      ),
    );
  }

  List<Widget> _buildList() {
    List<Widget> _widget_list = [];

    _widget_list.add(Padding(
      padding: EdgeInsets.only(
        top: 50,
      ),

      child: Icon(
        Icons.settings,
        color: Colors.white,
        size: 30,
      ),
    ));
    for (int i = 0; i < _list.length; i++) {
      _widget_list.add(Expanded(
        child: GestureDetector(
            onTap: () {
              indexChecked(i);
            },
            child: VerticalText(
                _list[i],
                _keys[i],                                        //This is where the second error occurs.
                checkIndex == i &&
                    (_animationController != null &&
                        _animationController.isCompleted))),
      ));
    }
    _widget_list.add(Padding(
      padding: EdgeInsets.only(
        top: 50,
        bottom: 50,
      ),
      child:  Image(image: AssetImage('assets/images/Voix.png')),
    ));
    return _widget_list;
  }

  void indexChecked(int i) {
    if (checkIndex == i) return;

    setState(() {
      checkIndex = i;
      calcuteCheckOffset();
      addAnimation();
    });
  }

  void addAnimation() {
    _animationController =
        AnimationController(duration: Duration(milliseconds: 300), vsync: this)
          ..addListener(() {
            setState(() {
              animationOffset =
                  Offset(checkedPositionOffset.dx, _animation.value);
            });
          });

    _animation = Tween(begin: lastCheckOffset.dy, end: checkedPositionOffset.dy)
        .animate(CurvedAnimation(
            parent: _animationController, curve: Curves.easeInOutBack));
    _animationController.forward();
  }
}

class CheckPointPainter extends CustomPainter {
  double pointRadius = 5;
  double radius = 30;

  Offset offset;

  CheckPointPainter(this.offset);

  @override
  void paint(Canvas canvas, Size size) {
    Paint paint = Paint()..style = PaintingStyle.fill;

    double startAngle = -math.pi / 2;
    double sweepAngle = math.pi;

    paint.color = Color(0xff000000);

    canvas.drawArc(
        Rect.fromCircle(center: Offset(offset.dx, offset.dy), radius: radius),
        startAngle,
        sweepAngle,
        false,
        paint);

    paint.color = Color(0xffffffff);
    canvas.drawCircle(
        Offset(offset.dx - pointRadius / 2, offset.dy - pointRadius / 2),
        pointRadius,
        paint);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return true;
  }
}

class VerticalText extends StatelessWidget {
  String name;
  bool checked;
  GlobalKey globalKey;

  VerticalText(this.name, this.globalKey, this.checked);

  @override
  Widget build(BuildContext context) {
    return RotatedBox(
      key: globalKey,
      quarterTurns: 3,
      child: Text(
        name,
        style: TextStyle(
          color: checked ? Color(0xffffffff) : Colors.grey,
          fontSize: 16,
        ),
      ),
    );
  }
}

class RightWidget extends StatefulWidget {
  @override
  _RightWidgetState createState() => _RightWidgetState();
}

class _RightWidgetState extends State<RightWidget>
    with TickerProviderStateMixin {
  TabController _tabController;

  @override
  void initState() {
    super.initState();
    _tabController = TabController(vsync: this, length: 5);
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: EdgeInsets.only(
        left: 15,
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          Padding(
            padding: EdgeInsets.only(top: 50, left: 20),
            child: Text(
              "Voix Home",
              style: TextStyle(
                color: Colors.black,
                fontSize: 25,
              ),
            ),
          ),
          Padding(
            padding: const EdgeInsets.only(top: 15, left: 10),
            child: SizedBox(
              height: 30,
              child: TabBar(
                isScrollable: true,
                unselectedLabelColor: Colors.black,
                labelColor: Color(0xffffffff),
                controller: _tabController,
                indicator: BoxDecoration(
                  color: Color(0xff9e9e9e),
                  borderRadius: BorderRadius.only(
                    topRight: Radius.circular(20),
                    bottomLeft: Radius.circular(20),
                  ),
                ),
                tabs: <Widget>[
                  Tab(
                    text: "Flash",
                  ),
                  Tab(
                    text: "Magazine",
                  ),
                  Tab(
                    text: "Newspaper",
                  ),
                  Tab(
                    text: "Kiddos",
                  ),
                  Tab(
                    text: "Editorial",
                  ),
                ],
              ),
            ),
          ),
          Expanded(
            child: TabBarView(
              controller: _tabController,
              children: <Widget>[
                TravelWidget(),
                HomeScreen(),
                News(),
                Kiddos(),
                RightBody(),
               // RightBody(),
              ],
            ),
          )
        ],
      ),
    );
  }
}

class RightBody extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      margin: EdgeInsets.only(
        left: 15,
      ),
      color: Colors.white,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          Padding(
            padding: EdgeInsets.only(
              top: 20,
            ),
            child: Text(
              "Flash!",
              style: TextStyle(
                color: Colors.black,
                fontSize: 20,
              ),
            ),
          ),
          Expanded(
            child: ListView(
              scrollDirection: Axis.horizontal,
              children: <Widget>[
                Container(
                  width: 220,
                  margin: EdgeInsets.symmetric(
                    horizontal: 10,
                    vertical: 10,
                  ),
                  decoration: BoxDecoration(
                    borderRadius: BorderRadius.circular(40),
                    image: new DecorationImage(
                      image: new AssetImage('assets/images/bottom1.jpg'),
                      fit: BoxFit.cover,
                    ),
                    boxShadow: [
                      BoxShadow(
                        spreadRadius: 5,
                        blurRadius: 5,
                        offset: Offset(1, 2),
                        color: Color(0x33757575),
                      ),
                    ],
                  ),
                ),
                Container(
                  width: 220,
                  margin: EdgeInsets.symmetric(
                    horizontal: 10,
                    vertical: 10,
                  ),
                  decoration: BoxDecoration(
                    color: Colors.white,
                    borderRadius: BorderRadius.circular(40),
                    boxShadow: [
                      BoxShadow(
                        spreadRadius: 5,
                        blurRadius: 5,
                        offset: Offset(1, 2),
                        color: Color(0x33757575),
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

class TravelWidget extends StatelessWidget {
  List<TravelBean> _list = TravelBean.generateTravelBean();

  @override
  Widget build(BuildContext context) {
    return PageView.builder(
      controller: PageController(viewportFraction: 0.9),
      itemBuilder: (context, index) {
        var bean = _list[index];
        return GestureDetector(
          onTap: () {
            Navigator.of(context).push(MaterialPageRoute(builder: (context) {
              return DetailPage(bean);
            }));
          },
          child: Hero(
            tag: bean.url,
            child: Stack(
              children: <Widget>[
                Padding(
                  padding: const EdgeInsets.only(bottom: 30, right: 10),
                  child: ClipRRect(
                    borderRadius: BorderRadius.circular(5),
                    child: Image.asset(
                      bean.url,
                      width: MediaQuery.of(context).size.width,
                      fit: BoxFit.cover,
                    ),
                  ),
                ),
                Positioned(
                  bottom: 80,
                  left: 15,
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: <Widget>[
                      Material(
                        color: Colors.transparent,
                        child: Text(
                          bean.location,
                          style: TextStyle(
                            color: Colors.black54,
                            fontSize: 15,
                          ),
                        ),
                      ),
                      Material(
                        color: Colors.transparent,
                        child: Text(
                          bean.name,
                          style: TextStyle(
                            color: Colors.black,
                            fontSize: 20,
                          ),
                        ),
                      ),
                    ],
                  ),
                ),
                Positioned(
                  bottom: 0,
                  right: 30,
                  child: Container(
                    width: 60,
                    height: 60,
                    decoration: BoxDecoration(
                      color: Colors.black,
                      borderRadius: BorderRadius.circular(30),
                    ),
                    child: Icon(
                      Icons.arrow_forward,
                      color: Colors.white,
                      size: 30,
                    ),
                  ),
                )
              ],
            ),
          ),
        );
      },
      itemCount: _list.length,
    );
  }
}

一开始,当我将列表 _keys 保留为 GlobalKey 类型并且不注释掉以下 4 GlobalKeys 时,我得到了输出,但侧面菜单栏不起作用。

This is my application with GlobalKeys in place of those Widgets

我希望那些相应的页面在点击时显示。但是该渲染对象只是在选项之间切换并显示相同的页面。

请帮帮我。

PS:如前所述,我是 Flutter 新手,如果我有什么问题,请不要误会我。

【问题讨论】:

  • 嗨,简而言之,你想做什么?
  • 嗨@IvánYoed。我在这里的首要任务是在单击选项时显示侧边栏页面。但我无法做到这一点,因为我不知道如何调用相应页面的小部件。你能帮帮我吗?

标签: android flutter dart


【解决方案1】:

我建议你检查一下flutter状态管理,尤其是Mobx with Provider,对你来说会更容易。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-28
    • 2018-05-10
    • 2020-05-23
    • 2021-07-18
    • 2020-08-23
    • 2021-08-04
    • 1970-01-01
    • 2011-10-21
    相关资源
    最近更新 更多