Reputation: 21
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).
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
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