I'm trying to create a leaderBoard. But I can't get the texts in the same alignment. How can I put the texts in the same line? As I understand it, I cannot put the texts in line because I use mainAxisAlignment: MainAxisAlignment.spaceBetween in the row section. Is there any other way to line up the texts?
return Container(
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text("Sıralama",style: TextStyle(fontSize: 20), ),
Text("İsim Soyisim",style: TextStyle(fontSize: 20) ),
Text("Doğru cevap",style: TextStyle(fontSize: 20) ),
],
),
Divider(thickness: 2,color: Colors.grey,),
Expanded(
child: ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
if (index == 0)
Container(
width: 50,
height: 50,
child: Image.asset(
"assets/images/gold.png"))
else if (index == 1)
Container(
color: Colors.red,
width: 50,
height: 50,
child: Image.asset(
"assets/images/silver.png"))
else if (index == 2)
Container(
width: 50,
height: 50,
child: Image.asset(
"assets/images/bronze.png"))
else if (index > 2)
Text('${index + 1}',
style: TextStyle(fontSize: 20)),
Align(
child: Text(
'${snapshot.data[index].name}',
style: TextStyle(fontSize: 20)),
alignment: Alignment.centerLeft,),
Text(
'${snapshot.data[index].dogruCevap.toString()}',
style: TextStyle(fontSize: 20))
],
),
);
}),
),
],
));
You can use the DataTable for better UI and easy to render the table.
List<String> images = [
"assets/images/gold.png",
"assets/images/silver.png",
"assets/images/bronze.png"
];
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text('DataTable'),
),
body: Container(
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: DataTable(
columns: [
DataColumn(
label: Text("Sıralama", style: TextStyle(fontSize: 20))),
DataColumn(
label:
Text("İsim Soyisim", style: TextStyle(fontSize: 20))),
DataColumn(
label: Text("Doğru cevap", style: TextStyle(fontSize: 20))),
],
rows: snapshot.data.asMap().entries.map<DataRow>((e) {
return DataRow(cells: [
DataCell(Image.asset(images[e.key])),
DataCell(Text(
'${e.value.name}',
style: TextStyle(fontSize: 20))),
DataCell(Text(
'${e.value.dogruCevap.toString()}',
style: TextStyle(fontSize: 20))),
]);
}).toList(),
),
),
),
),
);
}
Using a Table will simplify your widget:
import 'package:flutter/material.dart';
class Score {
final String name;
final int score;
Score(this.name, this.score);
static Widget getSymbol(int position) {
switch (position) {
case 0:
return Icon(Icons.directions_boat);
case 1:
return Icon(Icons.directions_train);
case 2:
return Icon(Icons.directions_bike);
default:
return Text((position + 1).toString(),
style: TextStyle(fontSize: 24.0));
}
}
}
List<Score> scores = [
Score('Azerty', 3),
Score('Qwertyuiop', 9),
Score('Wxcvbn', 0),
Score('Qsd', 7),
];
void main() {
runApp(
MaterialApp(
title: 'Flutter Demo',
home: Scaffold(
body: Table(
defaultVerticalAlignment: TableCellVerticalAlignment.middle,
columnWidths: {
0: FlexColumnWidth(2),
1: FlexColumnWidth(3),
2: FlexColumnWidth(3),
},
children: [
TableRow(
decoration: BoxDecoration(
border: Border(bottom: BorderSide(width: 2.0)),
),
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Text("Sıralama"),
),
Text("İsim Soyisim"),
Text("Doğru cevap"),
],
),
...scores
.asMap()
.entries
.map(
(entry) => TableRow(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Align(
alignment: Alignment.centerLeft,
child: Score.getSymbol(entry.key),
),
),
Text(
'${entry.value.name}',
),
Text(
'${entry.value.score.toString()}',
),
],
),
)
.toList(),
],
),
),
),
);
}
Related
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.
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),
),
],
),
}
}
I currently have a listview with an alphabet scroller on the side. I'm trying to add a searchbox to the top, but whenever I wrap something in a column, I get errors.
Using the current code, ListView inside Stack is throwing Vertical viewport was given unbounded height.
When I remove the column and Text('TestString'), my code works fine. I have tried adding an Expandable around the ListView.Builder but this also doesn't seem to solve it.
#override
Widget build(BuildContext context) {
height = MediaQuery.of(context).size.height;
return Scaffold(
appBar: AppBar(
title: Text(widget.title,
style: TextStyle(
fontSize: 20.0,
color: Colors.white,
fontWeight: FontWeight.bold)),
centerTitle: true,
),
body: Column(
children: [
Text('TestString'),
new LayoutBuilder(
builder: (context, constraints) {
return new Stack(children: [
//Causes the current issue
ListView.builder(
itemCount: exampleList.length,
controller: _controller,
itemExtent: _itemsizeheight,
itemBuilder: (context, position) {
return Padding(
padding: const EdgeInsets.only(right: 32.0),
child: Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
exampleList[position],
style: TextStyle(fontSize: 20.0),
),
),
));
},
),
Positioned(
right: _marginRight,
top: _offsetContainer,
child: _getSpeechBubble()),
Align(
alignment: Alignment.centerRight,
child: GestureDetector(
onTapDown: (details) {
_onTapDown(details);
},
child: GestureDetector(
onVerticalDragUpdate: _onVerticalDragUpdate,
onVerticalDragStart: _onVerticalDragStart,
onVerticalDragEnd: (details) {
setState(() {
isPressed = false;
});
},
child: Container(
//height: 20.0 * 26,
color: Colors.transparent,
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: []..addAll(
new List.generate(_alphabet.length,
(index) => _getAlphabetItem(index)),
),
),
),
),
),
),
]);
},
),
],
),
);
}
_getSpeechBubble() {
return isPressed
? new SpeechBubble(
nipLocation: NipLocation.RIGHT,
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
width: 30,
child: Center(
child: Text(
"${_text ?? "${_alphabet.first}"}",
style: TextStyle(
color: Colors.white,
fontSize: 18.0,
),
),
),
),
],
),
)
: SizedBox.shrink();
}
ValueGetter? callback(int value) {}
_getAlphabetItem(int index) {
return new Expanded(
child: new Container(
width: 40,
height: 20,
alignment: Alignment.center,
child: new Text(
_alphabet[index],
style: (index == posSelected)
? new TextStyle(fontSize: 16, fontWeight: FontWeight.w700)
: new TextStyle(fontSize: 12, fontWeight: FontWeight.w400),
),
),
);
}
You can wrap your LayoutBuilder() with Expanded() like this and it won't show an error.
return Container(
child: Column(
children: [
Text("Header"),
Expanded(
child: ListView.builder(
itemCount:50,
itemBuilder: (BuildContext context, int index) {
return Text("List Item $index");
},
),
),
Text("Footer"),
],
),
);
You can try the code here
What the problem is I have to render some texts which are in a row and also it should wrap when it doesn't have enough space but the row does not wrap.
I have used wrapping it Expanded, Wrap, and tried some stackoverflow answers but none of them work
Below is my code for it
Widget xyz(List _list) {
return Padding(
padding: const EdgeInsets.fromLTRB(50, 10, 40, 10),
child: InkWell(
onTap: () {},
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
'Title : ',
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 13),
),
Wrap(children: [
Row(children: [
for (int i = 0; i < _list.length; i++)
Container(
padding: const EdgeInsets.only(right: 8),
child: Text(
'${_list[i]}',
style: TextStyle(fontSize: 13),
),
),
]),
]),
],
),
),
);
}
class _Page3State extends State<Page3> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
xyz([
'Text1',
'Text2',
'Text3',
'Text4',
'Text5',
'Text6',
'Text7',
]),
//other widgets
],
),
);
}
}
And this is the output I am getting
I want the 'Text6' & 'Text7' Text widgets to go on the next line.
This is a working example:
The issues are incorrect Flexible (Expanded) placing, and your Wrap had a Row child instead of directly placed children.
Widget xyz(List _list) {
return Padding(
padding: const EdgeInsets.fromLTRB(50, 10, 40, 10),
child: InkWell(
onTap: () {},
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
'Title : ',
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 13),
),
Flexible(
child: Wrap(
children: [
for (int i = 0; i < _list.length; i++)
Container(
padding: const EdgeInsets.only(right: 8),
child: Text(
'${_list[i]}',
style: TextStyle(fontSize: 13),
),
),
],
),
),
],
),
),
);
}
class _Page3State extends State<Page3> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
xyz([
'Text1',
'Text2',
'Text3',
'Text4',
'Text5',
'Text6',
'Text7',
]),
//other widgets
],
),
);
}
}
I am developing an app and I have a page in which I show a block of data and below that I show the tabBars and TabBarView containing additional data. The problem I am struggling with is that if I try to wrap the widget "DefaultTabController" with "SingleChildScrollView" it throws an error and the page does not work.
I need to find a way to show the tabBars and TabBarView at the bottom of the page and make the entire page scrollable
I put the code:
In the build method I put 4 widgets inside the column
_showEventHeader shows a single image with a title
_showUserAndEventData shows plain text
_showTabs shows the tab headers
_showTabsContent shows the content of the tabs (images and comments)
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
backgroundColor: Theme.of(context).primaryColor,
body: Column(
children: [
..._showEventHeader(),
Container(
padding: EdgeInsets.all(15),
child: _showUserAndEventData()),
_showTabs(),
_showTabsContent(),
],
)
));
}
List<Widget> _showEventHeader() {
return [
SizedBox(
height: 20,
),
GestureDetector(
onTap: () {
if (Val.valStr(widget.evento.bannerUrl).isNotEmpty) {
Navigator.of(context).push(MaterialPageRoute(builder: (ctx) {
return FlypperFullImage(
imgURL: widget.evento.bannerUrl,
);
}));
}
},
child: Stack(
alignment: Alignment.bottomRight,
children: [
FlypperCustomImageNetWork(
imageURL: widget.evento.bannerUrl,
height: 200,
width: 200,
showAsRectangle: true,
fillWidth: true,
),
Container(
child: FlypperQrImage(
qrData: widget.evento.code,
size: 65,
),
)
],
),
),
SizedBox(
height: 20,
),
!_ticketsAvailable
? Text('$_noTicketAvailableMessage',
style: Theme.of(context).textTheme.headline2)
: SizedBox(
height: 1,
),
Card(
color: Theme.of(context).primaryColor,
elevation: 5,
child: Padding(
padding: const EdgeInsets.all(5),
child: Text(
Val.valStr(widget.evento.name).isNotEmpty
? Val.valStr(widget.evento.name)
: 'Sin nombre',
textAlign: TextAlign.justify,
style: Theme.of(context)
.textTheme
.headline1 /*FlypperStyleHelper.eventTitle(context)*/),
),
),
SizedBox(
height: 10,
),
];
}
Widget _showUserAndEventData() {
return SingleChildScrollView(
child: Container(
color: Theme.of(context).primaryColor,
child: Column(
children: [
SizedBox(height: 10),
Row(mainAxisAlignment: MainAxisAlignment.start, children: [
this.user != null
? /*FlypperCustomImageBase64(
imageBase64: this.user.profileImageUrl)*/
FlypperCustomImageNetWork(
imageURL: this.user.profileImageUrl,
keepImageCached: true,
height: 65,
width: 65,
)
: SizedBox(height: 1),
SizedBox(
height: 10,
),
Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
this.user != null
? this.user.userName.isEmpty
? this.user.email
: this.user.userName
: '',
style: Theme.of(context).textTheme.headline1,
/* FlypperStyleHelper.eventUserData(context, 18),*/
),
Text(
this.user != null
? Val.valInt(this.user.followers).toString() +
' seguidores'
: '',
style: Theme.of(context).textTheme.bodyText1
/*FlypperStyleHelper.eventUserData(context, 15),*/
)
],
),
)
]),
_getEventDetailInfo(),
SizedBox(
height: 20,
),
_showBuyButton(),
SizedBox(
height: 10,
),
FlypperIconButton(
icon: Icons.location_on,
width: 150,
handlerFunction: () => _openMapWithCalculatedRoute(context),
),
Divider(
color: Colors.grey,
thickness: 2,
)
],
),
),
);
}
Widget _showTabs() {
return TabBar(
isScrollable: true,
labelStyle: Theme.of(context).textTheme.headline2,
tabs: [
Tab(
text: 'Fotos, videos...',
/*icon: Icon(Icons.event, color: Theme.of(context).buttonColor)*/
),
Tab(
text: 'Comentarios',
/*icon: Icon(Icons.attach_file, color: Theme.of(context).buttonColor),*/
),
],
);
}
Widget _showTabsContent() {
return Flexible(
child: TabBarView(
children: [
SingleChildScrollView(
child: Column(
children: [
Container(
color: Theme.of(context).primaryColor,
child: Column(children: [_getDetailImage()]),
),
],
),
),
Container(child: Text('Comments section')) //comentarios, pendiente
// SingleChildScrollView(
// child: Container(
// color: Theme.of(context).primaryColor,
// child: Column(children: [_getDetailImage()]),
// ),
// ),
// Container(child: Text('Comments section')) //comentarios, pendiente
],
),
);
}
I also attached an screenshot so you can understand better what I am saying
Try this i have a give example and edit it some value :-
TabBar(
isScrollable: true,
unselectedLabelColor: Colors.white.withOpacity(0.3),
indicatorColor: Colors.white,
tabs: [
Tab(
child: Text('Tab 1'),
),
Tab(
child: Text('Investment'),
),
Tab(
child: Text('Your Earning'),
),
]),
And all Widget vale call in a List view Like this:-
_showEventHeader() {
return new Container(
height: 20,
child: ListView(
shrinkWrap: true,
scrollDirection: Axis.vertical,
Column(
children: [])));}
I am trying to show some data from the database and my app must contain UI like this.
But I am encountering this kind of problem.
Problems:
The text is overflowing and not wrapping (I tried to use Flexible and Expanded but it produces more exceptions, mostly of non-zero flex and so on)
The list needs fixed height and width, whereas I need height to match_parent. double.infinity don't work as well.
Here is my code:
class CategoryDetailPage extends StatefulWidget {
final Category category;
CategoryDetailPage({Key key, this.category}) : super(key: key);
#override
_CategoryDetailPageState createState() => _CategoryDetailPageState();
}
class _CategoryDetailPageState extends State<CategoryDetailPage> {
DatabaseProvider databaseProvider = DatabaseProvider.instance;
List<Phrase> phrases;
final List<Color> _itemColors = [
Color(0xff16a085),
Color(0xff2980b9),
Color(0xff8e44ad),
Color(0xff2c3e50),
Color(0xffd35400),
Color(0xffbdc3c7),
Color(0xff27ae60),
Color(0xfff39c12),
Color(0xff7f8c8d),
Color(0xffc0392b),
];
int _colorCounter = 0;
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Padding(
padding: EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Row(
children: [
Container(
child: ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Image(
image: AssetImage("assets/images/categories/${widget.category.image}"),
width: 32,
),
),
),
Padding(
padding: const EdgeInsets.only(left: 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
"Say ${widget.category.name}",
style: TextStyle(fontSize: 24, fontFamily: "Pacifico"),
),
Text(
"\"${widget.category.quote}\" --${widget.category.quoteAuthor} aaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
textAlign: TextAlign.left,
style: TextStyle(
color: Colors.grey,
fontStyle: FontStyle.italic
),
),
],
),
),
],
),
Row(
children: <Widget>[
RotatedBox(
quarterTurns: -1,
child: Column(
children: <Widget>[
Text(
"Informal",
style: TextStyle(
fontSize: 32,
color: Colors.grey.withOpacity(0.5),
fontFamily: "AbrilFatFace"),
),
],
),
),
Container(
height: 300,
width: 300,
child: FutureBuilder(
future: databaseProvider
.getPhrasesByCategoryId(widget.category.id),
builder: (context, snapshot) {
return snapshot.hasData
? ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, i) {
return _buildPhraseItem(snapshot.data[i]);
})
: Center(
child: CircularProgressIndicator(),
);
},
),
),
],
),
],
),
),
),
);
}
Widget _buildPhraseItem(Phrase phrase) {
Random random = Random();
int colorIndex = random.nextInt(_itemColors.length - 1);
Color currentColor = _itemColors[colorIndex];
if (_colorCounter >= 10) _colorCounter = 0;
return InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PhraseDetail(
phraseToShow: phrase.phrase,
color: currentColor,
)));
},
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 80,
decoration: BoxDecoration(
color: currentColor,
borderRadius: BorderRadius.all(Radius.circular(4)),
boxShadow: [
BoxShadow(
blurRadius: 8,
color: Colors.grey.withOpacity(0.5),
offset: Offset(0, 3))
]),
child: Center(
child: Text(
phrase.phrase,
style: TextStyle(color: Colors.white),
)),
),
),
);
}
}
wrap the second child(Padding) of the first Row with Flexible
wrap the second child(Container) of the second Row with Flexible and remove width: 300 from the container parameters.
import 'dart:math';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: CategoryDetailPage(),
);
}
}
Random random = Random();
class CategoryDetailPage extends StatefulWidget {
CategoryDetailPage({
Key key,
}) : super(key: key);
#override
_CategoryDetailPageState createState() => _CategoryDetailPageState();
}
class _CategoryDetailPageState extends State<CategoryDetailPage> {
final List<Color> _itemColors = [
Color(0xff16a085),
Color(0xff2980b9),
Color(0xff8e44ad),
Color(0xff2c3e50),
Color(0xffd35400),
Color(0xffbdc3c7),
Color(0xff27ae60),
Color(0xfff39c12),
Color(0xff7f8c8d),
Color(0xffc0392b),
];
int _colorCounter = 0;
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Padding(
padding: EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Row(
mainAxisSize: MainAxisSize.min,
// crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
child: ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Image(
image: NetworkImage(
'https://source.unsplash.com/random',
),
width: 32,
),
),
),
Flexible(
child: Padding(
padding: const EdgeInsets.only(left: 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
'say congratulations',
style:
TextStyle(fontSize: 24, fontFamily: "Pacifico"),
),
Text(
"At every party there are two kinds of people – those who want to go home and those who don’t. The trouble is, they are usually married to each other. - Ann Landers",
textAlign: TextAlign.left,
style: TextStyle(
color: Colors.grey,
fontStyle: FontStyle.italic),
),
],
),
),
),
],
),
Row(
children: <Widget>[
RotatedBox(
quarterTurns: -1,
child: Column(
children: <Widget>[
Text(
"Informal",
style: TextStyle(
fontSize: 32,
color: Colors.grey.withOpacity(0.5),
fontFamily: "AbrilFatFace"),
),
],
),
),
Flexible(
child: Container(
height: 300,
child: ListView(children: [
_buildPhraseItem(),
_buildPhraseItem(),
_buildPhraseItem(),
_buildPhraseItem(),
]),
),
),
],
),
],
),
),
),
);
}
Widget _buildPhraseItem() {
var colorIndex = random.nextInt(_itemColors.length - 1);
var currentColor = _itemColors[colorIndex];
if (_colorCounter >= 10) _colorCounter = 0;
return InkWell(
onTap: () {
print('Navigator.push');
},
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 80,
decoration: BoxDecoration(
color: currentColor,
borderRadius: BorderRadius.all(Radius.circular(4)),
boxShadow: [
BoxShadow(
blurRadius: 8,
color: Colors.grey.withOpacity(0.5),
offset: Offset(0, 3))
]),
child: Center(
child: Text(
'phrase.phrase',
style: TextStyle(color: Colors.white),
)),
),
),
);
}
}