Is it possible to implement widgets using list in flutter?

0

I am creating a Journal mobile application which would work as a medium to view magazines and daily news updates. This is my first flutter project and I am totally new to flutter. So kindly excuse me if I had said something wrong about something or didnt provide enough information.

I used a code from github for the main page of my application and made few changes to accommodate my needs. Now in my code, the home page consists of a side menu bar and this bar consists of 4 buttons, namely Home, My Profile, Premium and FAQ. The GlobalKeys for the side menu bar is called using a list by the name _keys which is of the type GlobalKey. I tried changing the data type of the list _keys to Widget and then called the corresponding Widgets of the classes. But then two errors popped out.

The getter 'currentContext' isn't defined for the class 'Widget'.

The argument type 'Widget' can't be assigned to the parameter type 'GlobalKey<State>'.

Now I would like the list _keys to be of the type Widget in order for me to call upon it's corresponding widgets of Home, My Profile, Premium and FAQ from each of it's classes in order for me to view the corresponding pages. Or if it is not possible, I would love to know an alternative for it to start working.

Following is the code of my application.

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,
    );
  }
}

At the beginning, when I leave the list _keys to be of the type GlobalKey and don't comment out the following 4 GlobalKeys I get the output but the side menu bar won't work.

This is my application with GlobalKeys in place of those Widgets

I want those corresponding pages to display when clicked on. But that render object just switches between the options and the same page is displayed.

So kindly help me out.

PS : As said earlier I'm new to flutter, so kindly don't mistake me if I had something wrong.

android
flutter
dart
asked on Stack Overflow Feb 16, 2021 by Amalesh MV • edited Feb 16, 2021 by Amalesh MV

1 Answer

0

I suggest you check about flutter state management, especially Mobx with Provider, it will be kind easier for you.

answered on Stack Overflow Feb 17, 2021 by Sadeny Alpha

User contributions licensed under CC BY-SA 3.0