Flutter: exclude one object from scrolling within a listview - google-maps

I have a listview of objects that contains basically a form with textfields, a google maps object and then another form of checkboxes.
What I would like to do is have the google maps object not part of the scroll physics of the listview as a whole, because then you cannot actually move the map around at all.
Some code:
Constructor inside the build widget:
Flexible(
child: StreamBuilder(
stream: Firestore.instance.collection('users').document(uid).snapshots(),
builder: (BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
if (snapshot.hasData) {
return ListView.builder(
physics: ScrollPhysics(),
shrinkWrap: true,
itemCount: 1,
itemBuilder: (context, index) =>
_buildListRows(context, snapshot.data),
);
} else {
return LoadingAnimation();
}
},
),
),
The _buildListRows Widget, simplified:
Widget _buildListRows(BuildContext context, DocumentSnapshot document) {
return Container(
child: Form(
child: Column(
children: <Widget>[
Container(
child: TextFormField(),
),
Container(
child: SizedBox(
child: GoogleMap(),
),
),
Expanded(
Container(
ListView(
physics: ScrollPhysics(),
children: keys.map(key) {
return Checkbox(value: key);
}
),
),
],
),
),
);
}
So a quick recap, I need to be able to scroll the objects above and below the map, to move the whole screen up and down, but on the map itself I need to be able to control the map, so that touch actions apply to map functionality instead.
I have read a lot about this and tried some of the suggestions like having a singlechildscrollview and then listviews underneath that parent but it seems anything else I try just completely breaks the app and nothing will display at all.

Related

How to passing new items on top List view

I am making an app and it depends to give data from API, so I have List view to show new news to the top list view the first when build List view it was showing new items to the end list view so I do Reverse :true after that it is showing new items to the top but when open page show me the end list ....
How can I Pass new items to the top list view and when open aloes show me the top list view like the list view news
This my function get data if you need
Future<List<Ravs>> fetchRav() async {
String token = await read();
final String url= 'listravs';
String FullURL = Serveurl+url;
var response =await http.post(FullURL,
headers: {HttpHeaders.contentTypeHeader: "application/json", HttpHeaders.authorizationHeader: "Bearer $token"});
print('Token : ${token}');
print(response);
if (response.statusCode==200){
final items =jsonDecode(response.body).cast<Map<String,dynamic>>();
List<Ravs> listrav =items.map<Ravs>((json){
return Ravs.fromjson(json);
}).toList();
return listrav;
}
else{
throw Exception('Failed to load data from Server.');
}
}
This my list
return Directionality(
textDirection: TextDirection.rtl,
child:Scaffold(
body:ListView(
reverse: true,
children: snapshot.data
.map((data) =>
Card(
child: InkWell(
onTap:(){
Navigator.push(context, MaterialPageRoute (builder:(context)=>Showpage(id:data.id.toString()),
),
);
},
child: Column(
children: <Widget>[
new Container(
padding: const EdgeInsets.only(top: 10),
width: 200,
alignment: Alignment.topLeft,
child: Image.network(data.image)
),
new Container(
padding: const EdgeInsets.all(10.0),
alignment: Alignment.topRight,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(data.nameravs,textDirection: TextDirection.rtl, style: Theme.of(context).textTheme.title),
Text(data.date_from,textAlign: TextAlign.right, style: TextStyle(color: Colors.black.withOpacity(0.5))),
Text(data.detalis , textAlign: TextAlign.right,),
],
)
)
],
),
),
)
)
.toList(),
)
)
);}, );
Since you are fetching news, I would recommend using ListView.builder. It is a more efficient way in showing a list of objects compared to ListView. The example below is how you can use it to display your data. Align is used to place your list items on top instead of in the bottom because setting the ListView.builder's reverse to true will make the list start at the bottom as well as position that whole list at the bottom.
Align(
alignment: Alignment.topCenter,
child: ListView.builder(
reverse:true,
itemCount: news.length,
itemBuilder: (context, index) {
return ListTile(
title: Text('${news[index]}'),
);
},
);
)
Here is the official docs on ListView.builder(): https://flutter.dev/docs/cookbook/lists/long-lists
Here is a great tutorial that can help you get started with ListView.builder(): https://www.youtube.com/watch?v=TdWhYERuv7g

RangeError (index): Invalid value: Not in range 0..7, inclusive: 8

I'm trying to display all the values from retrieved from an API request.
Here's what it's showing at the moment:
I'm using a listview builder for the page. The JSON can be retrieved from this link: Here
This is my entire code for the page: Code
The error is in your ListViewBuilder:
ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: _ListFamilyPageState.data.body.family.length,
itemBuilder: (context, index) {
return Container(
height: 74.0,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topRight: const Radius.circular(20.0),
bottomRight: const Radius.circular(20.0)),
),
width: MediaQuery.of(context).size.width - 50.0,
child: Center(
child: Text(
data.body.friends[index].id.toString(),
style:
TextStyle(fontSize: 24.0),
)));
},
)
You specified that there are family.length items (in your data: 15),
but you are pulling actual data from friends[index] (8 items in your data).
This gives you RangeError when rendering item at index 8.
On top of that: you use static data in your state:
class _ListFamilyPageState extends State<ListFamily> {
static Relations data;
// ...
}
Don't do that.
You've set the itemCount attribute of the ListView with _ListFamilyPageState.data.body.family.length and you've use the index of it's builder with another list data.body.friends[index].id.toString()
I don't think both have the same number of elements

How to load multiple list view inside single list view?

I'm working on flutter app in which I want to show feeds, I want to show 1st list(Horizontal list) with 4 workouts, 2nd list (Vertical list) with 4 posts, 3rd list (Horizontal list) with 4 coaches and 4th list again 4 posts. At the end of list there is 'Load More' button and after click on button again repeating 1st step i.e. 4 workouts, 4 Posts, 4 Coaches and 4 Posts. My question is What is the best way to display this type of view.
Video For clear my points
Here is an example of what you want to achieve:
List<List<String>> lists = [["A1","A2","A3","A4","A5"],["B1","B2","B3"],["C1","C2","C3","C4","C5"],["D1","D2","D3"]];
Widget buildCard(String text) {
return Container(
margin: EdgeInsets.all(4.0),
padding: EdgeInsets.all(40.0),
alignment: Alignment.center,
color: Colors.lightGreenAccent,
child: Text(text),
);
}
Widget buildHorizontalList(List<String> sublist) {
return SizedBox(
height: 200.0,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: sublist.length,
itemBuilder: (context, index) => buildCard("${sublist[index]}"),
),
);
}
Widget buildVerticalList(List<String> sublist) {
return ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: sublist.length,
itemBuilder: (context, index) {
return buildCard("${sublist[index]}");
},
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
itemCount: lists.length + 1,
itemBuilder: (context, index) {
if (index <= lists.length - 1) {
return index.isEven ? buildHorizontalList(lists[index]) : buildVerticalList(lists[index]);
}
return RaisedButton(
child: Text('Load More'),
onPressed: () {
setState(() {
lists.addAll([["X1","X2","X3","X4","X5"],["Y1","Y2","Y3"]]);
});
},
);
}),
);
}
Edit: I added the Load More button functionality, basically the button just update the 'lists' variable (a list that contains all the sublists). Then the ListViews are being build according to the 'lists' content.
Can't you, instead of showing every listview within another listview, just show it all within a SingleChildScrollView, and then just add all the listviews to a row widget.
SingleChildScrollView(
child: Column(
children<widget>[
// Put listviews here.
],
),
),

Flutter google_maps_flutter package blocking alertDialog

I am currently using the google_maps_flutter package, and I am placing it within a stack and overlaying it with a button. When the button is pressed, an alert should pop up.
The problem I am currently having is that it works upon first load, but if I exit the app, putting it in the background, and I reenter the app, the alertDialog is no longer showing up. It exists on the screen because I am unable to move the map, and I have to click the area where the button would normally be, but it is not visible.
Any ideas on what's going on?
#override
Widget build(BuildContext context) {
return new Scaffold(
body: new Center(
child: new Stack(
children: <Widget>[
new Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: new Opacity(
opacity: opacity,
child: new GoogleMap(
onMapCreated: initializeMap,
options: GoogleMapOptions(
//trackCameraPosition: true,
compassEnabled: true,
myLocationEnabled: true,
),
),
),
),
new Align(
alignment: new Alignment(0, 1),
child: new GestureDetector(
onTap: () {
alert();
},
child: new Image.asset(
'assets/test.png',
height: 150.0,
fit: BoxFit.cover,
),
),
),
],
),
),
),
}
alert() {
return showCupertinoDialog(
context: context,
builder: (BuildContext context) {
return new CupertinoAlertDialog(
title: new Text("hello"),
content: new Text("hello"),
actions: <Widget>[
CupertinoDialogAction(
isDefaultAction: true,
child: Text("Ok"),
onPressed: () {
Navigator.pop(context);
}
),
CupertinoDialogAction(
child: Text("Cancel"),
onPressed: () {
Navigator.pop(context);
}
)
],
);
},
);
}
Keep in mind google_maps_flutter is a developer preview at version 0.0.3. Give it some time!

many json loading in the same screen, how to await one and continue?

I have a screen with multiples json request, but it is loading all in the same time, i want to when finish one start the another until the end.
new CustomScrollView(
cacheExtent: height * 5,
slivers: [
new SliverList(
delegate: new SliverChildListDelegate(
[
new RelatorioVendPeriodoAPeriodo(),
new RelatorioDiasDaSemanas(),
new RelatorioVendasTotalidasPorPeriodo(),
new RelatorioDasVendasTotsProdutos(),
new RelatorioMensals(),
]
)
)
]
),
this classes loads a json request, how to divide and await one to start other?
Here one of this classes return method:
Widget build(BuildContext context) {
double height = (MediaQuery.of(context).size.height) - kRadialReactionRadius - kToolbarHeight;
return new Container(
height: height,
padding: new EdgeInsets.only(left: 5.0, right: 5.0),
child: new Card(
elevation: 10.0,
child:
new Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
new Column(crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new ListTile(
trailing:
_buildCounterButton(),
title: new Center(child: new Text('FATURAMENTO MENSAL', style: new TextStyle(fontWeight: FontWeight.bold))),
subtitle: new Icon(Icons.info),
onTap: _showDialog,
),
new FutureBuilder<List<RelatorioMensal>>(
future: fetchRelatorioMensal(new http.Client(), "", '$dateFinal1Sem'),
builder: (context, snapshot) {
if (snapshot.hasError) print(snapshot.error);
return snapshot.hasData
? new porVendaMensal(listVendasMensais: snapshot.data,)
: new Center(child: new CircularProgressIndicator());
}
),
],),]
),
),
);
}