I am trying to customize the map marker icon pop up card instead of default MarkerInfoWindow, there will be image+button+info on a card like bellow images. Bottom of the screen, I added cards with the action button but I need it to show in the middle of the screen as MarkerInfoWindow works. Please help me to do that.
Her's my code-
import 'package:earth_cam/model/cams.dart';
import 'package:earth_cam/splash/splash_screen.dart';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
class MapView extends StatefulWidget {
#override
_MapViewState createState() => _MapViewState();
}
class _MapViewState extends State<MapView> {
GoogleMapController _controller;
List<Marker> allMarkers = [];
PageController _pageController;
int prevPage;
bool isClicked = false;
#override
void initState() {
// TODO: implement initState
super.initState();
camDetails.forEach((element) {
allMarkers.add(Marker(
markerId: MarkerId(element.camTitle),
draggable: false,
infoWindow:
InfoWindow(title: element.camTitle, snippet: element.address),
position: element.locationCoords));
});
_pageController = PageController(initialPage: 1, viewportFraction: 0.8)
..addListener(_onScroll);
}
void _onScroll() {
if (_pageController.page.toInt() != prevPage) {
prevPage = _pageController.page.toInt();
moveCamera();
}
}
_coffeeShopList(index) {
return AnimatedBuilder(
animation: _pageController,
builder: (BuildContext context, Widget widget) {
double value = 1;
if (_pageController.position.haveDimensions) {
value = _pageController.page - index;
value = (1 - (value.abs() * 0.3) + 0.06).clamp(0.0, 1.0);
}
return Center(
child: SizedBox(
height: Curves.easeInOut.transform(value) * 125.0,
width: Curves.easeInOut.transform(value) * 350.0,
child: widget,
),
);
},
child: InkWell(
onTap: () {
// moveCamera();
},
child: Stack(children: [
Center(
child: Container(
margin: EdgeInsets.symmetric(
horizontal: 10.0,
vertical: 20.0,
),
height: 200.0,
width: 275.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.0),
boxShadow: [
BoxShadow(
color: Colors.black54,
offset: Offset(0.0, 4.0),
blurRadius: 10.0,
),
]),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.0),
color: Colors.white),
child: Row(children: [
Container(
height: 90.0,
width: 90.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(10.0),
topLeft: Radius.circular(10.0)),
image: DecorationImage(
image: NetworkImage(
camDetails[index].thumbNail),
fit: BoxFit.cover))),
SizedBox(width: 5.0),
Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
camDetails[index].camTitle,
style: TextStyle(
fontSize: 12.5,
fontWeight: FontWeight.bold),
),
Text(
camDetails[index].address,
style: TextStyle(
fontSize: 12.0,
fontWeight: FontWeight.w600),
),
// Container(
// width: 170.0,
// child: Text(
// coffeeShops[index].description,
// style: TextStyle(
// fontSize: 11.0,
// fontWeight: FontWeight.w300),
// ),
// ),
Container(
width: 150,
child: RaisedButton.icon(
elevation: 12,
shape: RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(
15
),
),
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (context)=>SplashScreen()));
},
icon: Icon(
Icons.play_arrow,
color: Colors.white,
),
label: Text(
'Play',
style: TextStyle(color: Colors.white),
),
color: Colors.redAccent,
),
)
])
]))))
])),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xFF1B2D45),
appBar: AppBar(
centerTitle: true,
title: Text('All Live Cams'),
leading: IconButton(
icon: Icon(
Icons.arrow_back,
color: Colors.white,
),
onPressed: null),
actions: [
IconButton(
icon: Icon(
Icons.do_not_disturb_off,
color: Colors.white,
size: 25,
),
onPressed: null),
],
),
body: Stack(
children: <Widget>[
Container(
height: MediaQuery.of(context).size.height - 50.0,
width: MediaQuery.of(context).size.width,
child: GoogleMap(
compassEnabled: true,
mapToolbarEnabled: false,
zoomControlsEnabled: false,
myLocationEnabled: true,
initialCameraPosition: CameraPosition(
target: LatLng(40.7128, -74.0060), zoom: 12.0),
markers: Set.from(allMarkers),
onMapCreated: mapCreated,
),
),
Positioned(
bottom: 0.0,
child: Container(
height: 200.0,
width: MediaQuery.of(context).size.width,
child: PageView.builder(
controller: _pageController,
itemCount: camDetails.length,
itemBuilder: (BuildContext context, int index) {
return _coffeeShopList(index);
},
),
),
),
isClicked
? Container(
padding: EdgeInsets.only(top: 30),
alignment: Alignment.topRight,
child: RaisedButton.icon(
elevation: 20,
shape: RoundedRectangleBorder(
borderRadius: new BorderRadius.only(
bottomLeft: Radius.circular(20),
topLeft: Radius.circular(20)),
),
onPressed: () {
print('YT cam Clicked');
setState(() {
isClicked = false;
});
},
icon: Icon(
Icons.play_arrow,
color: Colors.white,
),
label: Text(
'YT Cam',
style: TextStyle(color: Colors.white),
),
color: Colors.redAccent,
),
)
: Container(
padding: EdgeInsets.only(top: 30),
alignment: Alignment.topRight,
child: RaisedButton.icon(
elevation: 20,
shape: RoundedRectangleBorder(
borderRadius: new BorderRadius.only(
bottomLeft: Radius.circular(20),
topLeft: Radius.circular(20)),
),
onPressed: () {
print('IP cam Clicked');
setState(() {
isClicked = true;
});
},
icon: Icon(
Icons.linked_camera,
color: Colors.white,
),
label: Text(
'IP Cam',
style: TextStyle(color: Colors.white),
),
color: Colors.indigo,
),
)
],
));
}
void mapCreated(controller) {
setState(() {
_controller = controller;
});
}
moveCamera() {
_controller.animateCamera(CameraUpdate.newCameraPosition(CameraPosition(
target: camDetails[_pageController.page.toInt()].locationCoords,
zoom: 14.0,
bearing: 45.0,
tilt: 45.0)));
}
}
Related
I am trying to filter out the results of the data from a REST api but do not seem to have an understanding of how to go about it. Basically, what I am trying to achieve is that I want to have a single class that gets all my events data from the api and using different classes, be able to retrieve specific data by filtering the data from the original events class.
Below is my code:
late Future<List<EntertainerEvent>> _fetchEvents;
#override
void initState() {
_fetchEvents = _authAPI.fetchEvents();
super.initState();
}
#override
Widget build(BuildContext context) {
return FutureBuilder<List<EntertainerEvent>>(
future: _fetchEvents,
builder: (BuildContext context, AsyncSnapshot snapshot) {
var childCount = 0;
if (snapshot.connectionState != ConnectionState.done) {
childCount = 1;
} else {
childCount = snapshot.data.length;
}
return SliverList(
delegate: SliverChildBuilderDelegate((context, index) {
if (snapshot.hasData) {
List<EntertainerEvent> someData = snapshot.data;
return InkWell(
child: Container(
height: 380.0,
color: const Color(0xFF00001A),
child: Container(
padding: const EdgeInsets.all(0.0),
margin: const EdgeInsets.all(30.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(4.0)),
boxShadow: [
BoxShadow(
color: Color(0xFF0492C2),
blurRadius: 10,
offset: Offset(0, 0),
),
],
color: Colors.white,
),
child: Stack(
children: <Widget>[
Align(
alignment: Alignment.topCenter,
child: Padding(
padding: const EdgeInsets.all(0.0),
child: Container(
width: MediaQuery.of(context).size.width,
height: 210,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(4.0),
topRight: Radius.circular(4.0),
bottomLeft: Radius.circular(0.0),
bottomRight: Radius.circular(0.0)),
image: DecorationImage(
fit: BoxFit.cover,
image: DecorationImage(
fit: BoxFit.cover,
image: new NetworkImage(
_authAPI.mediaPath +
someData[index].imagePoster)),
),
),
),
),
Align(
alignment: Alignment.bottomCenter,
child: Padding(
padding: const EdgeInsets.all(0.0),
child: Container(
width: MediaQuery.of(context).size.width,
height: 120,
child: Container(
padding: const EdgeInsets.all(10),
child: Row(
children: [
Expanded(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Container(
padding: const EdgeInsets.only(
top: 10.0, bottom: 0.0),
child: Text(
someData[index]
.eventName
.toUpperCase(),
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
fontFamily: 'Nunito',
),
overflow:
TextOverflow.ellipsis,
softWrap: true,
maxLines: 1,
),
),
Container(
padding: const EdgeInsets.only(
top: 6.0, bottom: 0.0),
child: Text(
someData[index].eventTypeId ==
3
? 'Online Location'
: someData[index].suburb +
', ' +
someData[index].city +
', ' +
someData[index]
.province,
style: TextStyle(
color: Colors.black26,
),
overflow:
TextOverflow.ellipsis,
softWrap: true,
maxLines: 1,
),
),
Container(
padding:
EdgeInsets.only(top: 0.0),
child: Row(
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: [
Text(
_startDate(
someData[index])
.toString()
.toUpperCase(),
style: TextStyle(
color: Colors.red,
fontWeight:
FontWeight.bold,
fontSize: 10,
),
),
FavouriteWidget(
entEvent:
someData[index]),
IconButton(
icon: Icon(Icons.share),
onPressed: () {
Share.share(//Do Something);
},
),
],
),
),
],
),
),
],
),
),
),
),
),
],
),
),
),
onTap: () async {
Navigator.push(context,
MaterialPageRoute(builder: (BuildContext context) {
return EventDetails(
entEvent: someData[index],
isFavourited: _isFavourited);
}));
},
);
} else if (snapshot.hasError) {
return AlertDialog(
title: Text(
'An Error Occured!',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.redAccent,
),
),
content: Text(
"${snapshot.error}",
style: TextStyle(
color: Colors.blueAccent,
),
),
actions: <Widget>[
TextButton(
child: Text(
'Go Back',
style: TextStyle(
color: Colors.redAccent,
),
),
onPressed: () {
Navigator.of(context).pop();
},
)
],
);
} else {
return Center(
child: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height / 1.3,
child: Center(
child:
CircularProgressIndicator(color: Color(0xFFFFA500)),
),
),
);
}
}, childCount: childCount),
);
});
Bare in mind that in my HomePage(), I am calling this class using the code below:
return Container(
color: Color(0xFF00001A),
child: SafeArea(
top: false,
bottom: false,
child: Builder(
// This Builder is needed to provide a BuildContext that is
// "inside" the NestedScrollView, so that
// sliverOverlapAbsorberHandleFor() can find the
// NestedScrollView.
builder: (BuildContext context) {
return CustomScrollView(
// The "controller" and "primary" members should be left
// unset, so that the NestedScrollView can control this
// inner scroll view.
slivers: <Widget>[
SliverOverlapInjector(
// This is the flip side of the SliverOverlapAbsorber
// above.
handle:
NestedScrollView.sliverOverlapAbsorberHandleFor(context),
),
EventList(),
],
);
},
),
),
);
Thank you in advance.
if I'm understanding you right just do this for example:
if(someData[index].eventTypeId == '1'){
return SizedBox();
}
else{
return InkWell( ....
}
I've done all my API integration parts and results are also displaying in my App. For Ex. I've a ShowPackageDetails API, which giving me the specific package details on a page after clicking the Show Details button
Now I also implemented a global search where users search and if this came in search results I want to redirect to the same Details page.These search results are dynamic so how can I specifically redirect to the details page for each item after search?
Here after searching for Angi_ _ _ I want to redirect to the same Angioplasty details page after clicking the "Show Details" button in search results for this specific item.
Example 1API integration
class SurgPackDetails extends StatefulWidget {
final String encId;
SurgPackDetails({this.encId='IujvK/FS7g=='});
#override
_SurgPackDetailsState createState() => _SurgPackDetailsState();
}
class _SurgPackDetailsState extends State<SurgPackDetails> {
static String url="http://myapikkkk";
Dio dio = Dio();
SurgicalData _surgicalData=SurgicalData(packageId: '', encPackageId: '',
packageName: '', note: '', createBy: '', createDate: '',
modBy: '', modDate: '', activeStatus: '', permission: '',
fee: '', discountedFee: '', bookingFee: '',
description: '');
late List<PartnerDatum> surgPartnerData = [];
late List<PartnerDatum> _finalsurgpartnerData = [];
#override
void initState() {
super.initState();
getDocDetails(widget.encId);
}
Future getDocDetails(id) async{
dynamic data={"EncId": id};
print(id);
Response res = await dio.post(url, data: data);
print(res.data);
if (res.statusCode == 200) {
print('loop starts');
SurgicalData surgdata=SurgicalData(
packageId: res.data['SurgicalData']['PackageId'],
encPackageId: res.data['SurgicalData']['EncPackageId'],
packageName: res.data['SurgicalData']['PackageName'],
note: res.data['SurgicalData']['Note'],
createBy: res.data['SurgicalData']['CreateBy'],
createDate: res.data['SurgicalData']['CreateDate'],
modBy: res.data['SurgicalData']['ModBy'],
modDate: res.data['SurgicalData']['ModDate'],
activeStatus: res.data['SurgicalData']['ActiveStatus'],
permission: res.data['SurgicalData']['Permission'],
fee: res.data['SurgicalData']['Fee'],
discountedFee: res.data['SurgicalData']['DiscountedFee'],
bookingFee: res.data['SurgicalData']['BookingFee'],
description:res.data['SurgicalData']['Description'],
);
var k = res.data['PartnerData'].length;
print('Loop for partner data');
PartnerDatum obj;
for (var i = 0; i < k; i++) {
obj =PartnerDatum(
partnerId: res.data['PartnerData'][i]['PartnerId'],
encPartnerId: res.data['PartnerData'][i]['EncPartnerId'],
partnerName: res.data['PartnerData'][i]['PartnerName'],
partnerAddress: res.data['PartnerData'][i]['PartnerAddress'],
fee:res.data['PartnerData'][i]['Fee'],
discountedFee: res.data['PartnerData'][i]['DiscountedFee'],
bookingFee: res.data['PartnerData'][i]['BookingFee'],
dayList: res.data['PartnerData'][i]['DayList'],
);
surgPartnerData.add(obj);
}
setState(() {
_surgicalData=surgdata;
_finalsurgpartnerData=surgPartnerData;
// _docData=doctorData;
// _partnerData=;
});
} else {
print(res.statusCode);
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('${_surgicalData.packageName} details', style: TextStyle(fontFamily: 'Roboto_Condensed'),),
flexibleSpace: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.topRight,
colors: [
Theme
.of(context)
.primaryColor,
Theme
.of(context)
.accentColor
],
),
),
),
automaticallyImplyLeading: true,
leading: IconButton(icon: Icon(Icons.arrow_back),
onPressed: () {
Navigator.pop(context);
},
),
),
body: Stack(
children: [
Container(
padding: EdgeInsets.all(10),
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
color: Colors.lightBlue[50],
child: Column(
// mainAxisAlignment: MainAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: [
Container(
// height: 250,
// width: 200,
// color: Colors.grey,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.symmetric(vertical: 5.0,horizontal: 10),
child: Text(_surgicalData.packageName,style: TextStyle(fontWeight: FontWeight.bold,fontSize: 25,color: Theme.of(context).primaryColor,fontFamily: 'Roboto_Condensed',),),
),
Container(
margin: EdgeInsets.all(5),
padding: EdgeInsets.all(10),
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
shape: BoxShape.rectangle,
borderRadius: BorderRadius.circular(10),
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.topRight,
colors: [
Theme.of(context).primaryColor,
Theme.of(context).accentColor
],
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.symmetric(vertical: 10.0),
child: Text('Description:',style: TextStyle(fontWeight: FontWeight.bold,fontSize: 22,color:Colors.white,fontFamily: 'Roboto_Condensed',),),
),
Padding(
padding: const EdgeInsets.only(bottom: 10),
child: Text(_surgicalData.description,style: TextStyle(fontSize: 17,color:Colors.white,fontFamily: 'Roboto_Condensed',),),
),
],
)),
],
),
),
Container(
// height: 500,
width: MediaQuery.of(context).size.width,
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
// color: Colors.green,
shape: BoxShape.rectangle,
borderRadius: BorderRadius.circular(10)
),
child:
Container(
height: 250,
// color: Colors.blue,
child: ListView.separated(
itemCount: surgPartnerData.length,
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) =>
Column(
children: [
Container(
// color: Colors.green,
height: 200,
width: 300,
// margin: EdgeInsets.all(20),
decoration: BoxDecoration(
// color: Colors.green,
shape: BoxShape.rectangle,
borderRadius: BorderRadius.circular(10),
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.center,
colors: [
Theme.of(context).primaryColor,
Theme.of(context).accentColor
],
),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.all(4.0),
child: Text(surgPartnerData[index].partnerName,style: TextStyle(fontWeight: FontWeight.bold,fontSize: 20,color: Colors.white,fontFamily: 'Roboto_Condensed',),),
),
Padding(
padding: const EdgeInsets.all(4.0),
child: Text(surgPartnerData[index].partnerAddress,style: TextStyle(fontSize: 18,color: Colors.white,fontFamily: 'Roboto_Condensed',),),
),
SizedBox(height:10),
Padding(
padding: const EdgeInsets.all(2.0),
child: Text(
'Actual Fee: ${surgPartnerData[index].fee}',
style: TextStyle(
color: Colors.white,
fontSize: 16,
fontFamily: 'Roboto_Condensed',
),
),
),
Padding(
padding: const EdgeInsets.all(2.0),
child: Text(
'Discount Fee: ${surgPartnerData[index].discountedFee}',
style: TextStyle(
color: Colors.white,
fontSize: 16,
fontFamily: 'Roboto_Condensed',
),
),
),
Padding(
padding: const EdgeInsets.all(2.0),
child: Text(
'Booking Fee: ${surgPartnerData[index].bookingFee}',
style: TextStyle(
color: Colors.white,
fontSize: 16,
fontFamily: 'Roboto_Condensed',
),
),
),
Container(
alignment: Alignment.center,
height: 40,
width: 280,
margin: EdgeInsets.all(5),
decoration: BoxDecoration(
shape: BoxShape.rectangle,
borderRadius: BorderRadius.circular(10),
color: Colors.white
),
child: Text('BOOK',style: TextStyle(color:Theme.of(context).primaryColor ),),
),
],
),
),
],
),
separatorBuilder: (BuildContext context, int index) =>
const Divider(
color: Colors.transparent,
// height: 5,
),
),
),
),
],
),
),
],
),
);
}
}
Calling and printing the API result
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SurgPackDetails(
encId:
surglist[index].encPackageId)));
My Search API
Future<void> searchByUser() async {
var jsonResponse;
if (searchController.text.isNotEmpty) {
var response = await http.post(
Uri.parse("http://medjkkjkjkj"),
body: ({
'SearchKey': searchController.text,
}));
if (response.statusCode == 200) {
setState(() {
});
print("Correct");
print(response.body);
jsonResponse = json.decode(response.body.toString());
print(jsonResponse);
Navigator.push(context, MaterialPageRoute(builder: (context)=>AfterSearchPage(rresponse: SearchApiResponse.fromJson(jsonResponse))));
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(" ${jsonResponse['Message']}"),
backgroundColor: Color(0xFF152A38),
));
CREDENTIALS
} else {
print("Wronggooooooooooooooooooooooooooo");
print(response.body);
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text("Invalid credentials")));
}
} else {
}
}
Then displaying my search results
class AfterSearchPage extends StatefulWidget {
final SearchApiResponse rresponse;
const AfterSearchPage({required this.rresponse});
#override
_AfterSearchPageState createState() => _AfterSearchPageState();
}
class _AfterSearchPageState extends State<AfterSearchPage> {
// var responseRef;
// _SecondState(this.responseRef);
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.lightBlue[50],
appBar: AppBar(
flexibleSpace: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.topCenter,
colors: [
Theme.of(context).primaryColor,
Theme.of(context).accentColor
],
),
),
),
title: Text(
'Search Result',
style: TextStyle(
fontFamily: 'Roboto_Condensed',
),
),
),
body: SingleChildScrollView(
child: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
for (final item in widget.rresponse.data)
Container(
margin: EdgeInsets.all(20),
child: Column(
children: [
ListTile(
title: Text(item.name),
trailing: ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Theme.of(context).primaryColor),
onPressed: () {},
child: Text("Show details")),
leading: CircleAvatar(
backgroundColor: Colors.lightBlue[50],
radius: 30,
backgroundImage: NetworkImage(item.image),
),
),
Text(item.extra1),
Text(item.extra2),
],
),
),
SizedBox(
height: 50,
),
],
),
),
),
);
}
}
I have a search bar that queries a listview(JSON) to get likely close input text from the listview(JSON) for some reason my horizontal listview hide in the right side and won't show until I start typing on the search bar textfield and when it shows it won't show fully but partly and the rest list still hiding at the right side of my device screen. Below is my code and attached is my screenshot:
Container(
height: 120,
// width: 150,
child: ListView.builder(
scrollDirection: Axis.horizontal,
// padding: EdgeInsets.all(5.0),
itemCount: _notesForDisplay.length+1,
itemBuilder: (context, position) {
return position == 0 ? _searchBar() : _listItem(position-1);
}
)),
_listItem(position) {
return InkWell(
onTap: (){
_myFeatureSelection = position.toString();
debugPrint("myfeat:$_myFeatureSelection");
//_fetchFeaturePickedList();
_fetchComment();
},
child:Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Card(
semanticContainer: true,
clipBehavior: Clip.antiAliasWithSaveLayer,
child: Stack(
children: <Widget>[
Image.network(_notesForDisplay[position].img_link,
width: 120, height: 100, fit: BoxFit.cover),
/*Positioned(
// top: 16,
//left: 140,
child: Container(
height: 25,
width: 80,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0),
color: Colors.black, //Color(0xff0F0F0F),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.3),
)
]),
child: Center(
child: Text(
_notesForDisplay[position].title,
style: TextStyle(color: Colors.white),
),
),
))*/
],
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5.0)),
elevation: 5,
//margin: EdgeInsets.all(10),
),
// _FeatureText(featurePhoto.title,16),
//_FeatureText(featurePhoto.subtitle,12),
]));}
_searchBar() {
return
Container(
width: 240,
child: Align(
alignment: Alignment.center,
child: TextField(
//controller: searchController,
cursorColor: Colors.white,
style: TextStyle(color: Colors.white,fontSize: 12,
fontFamily: 'Montserrat'),
decoration: InputDecoration(
border: InputBorder.none,
prefixIcon: Icon(
Icons.search,
color: Colors.white,
size: 15,
),
hintStyle: TextStyle(
color: Colors.white,
fontSize: 12,
fontFamily: 'Montserrat'),
//alignLabelWithHint: true,
hintText: "Search...",//contentPadding: EdgeInsets.only(top: 2),
),
onChanged: (text) {
text = text.toLowerCase();
setState(() {
_notesForDisplay = feature.where((note) {
var noteTitle = note.title.toLowerCase();
return noteTitle.contains(text);
}).toList();
});
},
),
));
}
This is a problem associated with using column widget. to solve this, simply wrap the column with the SingleChildScrollView widget. it will solve the problem instantly
I have a signup page where i am making a http.post request to the server by passing the parameters email,username,password,firstname and lastname. I have tried everything but couldn't solve the problem. Whenever i tap on the signup button it says the following--
"I/flutter ( 2914): 400
I/flutter ( 2914): {"code":"rest_missing_callback_param","message":"Missing parameter(s): email, username, password","data":{"status":400,"params":["email","username","password"]}}"
I have gone through other posts but they didnt solve my problem so please help.
Thanks in advance.
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:restaurant_app/globalVar.dart';
import 'package:restaurant_app/homescreen.dart';
class SignUp extends StatefulWidget {
#override
_SignUpState createState() => _SignUpState();
}
class _SignUpState extends State<SignUp> with SingleTickerProviderStateMixin
{
TabController controller;
TextEditingController _firstnameController;
TextEditingController _lastnameController;
TextEditingController _usernameController;
TextEditingController _emailController;
TextEditingController _passwordController;
TextEditingController _rePasswordController;
bool loading;
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>
();
#override
void initState() {
// TODO: implement initState
super.initState();
controller = new TabController(length: 2, vsync: this);
loading = false;
_firstnameController = new TextEditingController(text: "Vishal");
_lastnameController = new TextEditingController(text: "Das");
_usernameController = new TextEditingController(text: "vishaldas");
_emailController = new TextEditingController(text: "vissudas#gmail.com");
_passwordController = new TextEditingController(text: "Vishal#123");
_rePasswordController = new TextEditingController(text: "Vishal#123");
}
#override
void dispose() {
// TODO: implement dispose
super.dispose();
controller.dispose();
setState(() {
loading = false;
});
_emailController.dispose();
_usernameController.dispose();
_passwordController.dispose();
_firstnameController.dispose();
_lastnameController.dispose();
_rePasswordController.dispose();
}
// static final String fullnameKey = 'fullname';
// static final String emailKey = 'email';
// static final String passwordkey = 'password';
signUp(email, username, password, firstname, lastname) async {
setState(() {
loading = true;
});
var body = json.encode({
"email": email,
"username": username,
"password": password,
"firstname": firstname,
"lastname": lastname,
});
String basicAuth =
'Basic' + base64Encode(utf8.encode('$username:$password'));
Map<String, String> headers = {
HttpHeaders.AUTHORIZATION: basicAuth,
};
print(basicAuth);
await http
.post("${GlobalVar.url}wp-json/wc/v2/customers",
body: body, headers: headers)
.then((response) {
var body = json.decode(response.body);
print(response.statusCode);
print(response.body);
if (response.statusCode == 200) {
loading = false;
Navigator.pushReplacement(context,
MaterialPageRoute(builder: (BuildContext ctx) => HomePage()));
} else {
final snackBar = SnackBar(content: Text(body['message']));
_scaffoldKey.currentState.showSnackBar(snackBar);
}
setState(() {
loading = false;
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomPadding: false,
key: _scaffoldKey,
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('images/art.png'),
fit: BoxFit.fill,
colorFilter: ColorFilter.mode(
Colors.white12.withOpacity(0.2), BlendMode.dstATop),
),
),
child: ListView(
shrinkWrap: true,
physics: BouncingScrollPhysics(),
children: <Widget>[
SizedBox(
height: MediaQuery.of(context).size.height / 35,
),
Align(
alignment: Alignment.topCenter,
child: CircleAvatar(
backgroundColor: Colors.grey,
radius: 55.0,
backgroundImage: AssetImage('images/logo.png'),
),
),
SizedBox(
height: MediaQuery.of(context).size.height / 40,
),
Stack(
alignment: Alignment.center,
children: <Widget>[
SizedBox(
height: 2.0,
child: new Center(
child: new Container(
height: 10.0,
color: Colors.black12,
),
),
),
Row(
children: <Widget>[
SizedBox(
width: MediaQuery.of(context).size.width / 4,
),
Chip(
label: Text(
"SIGN IN",
style: TextStyle(color: Colors.white, fontSize: 18.0),
),
backgroundColor: Color(0xFFD1A155),
),
SizedBox(
width: MediaQuery.of(context).size.width / 35,
child: Container(
width: MediaQuery.of(context).size.height / 12,
height: 2.0,
color: Colors.white,
),
),
Chip(
label: Text(
"SIGN UP",
style: TextStyle(color: Colors.white, fontSize: 18.0),
),
backgroundColor: Colors.black87,
),
],
)
],
),
SizedBox(
height: MediaQuery.of(context).size.height / 30,
),
Align(
alignment: Alignment.center,
child: Text(
"Sign Up Maa ki Rasoi",
style: TextStyle(
fontSize: 20.0,
color: Color(0xFFD1A155),
),
)),
SizedBox(
height: MediaQuery.of(context).size.height / 30,
),
Column(
children: <Widget>[
Theme(
data: ThemeData(
hintColor: Colors.black26,
primaryColor: Color(0xFFD1A155),
),
child: Padding(
padding: const EdgeInsets.only(left: 15.0, right: 15.0),
child: TextField(
controller: _firstnameController,
decoration: InputDecoration(
border: OutlineInputBorder(borderSide: BorderSide()),
prefixIcon: Icon(
Icons.person,
color: Color(0xFFD1A155),
),
hintText: 'First name',
hintStyle: TextStyle(
color: Colors.black,
fontWeight: FontWeight.w400)),
keyboardType: TextInputType.text,
),
),
),
SizedBox(
height: MediaQuery.of(context).size.height / 50,
),
Theme(
data: ThemeData(
hintColor: Colors.black26,
primaryColor: Color(0xFFD1A155),
),
child: Padding(
padding: const EdgeInsets.only(left: 15.0, right: 15.0),
child: TextField(
controller: _lastnameController,
decoration: InputDecoration(
border: OutlineInputBorder(borderSide: BorderSide()),
prefixIcon: Icon(
Icons.person,
color: Color(0xFFD1A155),
),
hintText: 'Last name',
hintStyle: TextStyle(
color: Colors.black,
fontWeight: FontWeight.w400)),
keyboardType: TextInputType.text,
),
),
),
SizedBox(
height: MediaQuery.of(context).size.height / 50,
),
Theme(
data: ThemeData(
primaryColor: Color(0xFFD1A155),
hintColor: Colors.black26),
child: Padding(
padding: const EdgeInsets.only(left: 15.0, right: 15.0),
child: TextField(
controller: _emailController,
decoration: InputDecoration(
border: OutlineInputBorder(borderSide: BorderSide()),
prefixIcon: Icon(
Icons.email,
color: Color(0xFFD1A155),
),
hintText: 'Email Address',
hintStyle: TextStyle(
color: Colors.black,
fontWeight: FontWeight.w400)),
keyboardType: TextInputType.emailAddress,
),
),
),
SizedBox(
height: MediaQuery.of(context).size.height / 50,
),
Theme(
data: ThemeData(
hintColor: Colors.black26,
primaryColor: Color(0xFFD1A155),
),
child: Padding(
padding: const EdgeInsets.only(left: 15.0, right: 15.0),
child: TextField(
controller: _usernameController,
decoration: InputDecoration(
border: OutlineInputBorder(borderSide: BorderSide()),
prefixIcon: Icon(
Icons.supervised_user_circle,
color: Color(0xFFD1A155),
),
hintText: 'Username',
hintStyle: TextStyle(
color: Colors.black,
fontWeight: FontWeight.w400)),
keyboardType: TextInputType.text,
),
),
),
SizedBox(
height: MediaQuery.of(context).size.height / 50,
),
Theme(
data: ThemeData(
hintColor: Colors.black26,
primaryColor: Color(0xFFD1A155),
),
child: Padding(
padding: const EdgeInsets.only(left: 15.0, right: 15.0),
child: TextField(
controller: _passwordController,
decoration: InputDecoration(
border: OutlineInputBorder(borderSide: BorderSide()),
prefixIcon: Icon(
Icons.lock,
color: Color(0xFFD1A155),
),
hintText: 'Password',
hintStyle: TextStyle(
color: Colors.black,
fontWeight: FontWeight.w400)),
keyboardType: TextInputType.text,
obscureText: true,
),
),
),
SizedBox(
height: MediaQuery.of(context).size.height / 50,
),
Theme(
data: ThemeData(
primaryColor: Color(0xFFD1A155),
hintColor: Colors.black26),
child: Padding(
padding: const EdgeInsets.only(left: 15.0, right: 15.0),
child: TextField(
controller: _rePasswordController,
decoration: InputDecoration(
border: OutlineInputBorder(borderSide: BorderSide()),
prefixIcon: Icon(
Icons.lock,
color: Color(0xFFD1A155),
),
hintText: 'Re - Password',
hintStyle: TextStyle(
color: Colors.black,
fontWeight: FontWeight.w400)),
keyboardType: TextInputType.text,
obscureText: true,
),
),
),
SizedBox(
height: MediaQuery.of(context).size.height / 50,
),
Padding(
padding: const EdgeInsets.only(left: 15.0, right: 15.0),
child: InkWell(
onTap: () {
print(_emailController.text);
print(_passwordController.text);
print(_usernameController.text);
signUp(
_emailController.text,
_usernameController.text,
_passwordController.text,
_firstnameController.text,
_lastnameController.text,
);
},
child: loading
? CircularProgressIndicator()
: Container(
height: MediaQuery.of(context).size.height / 13,
//width: MediaQuery.of(context).size.height / 1.8,
decoration: BoxDecoration(
color: Color(0xFFD1A155),
borderRadius: BorderRadius.circular(5.0),
),
child: Center(
child: Text(
"SIGN UP",
style: TextStyle(
color: Colors.white, fontSize: 18.0),
),
),
),
),
)
],
),
SizedBox(
height: MediaQuery.of(context).size.height / 30,
),
Stack(
alignment: Alignment.center,
children: <Widget>[
SizedBox(
height: 2.0,
child: new Center(
child: new Container(
height: 10.0,
color: Colors.black12,
),
),
),
Container(
height: MediaQuery.of(context).size.height / 18,
width: MediaQuery.of(context).size.height / 11,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(23.0),
color: Colors.white,
border: Border.all(color: Colors.black12)),
child: Center(
child: Text(
"OR",
style: TextStyle(fontSize: 18.0),
)),
),
],
),
SizedBox(
height: MediaQuery.of(context).size.height / 40,
),
Padding(
padding: const EdgeInsets.only(left: 15.0, right: 15.0),
child: Row(
children: <Widget>[
Container(
height: MediaQuery.of(context).size.height / 13,
width: MediaQuery.of(context).size.width / 2.2,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0),
color: Colors.white,
border: Border.all(color: Colors.black12)),
child: Row(
children: <Widget>[
SizedBox(
width: 18.0,
),
Icon(Icons.tag_faces),
SizedBox(
width: 10.0,
),
Text(
"Facebook",
style: TextStyle(fontSize: 22.0, color: Colors.blue),
),
],
),
),
SizedBox(
width: MediaQuery.of(context).size.width / 40,
),
Container(
height: MediaQuery.of(context).size.height / 13,
width: MediaQuery.of(context).size.width / 2.3,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0),
color: Colors.white,
border: Border.all(color: Colors.black12)),
child: Row(
children: <Widget>[
SizedBox(
width: 18.0,
),
Icon(Icons.tag_faces),
SizedBox(
width: 10.0,
),
Text(
"Google+",
style: TextStyle(fontSize: 22.0, color: Colors.red),
),
],
),
),
],
),
),
SizedBox(
height: MediaQuery.of(context).size.height / 30,
),
Align(
alignment: Alignment.center,
child: InkWell(
onTap: () => Navigator.pop(context),
child: RichText(
text: TextSpan(
text: "Already have an account?",
style: TextStyle(fontSize: 20.0, color: Colors.black87),
children: <TextSpan>[
TextSpan(
text: ' Log in',
style: TextStyle(
color: Color(0xFFD1A155),
fontWeight: FontWeight.bold)),
])),
),
),
SizedBox(
height: MediaQuery.of(context).size.height / 40,
),
],
),
),
);
}
}
Error code 400 commonly occurs due to bad requests that the server is unable to process (i.e. unexpected parameters, malformed syntax). If what has been mentioned in the comments is correct, and woocommerce is being used here, there's no way that I can test your setup. But what I can suggest is testing your config in a client following this guide. Postman is a commonly used tool that I can suggest to test HTTP Requests. If the API works well with Postman but the request still has issues in Flutter, we can start from there.
I am trying to implement the cart functionality having add and remove quantity functions. I am using controller.text and updating to text field my issue is when i am adding and removing all the list items updated because of the same controller for text field how to separate update for each item?
ListView.builder(
scrollDirection: Axis.vertical,
itemCount: (data != null) ? (data["items"].length) * 20 : 0,
itemBuilder: (BuildContext context, int index) {
return Container(
child: Column(
children: <widget>[
Container(
alignment: Alignment.topLeft,
width: double.infinity,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Container(
margin: const EdgeInsets.only(top: 8.0),
color: Colors.white,
child: ButtonTheme(
height: 16.0,
minWidth: 10.0,
child: RaisedButton(
padding: const EdgeInsets.all(4.0),
color: Colors.white,
child: Icon(Icons.remove,color: Colors.black,size: 20.0,),
onPressed: _removeQuantity
),
)
),
Container(
width: 60.0,
padding: const EdgeInsets.only(left: 1.0,right: 1.0),
child: Center(
child: TextField(
textAlign: TextAlign.center,
decoration: new InputDecoration(
hintText: "1",
),
keyboardType: TextInputType.number,
controller: _quantityController,
),
)
),
Container(
margin: const EdgeInsets.only(top: 8.0),
color: Colors.white,
child: ButtonTheme(
height: 16.0,
minWidth: 10.0,
child: RaisedButton(
padding: const EdgeInsets.all(4.0),
color: Colors.white,
child: Icon(Icons.add,color: Colors.black,size: 20.0),
onPressed: _addQuantity
),
),
),
],
),
),
]
Functions
void _addQuantity(){
setState(() {
quantity++;
_quantityController.text = '$quantity';
});
}
void _removeQuantity(){
setState(() {
if(quantity > 0){
quantity--;
}else{
quantity = 0;
}
_quantityController.text = '$quantity';
});
}
You need to provide a different controller for every text field.
Create a list of Controller
List<TextEditingController> _quantityController = new List();
and use it in your code like
ListView.builder(
scrollDirection: Axis.vertical,
itemCount: (data != null) ? (data["items"].length) * 20 : 0,
itemBuilder: (BuildContext context, int index) {
_quantityController.add(new TextEditingController());
return Container(
child: Column(
children: <Widget>[
Container(
alignment: Alignment.topLeft,
width: double.infinity,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Container(
margin: const EdgeInsets.only(top: 8.0),
color: Colors.white,
child: ButtonTheme(
height: 16.0,
minWidth: 10.0,
child: RaisedButton(
padding: const EdgeInsets.all(4.0),
color: Colors.white,
child: Icon(Icons.remove, color: Colors.black,
size: 20.0,),
onPressed: ()=>_removeQuantity(index)
),
)
),
Container(
width: 60.0,
padding: const EdgeInsets.only(left: 1.0, right: 1.0),
child: Center(
child: TextField(
textAlign: TextAlign.center,
decoration: new InputDecoration(
hintText: "1",
),
keyboardType: TextInputType.number,
controller: _quantityController[index],
),
)
),
Container(
margin: const EdgeInsets.only(top: 8.0),
color: Colors.white,
child: ButtonTheme(
height: 16.0,
minWidth: 10.0,
child: RaisedButton(
padding: const EdgeInsets.all(4.0),
color: Colors.white,
child: Icon(
Icons.add, color: Colors.black, size: 20.0),
onPressed: ()=>_addQuantity(index),
),
),
),
],
),
),
],
),
);
},
);
Now your function will change to
void _addQuantity(int index){
setState(() {
quantity++;
_quantityController[index].text = '$quantity';
});
}
void _removeQuantity(int index){
setState(() {
if(quantity > 0){
quantity--;
}else{
quantity = 0;
}
_quantityController[index].text = '$quantity';
});
}
Don't forget to dispose all the controller in the end.