Flutter editable text on canvas - flutter

I am trying to add an editable textbox to the canvas in Flutter, that will bring up the keyboard once selected.
I am using a custom painter to print text to a canvas (shown in the code below). Is it possible to make this text editable, or add a text input element over the canvas at a particular offset?
import 'package:flutter/material.dart' as Material;
class CanvasPainter extends Material.ChangeNotifier implements Material.CustomPainter {
..
void paint(Canvas canvas, Size size) {
Material.TextSpan textSpan = new Material.TextSpan(style: new material.TextStyle(color: new Maaterial.Color.fromRGBO(r, g, b, 1.0), fontSize: font.fontSize.toDouble(), fontFamily: 'Roboto'),text: "Hello there");
Material.TextPainter tp = new Material.TextPainter( text: textSpan, textAlign: TextAlign.left, textDirection: TextDirection.ltr, textScaleFactor: ratio);
tp.layout();
tp.paint(canvas, new Offset(50.0,50.0));
}
}

Not the best solution, but I could solve similar issue with OverlayEntry.
Steps:
create an OverlayEntry, put a (hidden) TextField into it with a FocusNode and TextEditController.
after added the overlay entry, request focus on the focusNode, so the keyboard will open.
Add an onChanged to the TextField, and notify the painter somehow (e.g. valueNotifier) on text change.
In the TextPainer use the TextEditController.text value

Related

Flutter GetX: Refresh all open pages because of new TextStyle

My Situation
I created this class for my own TextStyles (example code snippet)
class CustomTextStyles {
double textFactor = AppStorage.read(AppStorage.textSizeFactor) ?? 1.0;
// first custom text style
late TextStyle customTextStyle1 = GoogleFonts.roboto(
fontSize: 36 * textFactor,
fontWeight: FontWeight.w700
);
}
Calling it somewhere like
Text("Hello World", style: CustomTextStyles().customTextStyle1)
My Problem
In the SettingsPage the user changes the textFactor from 1.0 to 1.5, so the fontSize should increase.
This works, and the text is getting bigger, when navigating to a new page.
But I want to refresh all current open pages, after changing the textFactor so, when navigating back, the text gets bigger 1.5 times.
For example to the settings page I get by navigating:
From the Drawer Button of any page -> To the Drawer -> To the SettingsPage
What should happen:
All Text Widgets in the settingsPage, in the Drawer and in the Page where we called the Drawer should increase their fontSize by 1.5.
How can I achieve that?
Do I really need to wrap all of the used TextStyles (over 100+ occurrences in 36+ files) in Obx(() => Text(...))?

How can I use marquee package conditionally in Futter?

In the image you see that some texts take more space than the width provided by their parent widget. I want to use marquee so that when the text is longer than the width, it scrolls. But, it should not always be scrollable, only when it is longer, not even when the text is fitted inside the parent widget. How can I use marquee only when the text is long?
bool _willTextOverflow({required String text, required TextStyle style}) {
final TextPainter textPainter = TextPainter(
text: TextSpan(text: text, style: style),
maxLines: 1,
textDirection: TextDirection.ltr,
)..layout(minWidth: 0, maxWidth: maxWidth);
return textPainter.didExceedMaxLines;
}
Read more about this here.
Get the entire code here.

How to get the width of the dynamic text widget in flutter?

The fonts of the text in my text widget are dynamic. The width and height of the font change according to different font types. How to get the width or height value of the text widget that varies according to the font.
you can use a GlobalKey into the Text Widget and then check its size somewhere else
GlobalKey myKey = GlobalKey();
...
Text('MyText, key: myKey)
Then use the currentContext of the GlobalKey to check its size (in a callback after it has been built)
print(myKey?.currentContext?.size);
But before doing that you need to build the Text Widget
The current context is null if there is no widget in the tree that
matches this global key
If you want to know the size it will use before creating the TextWidget you can try creating a TextSpan somewhere (in the initState for example)
TextSpan longestParagraphTest = TextSpan(
text: "This is all my Text",
style: myTextStyle, //define the style it willl use, fontSize, etc.
);
TextPainter _textPainter = TextPainter(text: longestParagraphTest, textDirection: TextDirection.ltr, maxLines: 1)..layout(minWidth: 0.0, maxWidth: double.infinity);
width = _textPainter.width; //This is the width it requires
height = _textPainter.height; //This is the height it requires

How to change Font Family using setState in Flutter?

I want to change my Text Widget font family on button click.
Which means I created a Container and in this Container I added multiple text style widget with GestureDetector widget. So whenever I click on Particular font family, I want to change my Text widget Font-Family.
Any suggestion for doing this type of functionality.
Hope this works or modify accordingly:
code inside your Text Widget:
Text("Your Text",
style: tapped
?TextStyle(fontFamily: 'Your-Font-Family')
:TextStyle(fontFamily: 'Your-Second-Font-Family'),
),
code inside Gesture Detector:
GestureDetector(
child: your child widget,
onTap: () {
setState(() {
tapped = !tapped;
});
}),
and remember to define bool tapped; in your widget class.
Still, if you face any difficulty, add the code to comment so I can help you out.
Use a variable to store font name
reference it in your text Widget
then call setState to update the value of variable and UI
String fontName;
//your TextWidget
Text("some text for testing",
style: TextStyle( fontFamily: fontName )
)
//function to update the value
_updateFont(String name){
setState((){
fontName = name;
});
}
make sure you are importing the fonts to be used
add them in pubspec.yaml file under fonts
- family: font1
fonts:
- asset: assets/fonts/font1.ttf

How to animate TextSpans within Flutter TextFormField

I am currently working on a project that requires minor animations to text as it appears in a TextFormField.
I hav extended the TextEditingControler and overriden the buildTextSpan function to enable different TextSyles based on the types of words that were being typed in. For example if a word is ['the','a','me'].
For example I would add a TextSpan with a particular style for each matching word and for all other words I would just add the word in a TextSpan with normal style.
This is working fine, however, what I want to do is to animate the matched words for a period as they are entered, for example they would turn from blue to green.
Extended TextEditingController Class
class RichTextEditingController extends TextEditingController {
TextStyle matchedStyle = TextStyle(
color: Colors.green,
fontSize: 20,
fontWeight: FontWeight.w700,
);
#override
TextSpan buildTextSpan({TextStyle style, bool withComposing}) {
List<String> wordsToMatchList = ['the','a','me'];
List<String> splitText = text.split(' ');
List<TextSpan> textSpanList = [];
splitText.forEach((word) {
if (wordsToMatchList.contains(word)) {
textSpanList.add(TextSpan(style: boldStyle, text: '$word'));
} else {
textSpanList.add(TextSpan(style: style, text: '$word'));
}
});
return TextSpan(children: textSpanList);
}
}
I have tried various techniques like future.Delayed and others, but can't seem to find any approach that works and need some help.
Question: Is there a way to add a minor animation to TextSpans or other widgets that would show when new text is typed into a text field that matches a certain pattern?