AnimatedCrossFade with ListView got unbounded height error - dart

here is the code. what I want is showing progress when requesting result, and display the result as a list when requesting completed.
I choose the AnimatedCrossFade cause it had convinient transition animation;
Widget SearchResultPage() {
return AnimatedCrossFade(
firstChild: Center(
child: CircularProgressIndicator(),
),
secondChild: ListView.builder(
itemCount: _searchResult.length,
itemBuilder: (BuildContext context, int index) {
return SearchListItem(_searchResult[index]);
}),
crossFadeState: _searchResult.isEmpty
? CrossFadeState.showFirst
: CrossFadeState.showSecond,
duration: Duration(milliseconds: 500));
}
Widget SearchListItem(BookFuzzySearchDetail detail) {
return Container(
decoration:
BoxDecoration(border: Border(bottom: BorderSide(color: Colors.grey))),
child: ListTile(
contentPadding: EdgeInsets.symmetric(vertical: 5.0, horizontal: 4.0),
leading: Image.network(
detail.cover,
width: 50.0,
height: 50.0,
),
title: Text(
detail.title,
),
),
);
}
and I got the error:
I/flutter ( 6281): ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
I/flutter ( 6281): The following assertion was thrown during performResize():
I/flutter ( 6281): Vertical viewport was given unbounded height.
I/flutter ( 6281): Viewports expand in the scrolling direction to fill their container.In this case, a vertical
I/flutter ( 6281): viewport was given an unlimited amount of vertical space in which to expand. This situation
I/flutter ( 6281): typically happens when a scrollable widget is nested inside another scrollable widget.
I/flutter ( 6281): If this widget is always nested in a scrollable widget there is no need to use a viewport because
I/flutter ( 6281): there will always be enough vertical space for the children. In this case, consider using a Column
I/flutter ( 6281): instead. Otherwise, consider using the "shrinkWrap" property (or a ShrinkWrappingViewport) to size
I/flutter ( 6281): the height of the viewport to the sum of the heights of its children.
New to flutter and stucked here for a few days, appreciate for any advice please.

Try adding the property shrinkWrap to your ListView.builder
ListView.builder(
shrinkWrap: true,
itemCount: _searchResult.length,
itemBuilder: (BuildContext context, int index) {
return SearchListItem(_searchResult[index]);
}),

AnimatedCrossFade not only animates the opacity change of both widgets, but also the size transition; since the size of the list is unknown at build time (I mean build lifecycle method, not building the project) without shrinkWrap: true it throws an exception.
As #nickolay-savchenko pointed out in the comment to the accepted answer, shrinkWrap: true may cause significant performance issues and is definitely an unnecessary overkill for this case.
I'd advise using AnimatedSwitcher instead of AnimatedCrossFade, which will only do the opacity change (default behaviour).
Arguably, you don't need to animate the size change between a large possibly screen-overflowing list and "empty search results" widget.
Here is how I used it in one of my projects to animate transition between the list and "loading" widget:
AnimatedSwitcher(
duration: const Duration(milliseconds: 500),
child: items.isEmpty
? const LoadingWidget()
: ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) => ...
),
),

Related

Flutter: No Directionality widget found

I am getting below exception while running flutter code in android studio.
I/flutter ( 5360): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY
╞═══════════════════════════════════════════════════════════ I/flutter
( 5360): The following assertion was thrown building Text("xyz"): I/flutter ( 5360): No Directionality widget found. I/flutter
( 5360): RichText widgets require a Directionality widget ancestor.
I/flutter ( 5360): The specific widget that could not find a
Directionality ancestor was: I/flutter ( 5360): RichText(softWrap:
wrapping at box width, maxLines: unlimited, text: "xyz")
I/flutter ( 5360): The ownership chain for the affected widget is:
I/flutter ( 5360): RichText ← Text ← Center ← Container ← [root]
I/flutter ( 5360): Typically, the Directionality widget is introduced
by the MaterialApp or WidgetsApp widget at the I/flutter ( 5360): top
of your application widget tree. It determines the ambient reading
direction and is used, for I/flutter ( 5360): example, to determine
how to lay out text, how to interpret "start" and "end" values, and to
resolve I/flutter ( 5360): EdgeInsetsDirectional,
AlignmentDirectional, and other *Directional objects.
Code snippet:
import 'package:flutter/material.dart';
void main() {
runApp(
Container(child: Center(child: Text("xyz"))),
);
}
I am not sure why this exception says
I/flutter ( 5360): Typically, the Directionality widget is introduced by the MaterialApp or WidgetsApp widget at the ...
Because in flutter everything is a widget, so any widget should work for us.
If you are using a material widget component, like Scaffold, Material, you don't need to specify textDirection in your Text widget because Directionality is implicitly provided in these cases. So, a good solution would be to use:
Scaffold(body: Text("xyz"))
But if you don't use it, you will have to
Text(
'xyz',
textDirection: TextDirection.ltr,
)
If you are using Directionality constructor your problem will resolve
Widget build(BuildContext context) {
return Directionality(
textDirection: TextDirection.ltr,
child: Container(
color: myColor,
child: Center(
child: RaisedButton(
onPressed: () {
print('You pressed me');
changeColor();
},
child: Text('Click', textDirection: TextDirection.ltr)
),
),
),
);
}
Text widget needs to know whether it should display text left to right or right to left. There is no default. This information can be provided in 2 ways:
by nesting it in Directionality widget (as mentioned in the error message, typically MaterialApp or WidgetsApp)
explicitly, as an argument to the constructor:
Text(
'Hello World',
textDirection: TextDirection.ltr,
)
Second approach clearly is unmanageable in the long run.
late but I hope it can help.
I don't use any predefined root widget too. So I wrapped my App in Directionality widget in main function and flutter stopped complaining:
my code:
void main() {
runApp(
new Directionality(textDirection: TextDirection.ltr, child: MyApp())
);
}
A little more elaboration on what's happening internally.
When a Text widget is used without the specified style, it tries to inherit the style from the parents automatically. Here's the first few lines of the build method of Text Widget.
#override
Widget build(BuildContext context) {
final DefaultTextStyle defaultTextStyle = DefaultTextStyle.of(context);
TextStyle? effectiveTextStyle = style;
if (style == null || style!.inherit)
effectiveTextStyle = defaultTextStyle.style.merge(style);
if (MediaQuery.boldTextOverride(context))
effectiveTextStyle = effectiveTextStyle!.merge(const TextStyle(fontWeight: FontWeight.bold));
Look at the line - final DefaultTextStyle defaultTextStyle = DefaultTextStyle.of(context);
Now if a material widget is used in the widget tree before the Text Widget appears, they would have already set the default text style which Text widget automatically inherits from the Build Context. If none of the material widgets were used before Text, then we would need to specify the text style explicitly.

Placing a widget in a column gives RenderIndexedStack object was given an infinite size during layout

I am placing the following in column like this
Widget _getDropDownCombo()
{
Widget combo = new DropdownButton(
value: _currentItem,
items:_dropDownMenuItems,
onChanged: _changedDropDownItem
);
return Flexible(child:combo);
}
and _getDropDownCombo is being called from a row somewhere like this
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
_getDropDownCombo(),
getIcon(),
],)
This gives me the error
flutter: ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
flutter: The following assertion was thrown during performLayout():
flutter: RenderIndexedStack object was given an infinite size during layout.
flutter: This probably means that it is a render object that tries to be as big as possible, but it was put
flutter: inside another render object that allows its children to pick their own size.
flutter: The nearest ancestor providing an unbounded width constraint is:
flutter: RenderFlex#dfcbf relayoutBoundary=up17 NEEDS-LAYOUT NEEDS-PAINT
Why am I getting this error with DropDownButton ? Any suggestions ?
Their might be problem because of the items inside your DropdownButton.
I've tried using this in items and it works just fine:
items: ['Foo', 'Bar'].map((String value) {
return new DropdownMenuItem(
value: value,
child: new Text(value),
);
}).toList(),

How to calculate the distance of pointer in VerticalDragDown Gesture in Flutter?

In my app, when the user drags down, I want to execute a method. The problem is even when the user only taps on the screen, the VerticalDragDown event is fired. My guess is the tap event fired a drag event with a small distance. So I want to calculate the distance that users have dragged, if it's larger than a certain amount, then call the method.
Surprisingly there was no such info in the DragStartDetails, DragEndDetails, DragDownDetails classes. The details.globalPosition.distance property seems like the distance from the touched point to the screen edge, not dragged distance because I have tried to drag with different length but the result is almost the same. And only onVerticalDragDown callback was called.
Here is my code:
Widget _buildScanGuide() {
return GestureDetector(
onVerticalDragStart: (details) {
print('DragStart: $details');
},
onVerticalDragDown: (details) {
print('DragDown: $details');
},
onVerticalDragEnd: (details) {
print('DragEnd: $details');
},
onVerticalDragUpdate: (details) {
print('DragUpdate: $details');
},
child: ListView(
padding: EdgeInsets.only(top: 50.0),
children: <Widget>[
Center(
child: Text('No device founded!',
style: TextStyle(fontSize: 24.0, color: kTextColor))),
Padding(
padding: const EdgeInsets.symmetric(vertical: 40.0),
child: Icon(
Icons.arrow_downward,
size: 96.0,
color: kTextColor,
),
),
Center(
child: Text('Drag down to scan for devices.',
style: TextStyle(fontSize: 24.0, color: kTextColor))),
],
),
);
}
And in debug console:
I/flutter (20427): DragDown: DragDownDetails(Offset(268.0, 192.5))
I/flutter (20427): DragDown: DragDownDetails(Offset(288.4, 173.2))
I/flutter (20427): DragDown: DragDownDetails(Offset(92.7, 235.4))
I/flutter (20427): DragDown: DragDownDetails(Offset(264.5, 168.1))
I/flutter (20427): DragDown: DragDownDetails(Offset(264.5, 173.2))
I/flutter (20427): DragDown: DragDownDetails(Offset(280.3, 176.6))
I/flutter (20427): DragDown: DragDownDetails(Offset(267.6, 178.8))
I/flutter (20427): DragDown: DragDownDetails(Offset(63.9, 250.6))
I/flutter (20427): DragDown: DragDownDetails(Offset(277.8, 191.4))
I/flutter (20427): DragDown: DragDownDetails(Offset(279.2, 206.9))
I'm using flutter v0.5.7 dev channel.
I had to use Listener which is not recommended but it solves the problem
return Listener(
onPointerDown: (details) {
_pointerDownPosition = details.position;
},
onPointerUp: (details) {
if (details.position.dy - _pointerDownPosition.dy > 50.0) {
_dragHandler(pf10Bloc);
}
},
child: //...
More details could be found in docs https://flutter.io/gestures/
The onVerticalDragDown callback is called when
A pointer has contacted the screen and might begin to move vertically.
If you want to detect an vertical drag, I suggest you to handle the onVerticalDragUpdate callback. The DragUpdateDetails argument contains a primaryDelta property which is:
The amount the pointer has moved along the primary axis since the
previous update.
If only onVerticalDragDown is called, I think it's because of the ListView which captures the vertical drag event to scroll.
In your example you should use a Column widget if you don't need the scrolling feature, otherwise you will have to listen to the scroll position updates.

how to distribute space between multiple items

I am trying to add an image that covers the top 20% of the screen and the other 80% should be a grid of cards. The image needs to be in the body and not on the Appbar. I made the grid of cards, and then I tried to put the image and the grid in a column. The implementation is the following.
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
primary: true,
appBar: AppBar(
elevation: 4.0,
backgroundColor: Color(0xfff8f8f8),
title: Center(child: titleLogo,),
),
//------------ PROBLEM BELOW ----------------
body: new Column(
children: <Widget>[
titleLogo, //Image object
TheGridView().build() //Returns a GridView object
],
),
),
);
}
I am getting the following error
I/flutter (21751): The following assertion was thrown during performResize():
I/flutter (21751): Vertical viewport was given unbounded height.
I/flutter (21751): Viewports expand in the scrolling direction to fill their container.In this case, a vertical
I/flutter (21751): viewport was given an unlimited amount of vertical space in which to expand. This situation
I/flutter (21751): typically happens when a scrollable widget is nested inside another scrollable widget.
I/flutter (21751): If this widget is always nested in a scrollable widget there is no need to use a viewport because
I/flutter (21751): there will always be enough vertical space for the children. In this case, consider using a Column
I/flutter (21751): instead. Otherwise, consider using the "shrinkWrap" property (or a ShrinkWrappingViewport) to size
I/flutter (21751): the height of the viewport to the sum of the heights of its children.
Any suggestion is highly appreciated. Thank you in advance.
for distributing space between multiple items you should use the Expanded widget like this:
return new Column(
children: <Widget>[
new Expanded(
flex: 2,
child: new Container(
color: Colors.red,
),
),
new Expanded(
flex: 8,
child: new Container(//use your Gridview instead
color: Colors.green,
)
)
],
);

How to pass multiple widgets as children in Flutter? [duplicate]

This question already has answers here:
Can't add a ListView in Flutter
(3 answers)
Closed 4 years ago.
I recently started learning Flutter and have been going through the documentation. I am working on this small app, where the screen has a button on the top of the screen and a list below it.
Whenever I pass RaisedButton with a ListView widget into another ListView or Column Widget, its throwing error.
I/flutter ( 4734): ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
I/flutter ( 4734): The following assertion was thrown during performResize():
I/flutter ( 4734): Vertical viewport was given unbounded height.
I/flutter ( 4734): Viewports expand in the scrolling direction to fill their container.
////MORE LINES OF ERRORS/////
Here's the code I have been working on:
import 'package:flutter/material.dart';
void main() {
runApp(ListDemo(
items: new List<ListItem>.generate(
100,
(i) => i % 6 == 0
? new HeadingItem("Heading $i")
: new MessageItem("Sender $i", "Message body $i"),
),
));
}
// The base class for the different types of items the List can contain
abstract class ListItem {}
// A ListItem that contains data to display a heading
class HeadingItem implements ListItem {
final String heading;
HeadingItem(this.heading);
}
// A ListItem that contains data to display a message
class MessageItem implements ListItem {
final String sender;
final String body;
MessageItem(this.sender, this.body);
}
class ListDemo extends StatelessWidget {
final List<ListItem> items;
ListDemo({Key key, #required this.items}) : super(key: key);
#override
Widget build(BuildContext context) {
final ListView listView = ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
final item = items[index];
if (item is HeadingItem) {
return new ListTile(
title: new Text(
item.heading,
style: Theme.of(context).textTheme.headline,
),
);
} else if (item is MessageItem) {
return new ListTile(
title: new Text(item.sender),
subtitle: new Text(item.body),
);
}
},
);
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Lists'),
),
body: ListView( //Tried using ListView, Column.. None of them help solving the issue
children: <Widget>[
RaisedButton(
onPressed: null,
child: Text('Sample Button'),
),
Container(
child: listView,
)
]
)
)
);
}
}
Please help me solve this issue of letting know, how to pass multiple children, and also please make understand the concept as well.
EDITED
One of the possible solutions suggested wrapping ListView with Expanded class. When I did it threw me an error as below:
I/flutter ( 4190): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter ( 4190): The following assertion was thrown building NotificationListener<KeepAliveNotification>:
I/flutter ( 4190): Incorrect use of ParentDataWidget.
I/flutter ( 4190): Expanded widgets must be placed inside Flex widgets.
I/flutter ( 4190): Expanded(no depth, flex: 1, dirty) has no Flex ancestor at all.
So I wrapped the entire Widget code in Flex as below:
Flex(
direction: Axis.vertical,
children: <Widget>[
ListView(
children: <Widget>[
RaisedButton(
onPressed: null,
child: Text('Snackbar'),
),
Expanded(
child: listView
)
],
)
],
)
but then it threw me this error:
I/flutter ( 4388): ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
I/flutter ( 4388): The following assertion was thrown during performResize():
I/flutter ( 4388): Vertical viewport was given unbounded height.
I/flutter ( 4388): Viewports expand in the scrolling direction to fill their container.In this case, a vertical
I/flutter ( 4388): viewport was given an unlimited amount of vertical space in which to expand. This situation
I/flutter ( 4388): typically happens when a scrollable widget is nested inside another scrollable widget.
This question is already answered here
Can't add a ListView in Flutter
If you use a scrollable view(Listview) inside another scrollable view, the inner scrollable view doesn't know how much height it should occupy. You can tell the inner scrollable view about how much height it should take using an Expanded widget.

Resources