I have a scrollable listView full of quotes, now i want to display a toast message whenever the user scrolled to the bottom of the list. Tight now, I use scroll_edge_listener to detect the scrolling position. I tried to use 'if' condition to create a function to display a toast message, but it does not seem to be working. Really appreciate any help. Anyway, this is my code. Still new to Flutter.
import 'package:flutter/material.dart';
import 'quote.dart';
import 'package:scroll_edge_listener/scroll_edge_listener.dart';
import 'package:fluttertoast/fluttertoast.dart';
void main() => runApp(MaterialApp(
home: QuoteList(),
));
class QuoteList extends StatefulWidget {
#override
_QuoteListState createState() => _QuoteListState();
}
class _QuoteListState extends State<QuoteList> {
final controller = ScrollController(); //For detecting sroll activity
int index = 0;
List<Quote> quotes = [
Quote(author: 'Osca Wilde', text: '1'),
Quote(author: 'Oscar Wilde', text: '2'),
Quote(author: 'Osca Wilde', text: '3'),
Quote(author: 'Oscar Wilde', text: '4'),
Quote(author: 'Osca Wilde', text: '5'),
Quote(author: 'Oscar Wilde', text: '6'),
Quote(author: 'Osca Wilde', text: '7'),
Quote(author: 'Oscar Wilde', text: '8'),
Quote(author: 'Oscar Wilde', text: '6'),
Quote(author: 'Osca Wilde', text: '7'),
Quote(author: 'Oscar Wilde', text: '8'),
];
Widget quoteTemplate(quote) {
return Card(
margin: EdgeInsets.fromLTRB(16.0, 16.0, 16.0, 0.0),
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Text(
quote.text,
style: TextStyle(
fontSize: 18.0,
color: Colors.grey[800],
),
),
SizedBox(height: 6.0),
Text(
quote.author,
style: TextStyle(
fontSize: 14.0,
color: Colors.grey[800],
),
)
],
),
),
);
}
var refreshKey = GlobalKey<RefreshIndicatorState>();
#override
void initState() {
super.initState();
controller.addListener(listenScrolling);
}
void listenScrolling() {
if (controller.position.atEdge) {
final isTop = controller.position.pixels == 0;
if (isTop) {
Fluttertoast.showToast(
msg: "This is top of the list",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0);
} else {
Fluttertoast.showToast(
msg: "This is bottom of the list",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0);
}
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[200],
appBar: AppBar(
title: Text('Awesome Quotes'),
centerTitle: true,
backgroundColor: Colors.redAccent,
),
body: RefreshIndicator(
key: refreshKey,
onRefresh: refreshlist,
child: ListView(
children: quotes.map((quote) => quoteTemplate(quote)).toList(),
),
),
);
}
Future<void> refreshlist() async {
refreshKey.currentState?.show(atTop: false);
await Future.delayed(Duration(seconds: 1));
quotes.shuffle();
setState(() {});
}
}
My quote.dart model class
class Quote {
String text;
String author;
Quote({required this.text, required this.author});
}
in which scroll do you use your controller? You should use it in your ListView.
Related
I just want to pass the Featured Topics to another class, but that doesn't work. It is suggested to me to perform a zero check, but then the next ERROR comes. Also I need some help to properly display the quiz card with the answers
import 'package:flutter/material.dart';
import 'QuizScreen.item.dart';
class QuizCard {
String question;
List<String> answers;
int correctAnswerIndex;
QuizCard(
{required this.question,
required this.answers,
required this.correctAnswerIndex});
}
//------------------------------------------------------------------------------
class QuizTopic {
String topic;
List<QuizCard> quizCards;
QuizTopic({required this.topic, required this.quizCards});
}
//------------------------------------------------------------------------------
// ignore: must_be_immutable
class SchriftlFragenBW extends StatefulWidget {
const SchriftlFragenBW({super.key});
#override
State<SchriftlFragenBW> createState() => _SchriftlFragenBWState();
}
class _SchriftlFragenBWState extends State<SchriftlFragenBW> {
bool allSelected = false;
String number = '';
final List<String> _themes = [
'Theme 1',
'Theme 2',
'Theme 3',
'Theme 4',
'Theme 5',
'Theme 6',
'Theme 7',
'Theme 8',
];
final List<bool> _selected = List.filled(8, false);
final Map<String, List<QuizCard>> _quizCards = {
'Theme 1': [
QuizCard(
question: 'Question 1',
answers: ['Answer 1.1', 'Answer 1.2', 'Answer 1.3'],
correctAnswerIndex: 2),
QuizCard(
question: 'Question 1.1',
answers: ['Answer 1.1.1', 'Answer 1.1.2', 'Answer 1.1.3'],
correctAnswerIndex: 2),
],
'Theme 2': [
QuizCard(
question: 'Question 2',
answers: ['Answer 2.1', 'Answer 2.2', 'Answer 2.3'],
correctAnswerIndex: 1),
QuizCard(
question: 'Question 2.2',
answers: ['Answer 2.2.1', 'Answer 2.2.2', 'Answer 2.2.3'],
correctAnswerIndex: 1),
],
// Add more quiz cards for each theme
};
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[900],
body: ListView(
children: <Widget>[
for (int i = 0; i < _themes.length; i++)
CheckboxListTile(
value: _selected[i],
onChanged: (bool? value) {
setState(() {
_selected[i] = value ?? false;
});
},
title: Text(
_themes[i],
style: const TextStyle(color: Colors.white),
),
),
const SizedBox(
height: 8,
),
Row(
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.fromLTRB(20, 10, 10, 0),
child: Container(
decoration: BoxDecoration(
border: Border.all(
width: 1.0,
color: Colors.grey[850]!,
style: BorderStyle.solid)),
child: TextButton(
child: Text(
allSelected ? 'unselect all' : 'select all',
style: const TextStyle(color: Colors.white),
),
onPressed: () {
allSelected = !allSelected;
for (int i = 0; i < _selected.length; i++) {
_selected[i] = allSelected;
}
setState(() {});
}),
),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 10, 20, 0),
child: Container(
decoration: BoxDecoration(
border: Border.all(
width: 1.0,
color: Colors.grey[850]!,
style: BorderStyle.solid)),
child: TextButton(
child: const Text(
'learning',
style: TextStyle(color: Colors.white),
),
onPressed: () {
bool atLeastOneSelected = false;
for (int i = 0; i < _selected.length; i++) {
if (_selected[i]) {
atLeastOneSelected = true;
break;
}
}
if (atLeastOneSelected) {
List<QuizCard> quizCards = [];
for (int i = 0; i < _selected.length; i++) {
if (_selected[i]) {
quizCards.addAll(_quizCards[_themes[i]]!,
);
}
}
if (quizCards.isNotEmpty) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
QuizPage(quizCards: quizCards),
),
);
}
}
}),
),
),
),
],
),
],
),
);
}
}
//------------------------------------------------------------------------------
class QuizPage extends StatefulWidget {
final List<QuizCard> quizCards;
const QuizPage({super.key, required this.quizCards});
#override
// ignore: library_private_types_in_public_api
_QuizPageState createState() => _QuizPageState();
}
class _QuizPageState extends State<QuizPage> {
int currentQuizCardIndex = 0;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Quiz')),
body: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
widget.quizCards[currentQuizCardIndex].question,
style: const TextStyle(fontSize: 18.0),
),
),
Expanded(
child: ListView.builder(
itemCount: widget.quizCards[currentQuizCardIndex].answers.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(
widget.quizCards[currentQuizCardIndex].answers[index]),
onTap: () {
setState(() {
currentQuizCardIndex =
(currentQuizCardIndex + 1) % widget.quizCards.length;
});
},
);
},
),
),
],
),
);
}
}
I asked chatGPT, because why not, but it only gets me answers that where not very useful. I changed the code from displaying flipcharts to display quizcards with multiple answers, but now I got that ERROR and dont know why...
please can any one help me?
Text.rich widget does not work successfully with arabic text. there are a problem with the text direction.
lets give an example
when i run the app the order of the container in the below code is come reverse
that is a big problem for me
Text.rich(
TextSpan(
children: [
TextSpan(text: 'بِسۡمِ ٱللَّهِ ٱلرَّحۡمَٰنِ ٱلرَّحِيمِ'),
WidgetSpan(
child: Container(
width: 30,
height: 30,
color: Colors.green,child:Text('1'),
),
),
TextSpan(text: 'ٱلۡحَمۡدُ لِلَّهِ رَبِّ ٱلۡعَٰلَمِينَ'),
WidgetSpan(
child: Container(
width: 30,
height: 30,
color: Colors.blue,child:Text('2'),
),
),
TextSpan(text: 'ٱلرَّحۡمَٰنِ ٱلرَّحِيمِ'),
WidgetSpan(
child: Container(
width: 30,
height: 30,
color: Colors.red,child:Text('3'),
),
),
],
),
textDirection: TextDirection.rtl,
)
That's because you are WidgetSpans between TextSpans which ruins the TextDirection because WidgetSpan does not follow the directionality,
you can replace the WidgetSpan with a TextSpan and it will work I tested id
Text.rich(
TextSpan(
children: [
TextSpan(text: 'بِسۡمِ ٱللَّهِ ٱلرَّحۡمَٰنِ ٱلرَّحِيمِ'),
TextSpan(text: ' 1 ', style: TextStyle(
backgroundColor: Colors.green,
)),
TextSpan(text: 'ٱلۡحَمۡدُ لِلَّهِ رَبِّ ٱلۡعَٰلَمِينَ'),
TextSpan(text: ' 2 ', style: TextStyle(
backgroundColor: Colors.blue,
)),
TextSpan(text: 'ٱلرَّحۡمَٰنِ ٱلرَّحِيمِ'),
TextSpan(text: ' 3 ', style: TextStyle(
backgroundColor: Colors.red,
)),
],
),
style: TextStyle(
fontFamily: 'UthmanicHafs1'
),
textDirection: TextDirection.rtl,
),
Sometimes the most difficult problems can be solved by very simple things.
There may be many long and difficult ways to solve this problem.
[https://github.com/flutter/flutter/issues/54400#issuecomment-662558160][1]
But the simplest way that i found is
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Quran',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Quran Page'),
);
}
}
class MyHomePage extends StatefulWidget {
final String title;
const MyHomePage({
Key? key,
required this.title,
}) : super(key: key);
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<Widget> wrapList(List m) {
List<Widget> myList = [];
for (var i in m) {
String a = i['text'] as String;
int b = i['num'];
List l2 = a.split(' ');
myList.addAll(List.generate(l2.length, (e) {
return Text(
e == l2.length - 1 ? '${l2[e]}' : '${l2[e]} ',
style: const TextStyle(fontSize: 18),
);
}));
myList.add(
Container(
alignment: Alignment.center,
width: 20,
height: 20,
child: Text("$b"),
decoration: const BoxDecoration(
color: Colors.green,
),
),
);
}
return myList;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Wrap(
children: wrapList([
{'text': 'بِسۡمِ ٱللَّهِ ٱلرَّحۡمَٰنِ ٱلرَّحِيمِ', 'num': 1},
{'text': 'ٱلۡحَمۡدُ لِلَّهِ رَبِّ ٱلۡعَٰلَمِينَ', 'num': 2},
{'text': 'ٱلرَّحۡمَٰنِ ٱلرَّحِيمِ', 'num': 3},
{'text': 'مَٰلِكِ يَوۡمِ ٱلدِّينِ', 'num': 4},
{'text': 'إِيَّاكَ نَعۡبُدُ وَإِيَّاكَ نَسۡتَعِينُ', 'num': 5},
{'text': 'ٱهۡدِنَا ٱلصِّرَٰطَ ٱلۡمُسۡتَقِيمَ', 'num': 6},
{
'text':
'صِرَٰطَ ٱلَّذِينَ أَنۡعَمۡتَ عَلَيۡهِمۡ غَيۡرِ ٱلۡمَغۡضُوبِ عَلَيۡهِمۡ وَلَا ٱلضَّآلِّينَ',
'num': 7
},
]),
textDirection: TextDirection.rtl,
crossAxisAlignment: WrapCrossAlignment.center,
),
),
);
}
}
I am trying to do collapse paneItem in navigationpane after a lot of searcb and i didn't found anything about that if anyone used fluent ui with flutter and know how to do that it will be nice
That is mycode:
import 'dart:ui';
import 'package:fluent_ui/fluent_ui.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return FluentApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
brightness: Brightness.dark,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
int _selectedindex = 0;
bool _visible = true;
TextEditingController search = TextEditingController();
final autoSuggestBox = TextEditingController();
final values = ['Blue', 'Green', 'Yellow', 'Red'];
String? comboBoxValue;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
void initState() {
search.text = 'Search';
super.initState();
}
#override
Widget build(BuildContext context) {
return NavigationView(
appBar: NavigationAppBar(
title: Text(widget.title),
),
pane: NavigationPane(
displayMode: PaneDisplayMode.compact,
onChanged: (newindex) {
setState(() {
_selectedindex = newindex;
});
},
footerItems: [
PaneItemSeparator(),
PaneItem(
icon: const Icon(FluentIcons.settings),
title: const Text('Settings'),
),
],
selected: _selectedindex,
autoSuggestBox: AutoSuggestBox(
controller: TextEditingController(),
placeholder: 'Search',
trailingIcon: Icon(FluentIcons.search),
items: const ['Item 1', 'Item 2', 'Item 3', 'Item 4'],
),
autoSuggestBoxReplacement: const Icon(FluentIcons.search),
items: [
PaneItem(
icon: const Icon(FluentIcons.settings),
title: const Text('page 0')),
PaneItemHeader(header: Text('data')),
PaneItem(
icon: const Icon(FluentIcons.settings),
title: const Text('page 1')),
]),
content: NavigationBody(index: _selectedindex, children: [
ScaffoldPage(
padding: EdgeInsets.only(top: 0),
header: _visible
? InfoBar(
title: const Text('Update available'),
content:
const Text('Restart the app to apply the latest update.'),
severity: InfoBarSeverity.info,
onClose: () {
setState(() => _visible = false);
})
: null,
content: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
width: 200,
child: AutoSuggestBox(
controller: autoSuggestBox,
items: const [
'Blue',
'Green',
'Red',
'Yellow',
'Grey',
],
onSelected: (text) {
print(text);
}),
),
SizedBox(
height: 20,
),
SizedBox(
width: 200,
child: Combobox<String>(
placeholder: Text('Selected list item'),
isExpanded: true,
items: values
.map((e) => ComboboxItem<String>(
value: e,
child: Text(e),
))
.toList(),
value: comboBoxValue,
onChanged: (value) {
// print(value);
if (value != null) setState(() => comboBoxValue = value);
},
),
),
SizedBox(
height: 20,
),
FilledButton(
style: ButtonStyle(
backgroundColor: ButtonState.all(Colors.blue)),
onPressed: () {
// showDialog(
// context: context,
// builder: (context) {
// return ContentDialog(
// title: Text('No WiFi connection'),
// content: Text('Check your connection and try again'),
// actions: [
// Button(
// child: Text('Ok'),
// onPressed: () {
// Navigator.pop(context);
// })
// ],
// );
// },
// );
},
child: const Icon(FluentIcons.add),
)
],
),
),
),
const ScaffoldPage(
header: PageHeader(
title: Text(
'Your Page 1',
textAlign: TextAlign.center,
)),
content: Center(child: Text('Page 1')),
),
const ScaffoldPage(
header: PageHeader(
title: Text(
'Your Page 2',
textAlign: TextAlign.center,
)),
content: Center(child: Text('Page 2')),
),
const ScaffoldPage(
header: PageHeader(
title: Text(
'Your Page 3',
textAlign: TextAlign.center,
)),
content: Center(child: Text('Page 3')),
),
]),
);
}
}
I am trying to do multi-level of paneItem in navigationpane in fluent ui in flutter but i don't know how to do that if anyone used fluent ui with flutter and know how to do that it will be nice
I'm trying to create a custom Alert dialogue using this package rflutter_alert . But when return the Alert it gives me this error
The argument type 'Future<bool?>' can't be assigned to the parameter type 'Widget?'.
Update:
here i created a custom widget of dialogue
class DialogueTwoButton extends StatelessWidget {
DialogueTwoButton(
{Key? key,
context,
required this.text1,
required this.text2,
required this.onpres1,
required this.onpress2})
: super(key: key);
final String text1;
final String text2;
final Function onpres1;
final Function onpress2;
#override
Widget build(BuildContext context) {
return _onAlertButtonsPressed(context, text1, text2, onpres1, onpress2);
}
var alertStyle = AlertStyle(
animationType: AnimationType.fromTop,
isCloseButton: false,
isOverlayTapDismiss: false,
descStyle: GoogleFonts.montserrat(color: Colors.black, fontSize: 18),
titleStyle: GoogleFonts.montserrat(
color: Colors.red,
),
);
_onAlertButtonsPressed(context, desc, title, onPressYes, onPressNo) {
return Alert(
context: context,
style: alertStyle,
title: title,
desc: desc,
buttons: [
DialogButton(
child: Text(
"Yes",
style: GoogleFonts.montserrat(color: Colors.white, fontSize: 18),
),
onPressed: onPressYes,
color: HexColor("#5344ed")),
DialogButton(
child: Text(
"No",
style: GoogleFonts.montserrat(color: Colors.white, fontSize: 18),
),
onPressed: onPressNo,
color: HexColor("#5344ed"),
)
],
).show(); // here need to change
}
and here is my other file where i'm creating a button
updateProduct() {
DialogueTwoButton(
onpres1: () {},
onpress2: () {},
text1: 'df',
text2: 'dsf',
);
bottomButton(context, () {
updateProduct();
}, "Update Product"),
and updateProduct(); on this mehtod calling the custom class dialogue, but it's not showing , i want to do this something in this way.
please help how to do this.
you missing one closing ) bracket after ).show()
_onAlertButtonsPressed(context,desc,title,onPressYes,onPressNo) {
return Alert(
context: context,
style: alertStyle,
title: title,
desc: desc,
buttons: [
DialogButton(
child: Text(
"Yes",
style: GoogleFonts.montserrat(color: Colors.white, fontSize: 18),
),
onPressed: onPressYes,
color: HexColor("#5344ed")),
DialogButton(
child: Text(
"No",
style: GoogleFonts.montserrat(color: Colors.white, fontSize: 18),
),
onPressed: onPressNo,
color: HexColor("#5344ed"),
)
],
).show(); // here need to change
}
Complete src code:
import 'package:flutter/material.dart';
import 'package:rflutter_alert/rflutter_alert.dart';
const Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: darkBlue,
),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MyHomePage(),
),
),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key key}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
TextEditingController _textEditingController = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("title"),
),
body: Column(
children: [
InkWell(onTap: (){
_onAlertButtonsPressed(context,"test","title",(){},(){});
}, child: Text("test")),
],
),
);
}
}
_onAlertButtonsPressed(context,String desc,String title,onPressYes,onPressNo) {
return Alert(
context: context,
//style: alertStyle,
title: title,
desc: desc,
buttons: [
DialogButton(
child: Text(
"Yes",
//style: GoogleFonts.montserrat(color: Colors.white, fontSize: 18),
),
onPressed: onPressYes,
//color: HexColor("#5344ed")
),
DialogButton(
child: Text(
"No",
// style: GoogleFonts.montserrat(color: Colors.white, fontSize: 18),
),
onPressed: onPressNo,
// color: HexColor("#5344ed"),
)
],
).show(); // here need to change
}
Try below code hope its helpful to you. remove Container and Widget
onAlertButtonsPressed(context, desc, title, onPressYes, onPressNo) {
return Alert(
context: context,
style: alertStyle,
title: title,
desc: desc,
buttons: [
DialogButton(
child: Text(
"Yes",
),
onPressed: onPressYes,
),
DialogButton(
child: Text(
"No",
),
onPressed: onPressNo,
)
],
).show();
}
I have a Textfield widget that will be filled by the user. The problem is apart from filling in with text, the user should also have the ability to choose from a list of tags that could be added in between(or end) the text, an example case is shown in figure (In the figure I have used two text widgets and a chip, in actual case it will be a textfield and not text widget).
The solution from here doesn't fulfill the requirement since it only adds the chips and not the text. I also checked out the Extended text field package it didn't work out either. Any idea how to solve this?
Using the package extended_text_field package.
Result:
Whenever there's an # symbol, it will be in a Chip:
You need to extend SpecialTextSpanBuilder and override the build:
class MySpecialTextSpanBuilder extends SpecialTextSpanBuilder {
#override
TextSpan build(String data,
{TextStyle? textStyle, SpecialTextGestureTapCallback? onTap}) {
final lookingFor = "#";
final splitData = data.split(" ");
final spans = splitData.map((e) {
if (e == lookingFor) {
return WidgetSpan(
child: Chip(
label: Text(e),
),
);
} else {
return TextSpan(
text: e,
style: TextStyle(color: Colors.red),
);
}
}).toList();
return TextSpan(children: spans, style: textStyle);
}
#override
SpecialText? createSpecialText(String flag,
{TextStyle? textStyle,
SpecialTextGestureTapCallback? onTap,
required int index}) {
// TODO: implement createSpecialText
throw UnimplementedError();
}
}
In this code, if the text contains an # symbol, then well create a Chip with that data, otherwise, we'll add the actual text.
To use the created MySpecialTextSpanBuilder class:
Scaffold(
backgroundColor: Colors.blue,
body: ExtendedTextField(
style: TextStyle(color: Colors.red),
decoration: InputDecoration(
border: OutlineInputBorder(),
),
specialTextSpanBuilder: MySpecialTextSpanBuilder(),
),
)
Complete runnable snippet:
import 'package:extended_text_field/extended_text_field.dart';
import 'package:flutter/material.dart';
const Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
dividerColor: Colors.green,
scaffoldBackgroundColor: darkBlue,
),
debugShowCheckedModeBanner: false,
home: SafeArea(
child: Scaffold(
backgroundColor: Colors.blue,
body: ExtendedTextField(
cursorColor: Colors.black,
style: TextStyle(color: Colors.red),
decoration: InputDecoration(
border: OutlineInputBorder(),
),
specialTextSpanBuilder: MySpecialTextSpanBuilder(),
),
),
),
);
}
}
class MySpecialTextSpanBuilder extends SpecialTextSpanBuilder {
#override
TextSpan build(String data,
{TextStyle? textStyle, SpecialTextGestureTapCallback? onTap}) {
final lookingFor = "#";
final splitData = data.split(" ");
final spans = splitData.map((e) {
if (e == lookingFor) {
return WidgetSpan(
child: Chip(
label: Text(e),
),
);
} else {
return TextSpan(
text: e,
style: TextStyle(color: Colors.red),
);
}
}).toList();
return TextSpan(children: spans, style: textStyle);
}
#override
SpecialText? createSpecialText(String flag,
{TextStyle? textStyle,
SpecialTextGestureTapCallback? onTap,
required int index}) {
// TODO: implement createSpecialText
throw UnimplementedError();
}
}
Using a Text widget
You can use RichText with a WidgetSpan as a child:
An immutable widget that is embedded inline within text.
Result
Code
RichText(
text: TextSpan(
children: [
TextSpan(
text: "one",
),
WidgetSpan(
child: Chip(
label: Text("two"),
),
),
TextSpan(
text: "three",
),
],
),
)