How to create custom InlineSpans in Flutter? - flutter

How can I reuse pieces of code of InlineSpan type (e.g. TextSpan, WidgetSpan).
For example,
Text.rich(
TextSpan(
children: [
WidgetSpan(...), // code I like to reuse
... // other stuff
],
),
)
Of course I can write a function, that gives me this InlineSpan, like this:
InlineSpan myCustomWidgetSpan() {
return WidgetSpan(...);
}
This is technically ok, but usually I reuse parts of code by creating a class that extends some other Flutter class (like StatelessWidget or StatefulWidget).
I think that there should be some more idiomatic approach to this. So what are the best practices for reusing code that produces InlineSpan?

You can copy paste run full code below
You can use package https://pub.dev/packages/span_builder
code snippet
final spans = SpanBuilder("The quick brown fox")
.apply(TextSpan(text: "brown", style: TextStyle(fontWeight: FontWeight.bold)))
.apply(TextSpan(text: "🦊"), whereText: "fox")
.build();
Text.rich(
TextSpan(
children: spans
),
),
working demo
full code
import 'package:flutter/material.dart';
import 'package:span_builder/span_builder.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
final spans = SpanBuilder("The quick brown fox")
.apply(TextSpan(text: "brown", style: TextStyle(fontWeight: FontWeight.bold)))
.apply(TextSpan(text: "🦊"), whereText: "fox")
.build();
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text.rich(
TextSpan(
children: spans
),
),
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}

Related

FLUTTER: How to set auto font size in TextSpan

I want to implement that text with divider in between lines:
Smart City Text
Do you guys have any ideas how can I implement that in flutter? I tried few things but it is kind of a challenge for me, because I am beginner. Divider line have to be long as text above and under line.
You can make a screen using auto_size_text package.
Using AutoSizeText and AutoSizeText.rich widget in that package,
and set a maxLines option to 1 and set font size big.
Because we set maxLines to 1, although set font size big, text will not be overflowed screen.
import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: _buildBody(),
floatingActionButton: FloatingActionButton(
onPressed: () {},
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
Widget _buildBody() {
return Container(
padding: EdgeInsets.symmetric(horizontal: 50, vertical: 30),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
AutoSizeText(
'Smart City',
maxLines: 1,
style: TextStyle(
fontSize: 100,
fontWeight: FontWeight.bold,
),
),
Divider(color: Colors.black),
AutoSizeText.rich(
TextSpan(
children: [
TextSpan(
text: 'Advanced',
),
TextSpan(
text: ' urban',
style: TextStyle(
fontWeight: FontWeight.bold,
),
),
TextSpan(
text: ' lighting solution',
),
],
),
style: TextStyle(fontSize: 100),
maxLines: 1,
),
],
),
);
}
}

I need hashtag sign in url launcher TEL, but it gets removed automatically

i want to dial this number as it is, in flutter url launcher but it removes the hashtag sign in the last bit of the String,
onTap: () {
String no = '*477*4*1#';
launch('tel:$no');
},
You can copy paste run full code below
You can use Uri.encodeComponent('*477*4*1#');
code snippet
onPressed: () {
String no = Uri.encodeComponent('*477*4*1#');
launch('tel:$no');
},
working demo
full code
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
child: Text('click'),
onPressed: () {
String no = Uri.encodeComponent('*477*4*1#');
launch('tel:$no');
},
),
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
You need to use URL Encoding for special character so # is equals to \%23.

Flutter: Live TV channel steaming problem

I want streaming a Live TV channel. That's why I used flutter_vlc_player 3.0.3.
When I click the button to starting live TV channel, sometimes it takes a long time to open and sometimes doesn't open.
But When I click the button to starting live TV channel and then pressed "R" for Hot reload in terminal, at this time it opens quickly.
Here is my source code:
import 'package:flutter/material.dart';
import 'package:flutter_vlc_player/flutter_vlc_player.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String _streamUrl;
VlcPlayerController _vlcViewController;
#override
void initState() {
super.initState();
_vlcViewController = new VlcPlayerController();
}
void _incrementCounter() {
setState(() {
if (_streamUrl != null) {
_streamUrl = null;
} else {
_streamUrl =
"http://tempe.appv.jagobd.com:1934/c5V6mmMyX7RpbEU9Mi8xNy8yMDEOGIDU6RgzQ6NTAgdEoaeFzbF92YWxIZTO0U0ezN1IzMyfvcGVMZEJCTEFWeVN3PTOmdFsaWRtaW51aiPhnPTI/atnws-sg.stream/playlist.m3u8";
}
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
_streamUrl == null
? Container(
child: Center(
child: RichText(
text: TextSpan(children: [
TextSpan(
text: 'Stream Closed',
style: TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.bold,
color: Colors.white,
background: Paint()..color = Colors.red),
)
]),
),
),
)
: Container(
child: new VlcPlayer(
url: _streamUrl,
controller: _vlcViewController,
placeholder: Container(),
aspectRatio: 16 / 9,
),
)
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
child: Icon(_streamUrl == null ? Icons.play_arrow : Icons.pause),
),
);
}
}
Why does it behave like this and How can I fix this ?
I think it seems you need setState and you should initialize it inside a function like this:
_vControllerInit() async {
final response = await Dio().post(
"http://jsonplaceholder/api/v1/android-tv/movies",);
final data = MoviePlayerModel.fromJson(response.data);
_vController = VlcPlayerController.network(data.data!.file!);
setState(() {});
}

Flutter Web: How to fix SelectableText alignment?

I have a SelectableText and Icon inside a Row, but SelectableText does not seem to be properly aligned.
Right now it looks like this,
Expected Result:
This is code I am using,
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Icon(FontAwesomeIcons.whatsapp),
const Padding(padding: EdgeInsets.only(left: 8)),
SelectableText(
'+91-8**2**8**5',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.title,
)
],
),
PS: It works well with Text but I want SelectableText instead.
Issue Selectabletext widget on web is cutted on half
https://github.com/flutter/flutter/issues/40663 has been solved.
please upgrade to latest version
attached my full test code and result
full test code
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.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',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Icon(FontAwesomeIcons.whatsapp),
const Padding(padding: EdgeInsets.only(left: 8)),
SelectableText(
'+91-8**2**8**5',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.title,
)
],
),
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}

Using FontAwesomeIcons with value from custom class in Flutter

I'm trying to use fontawesome together with flutter. Depending on certain content of an Item I'd like to display a certain Icon from fontawesome.
Transaction(id: 1, title: 'lunch', amount: -23.10, type:'utensils'),
Transaction(id: 2, title: 'new shows', amount: -59.99, type:'tshirt'),
Transaction(id: 3, title: 'Falcon launch', amount: -62000000, type:'rocket')
so, I'd like to use the type as an indicator for my fontawesome icon.
When using FontAwesomeIcons.rocket, everything works quite well.
Column(children: <Widget>[
Card(
child: IconButton(
onPressed: null,
icon: new Icon(FontAwesomeIcons.rocket),
),
elevation: 0,
)
],),
since I'm using the map function I'm able to call the type itself without an issue like Text(tx.type). Is there a way to replace the static (in my case) rocket with the type from my transaction class? I'm trying to avoid if/switch cases at the moment just to get the basics going.
Any help very appreciated.
You can copy paste run full code below
You can use https://pub.dev/packages/icons_helper
just prefix rocket with fa.rocket
code snippet
Icon(getIconUsingPrefix(name: 'fa.rocket'),
color: Theme.of(context).backgroundColor, size: 60.0),
working demo
full code
import 'package:flutter/material.dart';
import 'package:icons_helper/icons_helper.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',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo + Icon Helper Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
Map iconMap = {"a":'fa.rocket'};
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(getIconUsingPrefix(name: 'fa.fiveHundredPx'),
color: Theme.of(context).backgroundColor, size: 60.0),
Icon(getIconUsingPrefix(name: 'fa.rocket'),
color: Theme.of(context).backgroundColor, size: 60.0),
Icon(getIconUsingPrefix(name: iconMap["a"]),
color: Theme.of(context).backgroundColor, size: 60.0),
Text(
'There should be an icon above. It\'s neat, isn\'t?\n\nYou can also push the + button and increment this counter for fun:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}