Thiago Oliveira
Thiago Oliveira

Reputation: 21

How to navigate with the side menu with just one screen

I have a demand to perform the navigation of this left side menu. This screen is already divided into 3, but I need the side menu only to update the second (middle). And I need the third one to receive the index data from the second (middle).

Image

main_scren.dart

class MainScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // It provide us the width and height
    Size _size = MediaQuery.of(context).size;
    return Scaffold(
      body: Responsive(
        // Let's work on our mobile part
        mobile: ListOfChannels(),
        tablet: Row(
          children: [
            Expanded(
              flex: 6,
              child: ListOfChannels(),
            ),
            Expanded(
              flex: 9,
              child: ChannelScreen(),
            ),
          ],
        ),
        desktop: Row(
          children: [
            // Once our width is less then 1300 then it start showing errors
            // Now there is no error if our width is less then 1340
            Expanded(
              flex: _size.width > 1340 ? 2 : 4,
              child: SideMenu(),
            ),
            Expanded(
              flex: _size.width > 1340 ? 3 : 5,
              child: ListOfChannels(),
            ),
            Expanded(
              flex: _size.width > 1340 ? 8 : 10,
              child: ChannelScreen(),
            ),
          ],
        ),
      ),
    );
  }
}

Here is the code for my side_menu.dart

    @override
  Widget build(BuildContext context) {
    return Container(
      height: double.infinity,
      padding: EdgeInsets.only(top: kIsWeb ? kDefaultPadding : 0),
      color: kBgLightColor,
      child: SafeArea(
        child: SingleChildScrollView(
          padding: EdgeInsets.symmetric(horizontal: kDefaultPadding),
          child: Column(
            children: [
              Row(
                children: [
                  Spacer(),
                  Image.asset(
                    "assets/images/logo_lado.png",
                    width: 100,
                  ),
                  Spacer(),
                  // We don't want to show this close button on Desktop mood
                  if (!Responsive.isDesktop(context)) CloseButton(),
                ],
              ),
              SizedBox(height: kDefaultPadding),

              SizedBox(height: kDefaultPadding),

              CircleAvatar(     
                        maxRadius: 65,
                        backgroundColor: Colors.transparent,
                        backgroundImage: AssetImage("assets/images/user_3.png"),
                      ),
              SizedBox(height: kDefaultPadding), 

              SizedBox(height: kDefaultPadding),       

              FlatButton.icon(
                minWidth: double.infinity,
                padding: EdgeInsets.symmetric(
                  vertical: kDefaultPadding,
                ),
                shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(10),
                ),
                color: kPrimaryColor,
                onPressed: () {},
                icon: WebsafeSvg.asset("assets/Icons/Edit.svg", width: 16),
                label: Text(
                  "Meu Perfil",
                  style: TextStyle(color: Colors.white),
                ),
              ).addNeumorphism(
                topShadowColor: Colors.white,
                bottomShadowColor: Color(0xFF234395).withOpacity(0.2),
              ),
              SizedBox(height: kDefaultPadding),
              FlatButton.icon(
                minWidth: double.infinity,
                padding: EdgeInsets.symmetric(
                  vertical: kDefaultPadding,
                ),
                shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(10),
                ),
                color: kBgDarkColor,
                onPressed: () async {
                  bool saiu = await logout();
                  if (saiu) {
                    Navigator.pushReplacement(
                      context,
                      MaterialPageRoute(builder: (context) => LoginPage())
                      );
                  }
                },
                icon: WebsafeSvg.asset("assets/Icons/Download.svg", width: 16),
                label: Text(
                  "Sair",
                  style: TextStyle(color: kTextColor),
                ),
              ).addNeumorphism(),
              SizedBox(height: kDefaultPadding * 2),
              // Menu Items
              SideMenuItem(
                press: () {
                  
                },
                title: "On Demand",
                iconSrc: "assets/Icons/new_releases_black_24dp.svg",
                isActive: false,
                //itemCount: 3,
              ),
              SideMenuItem(
                press: () {},
                title: "Assistir TV",
                iconSrc: "assets/Icons/tv_black_24dp.svg",
                isActive: true,
              ),
              SideMenuItem(
                press: () {},
                title: "Favoritos",
                iconSrc: "assets/Icons/star_border_black_24dp.svg",
                isActive: false,
              ),

              //SizedBox(height: kDefaultPadding * 2),
              // Tags
              //Tags(),
            ],
          ),
        ),
      ),
    );

And this is the screen that is in error, from which I need to receive the channel list data. channel_screen.dart

class ChannelScreen extends StatelessWidget {
  const ChannelScreen({
    Key key,
    this.channel,
  }) : super(key: key);

  final Channel channel;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        color: Colors.white,
        child: SafeArea(
          child: Column(
            children: [
              //Header(),
              //Divider(thickness: 1),
              Expanded(
                child: SingleChildScrollView(
                  padding: EdgeInsets.all(kDefaultPadding),
                  child: Row(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      CircleAvatar(
                        maxRadius: 24,
                        backgroundColor: Colors.transparent,
                        backgroundImage: NetworkImage(channel.midiaImagemUrl),
                      ),
                      SizedBox(width: kDefaultPadding),
                      Expanded(
                        child: Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            Row(
                              children: [
                                Expanded(
                                  child: Column(
                                    crossAxisAlignment:
                                        CrossAxisAlignment.start,
                                    children: [
                                      Text.rich(
                                        TextSpan(
                                          text: channel.midiaTitulo,
                                          style: Theme.of(context)
                                              .textTheme
                                              .button,
                                          children: [
                                            TextSpan(
                                                text:
                                                    "",
                                                style: Theme.of(context)
                                                    .textTheme
                                                    .caption),
                                          ],
                                        ),
                                      ),
                                      Text(
                                        channel.midiaTitulo,
                                        style: Theme.of(context)
                                            .textTheme
                                            .headline6,
                                      )
                                    ],
                                  ),
                                ),
                                SizedBox(width: kDefaultPadding / 2),
                                Text(
                                  "10:30 - 12:00",
                                  style: Theme.of(context).textTheme.caption,
                                ),
                              ],
                            ),
                            SizedBox(height: kDefaultPadding),
                            LayoutBuilder(
                              builder: (context, constraints) => SizedBox(
                                width: constraints.maxWidth > 850
                                    ? 800
                                    : constraints.maxWidth,
                                child: Column(
                                  crossAxisAlignment: CrossAxisAlignment.start,
                                  children: [
                                    Text(
                                      "Aqui ficará o EPG List",
                                      style: TextStyle(
                                        height: 1.5,
                                        color: Color(0xFF4D5875),
                                        fontWeight: FontWeight.w300,
                                      ),
                                    ),
                                    SizedBox(height: kDefaultPadding),
                                    Divider(thickness: 1),
                                    SizedBox(height: kDefaultPadding / 2),
                                    SizedBox(
                                      height: 500,
                                      width: 500,
                                      child: StaggeredGridView.countBuilder(
                                        physics: NeverScrollableScrollPhysics(),
                                        crossAxisCount: 1,
                                        itemCount: 1,
                                        itemBuilder:
                                            (BuildContext context, int index) =>
                                                ClipRRect(
                                          borderRadius:
                                              BorderRadius.circular(8),
                                          child: Image.asset(
                                            "assets/images/Img_$index.png",
                                            fit: BoxFit.cover,
                                          ),
                                        ),
                                        staggeredTileBuilder: (int index) =>
                                            StaggeredTile.count(
                                          2,
                                          index.isOdd ? 2 : 1,
                                        ),
                                        mainAxisSpacing: kDefaultPadding,
                                        crossAxisSpacing: kDefaultPadding,
                                      ),
                                    )
                                  ],
                                ),
                              ),
                            ),
                          ],
                        ),
                      ),
                    ],
                  ),
                ),
              )
            ],
          ),
        ),
      ),
    );
  }
}

Any help will be appreciated.

Upvotes: 2

Views: 978

Answers (1)

Michael Horn
Michael Horn

Reputation: 4089

The basic problem here is that ChannelScreen has a final channel property, but the property isn't passed into the constructor - so it's always null when you try to access it.

The most straightforward solution is to convert your MainScreen to a StatefulWidget, with a mutable channel property. Then add a function onChannelSelected to ListOfChannels to handle when a user selects a new channel from that view - You could then update the state from that handler.

For a bare minimum example:

class ListOfChannels extends StatelessWidget {
    final void Function(Channel) onChannelSelected;
    ListOfChannels({required this.onChannelSelected});

    @override
    Widget build(BuildContext context) {
        return Column(
            children: channels.map((channel) => FlatButton(
                onPressed: () { this.onChannelSelected(channel) },
            ))).toList(),
        );
    }
}

class _MainScreenState extends State<MainScreen> {
    Channel channel; // Initialize to an appropriate value, or handle null case

    @override
    Widget build(BuildContext context) {
        // Desktop section
        Row(
            children: [
                // Once our width is less then 1300 then it start showing errors
                // Now there is no error if our width is less then 1340
                Expanded(
                  flex: _size.width > 1340 ? 2 : 4,
                  child: SideMenu(),
                ),
                Expanded(
                  flex: _size.width > 1340 ? 3 : 5,
                  child: ListOfChannels(
                    onChannelSelected: (channel) {
                      setState(() { this.channel = channel; });
                    }
                  ),
                ),
                Expanded(
                  flex: _size.width > 1340 ? 8 : 10,
                  child: ChannelScreen(channel: channel),
                ),
            ],
        ),
    }
}

Upvotes: 1

Related Questions