Make Emojis bigger in text? - flutter

Any idea how to make only the fontsize of emojis larger in the Text() widget?
The issue is that the Text() widget parses the emojis automatically. Sure, I can increase the overall text size, but I want the text to stay at the same fontsize.

If you want to auto increase size of emojis in chat message you can use this method:
static final RegExp REGEX_EMOJI = RegExp(
r'(\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])');
Widget _buildContent(String content) {
final Iterable<Match> matches = REGEX_EMOJI.allMatches(content);
if (matches.isEmpty)
return Text(
'${content}',
style: TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.w500,
color: Colors.black,
),
);
return RichText(
text: TextSpan(children: [
for (var t in content.characters)
TextSpan(
text: t,
style: TextStyle(
fontSize: REGEX_EMOJI.allMatches(t).isNotEmpty ? 20.0 : 12.0,
color: Colors.black,
)),
]));
}

You can use the widget RichText
RichText(
text: TextSpan(
text: 'hello',
children: <TextSpan>[
TextSpan(text: '🙂', style: TextStyle(fontSize: 30))
]
),
),

I was facing the same issue and find beginning of solution here
I've modified the code a little to allow showing text and emoji with different font size.
import 'package:flutter/material.dart';
/// Widget to render emoji and text with different font size
class EmojisText extends StatelessWidget {
const EmojisText({
Key? key,
required this.text,
required this.color,
required this.emojiSize,
required this.textSize,
}) : super(key: key);
///The text which emoji and alpha-numeric characters
///emoji can be absent
final String text;
/// THe font size to set to emoji
final double emojiSize;
/// The font size to set to text
final double textSize;
/// the color of the text
final Color color;
#override
Widget build(BuildContext context) {
return RichText(
text: _buildText(),
);
}
TextSpan _buildText() {
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(
fontSize: isEmoji ? emojiSize : textSize,
color: color,
),
),
);
}
return TextSpan(children: children);
}
}

Related

Set the color of selected text

I'm setting up the theme for my app and I want to go with a minimalistic black & white color palette. For that I want the text to look black in a normal state and white when it's selected with the selection color being black.
So far I have found a way to set the selection color to black but now it just blends with the text because the color of the selected text stays black too. Is there a way to set the color of selected text?
TemeData(
textSelectionTheme: TextSelectionThemeData(
cursorColor: Colors.black,
selectionColor: Colors.black,
),
);
What I want:
I haven't found anything in the Flutter library, but you can try to use this Widget:
class SelectableColoredText extends StatefulWidget {
final String text;
final TextStyle? style;
final Color selectedColor;
final Color selectedBackgroundColor;
const SelectableColoredText(this.text, {
Key? key,
this.style,
required this.selectedColor,
required this.selectedBackgroundColor,
}) : super(key: key);
#override
_SelectableColoredTextState createState() => _SelectableColoredTextState();
}
class _SelectableColoredTextState extends State<SelectableColoredText> {
int? _start;
int? _end;
#override
Widget build(BuildContext context) {
final int start = _start ?? widget.text.length;
final int end = _end ?? widget.text.length;
return SelectableText.rich(
TextSpan(
style: widget.style ?? Theme.of(context).textTheme.bodyText2,
children: [
// Text before the selection
TextSpan(text: widget.text.substring(0, start)),
// Selected text
TextSpan(
text: widget.text.substring(start, end),
style: TextStyle(
color: widget.selectedColor,
backgroundColor: widget.selectedBackgroundColor,
),
),
// Text after the selection
TextSpan(text: widget.text.substring(end, widget.text.length)),
],
),
// Update the start and end positions of the selection
onSelectionChanged: (selection, _) {
final int newStart = min(selection.baseOffset, selection.extentOffset);
final int newEnd = max(selection.baseOffset, selection.extentOffset);
if (_start == newStart && _end == newEnd) return;
setState(() {
_start = newStart;
_end = newEnd;
});
},
);
}
}
You can use it like that:
SelectableColoredText(
'The quick brown fox jumps over the lazy dog',
// The default text style
style: TextStyle(fontSize: 40, color: Colors.black),
// The color of the selected text
selectedColor: Colors.white,
// The background color of the selected text
selectedBackgroundColor: Colors.black,
)
Sett the textSelectionColor for its ThemeData.

Animate specific part of txt?By RichText in Flutter, I changed background color by tween animation How to do brush stroke type animation on highlight

I want to make an Epub Reader with text highlighting, text selections. But I tried using RichText and highlight_text package. But it is static and does not add highlighting animations. Like I want to show the highlight happening (brush stroke from right to left on a word). In Flutter, is there any way to do it?
I want to add animations to each text highlight:
`TextHighlight(
//This widget uses RichText and nested TextSpan for highlighting
//I want to add animations to the text Inside TextSpan
text: text,
words: words as LinkedHashMap<String, HighlightedWord>,
textStyle: TextStyle(
fontSize: 20.0,
color: Colors.black,
backgroundColor: Colors.transparent,
),`
Flutter package I am using highlight_text
``
library highlight_text;
import 'dart:collection';
import 'dart:core';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
class HighlightedWord {
final TextStyle textStyle;
final VoidCallback onTap;
HighlightedWord({
required this.onTap,
required this.textStyle,
});
}
class TextHighlight extends StatefulWidget {
String text;
TextAlign textAlign;
TextDirection? textDirection;
bool softWrap;
TextOverflow overflow;
double textScaleFactor;
int? maxLines;
Locale? locale;
StrutStyle? strutStyle;
bool enableCaseSensitive;
TextHighlight({
required this.text,
required this.words,
this.textStyle = const TextStyle(
fontSize: 25.0,
color: Colors.black,
),
this.textAlign = TextAlign.start,
this.textDirection,
this.softWrap = true,
this.overflow = TextOverflow.clip,
this.textScaleFactor = 1.0,
this.maxLines,
this.locale,
this.strutStyle,
this.enableCaseSensitive = false,
});
#override
_TextHightlightState createState() => _TextHighlightState(
required this.text,
required this.words,
this.textStyle = const TextStyle(
fontSize: 25.0,
color: Colors.black,
),
this.textAlign = TextAlign.start,
this.textDirection,
this.softWrap = true,
this.overflow = TextOverflow.clip,
this.textScaleFactor = 1.0,
this.maxLines,
this.locale,
this.strutStyle,
this.enableCaseSensitive = false,
);
}
class _TextHighlightState extends State<TextHighlight> {
String text;
TextAlign textAlign;
TextDirection? textDirection;
bool softWrap;
TextOverflow overflow;
double textScaleFactor;
int? maxLines;
Locale? locale;
StrutStyle? strutStyle;
bool enableCaseSensitive;
#override
void initState(){
text = widget.text;
textAlign = widget.textAlign;
super.initState();
}
#override
Widget build(BuildContext context) {
List<String> _textWords = _bind();
return AnimatedDefaultTextStyle(
child: RichText(
text: _buildSpan(_textWords),
locale: locale,
maxLines: maxLines,
overflow: overflow,
softWrap: softWrap,
strutStyle: strutStyle,
textAlign: textAlign,
textDirection: textDirection,
textScaleFactor: textScaleFactor,
),
);
}
List<String> _bind() {
String bindedText = text;
for (String word in words.keys) {
if (enableCaseSensitive) {
bindedText = bindedText.replaceAll(
word, '<highlight>${words.keys.toList().indexOf(word)}<highlight>');
} else {
int strIndex = bindedText.toLowerCase().indexOf(word.toLowerCase());
print('$word\n');
bindedText = bindedText.replaceRange(strIndex, strIndex + word.length,
'<highlight>${words.keys.toList().indexOf(word)}<highlight>');
}
}
List<String> splitedTexts = bindedText.split("<highlight>");
splitedTexts.removeWhere((s) => s.isEmpty);
return splitedTexts;
}
TextSpan _buildSpan(List<String> bindedWords) {
if (bindedWords.isEmpty) return TextSpan();
String nextToDisplay = bindedWords.first;
bindedWords.removeAt(0);
int? index = int.tryParse(nextToDisplay);
if (index != null) {
String currentWord = words.keys.toList()[index];
return TextSpan(
text: currentWord,
style: words[currentWord]!.textStyle,
children: [
_buildSpan(bindedWords),
],
recognizer: TapGestureRecognizer()
..onTap = () => words[currentWord]!.onTap(),
);
}
return TextSpan(
text: nextToDisplay,
style: textStyle,
children: [
_buildSpan(bindedWords),
],
);
}
}
Is there any way to do animations, tweaking the package code in some way.. or any other workaround..
Baiscally I want to highlight a specific text, rendered by Text widget. In mobile and Web.

How to write a function (in flutter-dart) so that it accepts certain parameters when we call that function?

This is my code:
Text ButtonText = Text(
_buttonText, style: TextStyle(
color: Colors.white,
fontFamily: 'San francisco',
//fontSize: 21.0.ssp,
letterSpacing: 2.0,
wordSpacing: 2.0
),
);
when I use this Text in my button widget, I want to set font size explicitly. How can I do that?
you can create a class for your situation we can call it customtext
here is an example code :
import 'package:flutter/material.dart';
class CustomText extends StatelessWidget {
final String text;
final double size;
final Color color;
final FontWeight weight;
// name constructor that has a positional parameters with the text required
// and the other parameters optional
CustomText({#required this.text, this.size,this.color,this.weight});
#override
Widget build(BuildContext context) {
return Text(
text,style: TextStyle(fontSize: size ?? 16, color: color ?? Colors.black, fontWeight: weight ?? FontWeight.normal),
);
}
}

How can I know the string length of each line in Text?

I want to create a text widget which has a 'see more' function. I want to get the string length in third line so I can do the substring.
The following code is what I have so far:
class ExpandedTextState extends State<ExpandedTextWidget> {
String firstHalf;
String secondHalf;
bool flag = true;
#override
void initState() {
super.initState();
TextPainter textPainter = new TextPainter();
textPainter.maxLines = 3;
textPainter.text = TextSpan(text: widget.text);
textPainter.textDirection = TextDirection.ltr;
textPainter.layout(maxWidth: double.infinity , minWidth: 0.0);
if(textPainter.didExceedMaxLines){
firstHalf = widget.text.substring(0, 50); //substring here
secondHalf = widget.text.substring(50, widget.text.length);
}else{
firstHalf = widget.text;
secondHalf = "";
}
}
#override
Widget build(BuildContext context) {
return new Container(
padding: new EdgeInsets.symmetric(horizontal: 10.0, vertical: 10.0),
child: secondHalf.isEmpty
? new Text(firstHalf)
: Container(
child: new RichText(
text: TextSpan(children: [
TextSpan(
text: flag ? (firstHalf + "...") : (firstHalf + secondHalf),
style: TextStyle(fontSize: 13, color: Colors.amber),),
TextSpan(
text: flag ? "see more" : "",
style: TextStyle(fontSize: 13, color: Colors.black),
recognizer: new TapGestureRecognizer()
..onTap = () {
setState(() {
flag = !flag;
});
}),
]),
),
)
);
}
}
How can I know the string length in each line, or how can I know the last offset of the third line?
If you want a component that expands the text and starts wih only three lines i would suggest to use a simple approach , if you want to know the offset you would need to know the font dimensions, the screen dimensions, the font weight, the device orientation.
Flutter itself can't give you that, it would be kinda hard to implement..
But, if you want a text of 3 lines that expands when you click "see more" and if it's expanded "see more" dissapears, you can use this approach
class ExpandableText extends StatefulWidget {
#override
_ExpandableTextState createState() => _ExpandableTextState();
}
class _ExpandableTextState extends State<ExpandableText> {
final String text =
'ppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp';
bool isExpanded = false;
#override
Widget build(BuildContext context) {
return isExpanded
? Text(text + text + text,
style: TextStyle(fontSize: 13, color: Colors.amber))
: Column(children: <Widget>[
Text(text + text + text,
maxLines: 3,
overflow: TextOverflow.ellipsis,
style: TextStyle(fontSize: 13, color: Colors.amber)),
GestureDetector(
onTap: () => setState(() => isExpanded = true),
child: Text('See More...',
style: TextStyle(fontSize: 13, color: Colors.black)))
]);
}
}
in that component we use a maxlines property to tell if the text is expanded or not, if it is , it's null , if it's not, it's 3

How to knows where TextWidget will wrap?

When using Text widget with big strings, it happens that the displayed text is splitted on 2 or more lines.
My question is simple : How to know the exact character where a string is divided ?
I've digged inside Text code. Up to dart:ui's Paragraph. But I haven't found anything usable.
Actually the text in flutter is painted on canvas using a TextPainter which computes the layout size during runtime with the box constrains of its parent class. If you already know the available space, you can compute the layout width of the text and compare it with the available width to know where the text would break.
You can computer the width of the text with TextPainter like:
final TextPainter paint = new TextPainter(
text: new TextSpan(
text: "Hello World",
),
textDirection: TextDirection.ltr
);
paint.layout();
debugPrint(paint.width.toString());
You can also do it with CustomPainter like this:
import 'package:flutter/material.dart';
void main() {
String text = "Hello World";
void textShownOnUI(int size){
debugPrint(text.substring(0,size));
}
runApp(new MaterialApp(
title: "Example",
home: new Container(
width: 100.0,
padding: const EdgeInsets.all(175.0),
child: new CustomPaint(
painter: new MyTextWidget(
text: text,
style: new TextStyle(),
notifySize: textShownOnUI
),
child: new Container(),
),
),
));
}
class MyTextWidget extends CustomPainter {
Function notifySize;
String text;
TextStyle style;
TextDirection direction;
MyTextWidget({this.text,this.notifySize,this.style,this.direction});
#override
void paint(Canvas canvas, Size size){
debugPrint(size.width.toString());
final TextPainter _painterWithConstrains = new TextPainter(
text: new TextSpan(
text: text,
style: style
),
textDirection: direction??TextDirection.ltr
);
String _willBeShownOnUI = text;
int _size = text.length;
TextPainter _temp = new TextPainter(
text: new TextSpan(
text: _willBeShownOnUI,
style: style
),
textDirection: direction??TextDirection.ltr
);
_painterWithConstrains.layout(maxWidth: size.width);
_temp.layout();
while(_temp.width > _painterWithConstrains.width && _size != 0){
debugPrint(_temp.width.toString()+" "+ _size.toString());
_willBeShownOnUI = _willBeShownOnUI.substring(0, --_size);
_temp = new TextPainter(
text: new TextSpan(
text: _willBeShownOnUI,
style: style
),
textDirection: direction??TextDirection.ltr
);
_temp.layout();
}
_size = _willBeShownOnUI.split(" ")[0].length; // Get complete words that will be shown
Function.apply(notifySize,<int>[_size]);
_painterWithConstrains.paint(canvas, Offset.zero);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) => true;
}
Hope that helped!