How can I make a ListTile work inside this widget hierarchy:
SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column(
children: [
Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Radio(
value: 1,
groupValue: 1,
onChanged: (sel) {},
),
GestureDetector(
child: Row(
children: <Widget>[
//Text('Title'), -- This is OK, but ListTile fails
ListTile(
title: Text('Title'),
subtitle: Text('Subtitle'),
),
],
),
onTap: () {},
),
],
),
],
),
),
Please understand that I am not in full control of the widget hierarchy -- a framework is building the SingleChildScrollView, Radio, GestureDetector, etc. I am simply trying to supply a child widget for an option. (I replicated the hierarchy in a simplified form to debug and experiment.)
I'm getting an exception:
flutter: ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
flutter: The following assertion was thrown during performLayout():
flutter: BoxConstraints forces an infinite width.
flutter: These invalid constraints were provided to RenderParagraph's layout() function by the following
flutter: function, which probably computed the invalid constraints in question:
flutter: _RenderListTile._layoutBox (package:flutter/src/material/list_tile.dart:1318:9)
flutter: The offending constraints were:
flutter: BoxConstraints(w=Infinity, 0.0<=h<=Infinity)
Normally when I encounter this kind of problem, I simply wrap the widget in an Expanded, but that is not working in this case.
Note that if I replace the ListTile with a simple Text widget, then it renders fine.
You can wrap the ListTile in a Container or a ConstrainedBox and set its maxWidth:
ConstrainedBox(
constraints: BoxConstraints(
maxWidth: MediaQuery.of(context).size.width - 50,
),
child: ListTile(
title: Text('Title'),
subtitle: Text('Subtitle'),
trailing: Text('Trailing'),
),
),
You can copy paste run full code below
You can use IntrinsicWidth wrap Row and Expanded wrap ListTile and you can have more than one Expaned ListTile
GestureDetector(
child: IntrinsicWidth(
child: Row(
children: <Widget>[
//Text('Title'), -- This is OK, but ListTile fails
Expanded(
child: ListTile(
title: Text('Title'),
subtitle: Text('Subtitle'),
),
),
],
),
),
working demo
full code
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,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column(
children: [
Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Radio(
value: 1,
groupValue: 1,
onChanged: (sel) {},
),
GestureDetector(
child: IntrinsicWidth(
child: Row(
children: <Widget>[
//Text('Title'), -- This is OK, but ListTile fails
Expanded(
child: ListTile(
isThreeLine: true,
title: Text('Title'),
subtitle: Text('this is long text this is long text this is long text \n'* 10),
),
),
],
),
),
onTap: () {},
),
],
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
full code 2 relayout
import 'package:flutter/cupertino.dart';
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,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column(
children: [
Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
flex: 1,
child: Radio(
value: 1,
groupValue: 1,
onChanged: (sel) {},
),
),
Expanded(
flex: 5,
child: GestureDetector(
child: LayoutBuilder(
builder:(context, constraints) {
print(constraints.maxWidth);
print(constraints.minWidth);
return ConstrainedBox(
constraints: BoxConstraints(
maxWidth: constraints.maxWidth),
child: ListTile(
//isThreeLine: true,
title: Text('Title'),
subtitle: Text(
'Textlargeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee',
overflow: TextOverflow.ellipsis,
maxLines: 2,
style: TextStyle(
fontSize: 13.0,
fontFamily: 'Roboto',
color: Color(0xFF212121),
fontWeight: FontWeight.bold,
),
),
),
);
}
),
onTap: () {},
),
),
],
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
Related
I use BottomNavigationBar in my flutter app. I have additional requirements for appearance, this is the result that I got. everything is fine except for the top and bottom padding (arrows in the figure).
This is my code:
BottomNavigationBar(
selectedFontSize: 0,
type: BottomNavigationBarType.fixed,
currentIndex: currIndex,
items: tabs.map((e) {
return BottomNavigationBarItem(
title: SizedBox.shrink(),
icon: _buildIcon(e),
);
}).toList(),
)
Widget _buildIcon(Data data) {
return Container(
width: double.infinity,
height:kBottomNavigationBarHeight ,
child: Material(
color: _getBackgroundColor(data.index),
child: InkWell(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.email_outlined),
Text('111', style: TextStyle(fontSize: 12, color: Colors.white)),
],
),
onTap: () {
onTabSelected(data.index);
},
),
),
);
}
how can i remove those top and bottom padding? any ideas i will greatly appreciate.
I made a sample code using your part code.
But I can not reproduce like your problem with shared your code.
Could you share a part of Scaffold's bottomNavigationBar or other related to code.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
],
),
),
bottomNavigationBar: BottomNavigationBar(
selectedFontSize: 0,
type: BottomNavigationBarType.fixed,
currentIndex: 0,
items: [
new BottomNavigationBarItem(
icon: _buildIcon(),
title: SizedBox.shrink(),
),
new BottomNavigationBarItem(
icon: _buildIcon(),
title: SizedBox.shrink(),
),
new BottomNavigationBarItem(
icon: _buildIcon(),
title: SizedBox.shrink(),
)
]));
}
Widget _buildIcon() {
return Container(
width: double.infinity,
height: kBottomNavigationBarHeight,
child: Material(
color: Colors.grey,
child: InkWell(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.email_outlined),
Text('111', style: TextStyle(fontSize: 12, color: Colors.white)),
],
),
onTap: () {},
),
),
);
}
}
I have a RoundedLoadingButton in a SingleChildScrollView. There are 2 issues.
1: the bottom of the button is cut off (see the bottom shadow)
2: When I click the button or the button becomes a loader, an error pops up on the screen.
I tried adding an Expanded widget to the Column and RoundedLoadingButton, but nothing changed. I also tried changing the mainAxisSize of the column to min and max, but they both didn't help.
What am I doing wrong and how can I fix it?
return SingleChildScrollView(
child: Container(
padding: EdgeInsets.symmetric(horizontal: 40),
child: Form(
child: Column(
children: [
SizedBox(height: Constants.verticaleSectionSpacing * 2),
TextFormField(),
TextFormField(),
TextFormField(),
RoundedLoadingButton(
height: 45,
width: double.infinity,
controller: saveBtnController,
child: Text('Save'),
onPressed: _doSomething,
),
],
),
),
),
);
You can copy paste run full code below
You can change width from double.infinity to MediaQuery.of(context).size.width or a fixed number like 300
working demo
full code
import 'package:flutter/material.dart';
import 'package:rounded_loading_button/rounded_loading_button.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: SingleChildScrollView(
child: Container(
padding: EdgeInsets.symmetric(horizontal: 40),
child: Form(
child: Column(
children: [
//SizedBox(height: Constants.verticaleSectionSpacing * 2),
TextFormField(),
TextFormField(),
TextFormField(),
RoundedLoadingButton(
height: 45,
width: MediaQuery.of(context).size.width,
//controller: saveBtnController,
child: Text('Save'),
onPressed: () {},
),
],
),
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
I want to make a bottom navigation bar, with a Floating Action Button, in Flutter
when I click the Floating Action Button, the window will appear on the screen,
the photo in below will help to understand my request:
You can copy paste run full code below
You can use OverlayEntry and set color
entry = OverlayEntry(
builder: (context) {
return Center(
child: Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
color: Colors.black.withOpacity(0.5),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
RaisedButton(
onPressed: () {
entry.remove();
},
child: Text("abc"),
working demo
full code
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class BottomAppBarPage extends StatefulWidget {
#override
_BottomAppBarPageState createState() => _BottomAppBarPageState();
}
class _BottomAppBarPageState extends State<BottomAppBarPage> {
OverlayEntry entry;
#override
void initState() {
super.initState();
entry = OverlayEntry(
builder: (context) {
return Center(
child: Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
color: Colors.black.withOpacity(0.5),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
RaisedButton(
onPressed: () {
entry.remove();
},
child: Text("abc"),
),
RaisedButton(
onPressed: () {
entry.remove();
},
child: Text("def"),
),
RaisedButton(
onPressed: () {
entry.remove();
},
child: Text("123"),
),
],
),
),
);
},
);
}
#override
void dispose() {
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Bottom App Bar')),
body: ListView(
padding: const EdgeInsets.all(8),
children: <Widget>[
Container(
height: 50,
color: Colors.amber[600],
child: const Center(child: Text('Entry A')),
),
Container(
height: 50,
color: Colors.amber[500],
child: const Center(child: Text('Entry B')),
),
Container(
height: 50,
color: Colors.amber[100],
child: const Center(child: Text('Entry C')),
),
],
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.add),
onPressed: () {
Overlay.of(context).insert(entry);
},
),
bottomNavigationBar: BottomAppBar(
shape: CircularNotchedRectangle(),
notchMargin: 4.0,
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(
icon: Icon(Icons.menu),
onPressed: () {},
),
IconButton(
icon: Icon(Icons.search),
onPressed: () {},
)
],
),
),
);
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: BottomAppBarPage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
SolidBottomSheetController() is not working in my code, I am not able to listen_events of height or anything, hopefully, and I am sure my code is correct.
Can Anyone Please Give Example of SolidBottomSheet() working, with Controller, how you are implementing and listening to the events
You can copy paste run full code below , it's from official example and add listen event
You can use _controller.heightStream.listen
code snippet
SolidController _controller = SolidController();
#override
void initState() {
_controller.heightStream.listen((event) {
print(event);
});
}
working demo
full code
import 'package:flutter/material.dart';
import 'package:solid_bottom_sheet/solid_bottom_sheet.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: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
SolidController _controller = SolidController();
#override
void initState() {
_controller.heightStream.listen((event) {
print(event);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Solid bottom sheet example"),
),
body: ListView.builder(
itemCount: 20,
itemBuilder: (context, index) {
return Card(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Stack(
alignment: Alignment.bottomRight,
children: <Widget>[
Image.asset("assets/cardImg.png"),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"Flutter rules?",
style: Theme.of(context).textTheme.title,
),
),
],
),
ButtonTheme.bar(
child: ButtonBar(
children: <Widget>[
FlatButton(
child: const Text('NOPE'),
onPressed: () {
/* ... */
},
),
FlatButton(
child: const Text('YEAH'),
onPressed: () {
/* ... */
},
),
],
),
),
],
),
);
},
),
bottomSheet: SolidBottomSheet(
controller: _controller,
draggableBody: true,
headerBar: Container(
color: Theme.of(context).primaryColor,
height: 50,
child: Center(
child: Text("Swipe me!"),
),
),
body: Container(
color: Colors.white,
height: 30,
child: Center(
child: Text(
"Hello! I'm a bottom sheet ",
style: Theme.of(context).textTheme.display1,
),
),
),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.stars),
onPressed: () {
_controller.isOpened ? _controller.hide() : _controller.show();
}),
);
}
}
I have a row that spans the width of the screen and with three buttons and a text that are equally spaced(flex = 1). I want the text to be aligned to the center of the screen and the buttons at the ends. is this possible?
To cause a child to expand to fill the available space in the direction of this widget's main axis, wrap the child in an Expanded widget.
So you can try Expanded and declare Flex in second Expanded widget.
Solution
Row(
children: <Widget>[
Expanded(child: Container(padding: EdgeInsets.all(16),color: Colors.red,child: Text("text 1"))),
Expanded(flex: 3,child: Container(padding: EdgeInsets.all(16),color: Colors.blue,child: Text("text 2"))),
Expanded(child: Container(padding: EdgeInsets.all(16),color: Colors.yellow,child: Text("text 3"))),
Expanded(child: Container(padding: EdgeInsets.all(16),color: Colors.green,child: Text("text 4"))),
],
),
Output:
Hey check the code bellow I think it does what you want:
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter buttons demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
void initState() {
super.initState();
}
List<int> values = [1, 2, 3];
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Buttons demo'),
centerTitle: true,
),
body: Row(
children: <Widget>[
Flexible(
child: Container(
color: Colors.redAccent,
child: FlatButton(
onPressed: () => {},
child: Text('Button'),
),
),
),
Expanded(
flex: 2,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'Some text',
textAlign: TextAlign.right,
),
)),
Flexible(
child: Container(
color: Colors.green,
child: FlatButton(
onPressed: () => {},
child: Text('Button'),
),
),
),
Flexible(
child: Container(
color: Colors.purple,
child: FlatButton(
onPressed: () => {},
child: Text('Button'),
),
),
),
],
));
}
}
There are a few ways. The simplest I can think of is using a SizedBox widget.
In your example, you can use the SizedBox widget and add one additional box with the same dimensions as your left button on the left. The SizedBox will occupy the space but won't be rendered on screen.