How can i navigate to a different route in ListView querySnapshot.docs[index].data()['image']. In my case all the cards will navigate to different route.
Relevant code with facing this issue:
import 'dart:ui';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:fluttertravelapp/screens/home.dart';
import 'package:fluttertravelapp/screens/location_list_screen.dart';
import 'package:fluttertravelapp/widgets/nav_drawer.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class SelectedCategoryScreen extends StatefulWidget {
SelectedCategoryScreen();
#override
_SelectedCategoryScreen createState() => _SelectedCategoryScreen();
}
class _SelectedCategoryScreen extends State<SelectedCategoryScreen> {
#override
void initState() {
super.initState();
}
final Query query = FirebaseFirestore.instance
.collection("movies")
.orderBy('year', descending: true);
void gotoPage(String pageName) {
switch (pageName) {
case 'home':
{
// statements;
Navigator.push(
context, CupertinoPageRoute(builder: (redContext) => HomePage()));
}
break;
case 'yard':
{
//statements;
Navigator.push(
context,
CupertinoPageRoute(
builder: (redContext) => LocationListScreen()));
}
break;
default:
{
throw new Exception("Path ${pageName} not supported");
}
break;
}
}
/// Page Controller
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(Icons.arrow_back_ios_new_sharp),
),
title: Container(
width: 170,
child: Image.network(
'https://i.hizliresim.com/sf4asddsau.jpg',
),
),
centerTitle: true,
actions: [
IconButton(
onPressed: () {},
icon: Icon(Icons.cloud_queue_outlined),
),
],
),
drawer: NavDrawer(),
body: SafeArea(
child: Container(
child: StreamBuilder(
stream: query.snapshots(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(
child: CircularProgressIndicator(),
);
} else if (snapshot.hasError) {
return Center(
child: Icon(Icons.error),
);
}
final QuerySnapshot<Map<String, dynamic>> querySnapshot =
snapshot.data;
return ListView(
physics: BouncingScrollPhysics(),
children: <Widget>[
Container(
margin: EdgeInsets.only(top: 28.8, bottom: 16.8),
height: 724.8,
child: ListView.builder(
itemCount: querySnapshot.size,
padding: EdgeInsets.only(left: 28.8, right: 12),
scrollDirection: Axis.vertical,
physics: BouncingScrollPhysics(),
itemBuilder: (context, index) {
return Container(
height: 214.8,
width: 188.4,
margin: EdgeInsets.only(right: 16.8, bottom: 50),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(9.6),
image: DecorationImage(
fit: BoxFit.cover,
image: CachedNetworkImageProvider(
querySnapshot.docs[index].data()['image'],
maxHeight: 200,
maxWidth: 200),
),
),
child: Stack(
children: <Widget>[
GestureDetector(
onTap: () {
GestureDetector(
onTap: () => gotoPage(querySnapshot
.docs[index]
.data()['page']));
/* Navigator.push(
context,
CupertinoPageRoute(
builder: (redContext) => MyApp()));*/
},
),
Positioned(
bottom: 19.2,
left: 19.2,
child: ClipRRect(
borderRadius: BorderRadius.circular(4.8),
child: BackdropFilter(
filter: ImageFilter.blur(
sigmaY: 19.2, sigmaX: 19.2),
child: Container(
height: 26,
padding: EdgeInsets.only(
left: 0.0, right: 0.0),
alignment: Alignment.centerLeft,
child: Row(
children: <Widget>[
SizedBox(
width: 9.52,
),
SvgPicture.asset(
'assets/svg/icon_location.svg'),
SizedBox(
width: 9.52,
),
SvgPicture.asset(
'assets/svg/icon_location.svg',
height: 50,
),
SizedBox(
width: 9.52,
),
SvgPicture.asset(
'assets/svg/icon_location.svg'),
SizedBox(
width: 9.52,
),
/* Text(
recommendations[index].name,
style: GoogleFonts.lato(
fontWeight: FontWeight.w700,
color: Colors.white,
fontSize: 16.8),
) */
],
),
),
),
),
),
Align(
alignment: Alignment.center,
child: Container(
margin: EdgeInsets.all(70),
child: Text(
querySnapshot.docs[index].data()['title'],
style: TextStyle(
fontSize: 27,
color: Colors.white,
fontWeight: FontWeight.bold),
textAlign: TextAlign.left,
),
),
),
],
),
);
},
),
)
],
);
},
),
),
),
);
}
}
Firestore:
If you look at the picture you can easily understand what I mean.
I am not sure how your document from QuerySnapshot looks like but you could add a field/property that contains the name of the page to be navigated to. Then add a function with a switch-case or if-else statements that control which page to navigate to in your onTap().
void gotoPage(String pageName){
switch(pageName) {
case 'home': {
// statements;
Navigator.push(context,CupertinoPageRoute(builder: (redContext) => HomePage()));
}
break;
case 'yard': {
//statements;
Navigator.push(context,CupertinoPageRoute(builder: (redContext) => YardPage()));
}
break;
default: {
throw new Exception(`Path ${pageName} not supported`);
}
break;
}
}
then call it in onTap.
GestureDetector(onTap: () => gotoPage(querySnapshot.docs[index].data()['page']) ),
where page will be the field/property with the pageName that you would have added to your document
Related
How to scroll the search widget along with the list view result flutter whenever I use singlechildscrollview it gives an error.Help me to solve the issue.
How to scroll the search widget along with the list view result flutter whenever I use singlechildscrollview it gives an error.Help me to solve the issue
import 'package:coronavirus_app/Services/states_services.dart';
import 'package:coronavirus_app/resources/sizeconfig.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:shimmer/shimmer.dart';
import '../Modal/world_countries_modal.dart';
import '../resources/colormanager.dart';
import '../resources/routesmanager.dart';
class CountriesListScreen extends ConsumerStatefulWidget {
const CountriesListScreen({Key? key}) : super(key: key);
#override
ConsumerState<CountriesListScreen> createState() =>
_CountriesListScreenState();
}
class _CountriesListScreenState extends ConsumerState<CountriesListScreen> {
final TextEditingController searchcontroller = TextEditingController();
#override
Widget build(BuildContext context) {
SizeConfig().init(context);
StatesServices services = StatesServices();
final countrydata = ref.watch(countrydataProvider);
return Scaffold(
appBar: AppBar(
elevation: 0,
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
),
body: countrydata.when(
error: (err, stack) => Text('Error: ${err.toString()}'),
loading: () => Shimmer.fromColors(
baseColor: ColorManager.grey,
highlightColor: ColorManager.lightGrey,
child: ListView.builder(
itemCount: 5,
itemBuilder: ((context, index) {
return Column(
children: [
ListTile(
title: Container(
height: getProportionateScreenHeight(20),
width: getProportionateScreenWidth(89),
color: ColorManager.white,
),
leading: SizedBox(
height: getProportionateScreenHeight(100),
width: getProportionateScreenWidth(50),
child: Container(
color: ColorManager.white,
)),
subtitle: Container(
height: getProportionateScreenHeight(20),
width: getProportionateScreenWidth(89),
color: ColorManager.white,
),
)
],
);
})),
),
data: ((data) {
List<WorldCountriesModal> countrieslist =
data.map((e) => e).toList();
return Column(children: [
SizedBox(
height: getProportionateScreenHeight(50),
width: double.infinity,
child: TextFormField(
controller: searchcontroller,
onChanged: (value) {
setState(() {});
},
decoration: InputDecoration(
contentPadding:
const EdgeInsets.symmetric(vertical: 10),
hintText: 'Search with country name',
prefixIcon: const Icon(Icons.search),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(50))),
),
),
Expanded(
child: ListView.builder(
itemCount: countrieslist.length,
itemBuilder: ((context, index) {
var data = countrieslist[index];
var countrydata = countrieslist[index].country;
if (searchcontroller.text.isEmpty) {
return Column(
children: [
InkWell(
onTap: (() {
FocusScope.of(context).unfocus();
Navigator.pushNamed(context, Routes.detail,
arguments: data);
}),
child: ListTile(
title: Text(data.country.toString()),
leading: SizedBox(
height: getProportionateScreenHeight(100),
width: getProportionateScreenWidth(50),
child: Image(
image: Image.network(data
.countryInfo!.flag
.toString())
.image),
),
subtitle: Text(data.cases.toString()),
),
)
],
);
} else if (countrydata!
.toLowerCase()
.contains(searchcontroller.text.toLowerCase())) {
return Column(
children: [
InkWell(
onTap: (() {
FocusScope.of(context).unfocus();
Navigator.pushNamed(context, Routes.detail,
arguments: data);
}),
child: ListTile(
title: Text(data.country.toString()),
leading: SizedBox(
height: getProportionateScreenHeight(100),
width: getProportionateScreenWidth(50),
child: Image(
image: Image.network(data
.countryInfo!.flag
.toString())
.image),
),
subtitle: Text(data.cases.toString()),
),
)
],
);
} else {
return Container(
height: 0,
);
}
})),
),
]);
})
}
}
ListView.builder(
shrinkWrap: true,
primary: false
Hey If you want to use singlechildscrollview then you need to assign
ListView.builder(
shrinkWrap: true
to your ListView.builder.
Because you can't assign the 2 scroll views to your screen at a time.
Put your widgets in SingleChildScrollView widget as the following example:
return Scaffold(
appBar: AppBar( ..........) ,
body: Container(
margin: const EdgeInsets.only(top: 15, right: 10),
alignment: Alignment.topRight,
width: double.infinity,
height: double.infinity,
==> child:SingleChildScrollView(
scrollDirection: Axis.vertical,
child: .......
I have an algorithm working, and I need to click on the image to show it on the entire screen, I have not succeeded, I send all the code, add a comment "// THIS IS THE IMAGE I NEED TO LOOK BIG WHEN I CLICK" which is the image that I want to make it look large when I click it, I have tried in several ways but I have not been able to solve it, and the only thing I am missing is this functionality.
import 'dart:async';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:tienda/models/productos_model.dart';
import 'package:tienda/pages/otra_pagina.dart';
import 'package:tienda/pages/crear_productos.dart';
import 'package:tienda/pages/pedido_lista.dart';
import 'package:tienda/services/firebase_services.dart';
import 'package:tienda/widgets/header.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
//title: 'Flutter Demo',
theme: ThemeData(
//primarySwatch: Colors.yellow,
primaryColor: Colors.yellow[800],
),
home: MyHomePage(title: 'RETO SAN JOSE CHAPARRAL'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<ProductosModel> _productosModel = List<ProductosModel>();
List<ProductosModel> _listaCarro = [];
FirebaseService db = new FirebaseService();
StreamSubscription<QuerySnapshot> productSub;
#override
void initState() {
super.initState();
_productosModel = new List();
productSub?.cancel();
productSub = db.getProductList().listen((QuerySnapshot snapshot) {
final List<ProductosModel> products = snapshot.documents
.map((documentSnapshot) =>
ProductosModel.fromMap(documentSnapshot.data))
.toList();
setState(() {
this._productosModel = products;
});
});
}
#override
void dispose() {
productSub?.cancel();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
actions: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 16.0, top: 8.0),
child: GestureDetector(
child: Stack(
alignment: Alignment.topCenter,
children: <Widget>[
Icon(
Icons.shopping_cart,
size: 38,
),
if (_listaCarro.length > 0)
Padding(
padding: const EdgeInsets.only(left: 2.0),
child: CircleAvatar(
radius: 8.0,
backgroundColor: Colors.red,
foregroundColor: Colors.white,
child: Text(
_listaCarro.length.toString(),
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 12.0),
),
),
),
],
),
onTap: () {
if (_listaCarro.isNotEmpty)
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => Cart(_listaCarro),
),
);
},
),
)
],
),
drawer: Container(
width: 170.0,
child: Drawer(
child: Container(
width: MediaQuery.of(context).size.width * 0.5,
//color: Colors.black, //color de menu principal
color: Colors.yellow[800],
child: new ListView(
padding: EdgeInsets.only(top: 30.0),
children: <Widget>[
Container(
height: 120,
child: new UserAccountsDrawerHeader(
accountName: new Text(''),
accountEmail: new Text(''),
decoration: new BoxDecoration(
image: new DecorationImage(
fit: BoxFit.fill,
image: AssetImage('assets/images/food1x.png'),
),
),
),
),
new Divider(),
new ListTile(
title: new Text(
'productos',
style: TextStyle(color: Colors.white),
),
trailing: new Icon(
Icons.fastfood,
size: 30.0,
color: Colors.white,
),
onTap: () =>
Navigator.of(context).push(new MaterialPageRoute(
builder: (BuildContext context) => CrearProductos(),
)),
),
new Divider(),
],
),
),
),
),
body: SafeArea(
child: SingleChildScrollView(
child: Container(
child: Column(
children: <Widget>[
Stack(
children: <Widget>[
WaveClip(),
Container(
color: Colors.transparent,
padding: const EdgeInsets.only(left: 24, top: 48),
height: 170,
child: ListView.builder(
itemCount: _productosModel.length,
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) {
return Row(
children: <Widget>[
Container(
height: 300,
padding: new EdgeInsets.only(
left: 10.0, bottom: 10.0),
child: Card(
elevation: 7.0,
clipBehavior: Clip.antiAlias,
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(24)),
child: AspectRatio(
aspectRatio: 1,
child: CachedNetworkImage(
imageUrl:
'${_productosModel[index].image}' +
'?alt=media',
fit: BoxFit.cover,
placeholder: (_, __) {
return Center(
child:
CupertinoActivityIndicator(
radius: 15,
));
}),
),
),
),
],
);
},
))
],
),
Container(height: 3.0, color: Colors.grey),
SizedBox(
height: 5.0,
),
Container(
color: Colors.grey[300],
height: MediaQuery.of(context).size.height / 1.5,
child: GridView.builder(
padding: const EdgeInsets.all(4.0),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2),
itemCount: _productosModel.length,
itemBuilder: (context, index) {
final String imagen = _productosModel[index].image;
var item = _productosModel[index];
return Card(
elevation: 4.0,
child: Stack(
fit: StackFit.loose,
alignment: Alignment.center,
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
child: CachedNetworkImage(
// THIS IS THE IMAGE I NEED TO LOOK BIG WHEN I CLICK
imageUrl:
'${_productosModel[index].image}' +
'?alt=media',
fit: BoxFit.cover,
placeholder: (_, __) {
return Center(
child:
CupertinoActivityIndicator(
radius: 15,
));
}),
),
Text(
'${_productosModel[index].name}',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 20.0),
),
SizedBox(
height: 15,
),
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: <Widget>[
SizedBox(
height: 25,
),
Text(
'${_productosModel[index].price.toString()}COP',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20.0,
color: Colors.black),
),
Padding(
padding: const EdgeInsets.only(
right: 8.0,
bottom: 8.0,
),
child: Align(
alignment: Alignment.bottomRight,
child: GestureDetector(
child: (!_listaCarro
.contains(item))
? Icon(
Icons.shopping_cart,
color: Colors.yellow[800],
size: 38,
)
: Icon(
Icons.shopping_cart,
color: Colors.red,
size: 38,
),
onTap: () {
setState(() {
if (!_listaCarro
.contains(item))
_listaCarro.add(item);
else
_listaCarro.remove(item);
});
},
),
),
),
],
)
],
),
],
));
},
)),
],
),
)),
));
}
}
Another solution is to show the larger image on the same screen using the dialog below.
InkWell(
onTap: () => showDialog(
builder: (BuildContext context) => AlertDialog(
backgroundColor: Colors.transparent,
insetPadding: EdgeInsets.all(2),
title: Container(
decoration: BoxDecoration(),
width: MediaQuery.of(context).size.width,
child: Expanded(
child: Image.network(
'${_productosModel[index].image}' +
'?alt=media',
fit: BoxFit.fitWidth,
),
),
),
),
context: context),
child: ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Image.network(
BaseUrl.host + posts!.imageUrl!,
fit: BoxFit.cover,
),
),
)
You can create a new page, wrap the image widget in a InkWell widget, and when tapped navigate to the new page showing the image.
EDIT:
Your widget image would become:
// THIS IS THE IMAGE I NEED TO LOOK BIG WHEN I CLICK
return InkWell(
onTap: () => Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) => ImageScreen(
url: '${_productosModel[index].image}' + '?alt=media',
),
),
),
child: Expanded(
child: CachedNetworkImage(
imageUrl: '${_productosModel[index].image}' + '?alt=media',
fit: BoxFit.cover,
placeholder: (_, __) {
return Center(
child: CupertinoActivityIndicator(
radius: 15,
),
);
},
),
),
),
And then you create a new stateless widget which it builds a:
import 'package:flutter/material.dart';
class ImageScreen extends StatelessWidget {
final String? url;
ImageScreen({
Key? key,
#required this.url,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Expanded(
child: CachedNetworkImage(
imageUrl: '${this.url}',
// Ajust the image changing the box fit attributte
fit: BoxFit.cover,
placeholder: (_, __) {
return Center(
child: CupertinoActivityIndicator(
radius: 15,
),
);
},
),
),
);
}
}
After that when you click the app navigates to a new screen rendering only the image. You can add a back button later.
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")),
),
);
},
),
),
],
),
);
}
}
I would like to change all app language without reload app. I used flutter_i18n
I have a switch language button on appBar and AppHomeScreen in body, here is build function in MyHomePage class:
addClickFn(model) {
FocusScope.of(context).requestFocus(FocusNode());
Navigator.push<dynamic>(
context,
MaterialPageRoute<dynamic>(
builder: (BuildContext context) => MyPopupScreen(callback: (c, id) => { }),
fullscreenDialog: true),
);
}
#override
Widget build(BuildContext context) {
return ScopedModelDescendant<ResponseDataModel>(
builder: (context, _, model) => 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 AppHomeScreen(
addClickFn: () => addClickFn(model));
}
},
),
),
],
),
);
}
},
),
));
}
appBar with onTap switch button function:
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: Text(
FlutterI18n.translate(context, "title"),
style: TextStyle(
fontSize: 22,
color: AppTheme.darkText,
fontWeight: FontWeight.w700,
),
),
),
),
),
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: Image.asset(
'icons/flags/png/' + currentLang.languageCode + '.png',
package: 'country_icons'),
onTap: () async {
setState(() {
currentLang = currentLang.languageCode == 'vn'
? new Locale('gb')
: new Locale('vn');
});
await FlutterI18n.refresh(context, currentLang);
},
),
),
),
),
],
),
);
}
In AppHomePage I included BottomBarView with DashboardScreen as tab body
#override
Widget build(BuildContext context) {
return Container(
color: AppTheme.background,
child: Scaffold(
backgroundColor: Colors.transparent,
body: FutureBuilder<bool>(
future: getData(),
builder: (BuildContext context, AsyncSnapshot<bool> snapshot) {
if (!snapshot.hasData) {
return const SizedBox();
} else {
return Stack(
children: <Widget>[
tabBody,
bottomBar(),
],
);
}
},
),
),
);
}
Future<bool> getData() async {
await Future<dynamic>.delayed(const Duration(milliseconds: 200));
return true;
}
Widget bottomBar() {
return Column(
children: <Widget>[
const Expanded(
child: SizedBox(),
),
BottomBarView(
tabIconsList: tabIconsList,
addClick: () {
if (widget.addClickFn != null) widget.addClickFn();
},
changeIndex: (int index) {
if (index == 0) {
animationController.reverse().then<dynamic>((data) {
if (!mounted) {
return;
}
setState(() {
tabBody =
DashboardScreen(animationController: animationController);
});
});
}
},
),
],
);
}
And in DashboardScreen I show a label:
#override
Widget build(BuildContext context) {
return Container(
color: AppTheme.background,
child: Scaffold(
backgroundColor: Colors.transparent,
body: Stack(
children: <Widget>[
getMainListViewUI(),
// getAppBarUI(),
SizedBox(
height: MediaQuery.of(context).padding.bottom,
)
],
),
),
);
}
Widget getMainListViewUI() {
return ListView(
scrollDirection: Axis.vertical,
semanticChildCount: 10,
children: <Widget>[
Container(
padding:
EdgeInsets.only(top: 0.0, left: 24, right: 24, bottom: 24.0),
child: Text(FlutterI18n.translate(context, "label.welcome"),
textAlign: TextAlign.left,
style: TextStyle(
fontFamily: AppTheme.fontName,
fontWeight: FontWeight.w700,
fontSize: 30 + 6 - 6 * topBarOpacity,
letterSpacing: 1.2,
color: AppTheme.darkerText,
))),
],
);
}
When I click switch language button, all text in current context (title) translates very well, but in DashboardScreen (label.welcome) are not.
And when I click add button on bottomBar to redirect to MyPopupScreen then close this popup, text in DashboardScreen has been translated.
How can I change all text in DashboardScreen when click switch language button on MyHomePage?
Sorry for my bad english!!!
You call FlutterI18n.refresh with the old currentLang value.
Try this:
setState(() {
currentLang = currentLang.languageCode == 'vn'
? new Locale('gb')
: new Locale('vn');
FlutterI18n.refresh(context, currentLang);
});