This is the model of what i want to do !
I'm contacting you because I'm trying to copy the Libération newspaper application but I'm stuck (already!) on the question of the title.
I have attached a visual and I will try to be clear. I would like the first part of the title to be in red and then the title to continue in black and line up again, aligned to the left, under the red title. I have tried many methods to no avail. Expanded, Wrap... either the text sticks out or, when I manage to make the line break of the black text, it is positioned under the black text, not under the red text, considering that the block starts on the right of the red block.
I tried Wrap, Row, Expanded.
Thank you :-)
this is just an example ,
If it's dynamic you might want to use: a separator; to split the title or the text or another symbol
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
final String title =
"Chez Pol; Et si on mesurait le bruit à l'Assemblée pour la santé des députés?";
const MyApp({super.key});
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: SafeArea(
child: Scaffold(
body: RichText(
text: TextSpan(
text: title.split(';')[0].toString(),
style: TextStyle(color: Colors.red, fontWeight: FontWeight.bold),
children: <TextSpan>[
TextSpan(
text: title.split(';')[1].toString(),
style: const TextStyle(color: Colors.black),
),
],
),
),
),
),
);
}
}
Related
I have a SelectableText.rich widget in flutter where the usecase requires each word within the text to be its own TextSpan.
The app currently parses the text into words and sets up the list of TextSpans. I want the user to be able to select text and then trigger a modification to the styling of all TextSpans touched by the selection.
For example, let’s say the SelectableText.rich has the following text where each word is its own TextSpan:
The boy went to the store. He went to the store every day.
If the user selects “went to the store” in the first sentence and then taps on a ‘bold’ button, how can I identify which spans should be affected? Note that “went to the store” is in the source text twice but only the first instance should be modified (so I can’t simply search the source text).
Here's a stripped-down example (using only the first sentence):
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'RichText Selection Issue',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Selectable Text Problem')),
body: Padding(
padding: const EdgeInsets.all(30),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SelectableText.rich(
TextSpan(text: 'The ', style: TextStyle(fontSize: 20), children: [
TextSpan(text: 'boy '),
TextSpan(text: 'went '),
TextSpan(text: 'to '),
TextSpan(text: 'the '),
TextSpan(text: 'store '),
TextSpan(text: '.'),
])),
const SizedBox(height: 20),
// Add button to trigger selection
ElevatedButton(
onPressed: () {},
child: const Text('Select'),
),
],
),
),
);
}
}
What would I do in the ElevatedButton's onPressed callback to trigger a rebuild that modified the style associated with the TextSpans for 'went to the store'? I can't take the example further than this because I don't know how to associate the selected text with the spans (which obviously would need 'style' properties and presumably some sort of state logic relating to whether or not they should be rendered as bold).
Any suggestions on how this could be handled (or pointers to any online articles covering this sort of topic)?
Thanks in advance!
Note : For the purposes of this question, please ignore the fact that the user could select partial words using the SelectableText widget. I haven’t thought through that issue yet (the objective would be that a partially selected word would be treated as the full word).
Edited to add an example.
My issue is that flutter breaks Text at non whitespace characters:
How can I tell flutter not to beak text at the "/" but only when it encounters a whitespace?
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: Scaffold(
body: Center(
child: Container(
width: 220.0,
child: Text(
'This should not break here x/y/z',
style: TextStyle(fontSize: 30.0),
),
),
),
),
);
}
}
I have been looking into packages like auto_size_text, but found nothing addressing this problem.
Edit:
Working with '\n' is not an option since the length of the text varies,but it always includes the three x/y/z characters divided by slashes at the end.
I would rather not calculate the size of the rendered text in advance to determine whether a newline should be included before x/y/z. That would seem a little heavy, since these are card titles contained in a ListView.
On the web there is no issue, there the text is only broken at whitespaces:
<!DOCTYPE html>
<html>
<body>
<div style="background-color: grey; height: 200px; width: 400px;">
<p style="font-size: 24.0pt;">
This should not break here x/y/z
</p>
</div>
</body>
</html>
I usually use TextAlign.justify to fit the text, and to my liking, you can try:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: Scaffold(
body: Center(
child: Container(
width: 220.0,
child: Text(
'This should not break here x/y/z',
textAlign: TextAlign.justify,
style: TextStyle(fontSize: 30.0),
),
),
),
),
);
}
}
Also TextAlign.center not bad.
https://github.com/flutter/flutter/issues/61081#issuecomment-1103330522
Replace space with NO-BREAK SPACE '\u00a0' where you don't want to break. This forces two characters around it to stay put together in
the same line.
Insert ZERO WIDTH NO-BREAK SPACE '\ufeff' between the characters you don't want to break. Same as the above but takes no space.
Optionally insert ZERO WIDTH SPACE '\u200b' where you want to break. This allows two characters around it to break freely.
To break only around spaces, replace
Text(string)
with
Text(string.split('').join('\ufeff').replaceAll('\ufeff \ufeff', ' '))
I've recently started using Flutter just for fun, and I'm stuck on adding actual functionality to the code without having everything inside one class.
Essentially, I'm trying to use a FloatingActionButton to increment the value of a Text Widget which stores the value of the user's level as an integer, but I don't want to have the whole app as a StatefulWidget because only the level is going to be updated. When the button is pressed, the value should increment by 1 and then show the new value on the screen.
I have the Level Text Widget inside a StatefulWidget class along with a function to update the level by one and set the state; the MaterialApp inside a StatelessWidget class; and the main body code inside another StatelessWidget class.
If this isn't the best way to do it please do let me know so I can improve for future projects, thanks.
main.dart
import 'package:flutter/material.dart';
main() => runApp(Start());
/// The Material App
class Start extends StatelessWidget{
#override
Widget build(BuildContext context){
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
backgroundColor: Colors.grey[800],
appBar: AppBar(
title: Text("Home Page"),
backgroundColor: Colors.cyan,
centerTitle: true,
),
floatingActionButton: FloatingActionButton(
onPressed: () {},
backgroundColor: Colors.orange,
child: Icon(Icons.add, color: Colors.black,),
),
body: HomePage(),
),
);
}
}
/// Main Content for the page (body)
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
// removed other children so there's less code to scan through for you :)
Padding(
padding: EdgeInsets.fromLTRB(30, 0, 0, 0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
// Text that just says "Level"
Text(
"Level",
style: TextStyle(
color: Colors.orange,
fontWeight: FontWeight.bold,
fontSize: 32,
),
),
// space between text and actual level value
SizedBox(height: 10),
// Create new level widget
Level(),
],
),
),
],
),
);
}
}
/// Updating level using a Stateful Widget
class Level extends StatefulWidget{
#override
State<StatefulWidget> createState(){
return _LevelState();
}
}
class _LevelState extends State<Level>{
int level = 0;
void incrementLevel(){
setState(() {
level += 1;
});
}
#override
Widget build(BuildContext context){
return Text(
"$level",
style: TextStyle(
color: Colors.grey[900],
fontWeight: FontWeight.normal,
fontSize: 28,
),
);
}
}
It actually is a weird way of doing it. However, there is various ways of achieving this
To give an example:
You can use KEYs to remotely redraw the child state
If you want an advanced solution that can assist you in bigger projects. You can use state management tecniques. You can find a lot of tutorials in the internet but these are some of them. BLOC, Provider, InheritedWidget.
Basicaly all of them does the same thing. Lifts up the state data so the place of the redrawn widget on the widget tree will not be important.
I strongly encourage you to watch some tutorials starting with the Provider. I hope this helps
I don't want to change the text color of the whole app. Just all the text inside a container. Can I wrap it with some other widget or something for this ?
To apply certain TextStyle properties only to a subtree of your app. You can use DefaultTextStyle
DefaultTextStyle(
child: Container(child: /* your subtree */),
style: TextStyle(color: Colors.red),
),
as a comment pointed out, this replaces all defaults, not just the color. This can be mitigated by using the merge constructor:
DefaultTextStyle.merge(
child: Container(child: /* your subtree */),
style: TextStyle(color: Colors.red),
),
flutter's answer is good in my opinion. But the power of ThemeData is more than you think. Here is the official documentation about Themes for part of an application.
You could provide a Theme to wrap your container to provide a new theme. Here is two way to slove it:
1. Creating unique ThemeData
/*Not recommended, this could make a totally different If you just want a little part changed.*/
Theme(
// Create a unique theme with "ThemeData"
data: ThemeData(
textTheme: /* Your Text Theme*/,
),
child: Container(
onPressed: () {},
child: Text("Your Text Here"),
),
);
2. Extending the parent theme
Theme(
// Find and extend the parent theme using "copyWith". See the next
// section for more info on `Theme.of`.
data: Theme.of(context).copyWith(textTheme: /* Provide your theme here! */),
child: Container(
child: Text("your text here"),
),
);
You could also use existed theme with a little changed:
Theme.of(context).textTheme.copyWith(
body1: Theme.of(context).textTheme.body1.copyWith(color: Colors.red),
)
Use DefaultTextStyle.merge to keep your theme and just change the color.
DefaultTextStyle.merge(
style: TextStyle(color: Colors.grey[400]),
child: Column(...),
)
If you are using the MaterialApp widget you could use the theme property of it and set different Text themes and call them anywhere in your app. For example the following code defines 3 different text themes:
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: "Time Tracker",
theme: ThemeData(
textTheme: TextTheme(
headline: TextStyle(fontSize: 72.0, fontWeight: FontWeight.bold,color: Colors.blue),
title: TextStyle(fontSize: 36.0, fontStyle: FontStyle.italic,color: Colors.red),
body1: TextStyle(fontSize: 14.0, fontFamily: 'Hind',color: Colors.yellow),
),
),
home: LandingPage(),
);
}
}
You can then call a particular theme(headline) anywhere in your app like this:
Text('Home Page',style: Theme.of(context).textTheme.headline,)
Which gives you the headline TextTheme
I have functions for all my styles
TextStyle largeTextStyle() => TextStyle(fontSize: 150);
then I just do
Text("blah", style:largeTextStyle())
I'm very new to flutter but I'm interested in learning it pretty much from the beginning.
Right now I'm trying such a basic thing as changing the background color of some text, but I'm stuck.
import 'package:flutter/material.dart';
void main() {
final barColor = const Color(0xFFD63031);
var app = MaterialApp(
home: Scaffold(
backgroundColor: barColor,
),
);
Center(
child: Text('My Text',
textDirection: TextDirection.ltr,
),
);
runApp(app);
}
I do understand why the text doesn't show but I've been working on this for days now and I have tried a lot of different things without succeeding, so any help would be very appreciated.
Thank You
TL;DR - (Updated 07-08-2019)
Using style property (backgroundColor)
Text(
'Some text...',
style: TextStyle(backgroundColor: Colors.blue),
)
Using style property (background)
Text(
'Some text...',
style: TextStyle(background: Paint()..color = Colors.blue),
)
Using a DecoratedBox
const DecoratedBox(
decoration: const BoxDecoration(color: Colors.blue),
child: const Text('Some text...'),
);
Long answer
First of all, welcome to Flutter and StackOverflow :)
That happens because are misunderstand the way you should develop with Flutter.
As opposed to what happens with other architectures where you start in the main() function, instantiate your vars/objects and develop your flow from there, with Flutter you start your widget tree from your main() function as well, usually with a MaterialApp or CupertinoApp and fit in all its children to create your app.
So, as an example to get what you want, you must add your Center widget as the body of your Scaffold and then give a TextStyle to your Text widget, providing the property color. I gave it blue, but you can give it anything else you want. Thereby, this is your refactored code:
void main() => runApp(
MaterialApp(
home: Scaffold(
backgroundColor: const Color(0xFFD63031),
body: Center(
child: Text(
'MyText',
textDirection: TextDirection.ltr,
style: TextStyle(
background: Paint()..color = Colors.blue,
),
),
),
),
),
);
that will provide the following result
I suggest you take a look at the Awesome Flutter repo where you have a lot of good Flutter content to start with that can really help you out.
Simple you can set it in style property..
Text(
'My Text...',
style: TextStyle(backgroundColor: Colors.grey),
)
You can set this many properties to text in style: TextStyle()
{ bool inherit = true,
Color color,
Color backgroundColor,
double fontSize,
FontWeight fontWeight,
FontStyle fontStyle,
double letterSpacing,
double wordSpacing,
TextBaseline textBaseline,
double height,
Locale locale,
Paint foreground,
Paint background,
List<Shadow> shadows,
List<FontFeature> fontFeatures,
TextDecoration decoration,
Color decorationColor,
TextDecorationStyle decorationStyle,
double decorationThickness,
String debugLabel,
String fontFamily,
List<String> fontFamilyFallback,
String package
}