Flutter different screen navigation using on onTap uncertain ListView - flutter

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 search widget along with the list view result flutter

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: .......

large image when clicking - flutter

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.

How can I insert an initial element into Listview.builder

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()
),
],
),
),
),
),
),
),
)
],
),
);
},
)

How to create multiple horizontal `GridView` in the same screen using flutter

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")),
),
);
},
),
),
],
),
);
}
}

Flutter - How to change child widgets language

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);
});