can't refresh listview after update and delete flutter - flutter

Hello I'm a new flutter user, here I'm trying to complete CRUD but when I finish adding, editing, and deleting the listview page it can't be refreshed immediately. When I re-open the new page can be refreshed. Do you think friends here can solve my problem? Thank you good friends can help me.
Here's my source code snippet
Here is my source code snippet :
listnasabah.dart
class ListNasabah {
ApiService apiService;
ListNasabah({this.apiService});
void getNasabah() {
apiService.getNasabah().then((nasabah) {
print(nasabah);
});
}
Widget createViewList() {
return SafeArea(
child: FutureBuilder(
future: apiService.getNasabah(),
builder: (BuildContext context, AsyncSnapshot<List<Nasabah>> snapshot) {
if (snapshot.hasError) {
return Center(
child: Text(
'Something wrong with message: ${snapshot.error.toString()}',
textAlign: TextAlign.center,
),
);
} else if (snapshot.connectionState == ConnectionState.done) {
List<Nasabah> nasabah = snapshot.data;
return nasabahListView(nasabah);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
),
);
}
Widget nasabahListView(List<Nasabah> listnasabah) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0),
child: ListView.builder(
shrinkWrap: true,
itemBuilder: (context, index) {
Nasabah nasabah = listnasabah[index];
return Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Card(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
nasabah.nama_debitur,
style: Theme.of(context).textTheme.bodyText1,
),
Text(nasabah.alamat),
Text(nasabah.no_ktp),
Text(nasabah.no_telp),
Text(nasabah.no_selular),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
FlatButton(
onPressed: () {
apiService
.deleteNasabah(nasabah.id)
.whenComplete(() {
Alert(
context: context,
type: AlertType.success,
title: "Sukses",
desc: "Data berhasil dihapus",
buttons: [
DialogButton(
child: Text(
"OK",
style: TextStyle(
color: Colors.white, fontSize: 20),
),
onPressed: () {
Navigator.pop(context);
},
width: 120,
)
],
).show();
});
},
child: Text(
"Hapus",
style: TextStyle(color: Colors.red),
),
),
TextButton(
onPressed: () async {
var result = await Navigator.push(context,
MaterialPageRoute(builder: (context) {
return FormAddNasabah(nasabah: nasabah);
}));
},
child: Text(
'Edit',
style: TextStyle(color: Colors.blue),
),
),
],
)
],
),
),
),
);
},
itemCount: listnasabah.length,
),
);
}
}
datanasabah.dart
class DataNasabah extends StatefulWidget {
DataNasabah({Key key}) : super(key: key);
final String title = "Data Nasabah";
#override
_DataNasabahState createState() => _DataNasabahState();
}
class _DataNasabahState extends State<DataNasabah> {
ApiService apiService;
ListNasabah _listNasabah;
#override
void initState() {
super.initState();
apiService = ApiService();
_listNasabah = new ListNasabah(apiService: apiService);
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldState,
appBar: AppBar(
title: Text(
'Data Nasabah',
style: TextStyle(color: Colors.white),
),
actions: <Widget>[
GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => FormAddNasabah(),
),
);
},
child: Padding(
padding: const EdgeInsets.only(right: 16.0),
child: Icon(
Icons.add,
color: Colors.white,
),
),
)
],
),
body: _listNasabah.createViewList(),
);
}
}

If it's getting refreshed after you come back from another page then its problem with rendering UI as you are not using any state management here. You can check state management in flutter, I would suggest to use Provider(https://pub.dev/packages/provider).
For stateful widget you can use setState function.

Related

I want to get the sum total of the price of all the products in a list of cards with data from firestore

I want to get the sum total of the price of all the products in a list of cards with data from firestore and i don't how to do that on flutter.
This is the where i show the cards and where i want to show the total price too:
class ShopListPage extends StatelessWidget {
const ShopListPage({super.key});
Stream<List<ShopList>> readProducts() => FirebaseFirestore.instance
.collection('shoplist')
.orderBy('price')
.snapshots()
.map((snapshot) =>
snapshot.docs.map((doc) => ShopList.fromJson(doc.data())).toList());
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Theme.of(context).colorScheme.background,
body: StreamBuilder<List<ShopList>>(
stream: readProducts(),
builder: (context, snapshot) {
if (snapshot.hasError) {
return Text('Algo ha ocurrido! ${snapshot.error}');
} else if (snapshot.hasData) {
final shoplist = snapshot.data!;
return ListView(
children: shoplist
.map((p) => BuildListCards(shopList: p))
.toList());
} else {
return const Center(child: CircularProgressIndicator());
}
}),
floatingActionButton: FloatingActionButton(
child: const Icon(
Icons.paid,
),
onPressed: () {},
),
);
}
}
The BuildListCard Class: here is where i show the price individually
class BuildListCards extends StatelessWidget {
final ShopList shopList;
const BuildListCards({Key? key, required this.shopList}) : super(key: key);
#override
Widget build(BuildContext context) {
return Card(
margin: const EdgeInsets.all(8),
clipBehavior: Clip.hardEdge,
child: ConstrainedBox(
constraints: const BoxConstraints(maxHeight: 80),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Image(
image: NetworkImage(shopList.imageUrl),
fit: BoxFit.cover,
),
Padding(
padding: const EdgeInsets.all(8),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(shopList.name),
Text('Precio: ${shopList.price}\$'),
Text('Cantidad: ${shopList.quantity}')
],
),
),
const Spacer(),
Padding(
padding: const EdgeInsets.fromLTRB(0, 25, 8, 0),
child: ElevatedButton(
style: ButtonStyle(
foregroundColor: MaterialStateProperty.all<Color>(
const Color(0xFFFFFFFF),
),
backgroundColor: MaterialStateProperty.all<Color>(
const Color(0xFF6750A4),
),
),
onPressed: () => showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) => AlertDialog(
title: Text(
'¿Desea eliminar el producto ${shopList.name} de la base de datos?',
textAlign: TextAlign.center,
),
actions: <Widget>[
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text('Cancelar')),
TextButton(
onPressed: () {
final docShopList = FirebaseFirestore.instance
.collection('shoplist')
.doc(shopList.id);
docShopList.delete();
Navigator.pop(context);
},
child: const Text('Eliminar')),
],
),
),
child: const Text(
'Eliminar',
),
),
),
],
),
),
);
}
}
i want to calculate the sum total of the price, i use shoplist.price to show the price

flutter putting data from api in expansion tile

Hew guys , i got a small question .
im making a drawer that should have a titles and a neste titles so i use an expansion tile.
so the titles are displayed but when i press the arrow to open the nested titles it gives me an error.
i used future builder in the nested titles i think this is the problem the error gives me this
The following TypeErrorImpl was thrown building FutureBuilder<List<dynamic>>(dirty, state: _FutureBuilderState<List<dynamic>>#aeb31):
Unexpected null value.
this is my drawer
Drawer Image
this is my drawer code
import 'package:MyCima/Screens/drawer_title_page.dart';
import 'package:MyCima/models/drawer_shows_data_model.dart';
import 'package:MyCima/services/services.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import '../constants.dart';
class FilmsDrawer extends StatefulWidget {
const FilmsDrawer({Key? key}) : super(key: key);
#override
_FilmsDrawerState createState() => _FilmsDrawerState();
}
class _FilmsDrawerState extends State<FilmsDrawer> {
final ServicesClass _services = ServicesClass();
late DrawerShowsDataModel _showsModelClass;
late Future drawerListData;
List nestedListNames = [];
#override
void initState() {
drawerListData = getDrawerList();
super.initState();
}
Future<List> getDrawerList() async {
return await _services.getFilms('menus');
}
#override
Widget build(BuildContext context) {
return Drawer(
elevation: 150,
semanticLabel: 'More Shows',
backgroundColor: PRIMARY,
child: Padding(
padding: const EdgeInsets.only(top: 24),
child: FutureBuilder(
future: drawerListData,
builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.active:
case ConnectionState.waiting:
return const Center(
child: CircularProgressIndicator(),
);
case ConnectionState.done:
return Column(
children: [
Expanded(
flex: 5,
child: Column(
children: [
Expanded(
flex: 9,
child: Text(
'MyCima',
style: GoogleFonts.bevan(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
const Expanded(
flex: 1,
child: Divider(
color: Colors.white,
indent: 64,
endIndent: 64,
),
),
],
),
),
Expanded(
flex: 95,
child: ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
_showsModelClass = DrawerShowsDataModel.fromJson(
snapshot.data[index]);
if (_showsModelClass.listChildren.length > 0) {
return ExpansionTile(
title: Text(
_showsModelClass.name,
style: const TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
children: [
getNestedTitles(index),
],
);
} else {
return Container(
alignment: Alignment.centerLeft,
padding: const EdgeInsets.all(8),
child: TextButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
const DrawerTitlePage()));
},
child: Text(
'${_showsModelClass.name}',
style: const TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
),
);
}
}),
),
],
);
case ConnectionState.none:
return const Center(child: Text('No Connection'));
}
},
),
),
);
}
getNestedTitles(int index){
return FutureBuilder(
future: getDrawerList(),
builder: (BuildContext context, AsyncSnapshot<List<dynamic>> snapshot) {
return ListView.builder(
itemCount: snapshot.data![index]['children'].length,
itemBuilder: (BuildContext context, int index) {
_showsModelClass = DrawerShowsDataModel.fromNestedJson(snapshot.data![index]['children'][index]);
return TextButton(
onPressed: () {},
child: Text(
'${_showsModelClass.name}',
),
);
},
);
},
);
}
}
i found the answer
we need to make a list of widgets and add widgets on it then use it in the expansion
List<Widget> list = [];
List<Widget> getNestedTitles(int index) {
List<Widget> list = [];
drawerListData.then((value) {
for (var x in value[index]['children']) {
list.add(Padding(
padding: const EdgeInsets.all(8.0),
child: TextButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
const DrawerTitlePage()));
},
child: Text('${x['name']}',
style: const TextStyle(
color: Colors.white,
),),
),
));
}
});
return list;
}

The class 'SimpleFoldingCell' doesn't have a default constructor

https://github.com/flutter-devs/flutter_folding_cell_demo/blob/master/lib/demo_screen.dart
I'm trying to follow the code in the link above.
But in the SimpleFoldingCell part, an error named 'The class 'SimpleFoldingCell' doesn't have a default constructor.' occurs.
Could
Is there a way to resolve this error in Dart?
class Notific extends StatefulWidget{
#override
_State createState() => _State();
}
class _State extends State<Notific>{
late List<TechnologyModel> _technologyList;
#override
void initState() {
super.initState();
_technologyList = [
TechnologyModel(title: "Application Development",),
TechnologyModel(title: "Research & Development",),
TechnologyModel(title: "Big Data & Analytics",),
TechnologyModel(title: "Support Services",),
TechnologyModel(title: "QA & Software Testing",),
];
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
backgroundColor: Colors.pink[200],
title: Text("Folding Cell Demo",
style: TextStyle(color: Colors.white),),
),
body: Container(
child: ListView.builder(
itemCount: _technologyList.length,
itemBuilder: (context, index) {
return SimpleFoldingCell(
frontWidget: _buildFrontWidget(index),
innerTopWidget: _buildInnerWidget(index),
innerBottomWidget: _buildInnerBottomWidget(),
cellSize: Size(MediaQuery.of(context).size.width, 125),
padding: EdgeInsets.all(15),
animationDuration: Duration(milliseconds: 200),
borderRadius: 10,
onOpen: () => print('$index cell opened'),
onClose: () => print('$index cell closed'),
);
},
),
),
);
}
Widget _buildFrontWidget(int index) {
return Builder(
builder: (BuildContext context) {
return Container(
color: Colors.cyan[100],
alignment: Alignment.bottomCenter,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Aeologic Technology",
style: TextStyle(
fontSize:20.0,
color: Colors.black,
),
),
SizedBox(height: 10,),
FlatButton(
onPressed: () {
final foldingCellState = context
.findAncestorStateOfType<SimpleFoldingCellState>();
foldingCellState?.toggleFold();
},
child: Text(
"OPEN",
),
textColor: Colors.white,
color: Colors.indigoAccent[100],
splashColor: Colors.white.withOpacity(0.5),
),
],
),
);
},
);
}
Widget _buildInnerBottomWidget() {
return Builder(
builder: (context) {
return Container(
color: Colors.blueGrey[50],
alignment: Alignment.bottomCenter,
child: Padding(
padding: EdgeInsets.only(bottom: 10),
child: FlatButton(
onPressed: () {
final foldingCellState = context
.findAncestorStateOfType<SimpleFoldingCellState>();
foldingCellState?.toggleFold();
},
child: Text(
"Close",
),
textColor: Colors.white,
color: Colors.redAccent[100],
splashColor: Colors.white.withOpacity(0.5),
),
),
);
}
);
}
Widget _buildInnerWidget(int index) {
return Builder(
builder: (context) {
return Container(
color: Colors.pink[100],
padding: EdgeInsets.only(top: 10),
child: Align(
alignment: Alignment.center,
child: Text(
_technologyList[index].title,
style: TextStyle(
fontSize:20.0,
color: Colors.black,
),
),
),
);
},
);
}
}
class TechnologyModel {
String title;
TechnologyModel({
required this.title,
});
}
For some reason they've created only a named constructor.
return SimpleFoldingCell.create(
frontWidget: _buildFrontWidget(index),
innerWidget: _buildInnerWidget(index),
// innerTopWidget: _buildInnerWidget(index),
// innerBottomWidget: _buildInnerBottomWidget(),
cellSize: Size(MediaQuery.of(context).size.width, 125),
padding: EdgeInsets.all(15),
animationDuration: Duration(milliseconds: 200),
borderRadius: 10,
onOpen: () => print('$index cell opened'),
onClose: () => print('$index cell closed'),
);
It looks like the demo you're looking at is a bit outdated, since some of those properties don't exist anymore (see commented code).

Using TabBar like filter

i'm trying to make a Tabbar that appear in a new page when the search icon in pressed. The code works fine but i don't know how to implement this tabbar. I want to use the tabbar for splitting the search info, each icon has to show only specific info.
I guess each icon has a specific list?
This is my search_tool.dart this appear when the icon button at the main page is pressed
[EDIT] Now the result is shown correctly, but when I press the search box to write the error message contained in buildSuggestion always appears, instead it should only show the list with the relative records and if something not belonging to that category is searched then it must give the error message
import 'package:flutter/material.dart';
import 'package:solaris/lista_data.dart';
import 'constants.dart';
class LinkItemsSearch extends SearchDelegate<LinkItem>{
#override
PreferredSizeWidget buildBottom(BuildContext context) {
return PreferredSize(
child: Container(
alignment: Alignment.center,
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: [
Container(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: ElevatedButton(
onPressed: () {
query = 'Apps';
this.showResults(context);
},
child: Text('Apps'),
),
),
Container(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: ElevatedButton(
onPressed: () {
query = 'Movies';
this.showResults(context);
},
child: Text('Movies'),
),
),
Container(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: ElevatedButton(
onPressed: () {
query = 'Games';
this.showResults(context);
},
child: Text('Games'),
),
),
],
),
),
),
preferredSize: Size.fromHeight(60),
);
}
#override
List<Widget> buildActions(BuildContext context) {
return [IconButton(icon: Icon(Icons.clear),onPressed: () { query=""; },)];
}
#override
Widget buildLeading(BuildContext context) {
return IconButton(onPressed: () { Navigator.pop(context); }, icon: Icon(Icons.arrow_back),);
}
#override
Widget buildResults(BuildContext context) {
var mylist = loadLinkItem().where((p) => p.description.contains(query)).toList();
return Container(
color: blue,
child: ListView.builder(
itemCount: mylist.length,
itemBuilder: (context,index){
final LinkItem listitem = mylist[index];
return Container(
color: blue,
child: ListTile(
title:InkWell(
onTap: () { Navigator.pushReplacement(context,MaterialPageRoute(builder: (context) => listitem.link)); },
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget> [
Text(listitem.title, style: TextStyle(color: Colors.white),),
Text(listitem.description, style: TextStyle(color: Colors.white,fontSize: 14),),
Divider(color: white,),
],
),
),
),
);
}
),
);
}
#override
Widget buildSuggestions(BuildContext context) {
final mylist = query.isEmpty? loadLinkItem():loadLinkItem().where((p) => p.description.contains(RegExp(query, caseSensitive: false))).toList();
return mylist.isEmpty?
Container(
color: red,
child: Center(child: Text('No Result Found . . .', style: TextStyle(color: Colors.white,fontSize: 20,))),
):Container(
color: blue,
child: ListView.builder(
itemCount: mylist.length,
itemBuilder: (context,index){
final LinkItem listitem = mylist[index];
return Container(
color: blue,
child: ListTile(onTap: (){ showResults(context);},
title:InkWell(
onTap: () { Navigator.pushReplacement(context,MaterialPageRoute(builder: (context) => listitem.link)); },
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget> [
Text(listitem.title, style: TextStyle(color: Colors.white),),
Text(listitem.description, style: TextStyle(color: Colors.white,fontSize: 14),),
Divider(color: white,),
],
),
),
),
);
}
),
);
}
}
Search icon
IconButton(onPressed:(){
showSearch(context: context, delegate: LinkItemsSearch());
}, icon: Icon(Icons.search),),
List
class LinkItem{
final String title;
final String description;
final link;
LinkItem({
required this.title,
required this.description,
required this.link,
});
}
List<LinkItem> loadLinkItem(){
var link = <LinkItem>[
LinkItem(
title: 'Title1',
description: 'Apps',
link: Title1(),
),LinkItem(
title: 'Title2',
description: 'Movies',
link: Title2(),
),LinkItem(
title: 'Title3',
description: 'Games',
link: Title3(),
),
];
return link;
}
You can override the buildBottom method in your LinkItemsSearch:
#override
PreferredSizeWidget buildBottom(BuildContext context) {
return PreferredSize(
child: Container(
alignment: Alignment.center,
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: [
Container(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: ElevatedButton(
onPressed: () {
query = 'Apps';
mylist = loadLinkItem()
.where((p) => p.description.contains(query))
.toList();
this.showResults(context);
},
child: Text('Apps'),
),
),
Container(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: ElevatedButton(
onPressed: () {
query = 'Movies';
mylist = loadLinkItem()
.where((p) => p.description.contains(query))
.toList();
this.showResults(context);
},
child: Text('Movies'),
),
),
Container(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: ElevatedButton(
onPressed: () {
query = 'Games';
mylist = loadLinkItem()
.where((p) => p.description.contains(query))
.toList();
this.showResults(context);
},
child: Text('Games'),
),
),
],
),
),
),
preferredSize: Size.fromHeight(60),
);
}
For this to work, you have to create myList on the top of your LinkItemsSearch and reuse it when filtering everywhere.
Also, I just updated loadLinkItem method to have some input for filtering:
List<LinkItem> loadLinkItem() {
var link = <LinkItem>[
LinkItem(
title: 'Title1',
description: 'Movies',
link: '',
),
LinkItem(
title: 'Title2',
description: 'Games',
link: '',
),
LinkItem(
title: 'Title3',
description: 'Apps',
link: '',
),
];
return link;
}
Of course, I have not completely matched your style, so I did not style buttons as you need it, you might higher bottom bar than 60 as I used. I also have not attached any on press handlers since I am not sure what should they do, but it looks as it is expected: https://i.stack.imgur.com/osUkt.png
I wrapped them with a Column and SingleChildScrollView in case you have more of those items and they need to be scrollable: https://i.stack.imgur.com/FyWVX.png
You can even add some conditions in cases when you don't need this bottom bar to be displayed and in that case, you can just return null from the buildBottom method.
FIX
import 'package:flutter/material.dart';
import 'package:solaris/lista_data.dart';
import 'constants.dart';
class LinkItemsSearch extends SearchDelegate<LinkItem>{
#override
PreferredSizeWidget buildBottom(BuildContext context) {
return PreferredSize(
child: Container(
alignment: Alignment.center,
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: [
Container(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: ElevatedButton(
onPressed: () {
query = 'Apps';
this.showResults(context);
},
child: Text('Apps'),
),
),
Container(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: ElevatedButton(
onPressed: () {
query = 'Movies';
this.showResults(context);
},
child: Text('Movies'),
),
),
Container(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: ElevatedButton(
onPressed: () {
query = 'Games';
this.showResults(context);
},
child: Text('Games'),
),
),
],
),
),
),
preferredSize: Size.fromHeight(60),
);
}
#override
List<Widget> buildActions(BuildContext context) {
return [IconButton(icon: Icon(Icons.clear),onPressed: () { query=""; },)];
}
#override
Widget buildLeading(BuildContext context) {
return IconButton(onPressed: () { Navigator.pop(context); }, icon: Icon(Icons.arrow_back),);
}
#override
Widget buildResults(BuildContext context) {
var mylist = loadLinkItem().where((p) => p.description.contains(query)).toList();
return Container(
color: blue,
child: ListView.builder(
itemCount: mylist.length,
itemBuilder: (context,index){
final LinkItem listitem = mylist[index];
return Container(
color: blue,
child: ListTile(
title:InkWell(
onTap: () { Navigator.pushReplacement(context,MaterialPageRoute(builder: (context) => listitem.link)); },
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget> [
Text(listitem.title, style: TextStyle(color: Colors.white),),
Text(listitem.description, style: TextStyle(color: Colors.white,fontSize: 14),),
Divider(color: white,),
],
),
),
),
);
}
),
);
}
#override
Widget buildSuggestions(BuildContext context) {
final mylist = query.isEmpty? loadLinkItem():loadLinkItem().where((p) => p.description.contains(RegExp(query, caseSensitive: false))).toList();
return mylist.isEmpty?
Container(
color: red,
child: Center(child: Text('No Result Found . . .', style: TextStyle(color: Colors.white,fontSize: 20,))),
):Container(
color: blue,
child: ListView.builder(
itemCount: mylist.length,
itemBuilder: (context,index){
final LinkItem listitem = mylist[index];
return Container(
color: blue,
child: ListTile(onTap: (){ showResults(context);},
title:InkWell(
onTap: () { Navigator.pushReplacement(context,MaterialPageRoute(builder: (context) => listitem.link)); },
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget> [
Text(listitem.title, style: TextStyle(color: Colors.white),),
Text(listitem.description, style: TextStyle(color: Colors.white,fontSize: 14),),
Divider(color: white,),
],
),
),
),
);
}
),
);
}
}

Prevent keyboard from appearing on Flutter

I made this very simple aplication but im having a problem with it.
On every action that i do (like deleting something) the keyboard opens automatically.
I want to avoid that, and open the keyboard only when i click on the text form field (line 178 on code).
How can i do that?
I know this is something very simple to make, i have tried some things using focusnode, trying to disable the autofocus, but i didnt could make it work the way i need.
import 'dart:convert';
import 'dart:ffi';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:path_provider/path_provider.dart';
import 'package:http/http.dart' as http;
void main() {
runApp(MaterialApp(
home: Pedidos(),
));
}
class Pedidos extends StatefulWidget {
#override
_PedidosState createState() => _PedidosState();
}
class _PedidosState extends State<Pedidos> with TickerProviderStateMixin {
TabController _tabController;
final _pecasController = TextEditingController();
List _pecasList = [];
var _firstPress = true;
#override
void initState() {
super.initState();
_tabController = new TabController(length: 3, vsync: this);
}
void _addPecas() {
if ((_pecasController.text.isEmpty) ||
((_pecasController.text.trimLeft() == ("")))) {
print("Campo Vazio");
} else {
setState(() {
Map<String, dynamic> newPeca = Map();
newPeca["title"] = _pecasController.text.trimLeft();
//newPeca["ok"] = false;
_pecasController.text = "";
_pecasList.add(newPeca);
// _saveData();
print(_pecasList);
});
}
}
void _enviar() {
if (_pecasList.length < 1) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: new Text("Lista vazia"),
actions: <Widget>[
new FlatButton(
child: new Text("Fechar"),
onPressed: () {
Navigator.of(context).pop();
}),
]);
});
} else {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: new Text("Deseja enviar os itens?"),
actions: <Widget>[
new FlatButton(
child: new Text("Fechar"),
onPressed: () {
Navigator.of(context).pop();
}),
new FlatButton(
child: new Text("Enviar"),
onPressed: () async {
Map<String, String> headers = new Map<String, String>();
headers["Content-type"] = "application/json";
headers["Accept"] = "application/json";
//String str = '{"take":55, "skip":"0"}';
final resp = await http.post('http://172.16.14.109:5000/',
//body: str,
body: jsonEncode(_pecasList),
headers: headers);
if (resp.statusCode == 200) {
if (resp.body == "ok") {
setState(() {
print(_pecasList);
_pecasList.clear();
Navigator.of(context).pop();
});
} else {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: new Text(
"Erro: entre em contato com o suporte."),
actions: <Widget>[
new FlatButton(
child: new Text("Fechar"),
onPressed: () {
Navigator.of(context).pop();
Navigator.of(context).pop();
}),
]);
});
}
}
})
],
);
},
);
}
}
void _apagarTudo() {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: new Text("Deseja limpar a lista?"),
actions: <Widget>[
new FlatButton(
child: new Text("Fechar"),
onPressed: () {
Navigator.of(context).pop();
}),
new FlatButton(
child: new Text("Limpar"),
onPressed: () {
setState(() {
_pecasList.clear();
Navigator.of(context).pop();
});
}),
]);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
"Solicitação de Peças",
style: TextStyle(fontWeight: FontWeight.bold),
),
centerTitle: true,
backgroundColor: Colors.green,
),
body: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: <Widget>[
Expanded(
flex: 8,
child: TextFormField(
controller: _pecasController,
keyboardType: TextInputType.text,
style: TextStyle(
color: Colors.black,
fontSize: 18,
),
decoration: InputDecoration(
hintText: ("Adicionar item"),
),
),
),
Padding(
padding: EdgeInsets.only(right: 15),
),
Expanded(
flex: 2,
child: RaisedButton(
child: Icon(Icons.add, color: Colors.amber),
color: Colors.green,
onPressed: _addPecas,
),
)
],
),
),
Divider(
height: 02.0,
),
Expanded(
child: ListView.builder(
itemCount: _pecasList.length,
itemBuilder: (context, index) {
return ListTile(
dense: true,
key:
Key(DateTime.now().millisecondsSinceEpoch.toString()),
title: Text(
_pecasList[index]["title"],
style: TextStyle(fontSize: 15.0),
),
trailing: Icon(
Icons.delete_forever,
color: Colors.redAccent,
),
onLongPress: () {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title:
new Text("Deseja remover o item da lista?"),
actions: <Widget>[
new FlatButton(
child: new Text("Fechar"),
onPressed: () {
Navigator.of(context).pop();
},
),
new FlatButton(
child: new Text("Excluir"),
onPressed: () {
_pecasList.removeAt(index);
setState(() {
Navigator.of(context).pop();
});
},
),
],
);
},
);
});
}),
),
Row(
mainAxisAlignment: (MainAxisAlignment.center),
children: <Widget>[
Padding(
padding: const EdgeInsets.all(10.0),
child: RaisedButton(
color: Colors.green,
padding: EdgeInsets.all(5.0),
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(4.0),
child: Icon(
Icons.send,
color: Colors.white,
),
),
Padding(
padding: const EdgeInsets.all(2.0),
child: Text(
"Enviar",
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
),
],
),
onPressed: _enviar,
)),
Padding(
padding: const EdgeInsets.all(10.0),
child: RaisedButton(
color: Colors.redAccent,
padding: EdgeInsets.all(5.0),
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(4.0),
child: Icon(
Icons.delete,
color: Colors.white,
),
),
Padding(
padding: const EdgeInsets.all(2.0),
child: Text(
"Limpar",
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
),
],
),
onPressed: () {
_apagarTudo();
}))
],
)
],
),
);
}
}
Try these changes.
I have controlled enabled field of TextFormField. The TextFormField is disabled when you click on RaisedButton to add the item to list. And TextFormField is enabled when you click on itself.
void _addPecas() {
disableTextFormField();
...
}
bool textFormFieldEnabled = true;
void enableTextFormField(){
setState(() {
textFormFieldEnabled = true;
});
}
void disableTextFormField(){
setState(() {
textFormFieldEnabled = false;
});
}
Widget build(BuildContext context) {
....
child: TextFormField(
controller: _pecasController,
keyboardType: TextInputType.text,
enabled: textFormFieldEnabled,
onTap: () => enableTextFormField(),
style: TextStyle(
color: Colors.black,
fontSize: 18,
),
decoration: InputDecoration(
hintText: ("Adicionar item"),
),
),
...
}