The Problem
As of now, unfortunately, Flutter uses the default Emojis supported on a given platform. Therefore, when building a cross-platform app you may face issues of Emojis showing on certain devices and not on others.
The Solution
The solution I settled for is to use a custom Emoji font such as Emoji One and RichText
widget instead of the basic Text
widget.
With this, you can simply have:
RichText(
text: TextSpan(
children: <TextSpan>[
TextSpan(
text: 'Hello', // non-emoji characters
),
TextSpan(
text: '🧭 🏳️\u200d🌈', // emoji characters
style: TextStyle(
fontFamily: 'EmojiOne',
),
),
],
),
);
Generalized Solution
With this idea, we can even create a custom widget that given a string, builds a RichText
object with all the TextSpan
s autocreated:
class EmojiText extends StatelessWidget {
const EmojiText({
Key key,
@required this.text,
}) : assert(text != null),
super(key: key);
final String text;
@override
Widget build(BuildContext context) {
return RichText(
text: _buildText(this.text),
);
}
TextSpan _buildText(String text) {
final children = <TextSpan>[];
final runes = text.runes;
for (int i = 0; i < runes.length; /* empty */ ) {
int current = runes.elementAt(i);
// we assume that everything that is not
// in Extended-ASCII set is an emoji...
final isEmoji = current > 255;
final shouldBreak = isEmoji
? (x) => x <= 255
: (x) => x > 255;
final chunk = <int>[];
while (! shouldBreak(current)) {
chunk.add(current);
if (++i >= runes.length) break;
current = runes.elementAt(i);
}
children.add(
TextSpan(
text: String.fromCharCodes(chunk),
style: TextStyle(
fontFamily: isEmoji ? 'EmojiOne' : null,
),
),
);
}
return TextSpan(children: children);
}
}
Which can be used as:
EmojiText(text: 'Hello there: 🧭 🏳️\u200d🌈');
This has the advantage of having the consistent support of Emojis on your app that you can control on different platforms.
The downside is that it will add some MBs
to your app.
Updated Answer
resizeToAvoidBottomPadding
is now deprecated.
The updated solution is to set resizeToAvoidBottomInset
property to false
.
Original Answer
In your Scaffold
, set resizeToAvoidBottomPadding
property to false
.
Best Answer
The problem is having a
Scaffold
or not.Scaffold
is a helper forMaterial
apps (AppBar
,Drawer
, that sort of stuff). But you're not forced to useMaterial
.What you're missing is an instance of
Theme
as a parent.Why is that important to know? Because when you'll develop a Modal (using
showDialog
for example), you'll face the same problem. BUT Scaffold is an opaque fullscreen widget! And you obviously don't want that in your Modal.There are many ways to introduce a Theme instance. In Material App, this is usually achieved by instantiating a
Material
Widget. And guess what?Scaffold
creates one for you. ButDialog
too!