Flutter Web shows emojis in black&white - flutter

The bounty expires in 3 days. Answers to this question are eligible for a +50 reputation bounty.
mirkancal wants to draw more attention to this question.
In ios/android apps emojis are shown correctly. But using any web-browser (e.g. Chrome) the emoji appears in black and white. I also tried different Font-Families but with the same result.
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: Text('Enjoy! 🥳 If there\'s any question')
),
);
}
}

Use Noto Color Emoji from google (follow this steps):
Download the font Download Noto Color Emoji
Added it to pubspec.yaml `flutter:
fonts:
family: Noto Color Emoji
fonts:
asset: assets/fonts/NotoColorEmoji-Regular.ttf`
And in TextStyle class use it like this TextStyle( fontFamilyFallbackm: [ 'Apple Color Emoji', 'Noto Color Emoji', ], )
Unlike that try to:
. Delete web folder
. Update flutter by using command flutter upgrade
. Run command flutter create .

Related

Does Flutter/Dart know what glyphs are available in loaded font files?

I am trying to put a specified unicode character into a Text widget, but only if there is a glyph available in the fontFamily font specified in the TextStyle.
What currently happens by design is the fontFamilyFallback font is checked for a glyph, and if not found then the system font is checked, then if still no glyph found a 'not found' style glyph is rendered instead - usually a box with an X inside (depends on system I think).
I wonder if there is a way to disable that fall-back or even better have a list of available glyphs before building the text widget?
Attached some example code, and the results of the code in a screenshot. The code uses two fonts available via google fonts, and attempts to output the euro unicode character \u20ac. You can see from the screenshot that Syne has a glyph at u20ac, but Arvo does not. This could also be validated in for example Windows Character map.
Flutter Code (nothing in texttheme other than fontsize):
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'No fontfamily, no fontfamilyfallback \u20AC',
),
Text(
'fontfamily Syne Tactile: \u20AC',
style: TextStyle(fontFamily: 'Syne'),
),
Text(
'fontfamily Arvo, no fontfamilyfallback \u20AC',
style: TextStyle(fontFamily: 'Arvo'),
),
Text(
'fontfamily Arvo, fontfamilyfallback: Syne Tactile \u20AC',
style:
TextStyle(fontFamily: 'Arvo', fontFamilyFallback: ['Syne']),
),
],
),
),
); }
pubspec.yaml:
fonts:
- family: Arvo
fonts:
- asset: assets/Arvo-Regular.ttf
- family: Syne
fonts:
- asset: assets/SyneTactile-Regular.ttf
Flutter Web Output
Found a bit of a hack/workaround. If I load the AdobeBlank font into the package, and use that as fontFamilyFallback, then a glyph with zero width is displayed. Not ideal (better to know before building), but sort of does the job.
Can also then try and determine width before building using something like this.
Hopefully there is a better answer out there still, as I'd much rather be able to load a font and know what glyphs are available somehow.

why the UI rendering but did not run into build code block in flutter

Now I am facing a problem that in the Flutter Performance, shows the UI is rending all the time. But the code did not trigger the build code block breakpoint(shows code did not run into this block). This is the performance UI:
the gray circle tell me that component was rendering... , I try to tracing the rerender component, but the code did not going into the code block when I am tracing the render component, why would this happen? The UI debbuing is showing rendering too:
there have two page, one page have a click button, when click the button, navigate to a new page, this page show a gif picture. This is the full code main.dart:
import 'package:flutter/material.dart';
import 'package:flutter_html/flutter_html.dart';
import 'app.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',
checkerboardOffscreenLayers: true,
checkerboardRasterCacheImages: true,
showPerformanceOverlay: true,
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
// This makes the visual density adapt to the platform that you run
// the app on. For desktop platforms, the controls will be smaller and
// closer together (more dense) than on mobile platforms.
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
// This widget is the home page of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
// how it looks.
// This class is the configuration for the state. It holds the values (in this
// case the title) provided by the parent (in this case the App widget) and
// used by the build method of the State. Fields in a Widget subclass are
// always marked "final".
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
// This call to setState tells the Flutter framework that something has
// changed in this State, which causes it to rerun the build method below
// so that the display can reflect the updated values. If we changed
// _counter without calling setState(), then the build method would not be
// called again, and so nothing would appear to happen.
_counter++;
});
}
#override
void didUpdateWidget(covariant MyHomePage oldWidget) {
// TODO: implement didUpdateWidget
super.didUpdateWidget(oldWidget);
}
#override
Widget build(BuildContext context) {
print("Home");
// This method is rerun every time setState is called, for instance as done
// by the _incrementCounter method above.
//
// The Flutter framework has been optimized to make rerunning build methods
// fast, so that you can just rebuild anything that needs updating rather
// than having to individually change instances of widgets.
return Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
body: Center(
// Center is a layout widget. It takes a single child and positions it
// in the middle of the parent.
child: Column(
// Column is also a layout widget. It takes a list of children and
// arranges them vertically. By default, it sizes itself to fit its
// children horizontally, and tries to be as tall as its parent.
//
// Invoke "debug painting" (press "p" in the console, choose the
// "Toggle Debug Paint" action from the Flutter Inspector in Android
// Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
// to see the wireframe for each widget.
//
// Column has various properties to control how it sizes itself and
// how it positions its children. Here we use mainAxisAlignment to
// center the children vertically; the main axis here is the vertical
// axis because Columns are vertical (the cross axis would be
// horizontal).
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(onPressed: (){
Widget page = LearnApp();
Navigator.push(
context,
MaterialPageRoute(builder: (context) => page),
);
}, child: Text("Click")),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
this is a new page show gif:
import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/framework.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_html/flutter_html.dart';
class LearnApp extends HookWidget {
#override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text("widget title"),
),
body: SafeArea(
child: Html(
data: "<p><img src=\"https://tva1.sinaimg.cn/mw690/006v119zly1gsu8ni6jbbg30a007q1l2.gif\" /></p>"
),
),
);
}
}
this is the dependencies:
name: flutter_learn
description: A new Flutter application.
# The following line prevents the package from being accidentally published to
# pub.dev using `pub publish`. This is preferred for private packages.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# The following defines the version and build number for your application.
# A version number is three numbers separated by dots, like 1.2.43
# followed by an optional build number separated by a +.
# Both the version and the builder number may be overridden in flutter
# build by specifying --build-name and --build-number, respectively.
# In Android, build-name is used as versionName while build-number used as versionCode.
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 1.0.0+1
environment:
sdk: ">=2.7.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
flutter_hooks: ^0.12.0
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.0
flutter_html: 2.0.0
dev_dependencies:
flutter_test:
sdk: flutter
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
# The following section is specific to Flutter.
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
# To add assets to your application, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware.
# For details regarding adding assets from package dependencies, see
# https://flutter.dev/assets-and-images/#from-packages
# To add custom fonts to your application, add a fonts section here,
# in this "flutter" section. Each entry in this list should have a
# "family" key with the font family name, and a "fonts" key with a
# list giving the asset and other descriptors for the font. For
# example:
# fonts:
# - family: Schyler
# fonts:
# - asset: fonts/Schyler-Regular.ttf
# - asset: fonts/Schyler-Italic.ttf
# style: italic
# - family: Trajan Pro
# fonts:
# - asset: fonts/TrajanPro.ttf
# - asset: fonts/TrajanPro_Bold.ttf
# weight: 700
#
# For details regarding fonts from package dependencies,
# see https://flutter.dev/custom-fonts/#from-packages
the step to reproduce is: first click the button and then click back return to home page. You can see the problem what I facing.

Check for color during widget test?

The goal is to verify the color of a RaisedButton.icon
During my widget tests, I have the ability to look for text with find.text as well as icons with find.byIcon. There is no built in method for finding color.
How does one do the equivalent of find.color?
And example of my code is
RaisedButton.icon(
color: Color(_isAttendingEvent ? 0xFFD9FFB3 : 0xFFE3FFC7),
icon: Icon(_isAttendingEvent ? Icons.star : Icons.star_border),
label: Text(
_isAttendingEvent ? 'Attending' : 'Attend',
),
),
I'm trying to determine whether there is color: Color(0xFFD9FFB3) or color: Color(0xFFE3FFC7)
And I'm not sure if this is possible
I am not sure with RaisedButton.icon, but if it is just an icon you can try using:
expect((tester.firstWidget(find.byType(Icon)) as Icon).color, Color(0xFFE3FFC7));
If it not the first icon widget that appears on your screen, you can specific an index of it by:
expect((tester.widget(find.byType(Icon).at(/*index*/)) as Icon).color, Color(0xFFE3FFC7));
Note: To find a widget colour, you need to cast that widget to be something that contain a color property
For example:
To find Material color you can use:
expect((tester.firstWidget(find.byType(Material)) as Material).color, Colors.black);
To find Container with BoxDecoration color:
expect(((tester.firstWidget(find.byType(Container)) as Container).decoration
as BoxDecoration).color, Colors.black);
To find Text color:
expect(((tester.firstWidget(find.text('text')) as Text).style).color, Colors.black);
To find Appbar Material. color
final appbar = tester.widget<AppBar>(find.byKey(Key("appbar")));
expect(appbar.backgroundColor,Colors.white);
To find Text color Material
final text = tester.widget<Text>(find.text("text"));
expect(text.style.color, Colors.grey);
expect(text.style.fontSize, 15);
Update you flutter version. It's working now, i am able to access color in widget test. My current flutter version is "Flutter 1.15.18 • channel dev".
Earlier it was not working with version "Flutter v1.12.13+hotfix.5"
Hope this will help. More details here
If you're using a TextButton, ElevatedButton, or Outlined button, the background color will be a MaterialStateProperty. You can verify the color in almost the same way as mentioned above:
expect(
tester.widget(textButton.first),
isA<TextButton>().having(
(w) => w.style?.backgroundColor?.resolve({}),
'button color',
Colors.grey,
));

Text widget with wrong emoji on initialization in Flutter

I want to display an emoji within a text widget, using Flutter.
When I copy an example emoji from the internet, some of them shows up with 2 characters in my IDE.
E.g:
static String dualCharEmoji = "⚔️";
static String singleCharEmoji = "🗡";
When I use this variable in the text widget, both of them work fine:
Text("⚔️",)
Text("🗡",)
However, only when first running the app, the dual character emoji shows up as its first character only.
i.e. Only when first opening the app, the sword icon shows up as ⚔ instead of as ⚔️
After it gets reloaded it gets fixed, and hot reloading/hot restarting does not makes it bug again.
My question is:
Is this a bug? Am I missing some detail here? Why does it only happen when first opening the app?
How can I show a 2 sized emoji from the start?
I'm using the following Flutter version:
>flutter --version
Flutter 1.9.1+hotfix.4 • channel stable • https://github.com/flutter/flutter.git
Framework • revision cc949a8e8b (9 weeks ago) • 2019-09-27 15:04:59 -0700
Engine • revision b863200c37
Tools • Dart 2.5.0
See the minimum reproducible example below:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
static String dualCharEmoji = "⚔️";
static String singleCharEmoji = "🗡";
String text = dualCharEmoji;
int count = 0;
void swapText() {
setState(() {
if (count % 2 == 0)
text = singleCharEmoji;
else
text = dualCharEmoji;
count++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
text,
style: TextStyle(fontSize: 50),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: swapText,
),
);
}
}
After creating this question, doing many unsuccessful tries, and no working answer, I've created an issue on Flutter's official Github repository.
After I showed my problem, an user explained that that is a bug related to how Flutter renders and caches the fonts, in case of the default font cannot handle properly some character:
The first time that dualCharEmoji is rendered Flutter sees that the default font does not handle the 2694 character. [...]it can render the basic 2694 crossed swords character but not the 2694 FE0F emoji.
When singleCharEmoji is rendered Flutter now includes the NotoSansSymbols font in the list of fonts given to the HarfBuzz text shaper.[...] and matchFamilyStyleCharacter returns NotoColorEmoji. Flutter also adds this font to the cache.
The next time the engine tries to render dualCharEmoji it provides both cached fonts (NotoSansSymbols and NotoColorEmoji) to HarfBuzz. Now that HarfBuzz is aware of the sequences defined in NotoColorEmoji it can recognize the 2694 FE0F emoji and return it to Flutter.
I've referenced here only some parts of the discussion. You can read the full discussion and explanation on the issue page I've linked above.
Users suggested some workarounds, namely two:
First, you can force the engine to pre-cache a font that handles emojis correctly. You can do this by adding the following code in the build, or the initState method (anywhere that runs before building the Text Widget):
import 'dart:ui';
ParagraphBuilder pb = ParagraphBuilder(ParagraphStyle(locale: window.locale));
pb.addText('\ud83d\ude01'); // smiley face emoji
pb.build().layout(ParagraphConstraints(width: 100));
This worked on my example project, but as stated on the Issue page:
However, this relies on implementation details of the current Flutter text engine that may change in the future.
So be aware that this workaround can stop working at any given time.
The second workaround is given as follow:
For now the work around is to list the desired font in the text style and it will be resolved correctly.
Which is simply to give a TextStyle property to the Text Widget, with its fontFamily (or the fontFamilyFallback) property set. The chosen font must already support all characters required. This also worked for me, however I had to include a custom font from my computer (or from a public online package).

Starting with plain (non material ui) canvas in flutter

All tutorials and documentation I've seen so far start of with importing flutter material. I am wondering is this an absolute requirement? What if I want to start with a plain canvas and build my own theme / widgets. Can I do this, if so what package should be used here so I get access to default widgets?
Although the answers here are correct, I want to add a few more points. To use raw widgets use import 'package:flutter/widgets.dart';
Here is a working example:
import 'package:flutter/widgets.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(25.0),
child: Directionality(
textDirection: TextDirection.ltr,
child:Text("hello world",
style: TextStyle(
color: Color.fromRGBO(255, 255, 255, 1)
),
)));
}
}
The directionality is needed, the padding was added so that we see the message, otherwise it is masked by the menubar in phone.
Widgets in flutter makes the developers day easy. All the widgets are built on top dart:ui lib. It is up to you, to decide to use existing set of widgets or develop your ui from scratch. Flutter does not stop you from writing your own widgets.
You can find a few raw example of here, that does not use any widgets at all.
If you simple don't want only material widgets, then you can just build your own themed widgets with all other basic widgets and layouts available in flutter.
If you wanted to build few of your own widgets with a canvas and use it along with other widgets in flutter, you look into CustomPaint and CustomPainter widgets.
Hope this helped!
Just as Chandan Purohit answered, use import 'package:flutter/widgets.dart';. Flutter official gives a minimal app in Introduction to widgets as follows:
import 'package:flutter/material.dart';
void main() {
runApp(
const Center(
child: Text(
'Hello, world!',
textDirection: TextDirection.ltr,
),
),
);
}
Just change flutter/material.dart to flutter/widgets.dart, and you get a plain canvas to start.
Note: The color of Text is white by default.