This is the problem:
I have a grid (a crossword) and a list of questions below it. I need the list of questions to scroll indipendently from the grid. When I click on the grid to type the answer and the keyboard comes up I get an overflow error AND the grid doesn't move so the focused textfield that I use to input the answer is not visible (if it's low enough on the grid to be covered by the keyboard).
I tried all kind of combinations with ListView and Expanded widgets...no solution...I cannot use resizeToAvoidBottomInset: false because I need the grid to move up and keep the focused TextField visible.
Here is the code:
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Column(
children:[
FutureBuilder(
future: grid,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Align(
alignment: Alignment.topCenter,
child: Container(
width: MediaQuery.of(context).size.width-8,
margin: EdgeInsets.zero,
padding: EdgeInsets.zero,
child: GridView.count(
padding: EdgeInsets.only(left:0.0,top:5.0,right:0.0,bottom: 0.0),
shrinkWrap: true,
crossAxisCount: 15,
mainAxisSpacing: 2,
crossAxisSpacing: 2,
children: List.generate(snapshot.data.length, (index) {
if(gridFilled.length < snapshot.data.length) {
gridFilled.add(snapshot.data[index]);
}
return FocusScope(
node: _node,
child: Container(
decoration: BoxDecoration(
color: snapshot.data[index] == "#" ? Colors.black : Colors.white,
border: Border.all(color: Colors.black)),
child:
snapshot.data[index] == "#"
? Text('#')
: _isTextField(gridFilled[index], index),
));
}),
),
),
);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
return CircularProgressIndicator();
},
),
SizedBox(width: MediaQuery.of(context).size.width, height: 15.0,),
Expanded(
child: QPanel(dir: widget.dir, dbName: widget.xwordnumber),//this is a ListView with the questions
),
]),
drawer: Drawer(
child: ListView(
padding: EdgeInsets.zero,
children:<Widget>[
//just menu items
]
),
),
);
}
Unfortunately I'm not allowed to post pictures yet...not enough reputation..please, any help would be greatly appreciated!
wrap your Column inside SingleChildScrollView.
for example:
SingleChildScrollView(
child:Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Text('We move under cover and we move as one'),
Text('Through the night, we have one shot to live another day'),
Text('We cannot let a stray gunshot give us away'),
Text('We will fight up close, seize the moment and stay in it'),
Text('It’s either that or meet the business end of a bayonet'),
Text('The code word is ‘Rochambeau,’ dig me?'),
],
)
)
you can wrap your entire column inside SingleChildScrollView()
Related
I'm trying to create a contact book page that will load recent contact and all of my contact list, I managed to get the data and build it into the widget.
Design that I want to achieve for the screen body are:
a search widget which always stay on top even when the contact book can be scrolled.
List of the contact that can be scrolled
The problem is when there are a lot of contact (let say 20 contacts). If the screen size is small, it can only scroll until 7-8 contacts, but I know there's more to it. But I guess my ListView.Builder won't let me scroll down anymore. Like it's constrained by some properties but I don't know what is the reason
Can anyone please tell me the problem and how to fix this ?
Here's my code:
/// BODY
body: WillPopScope(
onWillPop: () {
print('hello');
},
child: ListView(
physics: BouncingScrollPhysics(),
shrinkWrap: true,
children: [
Container(
padding: EdgeInsets.symmetric(horizontal: 20),
height: MediaQuery.of(context).size.height,
child: NestedScrollView(
controller: _scrollController,
headerSliverBuilder: (context, isScrolled) {
return [
SliverPersistentHeader(
pinned: true,
floating: false,
delegate: ChooseUsersHeaderDelegate(
widgetList: Container(
color: Colors.white,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
/// Build Search Box Function
buildSearch(),
],
),
),
minHeight: selectedContactId.isNotEmpty ? 135 : 60,
maxHeight: selectedContactId.isNotEmpty ? 135 : 60,
parentContext: context,
),
),
];
},
body: Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
/// All Contacts Subtitle
Text(
'allContacts',
style: GoogleFonts.montserrat(
fontSize: 14,
fontWeight: FontWeight.w500,
color: primaryColor,
fontStyle: FontStyle.normal,
),
).tr(),
/// All Contacts
Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
isLoading
? ReusableLoadingContact()
: NotificationListener<
OverscrollIndicatorNotification>(
onNotification: (overScroll) {
overScroll.disallowIndicator();
return true;
},
/// Call function to return the widget for building contact list
child: buildWidget(context, 'contacts')),
],
),
],
),
),
),
)
],
),
),
Here's the code for building the contact List:
Widget build(BuildContext context) {
return contact.isEmpty
? Text('')
: ListView.builder(
/// Force to build only 2 items if recent, otherwise build all
itemCount: status == 'recent' ? contact.length > 2 ? 2 : contact.length : contact.length,
scrollDirection: Axis.vertical,
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
/// Return the widget of each contact
},
);
}
if you want to make your search bar stay on top here a very simple way
body : Column(
children:[
// this part will stay on top
Container() // your widget search bar
// listview widget will rendered after the Container
Expanded(
child: Listview.builder(
// this part will be scrollable
// return the widget contact
)
)
]
....
To attain this , use Container and Expanded as child widgets for Column
Format:
body : Column(
children:[
Container(
child: // Your search bar goes here
),
Expanded(
child: // Your list view goes here
)
)
]
I am facing this
Exception :
FlutterError (RenderViewport does not support returning intrinsic
dimensions. Calculating the intrinsic dimensions would require
instantiating every child of the viewport, which defeats the point of
viewports being lazy. If you are merely trying to shrink-wrap the
viewport in the main axis direction, consider a
RenderShrinkWrappingViewport render object (ShrinkWrappingViewport
widget), which achieves that effect without implementing the intrinsic
dimension API.)
When i add ProductsWidget the Exception occurs.
the code of Products Widget is:
class ProductsWidget extends GetResponsiveView<HomeTabController> {
#override
Widget build(BuildContext context) {
return ListView.builder(
shrinkWrap: true,
itemCount: 3,
// padding: EdgeInsets.symmetric(vertical: 20),
physics: NeverScrollableScrollPhysics(),
itemBuilder: (context, index) => Column(
children: [
Row()])}}
the calling code is:
body: LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
return SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: constraints.maxHeight,
),
child: IntrinsicHeight(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Expanded(
// flex: 1,
child: HomeAppBar()),
// listView
// i made shrinkWrap=true
// neverScroll
Flexible(fit: FlexFit.tight, child: ProductsWidget()),
],
),
),
),
);
}),
Try wrapping your ProductsWidget in a SizedBox and give it a width (width: double.maxFinite,) and potentially height.
I had a similar issue and I found the following post helpful: flutter listview with radio not showing in alertDialog
That is because ListView builds each child lazily. You can use a Column wrapped in a SingleChildScrollView instead of the ListView.
Replace SingleChildScrollView with CustomScrollView like this:
return Scaffold(
appBar: AppBar(
title: Text('Expanded Scrollable'),
),
body: CustomScrollView(
physics: AlwaysScrollableScrollPhysics(),
slivers: [
SliverFillRemaining(
fillOverscroll: true,
child: Column(
children: <Widget>[
Text('Hello ... '),
Divider(
height: 2,
),
Expanded(
child: Container(color: Colors.red,), // replace this Container with your listview
)
],
),
)
],
),
);
Newbie to Flutter. I want to design screen like below. I am using ListTile but it not allowing me to add multiple text. Help would be appreciated.
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: new ListView.builder(
itemCount: _ProductsList.length,
itemBuilder: (BuildContext ctxt, int i) {
final img = _ProductsList[i].image_urls;
return new Card(
child: Column(
children: <Widget>[
ListTile(
leading: ConstrainedBox(
constraints: BoxConstraints(
minWidth: 44,
minHeight: 44,
maxWidth: 64,
maxHeight: 64,
),
child: Image.network('$url$img'),
),
title: Text(_ProductsList[i].title, style: kListTileShopTitleText,),
onTap: () {
},
),
],
)
);
})
)
);
}
You can acheive this by using richtext but the code will become messy, listtile provides limited feature, instead of list you should use columns and rows like this:
Column(
Children:[
Row(
Children:[
Card/Container(
//your rectangle image wether using container or card
),
Column(
Children:[
Text(""$itemName),
Row(
Children:[
Icon(
//Rating Icon
),
Text(''$averagerating),
Text(''$totalratings),
]
),
Row(
Children:[
Icon(
//Currency Icon
),
Text(''$Discountedprice),
Text(''$Originalprice),
]
),
]
),]),]),
Use the properties of listile, title, and subtitle. Inside of this you can use any widget as a column so you can put more text. Another solultion is to construct your own widget to replace the listile.
Am fairly new to flutter please help how do i fill the children widget after performing network call?
class _BusResultScreenState extends State {
#override
Widget build(BuildContext context) {
helper myHelper = new helper();
myHelper.fetch(apiArg).then ((response) {
if(response['type']=="success") {
// Sample data from server in response.feedback
[
{"name":"bus1","id":"54"},
{"name":"bus2","id":"55"},
{"name":"bus3","id":"56"}
]
while(){
SharedBusCard(arg1,arg2,...) // This has to go into children Widget
}
}
});
return Scaffold(
backgroundColor: Colors.grey.shade200,
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(12),
child: Column(
children: <Widget>[
Material(
elevation: 4,
child: Container(
... code
.... code
SizedBox(height: 15),
Expanded(
child: Container(
width: double.infinity,
height: double.infinity,
child: ListView(
children: <Widget>[
//I wanted to display results here
SharedBusCard(arg1,arg2,...) // this is the card to be looped
],
),
),
)
],
),
),
),
);
}
}
Thanks for your help.
Use FutureBuilder widget for it. It is good for network calls and you can handle errors, show a loading screen in it. Here is documentation and a great video of using it.
I'm beginner at Flutter.
Currently in my app, I'm developing a "report screen" which includes complex widget like Timeseries chart.
What I'm noticed is that when I go to that "report screen", it takes about 3 seconds to appear this screen on the app. When I experiment by removing Timeseries chart widget from the screen, the app is responsive as best and instantly show the screen.
Therefore I would like to move this Timeseries Chart Widget building process to asynchronous and show the loading indicator while building the widget. By this way, I think the screen can appears instantly because no heavy widget building process at the start.
I've already tried the following way but no success.
// Chart Widget Building Method
Future<Widget> _buildChart(BuildContext context) async {
return Card(
elevation: 3.0,
margin: EdgeInsets.symmetric(vertical: 10.0, horizontal: 4.0),
child: Container(
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 8.0),
child: Row(
children: <Widget>[
_buildPeriodicButton(context, '1D'),
_buildPeriodicButton(context, '1W'),
_buildPeriodicButton(context, '1M'),
_buildPeriodicButton(context, '3M'),
],
),
),
Padding(
padding:
const EdgeInsets.symmetric(vertical: 16.0, horizontal: 12.0),
child: ReportChart(data: _chartData),
),
],
),
),
);
}
// Screen build Method
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: _buildAppBar(context),
backgroundColor: CustomColors.GreyBackground,
body: SingleChildScrollView(
child: Container(
padding: EdgeInsets.all(10.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
_buildFilters(context),
FutureBuilder(
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.none &&
snapshot.hasData == null) {
return Container(
child: Center(
child: Text("Loading"),
),
);
} else {
return snapshot.data;
}
},
future: _buildChart(context),
),
],
),
),
),
);
}
Thanks in advance for suggestions and solutions.
FutureBuilder(
builder: (context, snapshot) {
if (snapshot.hasData) {
return snapshot.data;
}
return Container(
child: Center(
child: Text("Loading"),
),
);
},
future: _buildChart(context),
),
I have used the fluttertoast: ^8.0.8 package as shown below. You can set the toast length to a longer duration if needed. FutureBuilder is not useful in the case, where your widget themselves take a long time render. FutureBuilder is useful while fetching the data required for your widgets.
#override
Widget build(BuildContext context) {
Fluttertoast.showToast(
msg: 'Loading...'
);
//Code for your complex widget here
}