I want to preface this question by saying that I am very new to flutter/dart.
Essentially, I have a list containing a bunch of strings. I want to list them in the main (and only) view. I have this code:
ListView(
shrinkWrap: true,
padding: const EdgeInsets.all(24.0),
children: _availableTraits.map((item) => new Text(item, style: TextStyle(fontSize: 24.0))).toList()
)
I guess I am fortunate that _availableTraits is a relatively large list so that I discovered this problem. The list goes beyond the bottom of the page and a sort of warning/caution tape is put up at the bottom of the screen by flutter along with the error message: BOTTOM OVERFLOWED BY 93 PIXELS.
So how can I force flutter to just use a scroll bar?
Edit:
Figured I should probably share a picture of the problem.
Edit 2:
The above ListView is wrapped in a column element. The column element is wrapped in a scaffold.
In order to fix your issue you need to expand your shrinked ListView, like this:
Column(
children: <Widget>[
Expanded(
child: ListView(
shrinkWrap: true,
...
Related
I have an image of a resistor with transparent regions where the color code goes. Behind the resistor I'm trying to position the colors so that I can generate any resistor combination.
I managed to get it right on my phone in portrait mode and it looks almost right in the browser when I resize it to a specific size:
However, in landscape mode or in a larger browser window, the colors no longer align with the image:
I am using a stack for putting items on top of each other in Z-direction
Stack(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: _rings,
),
Image(image: AssetImage('assets/resistor.png')),
]
),
and I use an ugly combination of spacers and my own Ring implementation, which is basically a constrained box
_rings = [
Spacer(flex: 10),
Ring( _ringColors[0]),
Spacer(flex: 1),
Ring( _ringColors[1]),
Spacer(flex: 1),
Ring( _ringColors[2]),
Spacer(flex: 14),
];
Ring:
return ConstrainedBox(
constraints: BoxConstraints(
minWidth: 40.0,
minHeight: 100.0,
),
child: Material(
color: _ringColors[widget.colorIndex.value],
));
}
I don't see how this will be responsive for all orientations and sizes.
How would one typically approach this in Flutter?
I followed the advise of #pskink and created one image per ring in the same size as the original one.
I then stack 4 images on top of each other, each with a different Color, using BlendMode to exchange the non-transparent color by a given one.
Stack(
children: <Widget>[
Image.asset("assets/ring1.png", color: Colors.yellow,),
Image.asset("assets/ring2.png", color: Colors.purple,),
Image.asset("assets/ring3.png", color: Colors.brown,),
Image.asset("assets/resistor.png",),
]
),
For real resistor values based on an input value, the color needs to be dynamic, of course.
The approach suggested by #Christopher Moore didn't work out for me, because I want compatibility for web. It may still be useful for someone. It uses the image package, for which I need I/O to get a byte[] which is then decoded as an image.
Reference in pubspec.yaml:
dev_dependencies:
image: ^3.0.2
Parts of the code (untested since I could not use await either, sorry):
import 'package:image/image.dart' as png;
import 'dart:io';
...
var file = File('assets/colors.png'); // direct I/O not allowed in web
var bytes = await file.readAsBytes();
var image = png.decodeImage(bytes);
I want to make this image or widget at the end transparent with a LinearGradient gradient.
Honestly I'm not entirely sure how to do this, because I only know how to make the entire image/widget transparent with the Opacity widget.
Can someone help me here with an general idea, how to do this?#
[]
[]
In the end the answer was fairly simple because there is already a widget available for this task. the widget name is ShadowMask.
Here is the part of the code which enabled me to get the above effect.
return ShaderMask(
shaderCallback: (rect) => LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [Colors.white, Colors.white.withOpacity(.2), Colors.transparent],
stops: [.6,.8, .9],
).createShader(rect),
child: ...
Depending on which degree you want to achieve this effect you can change the color or stops for it.
The flutter DropDownButton will automatically shrink to size of the largest label of the choices, like so :-
But a DropDownButtonFormField changes this behavior, and instead occupies the whole space available to it.
So, how do I make the DropDownButtonFormField mimic the space occupation behavior of a DropDownButton ?
I had a similar problem trying to make DropDownButtonFormField fit a minimal possible space in a Row. Unfortunately, InputDecorator widgets that are used inside the DropDownButtonFormField don't support children that can set their own width (such as DropDownButton) and require maxWidth to be capped by parent.
I managed to make it work using IntrinsicWidth widget (warning: according to the docs, this widget is relatively expensive because it adds a speculative layout pass before the final layout phase):
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
IntrinsicWidth(
child: DropdownButtonFormField<String>(
value: "1",
items: [
DropdownMenuItem(
value: "1",
child: Text("1"),
),
DropdownMenuItem(
value: "2",
child: Text("2"),
),
],
onChanged: _onCurrencyChanged,
)),
],
)
IntrinsicWidth sets child's width to the child's maximum intrinsic width, satisfying InputDecorator's need to have a fixed width.
I have been wondering why one should use [Expanded] / [Flexible] flex over [Align] alignment? You can precisely align your widget with [Align] and even potentially avoid [Padding].
Let's see it from another view, is using the flex of [Expanded] / [Flexible] more efficient and faster than [Align]?
There is no comparison between Expanded/Flex and Align. Take a look at the following snippet.
Column(
children: [
Container(color: Colors.blue, height: 200),
Align(child: Container(color: Colors.green)), // doesn't show anything
Expanded(child: Container(color: Colors.orange)), // shows up in the remaining space
],
);
Having Align as the parent of Container won't show anything on screen but if you use Expanded/Flex it will take up the left space.
Not sure what you a referring to. Expanded is for (more or less) "selecting" which widget inside a Row/Column should fill the remaining space. While Align just positions the child inside itself at the given alignment.
I am trying to add a dice feature to my Flutter application. In Java, I would generate a random number out of 20, and then pull up the corresponding image based on the result. For example a roll of 14 would pull up an image of dice_image_14.jpg.
I am not sure how to do this in Flutter due to the way build methods work.
The only way I can think to do this is a massive ugly pile of nested conditional statements:
#override
build(Buildcontext context) {
Stack (
diceRoll == 1 ?
Container(
BoxDecoration(
image: ('lib/images/dice_image_1.jpg),
),
) : diecroll == 2?
Container(
BoxDecoration(
image: ('lib/images/dice_image_2.jpg),
),
) : diecroll == 3? // etc etc etc. 20 times!!
);
}
Is there a more realistic solution for loading specific images into a container on demand post runtime?
Just interpolate your diceRoll with your asset path:
BoxDecoration(
image: ('lib/images/dice_image_$diceRoll.jpg)
)
From Dart docs
$variableName (or ${expression})
String interpolation: including a variable or expression’s
string equivalent inside of a string literal.