flutter
flutter copied to clipboard
Antialiasing behaviour when same-colour
Latest status update: https://github.com/flutter/flutter/issues/14288#issuecomment-1890250258; some work around suggestions: https://github.com/flutter/flutter/issues/14288#issuecomment-1026332976
Steps to Reproduce
Following source code:
import 'package:flutter/material.dart';
const Color color = const Color.fromARGB(255, 100, 100, 100);
void main() =>
runApp(
new Container(
color: const Color.fromARGB(255, 0, 0, 0),
child: new Row(
mainAxisAlignment: MainAxisAlignment.end,
textDirection: TextDirection.ltr,
children: [
new Expanded(
child: new Container(
color: color,
),
),
new Expanded(
child: new Container(
color: color,
),
),
new Expanded(
child: new Container(
color: color,
),
),
new Expanded(
child: new Container(
color: color,
),
),
new Expanded(
child: new Container(
color: color,
),
),
new Expanded(
child: new Container(
color: color,
),
),
new Expanded(
child: new Container(
color: color,
),
),
],
),
),
);
produces following result:

Looks like background of the container is popping out and we see vertical lines. That should not be the case as all children of the row are Expanded and thus should fill the whole area. If we remove one child lines are gone.
Logs
Launching lib/main.dart on Android SDK built for x86 in debug mode...
Initializing gradle...
Resolving dependencies...
Running 'gradlew assembleDebug'...
Built build/app/outputs/apk/app-debug.apk (22.4MB).
I/FlutterActivityDelegate( 8398): onResume setting current activity to this
D/EGL_emulation( 8398): eglMakeCurrent: 0xaad2c640: ver 3 1 (tinfo 0xa057c5b0)
E/eglCodecCommon( 8398): glUtilsParamSize: unknow param 0x000082da
E/eglCodecCommon( 8398): glUtilsParamSize: unknow param 0x000082da
E/eglCodecCommon( 8398): glUtilsParamSize: unknow param 0x00008cdf
E/eglCodecCommon( 8398): glUtilsParamSize: unknow param 0x00008cdf
E/eglCodecCommon( 8398): glUtilsParamSize: unknow param 0x00008824
E/eglCodecCommon( 8398): glUtilsParamSize: unknow param 0x00008824
D/ ( 8398): HostConnection::get() New Host Connection established 0xa31a3640, tid 8416
D/EGL_emulation( 8398): eglMakeCurrent: 0xaad2c640: ver 3 1 (tinfo 0xa3183790)
D/EGL_emulation( 8398): eglMakeCurrent: 0xaad2c760: ver 3 1 (tinfo 0xa057cc10)
Syncing files to device Android SDK built for x86...
Flutter Doctor
[✓] Flutter (on Linux, locale en_US.UTF-8, channel master)
• Flutter version unknown at <path_to_flutter>
• Framework revision 5ae770345a (3 days ago), 2018-01-23 13:46:14 -0800
• Engine revision 171d032f86
• Tools Dart version 2.0.0-dev.16.0
• Engine Dart version 2.0.0-edge.93d8c9fe2a2c22dc95ec85866af108cfab71ad06
[✓] Android toolchain - develop for Android devices (Android SDK 27.0.3)
• Android SDK at <path_to_android>
• Android NDK location not configured (optional; useful for native profiling support)
• Platform android-27, build-tools 27.0.3
• ANDROID_HOME = <path_to_android>
• Java binary at: <path_to_android-studio>/jre/bin/java
• Java version OpenJDK Runtime Environment (build 1.8.0_152-release-915-b01)
[✓] Android Studio (version 3.0)
• Android Studio at <path_to_android-studio>
• Java version OpenJDK Runtime Environment (build 1.8.0_152-release-915-b01)
[✓] Connected devices
• Android SDK built for x86 • emulator-5554 • android-x86 • Android 8.1.0 (API 27) (emulator)
Another example (I believe it is somehow related: )
import 'package:flutter/material.dart';
const Color grey = const Color.fromARGB(255, 100, 100, 100);
const Color black = const Color.fromARGB(255, 0, 0, 0);
void main() =>
runApp(
new Container(
color: grey,
child: new Center(
child: new Container(
width: 151.0,
height: 151.0,
color: black,
child: new Container(
color: grey,
),
),
),
),
);

We should not see border here. If widht/height are changed to 150.0, square is gone.
This is normal behaviour. What's happening is that the boxes are not quite aligned with pixel boundaries, so there's some anti-aliasing happening on the boundaries, which involves transparency, which means that for those pixels the two grays are overlapping and looking darker.
As a general rule when doing anti-aliasing you want to avoid putting identically-coloured boxes adjacent or over each other unless you can guarantee physical pixel alignment.
Alternatively, you can use saveLayer
(or RepaintBoundary
) to cause a bunch of paint operations to get merged into one and composited as one. Not sure that that would help in these cases specifically but it is a tool that can be useful in this kind of situation.
This is not boxes overlapping, but rather spare space between boxes, so color of background is popping up. I was changing background to different color and this color was popping out.
Root cause is that boxes can not be aligned with physical pixels. I would not call it "normal", I would rather call it "expected". On android similar (semantically) case is handled properly:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:background="#000000"
tools:context="com.radzish.android_lines_bug.MainActivity">
<FrameLayout
android:layout_width="0dp"
android:layout_weight="1"
android:background="#646464"
android:layout_height="match_parent"/>
<FrameLayout
android:layout_width="0dp"
android:layout_weight="1"
android:background="#646464"
android:layout_height="match_parent"/>
<FrameLayout
android:layout_width="0dp"
android:layout_weight="1"
android:background="#646464"
android:layout_height="match_parent"/>
<FrameLayout
android:layout_width="0dp"
android:layout_weight="1"
android:background="#646464"
android:layout_height="match_parent"/>
<FrameLayout
android:layout_width="0dp"
android:layout_weight="1"
android:background="#646464"
android:layout_height="match_parent"/>
<FrameLayout
android:layout_width="0dp"
android:layout_weight="1"
android:background="#646464"
android:layout_height="match_parent"/>
<FrameLayout
android:layout_width="0dp"
android:layout_weight="1"
android:background="#646464"
android:layout_height="match_parent"/>
</LinearLayout>
So I think flutter should improve in this case. The only workaround I found for me at the moment is sizing children manually like this:
int CHILDREN_COUNT = 7;
List<Widget> children = new List(CHILDREN_COUNT);
MediaQueryData mediaQueryData = MediaQuery.of(context);
int physicalWidth = (mediaQueryData.size.width * mediaQueryData.devicePixelRatio).floor();
for (int i = 0, pixelsLeft = physicalWidth; i < CHILDREN_COUNT; i++) {
int columnWidth = (pixelsLeft / (CHILDREN_COUNT - i)).floor();
children[i] = new Container(
width: columnWidth / mediaQueryData.devicePixelRatio,
color: color,
);
pixelsLeft -= columnWidth;
}
There are also
- #15035
- #17084
- #13675
- #25429
@radzish what is Android doing to avoid the problem?
These comments have suggestions for things to put in documentation: https://github.com/flutter/flutter/issues/14288#issuecomment-361375791 https://github.com/flutter/flutter/issues/17084#issuecomment-385718108 https://github.com/flutter/flutter/issues/15035#issuecomment-370028740
Any updates here? Because this is very annoying((
Or any examples how to use saveLayer
or RepaintBoundary
?
Any updates here?
Any updates here?
I have the problem too :(
Hi @blackraven96 the easiest workaround to this problem is to avoid using the same background color on adjacent elements, but use a background color for the whole list (or multi-child widget).
import 'package:flutter/material.dart';
void main() =>
runApp(
Container(
color: Colors.white,
child: Column(
children: <Widget>[
Container(
child: Text("Item 1"),
),
Container(
child: Text("Item 2"),
),
],
),
),
);
I hope this problem can be solved soon
I'm new to Flutter and I faced really quickly with this issue. I need to render a NxN grid of squares and the gaps between cells is quite annoying. Until there is a fix or a better workaround I'm using this delegate for CustomSingleChildLayout
that removes the minimum number of pixels to avoid the gaps.
class GridFix extends SingleChildLayoutDelegate {
GridFix(this.size, this.mediaQueryData);
final int size;
final MediaQueryData mediaQueryData;
@override
BoxConstraints getConstraintsForChild(BoxConstraints constraints) {
var dpr = mediaQueryData.devicePixelRatio;
var width = (((constraints.maxWidth * dpr) ~/ size) * size) / dpr;
var height = (((constraints.maxHeight * dpr) ~/ size) * size) / dpr;
return BoxConstraints.tightFor(width: width, height: height);
}
@override
Offset getPositionForChild(Size size, Size childSize) {
return Offset(
((size.width - childSize.width) / 2).floorToDouble(),
((size.height - childSize.height) / 2).floorToDouble(),
);
}
@override
bool shouldRelayout(GridFix oldDelegate) {
return oldDelegate.size != size;
}
}
Then within the layout I use it like this:
return AspectRatio(
aspectRatio: 1,
child: CustomSingleChildLayout(
delegate: GridFix(size, MediaQuery.of(context)),
child: /* insert content here */
),
);
Of course this solution is specific for this case of a square grid and it works because I can spare some pixels around without affecting the layout too much. Again, I'm new to Flutter so I'm open to improvements or suggestions.
At the end I think Flutter layouts could always (or optionally) round the calculated size and offsets to the nearest physical pixel to to avoid this issue.
Please also check some workaround discussions in https://github.com/flutter/flutter/issues/25009
testing the code above the issue still occurs with the latest master
screenshot
doctor
[✓] Flutter (Channel master, 1.21.0-6.0.pre.38, on Mac OS X 10.15.5 19F101, locale en-GB)
• Flutter version 1.21.0-6.0.pre.38 at /Users/nevercode/development/flutter_master
• Framework revision 8e0eee9008 (7 hours ago), 2020-07-26 23:38:01 -0700
• Engine revision 626244a72c
• Dart version 2.9.0 (build 2.9.0-21.0.dev a3815b6590)
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.2)
• Android SDK at /Users/nevercode/Library/Android/sdk
• Platform android-29, build-tools 29.0.2
• Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS (Xcode 11.5)
• Xcode at /Applications/Xcode.app/Contents/Developer
• Xcode 11.5, Build version 11E608c
• CocoaPods version 1.9.0
[✓] Chrome - develop for the web
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Android Studio (version 4.0)
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin version 46.0.2
• Dart plugin version 193.7361
• Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593)
[✓] VS Code
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension version 3.12.2
[✓] Connected device (3 available)
• macOS (desktop) • macos • darwin-x64 • Mac OS X 10.15.5 19F101
• Web Server (web) • web-server • web-javascript • Flutter Tools
• Chrome (web) • chrome • web-javascript • Google Chrome 84.0.4147.89
• No issues found!
In the meantime, I found a very simple workaround. It has a downside, though: it doesn't work 100% time of scrolling... :/
Just add this to each tile Container in the GridView/SliverGrid:
decoration: BoxDecoration(
color: Colors.black,
borderRadius:
BorderRadius.only(topRight: Radius.circular(1)),
),
Before (without the rounded corner)

After

Never mind my previous workaround since it doesn't work 100%.
@dhawalmehta22 found a fix (see original post: https://github.com/flutter/flutter/issues/25009) that works most of the time, although this doesn't work at all time, either :(
Just wrap the problematic container with another container and add this to the parenting container:
decoration: BoxDecoration(
color: Colors.black, //the color of the main container
border: Border.all(
//apply border to only that side where the line is appearing i.e. top | bottom | right | left.
width: 2.0, //depends on the width of the unintended line
color: Colors.black,
),
),
Is there an official solution to this problem ?
Let me add that this is not a problem of same color. I get the same result when trying to align multiple Positioned in a stack with different colors the moment the tile size isn't a full pixelsize you get this here:
Altough the y values of top+hight is the same as the next top value at some of these bounderies you have a gap where the black backgound is shining though.
this is the code:
class CheckerBoard extends StatelessWidget {
const CheckerBoard({
Key key,
@required this.tileSize,
}) : super(key: key);
final double tileSize;
@override
Widget build(BuildContext context) {
return Stack(
children: [
for (var x = 0; x < 20; x++)
for (var y = 0; y < 20; y++)
Positioned(
top: y * tileSize,
left: x * tileSize,
width: tileSize,
height: tileSize,
child: ColoredTile(
indexX: x,
indexY: y,
top: y * tileSize,
height: tileSize,
),
)
],
);
}
}
class ColoredTile extends StatelessWidget {
const ColoredTile({
Key key,
@required this.indexX,
@required this.indexY,
this.top,
this.height,
}) : super(key: key);
final int indexX;
final int indexY;
final double top;
final double height;
@override
Widget build(BuildContext context) {
Color color;
if (indexX.isEven && indexY.isEven) {
color = Colors.blue;
}
if (indexX.isEven && indexY.isOdd) {
color = Colors.red;
}
if (indexX.isOdd && indexY.isEven) {
color = Colors.green;
}
if (indexX.isOdd && indexY.isOdd) {
color = Colors.orange;
}
final m = MediaQuery.of(context);
return Container(
// clipBehavior: Clip.hardEdge,
decoration: BoxDecoration(
color: color,
),
// child: Image.network('https://picsum.photos/256'),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Stack(
children: [
Align(
alignment: Alignment.topCenter,
child: Text(
'Top: ${top * m.devicePixelRatio} \n Height: ${height * m.devicePixelRatio}',
style: TextStyle(color: Colors.black, fontSize: 12),
),
),
Align(
alignment: Alignment.bottomCenter,
child: Text(
'Top+Hight: ${(top + height) * m.devicePixelRatio}',
style: TextStyle(color: Colors.black, fontSize: 12),
),
),
Align(
alignment: Alignment.center,
child: Text(
'$indexX/$indexY',
style: TextStyle(color: Colors.black),
),
),
],
),
),
);
}
}
this happens on Windows and Android. with latests master 1.26.0-2.0.pre.222
Never mind my previous workaround since it doesn't work 100%.
@dhawalmehta22 found a fix (see original post: #25009) that works most of the time, although this doesn't work at all time, either :(
Just wrap the problematic container with another container and add this to the parenting container:
decoration: BoxDecoration( color: Colors.black, //the color of the main container border: Border.all( //apply border to only that side where the line is appearing i.e. top | bottom | right | left. width: 2.0, //depends on the width of the unintended line color: Colors.black, ), ),
Tried my solution in several projects and it worked perfectly.! Well, Working around is the only way till flutter resolves this bug.
@dhawalmehta22 It may have worked on certain resolutions. As I say it does work in some cases; however, I can assure you it doesn't work on all resolutions. If I remember correctly, I was figured it out it by changing the window size of a browser on my macOS—that way you can see when the bug happens.
Reproduces on various platforms - Android, Web Windiws, Desktop Windows
code sample
import 'package:flutter/material.dart';
Future<void> main() async {
runApp(
MaterialApp(
home: Scaffold(
body: CustomPaint(
painter: MyCustomPainter(),
child: SizedBox.expand(),
),
),
),
);
}
class MyCustomPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
int tilesInWidth = 20;
int tilesInHeight = 25;
double tileSize = 16.0;
canvas.translate(1, 1); // if you remove this it looks fine
for (int x = 0; x < tilesInWidth; x++) {
for (int y = 0; y < tilesInHeight; y++) {
canvas.drawRect(
Rect.fromLTWH(x * tileSize, y * tileSize, tileSize, tileSize),
Paint()..color = Colors.blue,
);
}
}
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}
flutter doctor -v
[✓] Flutter (Channel stable, 1.22.5, on macOS 11.1 20C69 darwin-x64, locale en-GB)
• Flutter version 1.22.5 at /Users/tahatesser/Code/flutter_stable
• Framework revision 7891006299 (6 weeks ago), 2020-12-10 11:54:40 -0800
• Engine revision ae90085a84
• Dart version 2.10.4
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
• Android SDK at /Volumes/Extreme/SDK
• Platform android-30, build-tools 30.0.3
• ANDROID_HOME = /Volumes/Extreme/SDK
• Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS (Xcode 12.3)
• Xcode at /Volumes/Extreme/Xcode.app/Contents/Developer
• Xcode 12.3, Build version 12C33
• CocoaPods version 1.10.1
[!] Android Studio (version 4.1)
• Android Studio at /Applications/Android Studio.app/Contents
✗ Flutter plugin not installed; this adds Flutter specific functionality.
✗ Dart plugin not installed; this adds Dart specific functionality.
• Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495)
[✓] VS Code (version 1.52.1)
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension version 3.18.1
[✓] Connected device (1 available)
• Taha’s iPhone (mobile) • 00008020-001059882212002E • ios • iOS 14.3
! Doctor found issues in 1 category.
[✓] Flutter (Channel beta, 1.25.0-8.3.pre, on macOS 11.1 20C69 darwin-x64, locale en-GB)
• Flutter version 1.25.0-8.3.pre at /Users/tahatesser/Code/flutter_beta
• Framework revision 5d36f2e7f5 (3 days ago), 2021-01-14 15:57:49 -0800
• Engine revision 7a8f8ca02c
• Dart version 2.12.0 (build 2.12.0-133.7.beta)
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
• Android SDK at /Volumes/Extreme/SDK
• Platform android-30, build-tools 30.0.3
• ANDROID_HOME = /Volumes/Extreme/SDK
• Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS
• Xcode at /Volumes/Extreme/Xcode.app/Contents/Developer
• Xcode 12.3, Build version 12C33
• CocoaPods version 1.10.1
[✓] Chrome - develop for the web
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Android Studio (version 4.1)
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495)
[✓] VS Code (version 1.52.1)
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension version 3.18.1
[✓] Connected device (2 available)
• Taha’s iPhone (mobile) • 00008020-001059882212002E • ios • iOS 14.3
• Chrome (web) • chrome • web-javascript • Google Chrome 87.0.4280.141
• No issues found!
[✓] Flutter (Channel dev, 1.26.0-8.0.pre, on macOS 11.1 20C69 darwin-x64, locale en-GB)
• Flutter version 1.26.0-8.0.pre at /Users/tahatesser/Code/flutter_dev
• Framework revision b9d06fffb2 (10 days ago), 2021-01-07 18:36:48 -0800
• Engine revision 42a8d4c681
• Dart version 2.12.0 (build 2.12.0-179.0.dev)
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
• Android SDK at /Volumes/Extreme/SDK
• Platform android-30, build-tools 30.0.3
• ANDROID_HOME = /Volumes/Extreme/SDK
• Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS (Xcode 12.3)
• Xcode at /Volumes/Extreme/Xcode.app/Contents/Developer
• Xcode 12.3, Build version 12C33
• CocoaPods version 1.10.1
[✓] Chrome - develop for the web
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Android Studio (version 4.1)
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495)
[✓] VS Code (version 1.52.1)
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension version 3.18.1
[✓] Connected device (3 available)
• Taha’s iPhone (mobile) • 00008020-001059882212002E • ios • iOS 14.3
• macOS (desktop) • macos • darwin-x64 • macOS 11.1 20C69 darwin-x64
• Chrome (web) • chrome • web-javascript • Google Chrome 87.0.4280.141
• No issues found!
[✓] Flutter (Channel master, 1.26.0-2.0.pre.402, on macOS 11.1 20C69 darwin-x64, locale en-GB)
• Flutter version 1.26.0-2.0.pre.402 at /Users/tahatesser/Code/flutter_master
• Framework revision 2a188eeca3 (8 hours ago), 2021-01-17 19:27:00 -0800
• Engine revision 609036f2bf
• Dart version 2.12.0 (build 2.12.0-236.0.dev)
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
• Android SDK at /Volumes/Extreme/SDK
• Platform android-30, build-tools 30.0.3
• ANDROID_HOME = /Volumes/Extreme/SDK
• Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS
• Xcode at /Volumes/Extreme/Xcode.app/Contents/Developer
• Xcode 12.3, Build version 12C33
• CocoaPods version 1.10.1
[✓] Chrome - develop for the web
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Android Studio (version 4.1)
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495)
[✓] VS Code (version 1.52.1)
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension version 3.18.1
[✓] Connected device (3 available)
• Taha’s iPhone (mobile) • 00008020-001059882212002E • ios • iOS 14.3
• macOS (desktop) • macos • darwin-x64 • macOS 11.1 20C69 darwin-x64
• Chrome (web) • chrome • web-javascript • Google Chrome 87.0.4280.141
• No issues found!
Having the same issue, 2 containers in column with same color showing a really fine line between them, manually setting border widths didn't help.
I had same issue some time ago with Row, I also was impelementing calendar for range picking. I found out that main problem was that width of container was not divisible by number of columns. So I did a small trick: added padding in outer container, so that width of container would be divisible by number of columns. Here is the example:
final numberOfColumns = 7;
final screenWidth = MediaQuery.of(context).size.width; // In my case row was full width of scree
final remainder = screenWidth % numberOfColumns;
var padded = screenWidth - remainder; // padded is width that is divisible by numberOfColumns
// This while is needed for padding to be not less than 30 pixels (by design). You may not doing this, if you don't need extra padding
while (screenWidth - padded < 30) {
padded -= numberOfColumns; // subtract number of columns to keep padded divisible by columns
}
final containerPadding = screenWidth - padded; // compute padding
return Padding(
padding: EdgeInsets.symmetrical(horizontal: containerPadding / 2), // MAIN LINE!
child: Row(
children: List.generate(numberOfColumns, (index) => Expanded(child: Container(color: Colors.red))),
),
);
I have another simple example item height: 20.0 -> no problem item height: 20.1, 20.2, 20.3 -> gap without scroll + moving gap with scroll item height: 20.01, 20.0001 -> no gap without scroll + moving gap with scroll
https://user-images.githubusercontent.com/10491866/110145431-c4bf7d80-7e1c-11eb-85fb-6919e59b7f26.mp4
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',
home: Scaffold(
backgroundColor: Colors.white,
body: SafeArea(
child: SingleChildScrollView(
child: Column(
children: [
buildListView(20),
buildListView(20.1),
buildListView(20.2),
buildListView(20.3),
buildListView(20.01),
buildListView(20.001),
],
),
),
),
),
);
}
ListView buildListView(double itemHeight) {
return ListView.builder(
shrinkWrap: true,
padding: EdgeInsets.symmetric(vertical: 10),
physics: NeverScrollableScrollPhysics(),
itemCount: 10,
itemBuilder: (context, index) => Container(
height: itemHeight,
color: Color(0xFF888888),
child: Text('$itemHeight - $index'),
)
);
}
}
Any update on this 2 years old issue? Ran into similar weirdness too: Code example: https://gist.github.com/Moonspeaker/0e8573ff6620a7e00b8f7b04937b51a1 This is how it looks on any flutter branch: https://www.youtube.com/watch?v=DDxu1NTkaMA&feature=youtu.be
Reproducible on 2.0.4
https://github.com/flutter/flutter/issues/80330#issue-856510027
Are there any plans to fix this or provide some recommended workarounds?
I have another simple example item height: 20.0 -> no problem item height: 20.1, 20.2, 20.3 -> gap without scroll + moving gap with scroll item height: 20.01, 20.0001 -> no gap without scroll + moving gap with scroll
Screen_Recording_20210306-013814.mp4
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', home: Scaffold( backgroundColor: Colors.white, body: SafeArea( child: SingleChildScrollView( child: Column( children: [ buildListView(20), buildListView(20.1), buildListView(20.2), buildListView(20.3), buildListView(20.01), buildListView(20.001), ], ), ), ), ), ); } ListView buildListView(double itemHeight) { return ListView.builder( shrinkWrap: true, padding: EdgeInsets.symmetric(vertical: 10), physics: NeverScrollableScrollPhysics(), itemCount: 10, itemBuilder: (context, index) => Container( height: itemHeight, color: Color(0xFF888888), child: Text('$itemHeight - $index'), ) ); } }
计算高度的时候使用以下代码可以解决这个问题 (itemHeight * WidgetsBinding.instance.window.devicePixelRatio).round() / WidgetsBinding.instance.window.devicePixelRatio
@WangYng Thanks for workaround. This looks good for fixed height or known height. But my actual case is dynamic height items in listview. Additionally, I use package https://pub.dev/packages/responsive_framework which make entire screen scales (decimal point). It still looks that needs fundamental fix on flutter level.