How can I pass a List to another class - flutter

I have a list in this file called check_symptoms.dart which the list is called _chosenItems
i want it to pass it to another file which is a stateful widget
here's my code for Check_symptoms.dart
import 'package:diagnose_app/results.dart';
import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:flutter/services.dart';
class SymptomsChecker extends StatefulWidget {
const SymptomsChecker({Key? key}) : super(key: key);
#override
State<SymptomsChecker> createState() => _SymptomsCheckerState();
}
class _SymptomsCheckerState extends State<SymptomsChecker> {
List _items = [];
List _itemsForDisplay = [];
List _chosenItems = [];
int maxheight = 0;
ScrollController _scrollController = ScrollController();
Future<void> readJson() async {
final String response =
await rootBundle.loadString('assets/data/Symptoms.json');
final data = await json.decode(response);
setState(() {
_items = data["Symptoms"];
_itemsForDisplay = _items;
});
}
#override
void initState() {
// TODO: implement initState
readJson();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color.fromARGB(255, 105, 120, 255),
body: Padding(
padding: const EdgeInsets.all(5),
child: Column(
children: [
// Display the data loaded from sample.json
// _ListChosenItem(23),
SizedBox(
height: 25,
),
_searchBar(),
Divider(
height: 1,
),
Expanded(
child: ListView.builder(
itemBuilder: (context, index) {
return _ListItem(index);
},
itemCount: _itemsForDisplay.length,
),
),
Divider(
height: 2,
),
Padding(
padding: const EdgeInsets.all(3.0),
child: LimitedBox(
maxHeight: 200,
child: Scrollbar(
controller: _scrollController,
child: SingleChildScrollView(
//scrollDirection: Axis.horizontal,
child: Wrap(
children: _chosenItems.map((item) {
//print(_chosenItems);
return chosenItems(item);
}).toList(),
),
),
),
),
),
Divider(
color: Colors.black,
height: 10,
thickness: 1,
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: Container(
height: 50,
width: double.infinity,
child: ElevatedButton(
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
// sending chosenItems to results.dart
builder: (context) => Results(list: _chosenItems)));
},
child: Text(
"Find Results",
style: TextStyle(fontSize: 20, fontWeight: FontWeight.w500),
),
style: ElevatedButton.styleFrom(),
),
),
),
SizedBox(
height: 5,
),
],
),
),
);
}
Padding chosenItems(item) {
return Padding(
padding: const EdgeInsets.all(3.0),
child: Builder(builder: (context) {
return ElevatedButton.icon(
onPressed: () {
setState(() {
_itemsForDisplay.add(item);
//_items.add(item);
_chosenItems.remove(item);
});
},
style: ElevatedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10)),
textStyle:
const TextStyle(fontSize: 15, fontWeight: FontWeight.w400)),
label: Text(item),
icon: Icon(
Icons.remove_circle,
color: Color.fromARGB(255, 255, 217, 216),
),
);
}),
);
}
_searchBar() {
return Padding(
padding: const EdgeInsets.all(8),
child: TextField(
decoration: InputDecoration(
border: OutlineInputBorder(borderRadius: BorderRadius.circular(10)),
filled: true,
fillColor: Color.fromARGB(255, 244, 244, 244),
hintText: 'Search Symptoms'),
style: TextStyle(color: Color.fromARGB(255, 22, 25, 52)),
maxLines: 1,
onChanged: (text) {
text = text.toLowerCase();
setState(() {
_itemsForDisplay = _items.where((item) {
var itemEntity = item.toLowerCase();
return itemEntity.contains(text);
}).toList();
});
},
),
);
}
_ListItem(index) {
return Wrap(
children: [
ElevatedButton(
onPressed: () {
setState(() {
_chosenItems.add(_itemsForDisplay[index]);
_itemsForDisplay.removeAt((index));
//_items.removeAt((index));
});
},
style: ElevatedButton.styleFrom(
textStyle:
const TextStyle(fontSize: 18, fontWeight: FontWeight.w500)),
child: Text(_itemsForDisplay[index]),
),
],
);
}
_ListChosenItem(index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Wrap(
children: [
ElevatedButton(
onPressed: () {},
style: ElevatedButton.styleFrom(
textStyle: const TextStyle(fontSize: 20)),
child: Text(_chosenItems[index]),
),
],
),
);
}
}
here's the way I'm receiving the list in results.dart
import 'package:flutter/material.dart';
class Results extends StatefulWidget {
final List list;
const Results({required this.list});
#override
State<Results> createState() => _ResultsState(list);
}
class _ResultsState extends State<Results> {
#override
Widget build(BuildContext context) {
print(list);
return Scaffold();
}
}
this line of code of results.dart
State<Results> createState() => _ResultsState(list);
is says:
List list Type: List
package:diagnose_app/results.dart
Don't put any logic in createState.dartno_logic_in_create_state Too
many positional arguments: 0 expected, but 1 found. Try removing the
extra arguments.
Am I passing the list in a wrong way? thanks for helping in advance.

First of all, an instance of State can access the members of its parent StatefulWidget via the widget property.
So your particular problem can be solved simply by accessing widget.list, you don't need to pass the list explicitly to _ResultsState:
import 'package:flutter/material.dart';
class Results extends StatefulWidget {
final List list;
const Results({required this.list});
#override
State<Results> createState() => _ResultsState();
}
class _ResultsState extends State<Results> {
#override
Widget build(BuildContext context) {
print(widget.list);
return Scaffold();
}
}
But further, if you do want to explicitly pass a value to a class constructor, you'll need to add the field as a member to the class and define the constructor that takes that value.

Related

The problem happens in the ListView.builder which the card can't clip at the top

The problem happens in the ListView.builder which the card can't clip at the top.Is my code have anything missing? How can I do?
The problem happens in the ListView.builder which the card can't clip at the top. Is my code have anything missing? How can I do?
The problem happens in the ListView.builder which the card can't clip at the top. Is my code have anything missing? How can I do?
There are a space between the card and with the top
[1]: https://i.stack.imgur.com/fpJ4h.png
This is what I want and expected
[2]: https://i.stack.imgur.com/aAhmh.png
This is the AllProduct.dart
import 'package:flutter/material.dart';
import 'package:penang_beachess/blog_page/blog_page.dart';
import 'package:penang_beachess/provider/favorite_list.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:penang_beachess/widget/background-image.dart';
import 'package:provider/provider.dart';
import '../widget/background.dart';
class AllBlog extends StatefulWidget {
const AllBlog({Key? key}) : super(key: key);
#override
State<AllBlog> createState() => _AllBlogState();
}
class _AllBlogState extends State<AllBlog> {
bool _isBookmarked(Beach newAddBeach) {
List favoritedBeach = favoriteBeachList;
if (favoritedBeach.contains(newAddBeach)) {
return true;
}
return false;
}
#override
Widget build(BuildContext context) {
var favoriteList = Provider.of<favoriteProvider>(context);
return Stack(
children: [
//problem Here
ListView.builder(
itemCount: beachList.length,
itemBuilder: (context, index) {
Beach beach = beachList[index];
int currentIndex = index;
return Card(
child: ListTile(
title: Text(beach.title,
style: GoogleFonts.permanentMarker(
textStyle: TextStyle(fontSize: 15),
)),
subtitle: Row(
children: [
const Icon(
Icons.location_on,
size: 16.0,
),
Text(
beach.location,
style: GoogleFonts.permanentMarker(
textStyle: TextStyle(fontSize: 12.0),
),
overflow: TextOverflow.ellipsis,
),
],
),
leading: SizedBox(
height: 80,
width: 80,
child: Image.asset(beach.urlToImage1),
),
// add bookmark here
trailing: IconButton(
onPressed: () {
if (!_isBookmarked(beach)) {
setState(() {
favoriteBeachList.add(beachList[currentIndex]);
});
} else {
setState(() {
favoriteBeachList.remove(beachList[currentIndex]);
});
}
Beach _beach = Beach(
title: beachList[index].title,
location: beachList[index].location,
source: beachList[index].source,
author: beachList[index].author,
description: beachList[index].description,
urlToImage1: beachList[index].urlToImage1,
urlToImage2: beachList[index].urlToImage2,
facilities: beachList[index].facilities,
urlToImage3: beachList[index].urlToImage3,
status: beachList[index].status,
likeCount: beachList[index].likeCount,
);
if (_beach.status == 'false') {
setState(() {
beachList[index].status = 'true';
});
favoriteList.addToList(_beach);
} else if (_beach.status == 'true') {
setState(() {
beachList[index].status = 'false';
});
favoriteList.removeFromList(_beach);
}
},
icon: Icon(_isBookmarked(beach)
? Icons.bookmark
: Icons.bookmark_border),
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => BlogPage(beach)));
}),
);
}),
],
);
}
}
This is Home.dart
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';
import 'package:two_life/model/product.dart';
import 'package:two_life/model/provider.dart/favorite_list.dart';
import 'package:two_life/screens/ReProductDetail.dart/Re3.dart';
import 'package:two_life/screens/allproduct.dart';
import 'package:two_life/screens/homepagecard.dart';
import 'package:two_life/screens/productDetails.dart';
import 'ReProductDetail.dart/Re1.dart';
import 'ReProductDetail.dart/Re2.dart';
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
color: Color.fromRGBO(211, 211, 211, 1),
child: Align(
alignment: Alignment.center,
child: Column(
children: [
SizedBox(
height: 70,
),
Container(
width: 350,
height: 100,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(30),
),
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Text(
"Welcome to 2.LIFE!\n\n Enjoy your shopping with us via 2.LIFE!!",
style:
TextStyle(fontWeight: FontWeight.bold, fontSize: 17)),
),
),
SizedBox(
height: 15,
),
Container(
width: 350,
child: Padding(
padding: const EdgeInsets.all(5.0),
child: Text("Recommended",
style:
TextStyle(fontWeight: FontWeight.bold, fontSize: 17)),
),
),
Container(
child: listview(),
),
Container(
width: 350,
height: 30,
child: Padding(
padding: const EdgeInsets.all(5.0),
child: Text("All Product",
style:
TextStyle(fontWeight: FontWeight.bold, fontSize: 17)),
),
),
// Here is the SizedBox for the AllProduct in AllProduct.dart
SizedBox(
height: 280,
child: AllProduct(),
),
],
),
),
));
}
}
class listview extends StatefulWidget {
const listview({super.key});
#override
State<listview> createState() => _listviewState();
}
class _listviewState extends State<listview> {
#override
Widget build(BuildContext context) {
return Container(
height: 200,
child: ListView(
scrollDirection: Axis.horizontal,
children: [
//Product 1
Padding(
......

how to append the callback data to Text widget flutter

In my page I have to open dialog and in that dialog we have to show listview of data. Once the user click any item in listview he have to show the item data to listview. I am using callback here. Can any one tell me how to pass the data to page (Text widget) .
code:
class PosSettingsPage extends StatefulWidget {
const PosSettingsPage({Key? key}) : super(key: key);
#override
State<StatefulWidget> createState() => _PosSettingPageState();
}
class _PosSettingPageState extends State<PosSettingsPage> {
#override
Widget build(BuildContext context) {
printerTerminalType = _documentService.hardware.paymentTerminalType.name;
return Scaffold(
........
........
InkWell(
onTap: () {
**openAppDialog(
context,
_buildContentDialog(
context, PaymentTerminalTypeName));**
},
child: Container(
margin: const EdgeInsets.only(left: 25),
width: 300,
decoration: BoxDecoration(
border: Border.all(color: Colors.white),
borderRadius: const BorderRadius.all(
Radius.circular(5),
),
),
child: Padding(
padding: const EdgeInsets.all(10.0),
/// This Text widget
child: Text(
printerTerminalType,
style: Theme.of(context)
.textTheme
.headline1
?.copyWith(color: Colors.white),
),
),
),
),
}
AppDialog _buildContentDialog(BuildContext context, List<String> data) {
return AppDialog(
dataList: data,
onValueChanged: (text) {
/// I want to append this "text" to text widget
},
);
}
}
class AppDialog extends StatefulWidget {
List<String> dataList = [];
final ValueChanged<String> onValueChanged;
AppDialog({
Key? key,
required this.dataList,
required this.onValueChanged,
}) : super(key: key);
#override
State<StatefulWidget> createState() => _AppDialogState();
}
class _AppDialogState extends State<AppDialog> {
TextEditingController editingController = TextEditingController();
final List<String>? items = [];
#override
void initState() {
items?.addAll(widget.dataList);
super.initState();
}
void filterSearchResults(String query) {
List<String> dummySearchList = <String>[];
dummySearchList.addAll(widget.dataList);
if (query.isNotEmpty) {
List<String> dummyListData = <String>[];
for (var item in dummySearchList) {
if (item.contains(query)) {
dummyListData.add(item);
}
}
setState(() {
items?.clear();
items?.addAll(dummyListData);
});
return;
} else {
setState(() {
items?.clear();
items?.addAll(widget.dataList);
});
}
}
#override
Widget build(BuildContext context) {
return Dialog(
child: SizedBox(
width: 500,
height: 400,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
onChanged: (value) {
filterSearchResults(value);
},
controller: editingController,
decoration: const InputDecoration(
hintText: "Search list",
hintStyle: TextStyle(fontSize: 12.0, color: Colors.white24),
),
),
),
Expanded(
child: SizedBox(
height: MediaQuery.of(context).size.height,
child: ListView.builder(
shrinkWrap: true,
itemCount: items?.length,
itemBuilder: (context, index) {
return ListTile(
onTap: (){
widget.onValueChanged.call(items![index].toString());
Navigator.pop(context);
},
title: Text(items![index],style: Theme.of(context).textTheme.headline5,),
);
},
),
),
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
margin: const EdgeInsets.all(10.0),
width: double.infinity,
child: Center(
child: Text(
'Cancel',
style: Theme.of(context).textTheme.subtitle1,
),
),
),
)
],
),
),
);
}
}
Future<void> openAppDialog(BuildContext context, Widget appDialog,) async {
return showDialog<dynamic>(
context: context,
builder: (BuildContext context) {
return appDialog;
},
);
}

I got an error when i want to pass the qr read data to my text field

I got an error when I want to pass the QR read data to my text field. I open camera first and dont get any error. But in second, i get a dump
Exception has occurred.
_AssertionError ('package:flutter/src/rendering/object.dart': Failed assertion: line 2250 pos 12: '!_debugDisposed': is not true.)
QR Scanner Widget:
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:intesasoft_case_study/screens/home_screen.dart';
import 'package:intesasoft_case_study/widgets/custom_appbar.dart';
import 'package:qr_code_scanner/qr_code_scanner.dart';
import '../controllers/controller.dart';
class ScannerWidget extends StatefulWidget {
const ScannerWidget({Key? key}) : super(key: key);
#override
State<ScannerWidget> createState() => _ScannerWidgetState();
}
class _ScannerWidgetState extends State<ScannerWidget> {
CitiesController c = Get.find();
final qrKey = GlobalKey(debugLabel: 'QR');
Barcode? barcode;
QRViewController? controller;
#override
void dispose() {
controller?.dispose();
super.dispose();
}
#override
void reassemble() async {
super.reassemble();
if (Platform.isAndroid) {
await controller!.pauseCamera();
}
controller!.resumeCamera();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: const PreferredSize(
child: CustomAppbar(),
preferredSize: Size.fromHeight(70),
),
body: Stack(
alignment: Alignment.center,
children: [
buildQrView(context),
Positioned(bottom: 10, child: buildResult())
],
),
);
}
Widget buildResult() => Container(
color: Colors.white,
child: Text(
barcode != null ? 'Result : ${barcode!.code}' : 'Scan a code',
maxLines: 3,
),
);
Widget buildQrView(BuildContext context) => QRView(
key: qrKey,
onQRViewCreated: onQRViewCreated,
overlay: QrScannerOverlayShape(),
);
void onQRViewCreated(QRViewController controller) {
setState(() => this.controller = controller);
controller.scannedDataStream.listen((barcode) => setState(() {
this.barcode = barcode;
print(barcode.code);
c.qrVal.value = barcode.code!;
Get.back();
}));
}
}
HomeScreen:
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:intesasoft_case_study/models/response_model.dart';
import 'package:intesasoft_case_study/screens/city_details_screen.dart';
import 'package:intesasoft_case_study/utils/colors.dart';
import 'package:intesasoft_case_study/widgets/custom_appbar.dart';
import 'package:intesasoft_case_study/widgets/drawer.dart';
import 'package:intesasoft_case_study/widgets/scanner.dart';
import '../controllers/controller.dart';
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
#override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
final textController = TextEditingController();
List<ResponseModel> _foundedCityList = [];
var scaffoldKey = GlobalKey<ScaffoldState>();
void openDrawer() {
scaffoldKey.currentState!.openDrawer();
}
CitiesController c = Get.find();
#override
void initState() {
c.getCitiesData();
_foundedCityList = c.cities;
super.initState();
}
void _runFilter(String enteredKeyword) {
List<ResponseModel> results = [];
if (enteredKeyword.isEmpty) {
results = c.cities;
} else {
results = c.cities
.where((data) =>
data.name!.toLowerCase().contains(enteredKeyword.toLowerCase()))
.toList();
// toLowerCase() method to make it case-insensitive
}
setState(() {
_foundedCityList = results;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: scaffoldKey,
appBar: PreferredSize(
child: CustomAppbar(
onPressed: () => openDrawer(),
),
preferredSize: const Size.fromHeight(70),
),
drawer: const DrawerWidget(),
body: Container(
padding: const EdgeInsets.all(24),
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
elevation: 10,
child: Obx(
() => Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Expanded(
child: TextField(
controller: textController,
onChanged: (value) {
_runFilter(value);
},
textInputAction: TextInputAction.search,
decoration: InputDecoration(
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: borderColor,
),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.grey,
),
),
hintText: c.qrVal.value,
hintStyle: TextStyle(color: Colors.grey)),
),
),
IconButton(
onPressed: () {
Get.to(() => ScannerWidget());
},
icon: const Icon(Icons.camera_alt_rounded),
),
],
),
),
const SizedBox(height: 10),
Container(
padding: const EdgeInsets.only(left: 16, top: 8),
color: Colors.red,
width: double.infinity,
height: 40,
child: const Text(
'Şehirler',
textAlign: TextAlign.start,
style: TextStyle(color: Colors.white),
),
),
Expanded(
child: ListView.builder(
itemCount: _foundedCityList.length,
itemBuilder: (ctx, i) {
return Column(
children: [
ListTile(
leading: CircleAvatar(
radius: 25,
backgroundColor: Colors.white,
child: Image.network(
_foundedCityList[i].image == null
? imageUrl
: _foundedCityList[i].image!,
fit: BoxFit.cover,
),
),
title: Text(_foundedCityList[i].name!),
subtitle: Text('Nüfus: ' +
_foundedCityList[i]
.populations![0]
.population!),
trailing: IconButton(
onPressed: () {
Get.to(const CityDetailsScreen(),
arguments: _foundedCityList[i].id);
print(_foundedCityList[i].id);
},
icon: const Icon(Icons.remove_red_eye)),
),
const Divider(
color: Colors.red,
thickness: 1,
),
],
);
},
),
),
],
),
),
),
),
);
}
}

Does anyone know what's going on with my Listview?

I needed to insert a TextField to search/filter records, but I don't know what's going on.
When I click on the "Cães" option of the BottomNavigationBar, on main.dart,
I only get a CircularProgressIndicator and the data does show up.
Have any of you experienced this problem?
Does anyone know why my Listview doesn't show up?
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:ssk_final/addeditpage.dart';
//import 'package:flutter_localizations/flutter_localizations.dart';
List<dynamic> list = [];
class CaesPage extends StatefulWidget {
// CaesPage({Key key}) : super(key: key);
#override
_CaesPageState createState() => _CaesPageState();
Widget build(BuildContext context) {
return Container(
child: Center(
child: Text("Cadastro de Cães"),
),
);
}
}
class _CaesPageState extends State<CaesPage> {
String searchString = "";
Future<List<Caes>> caes;
Future getData() async {
var url = 'http://.../api2.php?opcao=read';
var response = await http.get(Uri.parse(url));
return json.decode(response.body);
}
/*
Future _showMyDialog(id, nome) async {
return showDialog<void>(
context: context,
barrierDismissible: false, // user must tap button
builder: (BuildContext context) {
return AlertDialog(
title: Text('Exclusão'),
content: SingleChildScrollView(
child: Column(
children: <Widget>[
Text('Confirma a exclusão de ' + nome + '?'),
],
),
),
actions: <Widget>[
TextButton(
child: Text('Confirma'),
onPressed: () {
setState(() {
var url = 'http://.../api.php?opt=delete';
http.post(Uri.parse(url), body: {
'id': id,
});
});
Navigator.pop(context, true);
},
),
TextButton(
child: Text('Cancelar'),
onPressed: () {
Navigator.pop(context);
},
),
],
);
},
);
}
*/
#override
void initState() {
super.initState();
caes = fetchCaes();
}
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
backgroundColor: Color.fromRGBO(1, 87, 155, 1),
focusColor: Colors.blue,
foregroundColor: Colors.white,
hoverColor: Colors.green,
splashColor: Colors.tealAccent,
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => AddEditPage(),
),
);
debugPrint('Clicked FloatingActionButton Button');
},
),
body: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Divider(),
//SizedBox(height: 10),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 15.0),
child: TextField(
onChanged: (value) {
setState(() {
searchString = value.toLowerCase();
});
},
decoration: const InputDecoration(
//contentPadding: EdgeInsets.symmetric(vertical: 10),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.blue, width: 1.0),
borderRadius: BorderRadius.all(Radius.circular(25.0))),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.blue, width: 1.0),
borderRadius: BorderRadius.all(Radius.circular(25.0)),
),
labelText: 'Pesquisa',
suffixIcon: Icon(Icons.search))),
),
SizedBox(height: 10),
Expanded(
child: FutureBuilder<List<Caes>>(
builder: (context, snapshot) {
if (snapshot.hasData) {
return Center(
child: ListView.separated(
padding: const EdgeInsets.all(8),
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return snapshot.data[index].nome
.toLowerCase()
.contains(searchString)
? Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new InkWell(
onTap: () {
print(index);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => AddEditPage(
caes: snapshot.data,
index: index,
),
),
);
},
child: new Container(
child: Column(
children: [
Text(
(snapshot.data[index].nome),
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold),
),
Text(
('${snapshot.data[index].microchip}'),
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 13,
),
),
Text(
('${snapshot.data[index].pedigree}'),
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 13,
),
),
Text(
(snapshot
.data[index].data_nascimento),
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 13,
),
),
Text(
(snapshot.data[index].sexo),
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 13,
),
),
Text(
(snapshot.data[index].castrado),
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 13,
),
),
],
),
),
),
])
: Container();
},
separatorBuilder: (BuildContext context, int index) {
return snapshot.data[index].nome
.toLowerCase()
.contains(searchString)
? Divider()
: Container();
},
),
);
} else if (snapshot.hasError) {
return Center(child: Text('Error: ${snapshot.error}'));
}
return Center(
child: CircularProgressIndicator(),
);
},
// future: list,
),
),
],
),
);
}
}
class Caes {
final int id;
final String nome;
final int microchip;
final int pedigree;
final String data_nascimento;
final String castrado;
final String sexo;
Caes({
this.id,
this.nome,
this.microchip,
this.pedigree,
this.data_nascimento,
this.castrado,
this.sexo,
});
factory Caes.fromJson(Map<String, dynamic> json) {
return Caes(
id: json['id'],
nome: json['nome'],
microchip: json['microchip'],
pedigree: json['pedigree'],
data_nascimento: json['data_nascimento'],
castrado: json['castrado'],
sexo: json['sexo'],
);
}
}
class Titulos {
Titulos({this.data, this.titulo, this.exposicao});
// non-nullable - assuming the score field is always present
final String data;
final String titulo;
final String exposicao;
factory Titulos.fromJson(Map<String, dynamic> json) {
final data = json['data'] as String;
final titulo = json['titulo'] as String;
final exposicao = json['exposicao'] as String;
return Titulos(data: data, titulo: titulo, exposicao: exposicao);
}
Map<String, dynamic> toJson() {
return {
'data': data,
'titulo': titulo,
'exposicao': exposicao,
};
}
}
Future<List<Caes>> fetchCaes() async {
final response = await http.get(Uri.parse('http://.../api.php?opt=read'));
if (response.statusCode == 200) {
var caesJson = jsonDecode(response.body) as List;
return caesJson.map((caes) => Caes.fromJson(caes)).toList();
} else {
throw Exception('Failed to load Caes');
}
}
Screen
I cant really provide an answer in your list view cause it needs more files to run for me. However I can provide you a nice way to search in a list for items and update it with a text field. You can copy and run the code in the main of a test project to see how it is working.
import 'dart:async';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final StreamController<List<String>> _exercisesStreamController =
StreamController<List<String>>();
late Stream<List<String>> _exercisesStream;
final List<String> _exercises = [
"Running",
"Swimming",
"Football",
"Basketball",
"Volleyball",
"Karate",
"Ski",
"Snowboard",
"Baseball",
"Running1",
"Swimming1",
"Football1",
"Basketball1",
"Volleyball1",
"Karate1",
"Ski1",
"Snowboard1",
"Baseball1",
"Running2",
"Swimming2",
"Football2",
"Basketball2",
"Volleyball2",
"Karate2",
"Ski2",
"Snowboard2",
"Baseball2",
"Running3",
"Swimming3",
"Football3",
"Basketball3",
"Volleyball3",
"Karate3",
"Ski3",
"Snowboard3",
"Baseball3",
];
#override
void initState() {
super.initState();
_exercisesStreamController.sink.add(_exercises);
_exercisesStream = _exercisesStreamController.stream.asBroadcastStream();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(),
body: Padding(
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10),
child: Column(
children: [
TextFormField(
maxLines: 1,
style: TextStyle(color: Colors.white),
onChanged: (String value) async {
List<String> temp = List.from(_exercises);
temp.removeWhere((element) =>
!element.toLowerCase().contains(value.toLowerCase()));
_exercisesStreamController.sink.add(temp);
},
decoration: InputDecoration(
prefixIcon: Icon(
Icons.search,
color: Colors.white,
),
border: OutlineInputBorder(
borderSide: BorderSide.none,
borderRadius: BorderRadius.circular(15.0),
),
contentPadding: EdgeInsets.only(left: 15),
filled: true,
fillColor: Colors.blueGrey,
hintText: "search",
hintStyle: TextStyle(
color: Colors.white,
),
),
),
_listViewWidget()
],
),
),
);
}
Widget _listViewWidget() {
return Expanded(
child: StreamBuilder<List<String>>(
initialData: [],
stream: _exercisesStream,
builder: (context, snapshot) {
return ListView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
return Container(
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
color: Colors.blueGrey,
borderRadius: BorderRadius.all(
Radius.circular(15),
),
),
padding: EdgeInsets.all(15),
margin: EdgeInsets.symmetric(vertical: 10),
child: Center(
child: Text(
snapshot.data![index],
style: TextStyle(color: Colors.white),
),
),
);
});
},
),
);
}
}
If you need further instructions i am happy to help.

Flutter - Chat Screen built with a StreamBuilder showing messages multiple times

I am struggling with this Chat Screen. The app is meant to ask questions (not part of the below code) and the user either selects answers or types them. When the user types a first answer everything goes according to the plan and a first message is displayed. However the app then goes on displaying the second answer twice, the third one three times and so on.
I have been facing this issue for a few days and I cannot figure out why the app behaves the way it does. Could you please take a look at the code and suggest a way to fix this?
To give you some background information, this Chat Screen is part of a larger application. It should subscribe to a stream when the user opens the app. Then each message is pushed to the stream, whether it is a question asked by the bot or an answer given by the User. The system listens to the stream and displays a new message each time the stream broadcasts something, in our case the latest user input.
I am using a list of message models built from the stream to display the messages. For the purpose of asking this question I simplified the model to the extreme but in practice it has 23 fields. Creating this list of messages is the best solution I managed to think of but there may be a better way to handle this situation. Feel free to let me know if you know of any.
Here is the code that I am running.
import 'package:flutter/material.dart';
import 'dart:async';
StreamController<ChatMessageModel> _chatMessagesStreamController = StreamController<ChatMessageModel>.broadcast();
Stream _chatMessagesStream = _chatMessagesStreamController.stream;
const Color primaryColor = Color(0xff6DA7B9);
const Color secondaryColor = Color(0xffF0F0F0);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Chat Screen',
home: ChatScreen(),
);
}
}
class ChatMessageModel {
final String message;
const ChatMessageModel({
this.message,
}
);
factory ChatMessageModel.turnSnapshotIntoListRecord(Map data) {
return ChatMessageModel(
message: data['message'],
);
}
#override
List<Object> get props => [
message,
];
}
class ChatScreen extends StatefulWidget {
static const String id = 'chat_screen9';
#override
_ChatScreenState createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> {
final _messageTextController = TextEditingController();
String _userInput;
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: secondaryColor,
appBar: AppBar(
title: Row(
children: [
Container(
padding: EdgeInsets.all(8.0),
child: Text('Chat Screen',
style: TextStyle(color: Colors.white,),
),
)
],
),
backgroundColor: primaryColor,
),
body: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
MessagesStream(),
Container(
decoration: BoxDecoration(
border: Border(
top: BorderSide(
color: primaryColor,
width: 1.0,
),
),
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
child: TextField(
controller: _messageTextController,
onChanged: (value) {
_userInput = value;
},
decoration: InputDecoration(
contentPadding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0),
hintText: 'Type your answer here',
// border: InputBorder.none,
),
),
),
TextButton(
onPressed: () {
_messageTextController.clear();
debugPrint('Adding a ChatMessageModel with the message $_userInput to the Stream');
ChatMessageModel chatMessageModelRecord = ChatMessageModel(message: _userInput);
_chatMessagesStreamController.add(chatMessageModelRecord,);
},
child: Text(
'OK',
style: TextStyle(
color: primaryColor,
fontWeight: FontWeight.bold,
fontSize: 18.0,
),
),
),
],
),
),
],
),
),
);
}
}
class MessagesStream extends StatelessWidget {
List<ChatMessageModel> _allMessagesContainedInTheStream = [];
#override
Widget build(BuildContext context) {
return StreamBuilder<ChatMessageModel>(
stream: _chatMessagesStream,
builder: (context, snapshot) {
_chatMessagesStream.listen((streamedMessages) {
// _allMessagesContainedInTheStream.clear();
debugPrint('Value from controller: $streamedMessages');
_allMessagesContainedInTheStream.add(streamedMessages);
}
);
return Expanded(
child: ListView.builder(
// reverse: true,
padding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 20.0),
itemCount: _allMessagesContainedInTheStream.length,
itemBuilder: (BuildContext context, int index) {
if (snapshot.hasData) {
return UserChatBubble(chatMessageModelRecord: _allMessagesContainedInTheStream[index]);
}
},
),
);
},
);
}
}
class UserChatBubble extends StatelessWidget {
final ChatMessageModel chatMessageModelRecord;
const UserChatBubble({
Key key,
#required this.chatMessageModelRecord,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Padding(
padding: EdgeInsets.symmetric(vertical: 5, horizontal: 5,),
child: Container(
constraints: BoxConstraints(maxWidth: MediaQuery.of(context).size.width * 7 / 10,),
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(15.0),
bottomRight: Radius.circular(15.0),
topLeft: Radius.circular(15.0),
),
color: primaryColor,
),
padding: EdgeInsets.symmetric(vertical: 8, horizontal: 20,),
child: Text(chatMessageModelRecord.message,
style: TextStyle(
fontSize: 17,
// fontWeight: FontWeight.w500,
color: Colors.white,
),
),
),
),
],
);
}
}
First of all, thank you for the interesting problem and functioning example provided. I had to do some small changes to convert it to "null-safety", but my code should work on your computer too.
The only problem you had initialization of _chatMessagesStream listener. You should do it only once and ideally in initState, to call it only once.
So here is the fix for you:
class MessagesStream extends StatefulWidget {
#override
_MessagesStreamState createState() => _MessagesStreamState();
}
class _MessagesStreamState extends State<MessagesStream> {
final List<ChatMessageModel> _allMessagesContainedInTheStream = [];
#override
void initState() {
_chatMessagesStream.listen((streamedMessages) {
// _allMessagesContainedInTheStream.clear();
debugPrint('Value from controller: $streamedMessages');
_allMessagesContainedInTheStream.add(streamedMessages);
});
super.initState();
}
#override
Widget build(BuildContext context) {
return StreamBuilder<ChatMessageModel>(
stream: _chatMessagesStream,
builder: (context, snapshot) {
return Expanded(
child: ListView.builder(
// reverse: true,
padding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 20.0),
itemCount: _allMessagesContainedInTheStream.length,
itemBuilder: (BuildContext context, int index) {
if (snapshot.hasData) {
return UserChatBubble(
chatMessageModelRecord:
_allMessagesContainedInTheStream[index],
);
} else {
print(snapshot.connectionState);
return Container();
}
},
),
);
},
);
}
}
Also providing full code for null-safety just in case!
import 'package:flutter/material.dart';
import 'dart:async';
final StreamController<ChatMessageModel> _chatMessagesStreamController =
StreamController<ChatMessageModel>.broadcast();
final Stream<ChatMessageModel> _chatMessagesStream =
_chatMessagesStreamController.stream;
const Color primaryColor = Color(0xff6DA7B9);
const Color secondaryColor = Color(0xffF0F0F0);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Chat Screen',
home: ChatScreen(),
);
}
}
class ChatMessageModel {
final String? message;
const ChatMessageModel({
this.message,
});
factory ChatMessageModel.turnSnapshotIntoListRecord(Map data) {
return ChatMessageModel(
message: data['message'],
);
}
List<Object> get props => [
message!,
];
}
class ChatScreen extends StatefulWidget {
static const String id = 'chat_screen9';
#override
_ChatScreenState createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> {
final _messageTextController = TextEditingController();
String? _userInput;
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: secondaryColor,
appBar: AppBar(
title: Row(
children: [
Container(
padding: EdgeInsets.all(8.0),
child: Text(
'Chat Screen',
style: TextStyle(
color: Colors.white,
),
),
)
],
),
backgroundColor: primaryColor,
),
body: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
MessagesStream(),
Container(
decoration: BoxDecoration(
border: Border(
top: BorderSide(
color: primaryColor,
width: 1.0,
),
),
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
child: TextField(
controller: _messageTextController,
onChanged: (value) {
_userInput = value;
},
decoration: InputDecoration(
contentPadding: EdgeInsets.symmetric(
vertical: 10.0, horizontal: 20.0),
hintText: 'Type your answer here',
// border: InputBorder.none,
),
),
),
TextButton(
onPressed: () {
_messageTextController.clear();
debugPrint(
'Adding a ChatMessageModel with the message $_userInput to the Stream');
ChatMessageModel chatMessageModelRecord =
ChatMessageModel(message: _userInput);
_chatMessagesStreamController.add(
chatMessageModelRecord,
);
},
child: Text(
'OK',
style: TextStyle(
color: primaryColor,
fontWeight: FontWeight.bold,
fontSize: 18.0,
),
),
),
],
),
),
],
),
),
);
}
}
class MessagesStream extends StatefulWidget {
#override
_MessagesStreamState createState() => _MessagesStreamState();
}
class _MessagesStreamState extends State<MessagesStream> {
final List<ChatMessageModel> _allMessagesContainedInTheStream = [];
#override
void initState() {
_chatMessagesStream.listen((streamedMessages) {
// _allMessagesContainedInTheStream.clear();
debugPrint('Value from controller: $streamedMessages');
_allMessagesContainedInTheStream.add(streamedMessages);
});
super.initState();
}
#override
Widget build(BuildContext context) {
return StreamBuilder<ChatMessageModel>(
stream: _chatMessagesStream,
builder: (context, snapshot) {
return Expanded(
child: ListView.builder(
// reverse: true,
padding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 20.0),
itemCount: _allMessagesContainedInTheStream.length,
itemBuilder: (BuildContext context, int index) {
if (snapshot.hasData) {
return UserChatBubble(
chatMessageModelRecord:
_allMessagesContainedInTheStream[index],
);
} else {
print(snapshot.connectionState);
return Container();
}
},
),
);
},
);
}
}
class UserChatBubble extends StatelessWidget {
final ChatMessageModel chatMessageModelRecord;
const UserChatBubble({
Key? key,
required this.chatMessageModelRecord,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Padding(
padding: EdgeInsets.symmetric(
vertical: 5,
horizontal: 5,
),
child: Container(
constraints: BoxConstraints(
maxWidth: MediaQuery.of(context).size.width * 7 / 10,
),
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(15.0),
bottomRight: Radius.circular(15.0),
topLeft: Radius.circular(15.0),
),
color: primaryColor,
),
padding: EdgeInsets.symmetric(
vertical: 8,
horizontal: 20,
),
child: Text(
"${chatMessageModelRecord.message}",
style: TextStyle(
fontSize: 17,
// fontWeight: FontWeight.w500,
color: Colors.white,
),
),
),
),
],
);
}
}