I would like to create a generic dialog but I have some issue with the callback... Here is my code :
The dialog :
class ConfirmDialog {
static Future show<T>(BuildContext context, String message,
void Function(T) onConfirm, VoidCallback? onRefuse) {
return showDialog(
context: context,
builder: (context) {
return Container(
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.grey[300],
),
child: Container(
padding: EdgeInsets.fromLTRB(0, 20, 0, 0),
width: 400,
height: 200,
child: Card(
child: Column(
children: [
Text(
message,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 30),
),
Container(
margin: EdgeInsets.fromLTRB(0, 20, 0, 0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
GestureDetector(
child: Container(
height: 70,
padding: EdgeInsets.fromLTRB(0, 0, 20, 0),
child: Image.asset("assets/images/confirm.png"),
),
onTap: () => {
onConfirm,
print("accept"),
Navigator.pop(context),
}),
GestureDetector(
child: Container(
height: 70,
padding: EdgeInsets.fromLTRB(20, 0, 0, 0),
child: Image.asset("assets/images/cancel.png"),
),
onTap: () => {
if (onRefuse != null)
{
onRefuse,
}
else
{
Navigator.pop(context),
}
print("refuse")
},
),
],
),
),
],
),
),
),
);
},
);
}
The widget :
Widget listView(List<Product> products) {
return ListView.builder(
itemCount: products.length,
itemBuilder: (context, index) {
Product product = products[index];
return GestureDetector(
child: Container(
height: 150,
child: Card(
child: Row(
children: [
Container(
alignment: Alignment.center,
padding: EdgeInsets.fromLTRB(5, 10, 5, 10),
width: 150,
height: 150,
child: Image.network(product.small),
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
product.name,
overflow: TextOverflow.ellipsis,
maxLines: 1,
softWrap: false,
style: TextStyle(
fontSize: 30,
),
),
Text(
product.getBrand(),
style: TextStyle(
color: Colors.grey,
fontSize: 25,
fontFamily: "Antonio",
),
)
],
),
)
],
),
),
),
onTap: () => {},
onLongPress: () => {
ConfirmDialog.show<Product>(
context,
"Are you sure you want to delete\n${product.name} ?",
deleteSelectedProduct(product),
null,
)
},
);
},
);
}
Everytime I "longpress", I got this error message :
The following _TypeError was thrown while handling a gesture: type
'Null' is not a subtype of type '(Product) => dynamic'
The product I pass as parameter is not null and the dialog don't show up but the method "deleteSelectedProduct" is triggered.
I can't figure out where I got it wrong?
If someone can help, it would be great!
Thank you in advance
The function is being called before it is passed in, so it will return null and pass that value in. You would need to use deleteSelectedProduct instead of deleteSelectedProduct(product)
Related
Using the NotificationListener, I am trying to integrate pagination with the ListView.Builder, but I don't get the expected result. While the list is working, it scrolls very slowly.
The code I wrote is below
NotificationListener<ScrollNotification>(
onNotification: (scrollNotification) {
if (_controller.position.maxScrollExtent ==
_controller.offset) {
if (state is LoghistorySuccess) {
if (logsData.length == _index) {
if (pagecount > page) {
setState(() {
page = page + 1;
print(page);
BlocProvider.of<LogHistoryBloc>(
context)
.add(LogHistoryFetchEvent(
page: page));
});
}
}
}
}
if (scrollNotification
is ScrollStartNotification) {
_onStartScroll(scrollNotification.metrics);
} else if (scrollNotification
is ScrollUpdateNotification) {
_onUpdateScroll(scrollNotification.metrics);
} else if (scrollNotification
is ScrollEndNotification) {
_onEndScroll(scrollNotification.metrics);
}
return true;
},
child: logsData.isNotEmpty
? ListView.builder(
controller: _controller,
shrinkWrap: true,
scrollDirection: Axis.vertical,
itemCount: logsData.length,
//state.logHistoryModel.results?.logs?.length ?? 0,
itemBuilder: (context, index) {
return Padding(
padding:
const EdgeInsets.only(top: 12.0),
child: DottedBorder(
borderType: BorderType.RRect,
strokeWidth: 1,
dashPattern: [2.5, 2.5],
color:
HexColor(Constants.primary),
radius: Radius.circular(10),
child: Padding(
padding: const EdgeInsets.only(
top: 15.0,
left: 15,
right: 15,
bottom: 8.0),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: [
Container(
width: MediaQuery.of(
context)
.size
.width /
2,
child: Text(
"${logsData[index].date}",
style: TextStyle(
overflow:
TextOverflow
.ellipsis,
fontWeight:
FontWeight
.w500,
fontSize: 16,
color: HexColor(
Constants
.primary),
)),
),
// Text(
// "${state.logHistoryEntity.logs?[index]["entry_date"]}",
// style: TextStyle(
// color:
// Color(0xff555B5F)),
// ),
],
),
Container(
margin: EdgeInsets.only(
top: 15,
),
child: ListView.builder(
shrinkWrap: true,
physics:
NeverScrollableScrollPhysics(),
itemCount:
logsData[index]
.log
?.length ??
0,
//state.logHistoryModel.results?.logs?[index].log?.length ?? 0,
itemBuilder:
(context, _index) {
var _data =
logsData[index]
.log?[_index];
return Padding(
padding:
const EdgeInsets
.only(
bottom:
8.0),
child: Row(
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: [
InkWell(
onTap: () {
summaryPopUp(
context,
_data!);
},
child: Text(
"• ${_data?.startTime} to ${_data?.endTime}",
style: TextStyle(
color: Color(
0xff555B5F)),
),
),
Row(
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: [
Text(
"${_data?.logtype}",
style: TextStyle(
color:
Color(0xffED5B2E)),
),
SizedBox(
width: 20,
),
_data?.createdDate ==
formatted
? Row(
children: [
InkWell(
onTap: () {
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => EditLogsScreen(log: _data!),
));
},
child: ImageIcon(
AssetImage("assets/icons/pencil.png"),
color: Color(0xff18A558),
size: 20,
),
),
SizedBox(
width: 8,
),
InkWell(
onTap: () {
showDialog(
context: context,
builder: (context) {
return DeletLogConfPopUp(
logId: _data?.id,
log: logsData[_index].log,
index: _index,
);
},
);
},
child: ImageIcon(
AssetImage("assets/icons/delete_icon.png"),
color: Color(0xffE72323),
size: 18,
),
),
],
)
: Container()
],
)
],
),
);
},
),
)
],
),
)),
);
},
)
: Container(),
// Center(
// child: Column(
// children: [
// Image(
// image: AssetImage(
// "assets/images/no_task.png")),
// Text("You don't have any logs yet")
// ],
// ),
// ),
)
with this code pagination works fine but not scrolling fast.
I Have an (infinitepagedgridview) which I constructed using the "infinite_scroll_pagination" Library
everything is running perfectly for me but I'm facing an issue using the pagingcontroller.refresh()
method, which is triggered using a button which changes a variable state which controls a specific parameter that causes different api results in the (infinitepagedgridview), My issue is that whenever I click the button, the pagingcontroller gets refreshed but the first three elements in the gridview which are the first page results come from the last api request before the button got pressed and the rest of the paginated pages work perfectly.
button code:
onTap: () async {
setState(() => FFAppState().homecat = 'Bags');
setState(() => _pagingController?.refresh());
}
listcode and api call:
child: GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),
child: RefreshIndicator(
onRefresh: () async {
setState(() => _pagingController?.refresh());
await waitForOnePage();
},
child: PagedGridView<ApiPagingParams, dynamic>(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
mainAxisSpacing: 0.0,
crossAxisSpacing: 5.0,
crossAxisCount: 2,
childAspectRatio: 0.59,
),
pagingController: () {
if (_pagingController != null) {
return _pagingController!;
}
_pagingController = PagingController(
firstPageKey: ApiPagingParams(
nextPageNumber: 0,
numItems: 0,
lastResponse: null,
),
);
_pagingController!
.addPageRequestListener((nextPageMarker) {
GetAllProductsCall.call(
offset: nextPageMarker.numItems,
categoryCatName: FFAppState().homecat)
.then((gridViewinfiniteGetAllProductsResponse) {
List pageItems = getJsonField(
gridViewinfiniteGetAllProductsResponse.jsonBody,
r'''$.results''',
).toList() as List;
// print('22' + pageItems.toString());
final newNumItems =
nextPageMarker.numItems + pageItems.length;
_pagingController!.appendPage(
pageItems,
(pageItems.length > 0)
? ApiPagingParams(
nextPageNumber:
nextPageMarker.nextPageNumber + 1,
numItems: newNumItems,
lastResponse:
gridViewinfiniteGetAllProductsResponse,
)
: null,
);
});
#override
#override
void didUpdateWidget(PagedGridView oldWidget) {
_pagingController?.refresh();
}
});
return _pagingController!;
}(),
padding: EdgeInsets.zero,
scrollDirection: Axis.vertical,
builderDelegate: PagedChildBuilderDelegate<dynamic>(
// Customize what your widget looks like when it's loading the first page.
firstPageProgressIndicatorBuilder: (_) => Center(
child: SizedBox(
width: 50,
height: 50,
child: CircularProgressIndicator(
color: FlutterFlowTheme.of(context).primaryColor,
),
),
),
itemBuilder: (context, _, kokoIndex) {
final kokoItem =
_pagingController!.itemList![kokoIndex];
return InkWell(
onTap: () async {
await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ProductDetailsWidget(
id: getJsonField(
kokoItem,
r'''$.id''',
).toString(),
),
),
);
},
child: Container(
width: double.infinity,
height: double.infinity,
decoration: BoxDecoration(
color: FlutterFlowTheme.of(context)
.secondaryBackground,
borderRadius: BorderRadius.circular(12),
),
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment:
MainAxisAlignment.spaceAround,
children: [
Expanded(
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
Padding(
padding: EdgeInsetsDirectional
.fromSTEB(0, 0, 0, 0),
child: ClipRRect(
borderRadius:
BorderRadius.circular(0),
child: Image.network(
getJsonField(
kokoItem,
r'''$.thumbnail_img1''',
),
width: MediaQuery.of(context)
.size
.width,
height: MediaQuery.of(context)
.size
.height *
0.3,
fit: BoxFit.cover,
),
),
),
],
),
),
],
),
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: AutoSizeText(
getJsonField(
kokoItem,
r'''$.title''',
).toString(),
textAlign: TextAlign.right,
maxLines: 2,
style: FlutterFlowTheme.of(context)
.bodyText1
.override(
fontFamily: 'Cairo',
fontSize: 13,
useGoogleFonts: GoogleFonts
.asMap()
.containsKey(
FlutterFlowTheme.of(
context)
.bodyText1Family),
),
),
),
ToggleIcon(
onPressed: () async {
setState(() =>
FFAppState().smallsize =
!FFAppState().smallsize);
},
value: FFAppState().smallsize,
onIcon: Icon(
Icons.favorite,
color: Colors.black,
size: 25,
),
offIcon: Icon(
Icons.favorite_border,
color: Colors.black,
size: 25,
),
)
],
),
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
functions.priceformat(getJsonField(
kokoItem,
r'''$.price''',
)),
style: FlutterFlowTheme.of(context)
.bodyText1,
),
Icon(
FFIcons.kshekel,
color: Color(0xD8000000),
size: 13,
),
],
),
],
),
),
);
},
),
),
),
),
),
],
),
).animateOnActionTrigger(
animationsMap['columnOnActionTriggerAnimation']!,
hasBeenTriggered: hasColumnTriggered),
),
);
}
I tried loading using future or clearing the paging controller before refreshing neither worked,
any help would be much appreciated :)
I am using AnimatedPositioned to make animation.
Obx(() {
return AnimatedBuilder(
animation: controller.animationController,
builder: (context, child) =>
AnimatedPositioned(
duration: const Duration(milliseconds: 1000),
bottom: controller.actionsBottom,
child: child!,
),
child:
!controller.trloaded.value
? const SizedBox()
: Column(
children: [
Row(
mainAxisSize: MainAxisSize.min,
children: [
GlobalButton(
title: controller.trLanding('signUp'),
type: ButtonType.outlinedPrimary,
width: 154.w,
height: 56,
onTap: () => controller.goToSignUp(),
),
SizedBox(width: 20.w),
GlobalButton(
borderWidth: 1,
borderColor: AppColors.primary[800]!,
title: controller.trLanding("signIn"),
width: 154.w,
height: 56,
onTap: () => controller.goToSignIn()),
],
),
Container(
margin: const EdgeInsets.only(top: 16, bottom: 16),
child: Row(
children: [
Text(
"By Signing up you agree with our ",
style: textTheme.bodyText2!.copyWith(
color: AppColors.neutral[400],
),
),
GestureDetector(
onTap: () {
// clearData();
push(TermsPage());
},
child: Text(
"Terms and Conditions",
style: textTheme.bodyText2!.copyWith(
color: AppColors.primary[700],
),
),
),
],
),
),
],
),
);
}),
When I run the app by profile mode I got these problems:
To fix that I am using Animation Builder and I added my widgets to its child but I have the above problem. How can I fix that?
I am trying to use a dialog widget which will get some info from future builder, when I build the dialog under onTap it works but code looks so weird in that way because I use that build more then once, so I want to make a dialog class then call it when I needed but I couldn't achieve that yet, is this possible? My related code samples are below;
Code in the screen that I tried to call dialog box(homepage.dart):
void showCast() {
showDialog<void>(
context: context,
builder: (context){
return CastDialog();
}
);
}
#override
Widget build(BuildContext context) {
return FutureBuilder<Payload>(
...
...
...
child: GestureDetector(
child: Image.network(
snapshot.data
.movieCast[index]
.image != null
? "http://image.tmdb.org/t/p/w185" +
snapshot.data
.movieCast[index]
.image
: "http://image.tmdb.org/t/p/original/zUqyn3aQXTzeP1n8yd8Udt1twYA.jpg",
fit: BoxFit.contain,),
onTap: () async {
List<dynamic> castVar;
http.Response responseC = await http.get("http://lunedor.pythonanywhere.com/query?castid=${snapshot.data.movieCast[index].castID}&language=${AppLocalizations.of(context).translate('lan_code')}").timeout(const Duration(seconds: 10));
Map<String, dynamic> castV = jsonDecode(responseC.body);
castVar = castV['moviecastimages'];
print(castVar);
String nameC = (snapshot.data.movieCast[index]).toString();
String _movieCast = (snapshot.data.movieCast[index]).toString();
String _url = (snapshot.data.movieCast[index].castID).toString();
return
showCast();
},
),
Code for dialog(dialogs.dart):
class CastDialog extends StatefulWidget{
#override
_CastDialogState createState() => _CastDialogState();
}
class _CastDialogState extends State<CastDialog> {
String nameC;
String _movieCast;
String _url;
List castVar;
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return SimpleDialog(
title:
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
SizedBox(
width: 20,
height: 20,
child: GestureDetector(
onTap: () async{
http.Response responseB = await http.get("https://api.themoviedb.org/3/person/$_url?api_key=1b8cfaea32775f684a7baff93bb1a3fc&language=${AppLocalizations.of(context).translate('lan_code')}").timeout(const Duration(seconds: 10));
Map<String, dynamic> castCB = jsonDecode(responseB.body);
return showDialog(context: context,
builder: (context) {
return SimpleDialog(
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(nameC),
SizedBox(
width: 20,
height: 20,
child: GestureDetector(
onTap: (){ Navigator.pop(context);},
child: Icon(Icons.close)),
),
],
),
children: <Widget>[
Divider(
color: Colors.black.withOpacity(0.5),
height: 5,
thickness: 3,
),
Wrap(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
child: Text(castCB['biography'], style: TextStyle(fontSize: 14),),
),
),
],
),],
);
});
},
child: Icon(Icons.info)),
),
Text(_movieCast),
SizedBox(
width: 20,
height: 20,
child: GestureDetector(
onTap: (){ Navigator.pop(context);},
child: Icon(Icons.close)),
),
],
),
shape: RoundedRectangleBorder(borderRadius: new BorderRadius.circular(15.0)),
children: <Widget>[
Divider(
color: Colors.black.withOpacity(0.5),
height: 5,
thickness: 3,
),
Material(
child: Container(
width: 400,
height: 600,
child: new GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: 1.5 /
2.5,
),
itemCount: castVar.length,
itemBuilder: (context, index) {
return Column(
children: <
Widget>[
SizedBox(
height: 220,
child: Stack(
children: <Widget>[
Image.network(castVar[index]['poster'] != null ? "http://image.tmdb.org/t/p/w185" + castVar[index]['poster']
: "https://i.hizliresim.com/bbn0VB.jpg", fit: BoxFit.contain),
Container(
width: MediaQuery
.of(context)
.size
.width,
height: 220,
alignment: Alignment.bottomLeft,
padding: EdgeInsets.only(bottom: 5.0),
margin: const EdgeInsets.only(
left: 5.0),
child: new CircularPercentIndicator(
radius: 40.0,
lineWidth: 5.0,
percent: double.tryParse(
castVar[index]['vote'])/10,
center: Stack(
children: <Widget>[
Text(
castVar[index]['vote'],
style: TextStyle(
foreground: Paint()
..style = PaintingStyle.stroke
..strokeWidth = 3
..color = Colors.black,
),
),
new Text(castVar[index]['vote'],
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.amber,),),
],
),
progressColor: Colors.amber,
)
),],
),
),
Text(castVar[index]['title'], maxLines: 1,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.bold)
),
Text("(" + castVar[index]['year'] + ")", maxLines: 1,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.bold,),
)
],
);
}),
),
),
],
);
}
}
I have an application that stores data with sqflite. I access the records that I list with listview from the detail page with the constructor method. Short and simple codes are as follows.
notes.dart --> main page
child: ListView.builder(
itemCount: notes.length,
itemBuilder: (context, index) {
return NoteClass(
notes: notes[index],
);
},
),
note_class.dart -->
return Column(
children: <Widget>[
Dismissible(
key: UniqueKey(),
movementDuration: Duration(milliseconds: 400),
background: Container(
child: Padding(
padding: EdgeInsets.only(left: 38),
child: Align(
alignment: Alignment.centerLeft,
child: Icon(
LineIcons.trash,
color: Colors.red.shade900,
size: 27,
),
),
),
),
onDismissed: (direction) {
_deleteNote(widget.notes.noteID);
},
child: Card(
margin: EdgeInsets.only(top: 2, bottom: 2),
elevation: 2,
shape: RoundedRectangleBorder(),
child: Container(
height: 80,
child: ListTile(
onTap: (){
_detailPage(context, widget.notes);
},
contentPadding: EdgeInsets.only(left: 10, right: 5),
title: Stack(
children: <Widget>[
Container(
padding: EdgeInsets.only(top: 17),
child: Icon(Icons.note)
),
Container(
padding: EdgeInsets.only(left: 45),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: <Widget>[
Column(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
crossAxisAlignment:
CrossAxisAlignment.start,
children: <Widget>[
Container(
padding: EdgeInsets.only(top: 0),
child: Text(
widget.notes.noteHeader,
style: TextStyle(
fontSize: 19,
color: Colors.grey[900]),
)),
Container(
padding: EdgeInsets.only(top: 0),
child: Text(
widget.notes.noteBody,
style: TextStyle(
fontSize: 17,
color: Colors.grey[900]),
),
),
],
),
],
),
),
],
),
),
),
)),
],
);
_detailPage(BuildContext context, NoteModel noteModel) {
Navigator.push(
context,
PageTransition(
type: PageTransitionType.rightToLeft,
child: NoteDetail(
content: noteModel,
)));
}
note_detail.dart
Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Card(
elevation: 3,
shape: RoundedRectangleBorder(),
child: Container(
alignment: Alignment.centerLeft,
height: 50,
width: MediaQuery.of(context).size.width,
padding: EdgeInsets.only(left: 8, top: 0),
child: SelectableText(
widget.content.noteHeader,
style: TextStyle(fontSize: 18, color: Colors.grey[800],),
),
),
),
Card(
elevation: 3,
shape: RoundedRectangleBorder(),
child: Container(
alignment: Alignment.centerLeft,
height: 50,
width: MediaQuery.of(context).size.width,
padding: EdgeInsets.only(left: 8, top: 0),
child: SelectableText(
widget.content.noteBody,
style: TextStyle(fontSize: 18, color: Colors.grey[800],),
),
),
),],
),
On the note detail page I set notifications with flutterLocalNotificationsPlugin.schedule and I can view note details with notifications. But when I click on the notification I want to go to the detail page of the related note. I sent the ID of the record with the payload parameter.
Then, I added the onSelectNotification method in notes.dart.
Future onSelectNotification(String payload) async {
if (payload != null) {
######## what should I write here? ########
}
}
There is an ID value in payload. How can I access the note detail about ID information. Or click on the notification in which way I can go to the note detail page.
You're almost there. All you have to do is something similar to this:
class NoteDetail extends StatefulWidget {
final String payload;
NoteDetail (this.payload);
#override
State<StatefulWidget> createState() => NoteDetailState(payload);
}
class NoteDetailState extends State {
String payload;
NoteDetailState (this.payload);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar()
body:Column( your column code here))
}
// call this after something
void save() {
//dosomething
// go back to the old page
// notice the true, if all goes good with save send true otherwise false
Navigator.pop(context, true);
}
}
// use this code to go to detail
void navigateToDetail(String payload) async {
bool result = await Navigator.push(context,
MaterialPageRoute(builder: (context) => NoteDetail(payload)),
);
if (result == true) {
getData(); // refresh data from db
}
}