How can I split the screen into two different parts. I'm learning filters and I made this code
I want to add images from the server
When I put picture number 1 or 2 for the first time, there is no problem
But when choosing the second image, the first image is deleted. I think because it refreshed the page (rebuild)
How can I keep the two images in one screen? What is the best way?
Thank you
ٍ Split the screen into two parts
import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:lifetb/constants/my_colors.dart';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
class BeforeAfter2 extends StatefulWidget {
const BeforeAfter2({
Key? key,
this.imageSelected1,
this.imageSelected2,
}) : super(key: key);
final imageSelected1;
final imageSelected2;
#override
_BeforeAfter2State createState() => _BeforeAfter2State();
}
/// change it to Cata
var imageSelected1;
var imageSelected2;
var imageBody = true;
var id;
var username;
var email;
getPref() async {
SharedPreferences preferences = await SharedPreferences.getInstance();
username = preferences.getString("username");
id = preferences.getString("id");
email = preferences.getString("email");
if ( id == null) {
print("empty");
}
}
Future getData() async {
getPref();
if ( id == null) {
print("empty 2");
}
var url = "http://10.0.2.2/641984.php";
var data = {"user_id": "$id"};
var response = await http.post(Uri.parse(url), body: data);
var responsebody = jsonDecode(response.body);
return responsebody;
}
class _BeforeAfter2State extends State<BeforeAfter2> {
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: Column(
children: [
Expanded(
flex: 1,
child: SizedBox(
height: double.infinity,
width: double.infinity,
child: widget.imageSelected1 == null
? addImage(true,true)
: showCata()
),
),
Expanded(
flex: 1,
child: SizedBox(
height: double.infinity,
width: double.infinity,
child: widget.imageSelected2 == null
? addImage(false,true)
: showCata1()
),
),
],
),
));
}
}
addImage(addText, goToAdd) {
return Column(
children: [
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
addText ? Text("Add 1 Photo") : Text("Add 2 Photo"),
SizedBox(height: 26),
Container(
alignment: Alignment.center,
child: FloatingActionButton(
heroTag: null,
child: Icon(
Icons.add,
color: white,
size: 45,
),
onPressed: () {
goToAdd
? showCata()
: showCata1();
},
)),
],
),
],
);
}
showCata(){
return FutureBuilder(
future: getData(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text('Loading...'),
Center(child: CircularProgressIndicator())
],
);
} else if (snapshot.data.isEmpty) {
return Padding(
padding: EdgeInsets.all(15),
child: Text("You don't Have any Photo")
);
}
return GridView.builder(
// shrinkWrap: true,
itemCount: snapshot.data.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
// crossAxisSpacing: 10
),
itemBuilder: (context, i) {
return Padding(
padding: const EdgeInsets.all(4.0),
child: InkWell(
onTap: () {
Navigator.of(context)
.pushReplacement(MaterialPageRoute(builder: (context) {
return BeforeAfter2(
imageSelected1: snapshot.data[i]["post_image"],
);
}));
},
child: Container(
margin: EdgeInsets.only(top: 10, left: 10),
decoration: BoxDecoration(
border: Border.all(
color: Colors.deepPurple.shade500,
width: 2),
borderRadius:
BorderRadius.all(Radius.circular(35)),
image: DecorationImage(
fit: BoxFit.cover,
image: NetworkImage(
"http://10.0.2.2/upload/" +
snapshot.data[i]["post_image"]),
)),
),
),
);
},
);
},
);
}
showCata1(){
return FutureBuilder(
future: getData(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text('Loading...'),
Center(child: CircularProgressIndicator())
],
);
} else if (snapshot.data.isEmpty) {
return Padding(
padding: EdgeInsets.all(15),
child: Text("You don't Have any Photo")
);
}
return GridView.builder(
// shrinkWrap: true,
itemCount: snapshot.data.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
// crossAxisSpacing: 10
),
itemBuilder: (context, i) {
return Padding(
padding: const EdgeInsets.all(4.0),
child: InkWell(
onTap: () {
Navigator.of(context)
.pushReplacement(MaterialPageRoute(builder: (context) {
return BeforeAfter2(
imageSelected2: snapshot.data[i]["post_image"],
);
}));
},
child: Container(
margin: EdgeInsets.only(top: 10, left: 10),
decoration: BoxDecoration(
border: Border.all(
color: Colors.deepPurple.shade500,
width: 2),
borderRadius:
BorderRadius.all(Radius.circular(35)),
image: DecorationImage(
fit: BoxFit.cover,
image: NetworkImage(
"http://10.0.2.2/upload/" +
snapshot.data[i]["post_image"]),
)),
),
),
);
},
);
},
);
}
remove SizedBox()s and change SafeArea with child
class _BeforeAfter2State extends State<BeforeAfter2> {
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: Column(
children: [
Expanded(
flex: 1,
child: widget.imageSelected1 == null
? addImage(true,true)
: showCata()
),
Expanded(
flex: 1,
child: widget.imageSelected2 == null
? addImage(false,true)
: showCata1()
),
],
),
));
}
}
addImage(addText, goToAdd) {
return Column(
children: [
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
addText ? Text("Add 1 Photo") : Text("Add 2 Photo"),
SizedBox(height: 26),
Container(
alignment: Alignment.center,
child: FloatingActionButton(
heroTag: null,
child: Icon(
Icons.add,
color: white,
size: 45,
),
onPressed: () {
goToAdd
? showCata()
: showCata1();
},
)),
],
),
],
);
}
showCata(){
return FutureBuilder(
future: getData(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text('Loading...'),
Center(child: CircularProgressIndicator())
],
);
} else if (snapshot.data.isEmpty) {
return Padding(
padding: EdgeInsets.all(15),
child: Text("You don't Have any Photo")
);
}
return GridView.builder(
// shrinkWrap: true,
itemCount: snapshot.data.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
// crossAxisSpacing: 10
),
itemBuilder: (context, i) {
return Padding(
padding: const EdgeInsets.all(4.0),
child: InkWell(
onTap: () {
Navigator.of(context)
.pushReplacement(MaterialPageRoute(builder: (context) {
return BeforeAfter2(
imageSelected1: snapshot.data[i]["post_image"],
);
}));
},
child: Container(
margin: EdgeInsets.only(top: 10, left: 10),
decoration: BoxDecoration(
border: Border.all(
color: Colors.deepPurple.shade500,
width: 2),
borderRadius:
BorderRadius.all(Radius.circular(35)),
image: DecorationImage(
fit: BoxFit.cover,
image: NetworkImage(
"http://10.0.2.2/upload/" +
snapshot.data[i]["post_image"]),
)),
),
),
);
},
);
},
);
}
showCata1(){
return FutureBuilder(
future: getData(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text('Loading...'),
Center(child: CircularProgressIndicator())
],
);
} else if (snapshot.data.isEmpty) {
return Padding(
padding: EdgeInsets.all(15),
child: Text("You don't Have any Photo")
);
}
return GridView.builder(
// shrinkWrap: true,
itemCount: snapshot.data.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
// crossAxisSpacing: 10
),
itemBuilder: (context, i) {
return Padding(
padding: const EdgeInsets.all(4.0),
child: InkWell(
onTap: () {
Navigator.of(context)
.pushReplacement(MaterialPageRoute(builder: (context) {
return BeforeAfter2(
imageSelected2: snapshot.data[i]["post_image"],
);
}));
},
child: Container(
margin: EdgeInsets.only(top: 10, left: 10),
decoration: BoxDecoration(
border: Border.all(
color: Colors.deepPurple.shade500,
width: 2),
borderRadius:
BorderRadius.all(Radius.circular(35)),
image: DecorationImage(
fit: BoxFit.cover,
image: NetworkImage(
"http://10.0.2.2/upload/" +
snapshot.data[i]["post_image"]),
)),
),
),
);
},
);
},
);
}
Related
I am trying to pass firebase snapshot data from first page to second page in flutter using GET. I'm able to pass data from one screen to another in debug mode but not in release mode.
I have used a streambuilder on the page and a Future on second . Please where am i going wrong ?
here is code..
first page:
Container(
child: Expanded(
child: StreamBuilder(
stream: FirebaseFirestore.instance
.collection('Songs')
.snapshots(),
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
}
return Container(
color: Colors.white24,
padding: EdgeInsets.all(10),
child: ListView(
children: snapshot.data!.docs.map((document) {
return Container(
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25),
side: BorderSide(
color: Colors.purple, width: 2)),
elevation: 4,
child: ListTile(
title: Text(document['title'],
style: TextStyle(fontSize: 16)),
subtitle: Text(
document['artist'],
style: TextStyle(color: Colors.purple),
),
onTap: () {
Get.to(() => DetailsPage(
piss: document,
post: document.id,
));
},
contentPadding: EdgeInsets.all(20),
leading: Image.asset('assets/logo.png'),
trailing: document['isNew'] == true
? Image.asset(
'assets/new.gif',
)
: null),
),
);
}).toList(),
),
);
}),
),
),
_banner == null
? Container()
: Container(
margin: const EdgeInsets.only(bottom: 12),
height: 52,
child: AdWidget(
ad: _banner!,
),
),
],
),
),
);
}
}
second page
FutureBuilder(
future: getData(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(
child: CircularProgressIndicator(),
);
} else {
return Expanded(
child: ListView.builder(
itemCount: widget.piss['tileHeaders'].length,
itemBuilder: (context, index) {
return GestureDetector(
onTap: () {
setState(() {
_index = index;
counter = counter + 1;
print('COUNTER: $counter');
if (counter == 3) {
_showRewardedAd();
_controller.play();
print("Counter is $counter");
counter = 0;
_createRewardedAd();
}
});
index > 0
? playIt(index)
: _controller
.load(widget.piss['videos'][index]);
},
child: Card(
elevation: 5,
child: Column(
children: [
Container(
height: 100,
child: Row(
children: [
Center(
child: Padding(
padding: EdgeInsets.all(10),
child: Expanded(
child: Image.asset(
"assets/logo.png"),
flex: 2,
// flex: 2,),
),
)),
Expanded(
child: Container(
alignment:
Alignment.topLeft,
child: Column(
children: [
Expanded(
flex: 5,
child: ListTile(
title: Text(
widget.piss[
'tileHeaders']
[index],
style: TextStyle(
fontSize:
26)),
),
),
Expanded(
flex: 5,
child: Row(
mainAxisAlignment:
MainAxisAlignment
.end,
children: [
Container(
child: widget
.piss[
'videos']
[
index]
.toString()
.contains(
'PL')
? Center(
child:
Container(child: playlist()),
)
: Center(
child:
Container(
child:
notPlaylist(),
),
),
),
],
))
],
)),
)
],
))
],
)),
);
}),
);
}
})
Please help
I am trying to list out a few texts after a bottom sheet opens, this is dynamic and comes from an API. Once the bottom sheet function is triggered, the API is called and the list view updates. In this list view I used CheckboxListTile, the problem is I am not able to do multiple selections (nor single select) on the checkboxes.
This is what I have so far:
var selectedIndex = [];
The above code is in the _MainScreenState and the function for the bottom screen is triggered in one of the buttons as:
...
onPressed: () {
_showModalBottomSheet(context).then((value) => setState(() {
index = value;
}));
}
...
Bottom sheet code
Future<AllApps?> _showModalBottomSheet(BuildContext context) {
return showModalBottomSheet<AllApps>(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
top: Radius.circular(20),
),
),
clipBehavior: Clip.antiAliasWithSaveLayer,
context: context,
isScrollControlled: true,
builder: (context) {
return FractionallySizedBox(
heightFactor: 0.9,
child: Column(
children: [
Padding(
padding: const EdgeInsets.fromLTRB(150.0, 20.0, 150.0, 20.0),
child: Container(
height: 8.0,
width: 80.0,
decoration: BoxDecoration(
color: Colors.grey[200],
borderRadius: BorderRadius.circular(20.0),
),
),
),
FutureBuilder<AllApps>(
future: getAllApps(), // <- API call
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
shrinkWrap: true,
physics: const ScrollPhysics(),
itemCount: snapshot.data?.data.length,
itemBuilder: (context, index) {
final app = snapshot.data?.data[index];
return CheckboxListTile(
enableFeedback: true,
title: Text(app!.name),
value: selectedIndex.contains(app.id),
onChanged: (_) {
if (selectedIndex.contains(app.id)) {
setState(() {
selectedIndex.remove(app.id);
});
} else {
setState(() {
selectedIndex.add(app.id);
});
}
},
);
},
);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
return const Center(child: CircularProgressIndicator());
},
),
Padding(
padding: const EdgeInsets.only(top: 20.0, right: 5.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Padding(
padding: const EdgeInsets.only(right: 8.0),
child: ElevatedButton(
child: const Text('Cancel'),
onPressed: () {
Navigator.pop(context);
},
),
),
ElevatedButton(
child: const Text('Save'),
onPressed: () {
Navigator.pop(context);
},
),
],
),
)
],
),
);
});
}
I am able to see the lists being built but I am not able to select any one of them (gif screenshot):
How should I enable multiple selections?
In order to apply changes in the state to the modal, use StateFulBuilder:
showModalBottomSheet(
isScrollControlled: true,
context: context,
builder: (context) {
return StatefulBuilder( // this is new
builder: (BuildContext context, StateSetter setState) {
return FractionallySizedBox(
heightFactor: 0.9,
child: Column(
children: [
Padding(
padding: const EdgeInsets.fromLTRB(150.0, 20.0, 150.0, 20.0),
child: Container(
height: 8.0,
width: 80.0,
decoration: BoxDecoration(
color: Colors.grey[200],
borderRadius: BorderRadius.circular(20.0),
),
),
),
FutureBuilder<AllApps>(
future: getAllApps(), // <- API call
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
shrinkWrap: true,
physics: const ScrollPhysics(),
itemCount: snapshot.data?.data.length,
itemBuilder: (context, index) {
final app = snapshot.data?.data[index];
return CheckboxListTile(
enableFeedback: true,
title: Text(app!.name),
value: selectedIndex.contains(app.id),
onChanged: (_) {
if (selectedIndex.contains(app.id)) {
setState(() {
selectedIndex.remove(app.id);
});
} else {
setState(() {
selectedIndex.add(app.id);
});
}
},
);
},
);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
return const Center(child: CircularProgressIndicator());
},
),
Padding(
padding: const EdgeInsets.only(top: 20.0, right: 5.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Padding(
padding: const EdgeInsets.only(right: 8.0),
child: ElevatedButton(
child: const Text('Cancel'),
onPressed: () {
Navigator.pop(context);
},
),
),
ElevatedButton(
child: const Text('Save'),
onPressed: () {
Navigator.pop(context);
},
),
],
),
)
],
),
);
});
});
You can use StatefulBuilder for providing setState in bottom sheet. Try as follows:
return StatefulBuilder(
builder:(BuildContext context,setState){
return FractionallySizedBox(....);
})
I have been trying to add the code below within the card grid view. The text widget is just for testing purposes. When I tap on the card I want to perform the action that is written for the iconButton onPressed method.
Expanded(
child: StreamBuilder(
stream:
FirebaseFirestore.instance.collection('location').snapshots(),
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) {
return Center(child: CircularProgressIndicator());
}
return ListView.builder(
itemCount: snapshot.data?.docs.length,
itemBuilder: (context, index) {
return ListTile(
title:
Text(snapshot.data!.docs[index]['name'].toString()),
subtitle: Row(
children: [
Text(snapshot.data!.docs[index]['latitude']
.toString()),
SizedBox(
width: 20,
),
Text(snapshot.data!.docs[index]['longitude']
.toString()),
],
),
trailing: IconButton(
icon: Icon(Icons.directions),
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) =>
MyMap(snapshot.data!.docs[index].id)));
},
),
);
});
},
)),
Here is the card grid
return Scaffold(body: Container(decoration: BoxDecoration(
image:DecorationImage(
image: AssetImage("assets/background.jpg"), fit: BoxFit.cover),),child: Container(
margin: const EdgeInsets.only(top: 120.0),
child: GridView(
physics: BouncingScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
children: events.map((title){
return GestureDetector(
child: Card(
elevation: 0,
color: Colors.transparent,
margin: const EdgeInsets.all(13.0),
child: getCardByTile(title)
),
onTap: () {
Fluttertoast.showToast(msg: title);
},
);
}).toList(),
),
),));
Here is the CardByTile() method used above.
getCardByTile(String title) {
String img = "";
if(title == "Navigation") {
img = "assets/navi.png";
}
if(title == "Current location") {
img = "assets/currentloc.png";
}
if(title == "Enable live location") {
img = "assets/track.png";
}
if(title == "Stop live location") {
img = "assets/stoplive.png";
}
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Center(
child: new Stack(
children: <Widget>[
new Image.asset(
img,
fit: BoxFit.contain,
//width: 80.0,
//height: 80.0,
)
],
),
)
]
);
}
and the event list.
List<String> events = [
"Navigation",
"Current location",
"Enable live location",
"Stop live location"
];
I want to show the defaultUserContainer() in case the stream is empty but also in case it's not, as an initial element of the list.
Currently. I can't seem to make either scenarios work. How can I design this better?
Column(
children: [
Row(
children: [
Padding(
padding: const EdgeInsets.only(left: 16.0, top: 8.0),
child: Padding(
padding: const EdgeInsets.only(bottom: 8.0),
child: Align(
alignment: Alignment.centerLeft,
child: Text(
"users",
style: TextStyle(fontSize: 20.0, color: Colors.black87),
)
),
),
),
],
),
SizedBox(
height: 120,
child: FutureBuilder(
builder: (context, snapshot) {
return StreamBuilder(
stream: _firestore.collection('ts').where('userid', isEqualTo: widget.user.id).snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
defaultUserContainer(); //If there's no users. tried returning it, or doing like it is here. never shows
return Text("");
} else {
return ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: snapshot.data.documents.length,
itemBuilder: (BuildContext context, int index) {
DocumentSnapshot userDoc = snapshot.data.documents[index];
if(index < snapshot.data.documents.length){
return Padding(
padding: const EdgeInsets.only(bottom: 8.0, left: 8.0, right: 8.0),
child: GestureDetector(
onTap: () => {},
child: Container(
child: FittedBox(
child: Material(
color: Colors.white,
elevation: 4.0,
borderRadius: BorderRadius.circular(8.0),
shadowColor: Colors.grey,
child: Row(
children: <Widget>[
Container(
child: myDetailsContainer(userDoc), //This guy works. it's just a more complicated defaultuserContainer()
),
],
),
)
)
),
),
);
}
return ListTile(leading:defaultuserContainer()); //Doesn't show when there's users users (my goal is to always have this as an initial item)
}
);
}
},
);
},
),
)
]
);
Widget defaultUserContainer() {
return ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Container(
height: 120,
width: 120,
color: myColors.blue,
child: Center(
child: Icon(Icons.add, size: 65, color: Colors.white),
),
),
);
}
You can define it as the first/last element of your ListView/GridView/Column/etc.
Here is a simple example with a GridView:
Full source code
import 'dart:math' show Random;
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
void main() {
runApp(
MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Random Generator',
home: RandomGeneratorPage(),
),
);
}
class RandomGeneratorPage extends HookWidget {
final int max;
final random = Random();
RandomGeneratorPage({Key key, this.max = 20}) : super(key: key);
#override
Widget build(BuildContext context) {
final numbers = useState<List<int>>([]);
return Scaffold(
appBar: AppBar(title: Text('Random Generator')),
body: GridView.count(
crossAxisCount: 5,
childAspectRatio: 1,
children: [
InkWell(
onTap: () =>
numbers.value = [...numbers.value, random.nextInt(max)],
child: Card(
color: Colors.blue.shade100,
child: Icon(Icons.add),
),
),
...numbers.value
.map(
(number) => InkWell(
onTap: () => numbers.value =
numbers.value.where((x) => x != number).toList(),
child: Card(
child: Center(child: Text(number.toString())),
),
),
)
.toList(),
],
),
);
}
}
In your case:
For your particular case, it would probably look like this: [NOT TESTED]
FutureBuilder(
builder: (context, snapshot) {
return StreamBuilder(
stream: _firestore
.collection('ts')
.where('userid', isEqualTo: widget.user.id)
.snapshots(),
builder: (context, snapshot) => ListView(
scrollDirection: Axis.horizontal,
children: [
InkWell(
onTap: () {},
child: Card(
color: Colors.blue.shade100,
child: Icon(Icons.add),
),
),
...snapshot.data.documents.map(
(doc) => Padding(
padding:
const EdgeInsets.only(bottom: 8.0, left: 8.0, right: 8.0),
child: GestureDetector(
onTap: () => {},
child: Container(
child: FittedBox(
child: Material(
color: Colors.white,
elevation: 4.0,
borderRadius: BorderRadius.circular(8.0),
shadowColor: Colors.grey,
child: Row(
children: <Widget>[
Container(
child: myDetailsContainer(
doc), //This guy works. it's just a more complicated defaultuserContainer()
),
],
),
),
),
),
),
),
)
],
),
);
},
)
Is there's a way to create a lists of GridViews as the below image in one screen...
I have a some Screen as the below one:
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
var _showOnlyFavorites = false;
AnimationController animationController;
bool multiple = true;
#override
void initState() {
animationController = AnimationController(
duration: const Duration(milliseconds: 2000), vsync: this);
super.initState();
}
Future<bool> getData() async {
await Future<dynamic>.delayed(const Duration(milliseconds: 0));
return true;
}
#override
void dispose() {
animationController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppTheme.white,
body: FutureBuilder<bool>(
future: getData(),
builder: (BuildContext context, AsyncSnapshot<bool> snapshot) {
if (!snapshot.hasData) {
return const SizedBox();
} else {
return Padding(
padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
appBar(),
Expanded(
child: FutureBuilder<bool>(
future: getData(),
builder:
(BuildContext context, AsyncSnapshot<bool> snapshot) {
if (!snapshot.hasData) {
return const SizedBox();
} else {
return PropertiesGrid(_showOnlyFavorites);
}
},
),
),
],
),
);
}
},
),
);
}
Widget appBar() {
return SizedBox(
height: AppBar().preferredSize.height,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 8, left: 8),
child: Container(
width: AppBar().preferredSize.height - 8,
height: AppBar().preferredSize.height - 8,
),
),
Expanded(
child: Center(
child: Padding(
padding: const EdgeInsets.only(top: 4),
child:
Image.asset('assets/images/logo.png', fit: BoxFit.contain),
),
),
),
Padding(
padding: const EdgeInsets.only(top: 8, right: 8),
child: Container(
width: AppBar().preferredSize.height - 8,
height: AppBar().preferredSize.height - 8,
color: Colors.white,
child: Material(
color: Colors.transparent,
child: InkWell(
borderRadius:
BorderRadius.circular(AppBar().preferredSize.height),
child: Icon(
multiple ? Icons.dashboard : Icons.view_agenda,
color: AppTheme.dark_grey,
),
onTap: () {
setState(() {
multiple = !multiple;
});
},
),
),
),
),
],
),
);
}
}
as I have a widget which have the GridView.builder as the below code:
import 'package:aradi_online_vtwo/providers/properties.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../providers/properties.dart';
import './property_item.dart';
class PropertiesGrid extends StatelessWidget {
final bool showFavs;
PropertiesGrid(this.showFavs);
#override
Widget build(BuildContext context) {
final productsData = Provider.of<Properties>(context);
final products = showFavs ? productsData.favoriteItems : productsData.items;
return GridView.builder(
padding: const EdgeInsets.all(10.0),
itemCount: products.length,
itemBuilder: (ctx, i) => ChangeNotifierProvider.value(
// builder: (c) => products[i],
value: products[i],
child: PropertyItem(
// products[i].id,
// products[i].title,
// products[i].imageUrl,
),
),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 1,
childAspectRatio: 3 / 2,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
), scrollDirection: Axis.horizontal,
);
}
}
I tried to set the height of the grid by wrapping it with a Container and set the height of it as to add more grids but it doesn't work.
and here's my Grid Item widget code:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../providers/property.dart';
class PropertyItem extends StatelessWidget {
#override
Widget build(BuildContext context) {
final property = Provider.of<Property>(context, listen: false);
return InkWell(
onTap: () => {},
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15),
),
elevation: 7,
margin: EdgeInsets.all(2),
child: Stack(
children: <Widget>[
ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(15),
topRight: Radius.circular(15),
),
// color: Colors.transparent,
child: Image.asset(
property.image,
fit: BoxFit.fill,
),
),
Positioned(
top: 8,
right: 8,
child: Consumer<Property>(
builder: (ctx, property, _) => IconButton(
icon: Icon(
property.isFavorite ? Icons.favorite : Icons.favorite_border,
),
color: Colors.red,
onPressed: () {
property.toggleFavoriteStatus();
},
),
),
),
Positioned(
right: 20,
top: 100,
child: Container(
width: 300,
color: Colors.black54,
padding: EdgeInsets.symmetric(
vertical: 5,
horizontal: 20,
),
child: Text(
property.title,
style: TextStyle(
fontSize: 20,
color: Colors.white,
),
softWrap: true,
overflow: TextOverflow.fade,
),
),
)
],
),
),
);
}
}
You'll need a column where each ListView or GridView is wrapped inside a SizedBox (if you have a specific height) and you also can use Expanded to take whatever available space (like the last one in the given example):
You can post the code below in dartpad.dev and see how it works:
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyApp(),
));
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
children: [
SizedBox(
height: 100,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 10,
itemBuilder: (c, i) {
return Card(
child: Container(
height: 100,
width: 100,
child: Center(child: Text("$i")),
),
);
},
),
),
Padding(
padding: const EdgeInsets.all(16.0),
child: Align(
child: Text("The Second List"),
alignment: Alignment.centerRight,
),
),
SizedBox(
height: 100,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 10,
itemBuilder: (c, i) {
return Card(
child: Container(
height: 100,
width: 100,
child: Center(child: Text("$i")),
),
);
},
),
),
Padding(
padding: const EdgeInsets.all(16.0),
child: Align(
child: Text("The Third List"),
alignment: Alignment.centerRight,
),
),
Expanded(
//height: 200,
child: GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: 3 / 2,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
),
scrollDirection: Axis.vertical,
itemCount: 20,
itemBuilder: (c, i) {
return Card(
child: Container(
height: 100,
width: 100,
child: Center(child: Text("$i")),
),
);
},
),
),
],
),
);
}
}