I am getting findAncestorStateOfType error in flutter . What should I do about this? I am stuck here - flutter

How to solve findAncestorStateOfType error in Flutter? I am not able to navigate to other page using these codes. What is wrong with this code?
The error which I am getting is this
The method 'findAncestorStateOfType' was called on null.
Receiver: null
Tried calling: findAncestorStateOfType()
My code is this:
// entry point for the app,
// the => operator is shorthand for {} when there is only one line of code
void main() {
runApp(MaterialApp(
home: HomeRoute(),
));
}
// the root widget of our application
class HomeRoute extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Color(0xFFFAAC98),
appBar: AppBar(
backgroundColor: Color(0xFFFAAC98),
),
body: myLayoutWidget(),
),
);
}
}
// replace this method with code in the examples below
Widget myLayoutWidget() {
return Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: 300,
height: 50,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30.0),
color: const Color(0xff89C5CC),
),
child: Center(
child: new Text(
'Gram Panchayat App',
style: TextStyle(
fontSize: 27,
fontWeight: FontWeight.bold,
color: Color(0xFF2F3676)),
),
),
),
),
Row(
children: [
Padding(
padding: const EdgeInsets.only(right: 18.0, top: 18.0),
child: Image.asset(
'assets/images/human1.png',
width: 150,
height: 150,
),
),
Padding(
padding: const EdgeInsets.only(left: 58.0),
child: elevatedButton(),
),
],
),
new Row(
children: [
Padding(
padding: const EdgeInsets.only(left: 28.0),
child: elevatedButton1(),
),
Padding(
padding: const EdgeInsets.only(top: 58.0, left: 68.0),
child: new Image.asset(
'assets/images/human2.png',
width: 200,
height: 170,
),
),
],
),
Padding(
padding: const EdgeInsets.only(left: 60.0),
child: Row(children: [
new Image.asset(
'assets/images/img3.png',
width: 180,
height: 80,
),
]),
)
],
),
);
}
ElevatedButton elevatedButton() => ElevatedButton(
onPressed: () {
BuildContext context;
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondRoute()),
);
},
child: Text('Citizen'),
);
ElevatedButton elevatedButton1() =>
ElevatedButton(onPressed: () {}, child: Text('Staff'));
class SecondRoute extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Second Route"),
),
body: Center(
child: ElevatedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('Go back!'),
),
),
);
}
}```
*Please help me I am stuck. I have gone through many sites but couldnt find what is wrong and the solution also.*

make myLayoutWidget() inside your HomeRoute class
and use
Navigator.of(context,rootNavigator:true).pop();
instead of
Navigator.pop(context);

Related

How to stack two bottom sheet in flutter?

I want to stack two bottom sheet each other in flutter as show in photo. The upper one is shown when in error state. In photo, it build with alert dialog. I want is with bottom sheet. How can I get it?
Edit:
Here is my code that I want to do. Lower bottom sheet is with pin field, autoComplete. autoComplete trigger StreamController, and then streamBuilder watch Error state and show dialog.
confirmPasswordModalBottomSheet(
BiometricAuthRegisterBloc biometricAuthRegBloc) {
showMaterialModalBottomSheet(
context: context,
builder: (BuildContext context) {
return StreamBuilder(
stream: biometricAuthRegBloc.biometricAuthRegisterStream,
builder: (context,AsyncSnapshot<ResponseObject>biometricAuthRegSnapShot) {
if (biometricAuthRegSnapShot.hasData) {
if (biometricAuthRegSnapShot.data!.messageState ==
MessageState.requestError) {
showModalBottomSheet(context: context, builder:
(BuildContext context){
return Container(
width: 200,height: 200,
child: Center(child: Text('Helllllllllo'),),);
});
}
}
return SizedBox(
width: 100,
height: 300,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(
height: margin30,
),
Text(CURRENT_PIN_TITLE),
SizedBox(
height: margin30,
),
Padding(
padding: const EdgeInsets.only(
left: margin60, right: margin60),
child: PinCodeField(
pinLength: 6,
onChange: () {},
onComplete: (value) {
biometricAuthRegBloc.biometricAuthRegister(
biometricType:_biometricAuthTypeForApi,
password: value);
},
),
),
SizedBox(
height: margin30,
),
Padding(
padding: const EdgeInsets.symmetric(horizontal:
margin80),
child: AppButton(
onClick: () {},
label: CANCEL_BTN_LABEL,
),
),
Container(
padding: const EdgeInsets.all(8.0),
margin:
EdgeInsets.symmetric(vertical: 8.0,
horizontal: 30),
decoration: BoxDecoration(
color: Colors.grey,
border: Border.all(color: Colors.black),
),
child: const Text(
FINGER_PRINT_DIALOG,
textAlign: TextAlign.center,
),
)
],
),
);
});
},
);
}
When I do like that above, I get setState() or markNeedsBuild() called during build. Error and why? Sorry for my previous incomplete question.
I am bit confused with your question but stacking two bottomsheet is just easy. You just need to call the showModalBottomSheet whenever you want it shown to user. You can check out the following implementation:
class HomeScreen extends StatelessWidget {
const HomeScreen({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: ElevatedButton(
onPressed: () {
showModalBottomSheet<void>(
context: context,
builder: (BuildContext context) {
return Container(
height: 500,
color: Colors.amber,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const Text('Modal BottomSheet 1'),
ElevatedButton(
child: const Text('Show second modal 2'),
onPressed: () {
showModalBottomSheet<void>(
context: context,
builder: (BuildContext context) {
return Container(
height: 200,
color: Colors.redAccent,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const Text('Modal BottomSheet 2'),
ElevatedButton(
child: const Text('Close BottomSheet'),
onPressed: () => Navigator.pop(context),
),
],
),
),
);
},
);
},
),
],
),
),
);
},
);
},
child: Text('Show bottom sheet 1'),
),
);
}
}
I have solution. All I need to do is, need to add WidgetBinding.insatance.addPostFrameCallback((timeStamp){showModalBottomSheet()}); in the StreamBuilder return.

Error: The getter 'context' isn't defined for the class 'MyApp'

I want to make an app that contain 4 buttons and it will go to other page if I click the button. But when I use the navigator it shows an error at context.
import 'package:flutter/material.dart';
import 'package:mytestapp/LectureVideo.dart';
import 'package:path/path.dart';
void main() {
runApp( MaterialApp(
debugShowCheckedModeBanner: false, //hide debug sash at top right
title: 'HomePage',
home: MyApp(),
)
);
}
class MyApp extends StatelessWidget{
#override
Widget build(BuildContext context) {
double width = MediaQuery.of(context).size.width; //getting screen width
return Scaffold(
appBar: AppBar(title: Text('Welcome to EMTeach'),
centerTitle: true,
backgroundColor: Colors.lime[200],
),
body: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Container(margin: EdgeInsets.only(bottom: 20.0)),
FirstButton(width),
Container(margin: EdgeInsets.only(bottom: 20.0)),
SecondButton(width),
Container(margin: EdgeInsets.only(bottom: 20.0)),
ThirdButton(width),
Container(margin: EdgeInsets.only(bottom: 20.0)),
FourthButton(width),
Container(margin: EdgeInsets.only(bottom: 20.0)),
],
),
),
);
}
Widget FirstButton(double width) {
return Expanded(
child: SizedBox(
width: width - 20,
child: RaisedButton(
onPressed: () {
Navigator.push(
context, //error
MaterialPageRoute(builder: (context) => LectureVideo()));
},
color: Colors.red,
child: Text(
"Lecture Video",
textScaleFactor: 2.0,
),
),
//fit: BoxFit.cover,
),
);
}
Widget SecondButton(double width) {
return Expanded(
child: SizedBox(
width: width - 20,
child: RaisedButton(
onPressed: () {},
color: Colors.lightGreen,
child: Text(
"Application Video",
textScaleFactor: 2.0,
),
),
//fit: BoxFit.cover,
),
);
}
Widget ThirdButton(double width) {
return Expanded(
child: SizedBox(
width: width - 20,
child: RaisedButton(
onPressed: () {},
color: Colors.lightBlue,
child: Text(
"List of Equation",
textScaleFactor: 2.0,
),
),
//fit: BoxFit.cover,
),
);
}
Widget FourthButton(double width) {
return Expanded(
child: SizedBox(
width: width - 20,
child: RaisedButton(
onPressed: () {},
color: Colors.orange,
child: Text(
"List of Question",
textScaleFactor: 2.0,
),
),
//fit: BoxFit.cover,
),
);
}
}
the problem is you are not passing the context which is the parameter of the build function over to your buttons try this:
Widget FirstButton(double width,BuildContext context ) {
return Expanded(
child: SizedBox(
width: width - 20,
child: RaisedButton(
onPressed: () {
Navigator.push(
context, //error
MaterialPageRoute(builder: (context) => LectureVideo()));
},
color: Colors.red,
child: Text(
"Lecture Video",
textScaleFactor: 2.0,
),
),
//fit: BoxFit.cover,
),
);
}

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 to get data from previous page flutter

I'm trying to build a page about description of a photo with this code:
import 'package:flutter/material.dart';
import 'description_widget.dart';
class ImageDescription extends StatefulWidget {
#override
_ImageDescriptionState createState() => _ImageDescriptionState();
}
class _ImageDescriptionState extends State<ImageDescription> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
backgroundColor: Colors.white10,
elevation: 0,
leading: Container(
padding: EdgeInsets.fromLTRB(20, 20, 0, 0),
child: InkWell(
child: Hero(
tag: 'back',
child: Image.asset(
'assets/images/wp_back_button_icon.png',
height: 250,
),
),
onTap: () {
Navigator.pop(context);
},
),
),
actions: <Widget>[
Container(
padding: EdgeInsets.fromLTRB(0, 20, 20, 0),
child: Hero(
tag: 'logo',
child: Image.asset(
'assets/images/wp_logo.png',
height: 250,
),
),
),
],
),
body: SingleChildScrollView(
child: imageDescription(
"assets/images/gallery/Image1.jpg",
"Tittle 1",
"Description 1.",
"Image1"),
),
);
}
}
Using this Widget that i've created:
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
Widget imageDescription(String url, title, description, tag) {
return Container(
child: Column(
children: <Widget>[
Container(
child: Column(
children: <Widget>[
Center(
child: Text(title, style: TextStyle(fontSize: 30)),
),
Center(
child: Text("Let's educate in the fun way!"),
)
],
),
),
Container(
child: Column(
children: <Widget>[
Container(
padding: const EdgeInsets.all(10),
child: ClipRRect(
borderRadius: BorderRadius.circular(20),
child: Hero(tag: tag, child: Image.asset(url)),
),
),
Container(
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
child: Card(
child: Container(
margin: const EdgeInsets.all(10),
child: Text(
description,
textAlign: TextAlign.justify,
style: TextStyle(fontSize: 20),
),
),
),
)
],
),
)
],
),
);
}
But instead of manually adding the imageDescription(
"assets/images/gallery/Image1.jpg",
"Tittle 1",
"Description 1.",
"Image1"),
I want to get the variables from the image that i clicked on previous page :
import 'package:flutter/material.dart';
import 'image_description.dart';
import 'show_image.dart';
class Gallery extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomPadding: false,
appBar: AppBar(
automaticallyImplyLeading: false,
backgroundColor: Colors.white10,
elevation: 0,
leading: Container(
padding: EdgeInsets.fromLTRB(20, 20, 0, 0),
child: InkWell(
child: Hero(
tag: 'back',
child: Image.asset(
'assets/images/wp_back_button_icon.png',
height: 250,
),
),
onTap: () {
Navigator.pop(context);
},
),
),
actions: <Widget>[
Container(
padding: EdgeInsets.fromLTRB(0, 20, 20, 0),
child: Hero(
tag: 'logo',
child: Image.asset(
'assets/images/wp_logo.png',
height: 250,
),
),
),
],
),
body: SafeArea(
child: Column(
children: <Widget>[
Container(
child: Text(
'AR Gallery',
style: TextStyle(fontSize: 30),
),
),
Container(
child: Text("Let's educate in the fun way"),
),
Expanded(
child: SizedBox(
height: double.infinity,
child: GridView.count(
primary: false,
padding: const EdgeInsets.all(20),
crossAxisSpacing: 10,
mainAxisSpacing: 10,
crossAxisCount: 3,
children: <Widget>[
InkWell(
child: Stack(
children: <Widget>[
ShowImage(
url: "assets/images/gallery/Image1.jpg",
tag: "Image1",
title: "Title 1",
)
],
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ImageDescription()));
},
),
InkWell(
child: Stack(
children: <Widget>[
ShowImage(
url: "assets/images/gallery/Image2.jpg",
tag: "Image2",
title: "Title 2",
)
],
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ImageDescription()));
},
),
InkWell(
child: Stack(
children: <Widget>[
ShowImage(
url: "assets/images/gallery/Image3.jpg",
tag: "Image3",
title: "Title 3",
)
],
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ImageDescription()),
);
}),
],
),
),
),
],
),
),
);
}
}
using this widget:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class ShowImage extends StatelessWidget {
final String tag;
final String url;
final String title;
const ShowImage({Key key, this.tag, this.url, this.title}) : super(key: key);
#override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
Container(
height: double.infinity,
width: double.infinity,
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child:
Hero(tag: tag, child: Image.asset(url, fit: BoxFit.fitHeight)),
),
),
Container(
padding: const EdgeInsets.all(5),
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Text(title,
style: TextStyle(
backgroundColor: Colors.deepOrange, color: Colors.white)),
),
)
],
);
}
}
or simply:
open gallery page
click an image
open image description page with title & image path of clicked image
Regards, Slim
I would recommend you to follow this tutorial.
For you this would mean:
Create a class that contains all the data you would like to pass:
class ImageData {
final String title;
final String url;
final String description;
final String tag;
Image(this.title, this.url, this.description, this.tag);
}
Set Up your ImageDescriptionScreen to require an Image object:
import 'package:flutter/material.dart';
import 'description_widget.dart';
import 'image_data.dart';
class ImageDescription extends StatefulWidget {
final ImageData imageData;
// In the constructor, require an Image Object.
ImageDescriptionScreen({Key key, #required this.imageData}) :
super(key: key);
#override
_ImageDescriptionState createState() => _ImageDescriptionState();
}
class _ImageDescriptionState extends State<ImageDescription> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
backgroundColor: Colors.white10,
elevation: 0,
leading: Container(
padding: EdgeInsets.fromLTRB(20, 20, 0, 0),
child: InkWell(
child: Hero(
tag: 'back',
child: Image.asset(
'assets/images/wp_back_button_icon.png',
height: 250,
),
),
onTap: () {
Navigator.pop(context);
},
),
),
actions: <Widget>[
Container(
padding: EdgeInsets.fromLTRB(0, 20, 20, 0),
child: Hero(
tag: 'logo',
child: Image.asset(
'assets/images/wp_logo.png',
height: 250,
),
),
),
],
),
body: SingleChildScrollView(
child: imageDescription(
widget.imageData.url,
widget.imageData.title,
widget.imageData.description,
widget.imageData.tag
),
),
);
}
}
Pass the image object when navigating to the new page:
Navigator.push(context, MaterialPageRoute(builder: (context) =>
ImageDescription(imageData: ImageData('title', 'url', 'description', 'tag'),)));
EDIT: I put my solution outlined below into dartpad, feel free to try it out there and copy & paste the code.
Short remarks to my dartpad solution:
All image data is maintained and contained in this list of ImageData Objects. Relevant information for other screens is passed via Navigator. With this solution you only need to maintain image data in this list. The grid view automatically expands if more items are added to the list.
final List<ImageData> imageList = [
ImageData(title: 'MacBook',url: 'https://picsum.photos/250?image=9',
description: 'this is a macbook', tag: 'macbook'),
ImageData(title: 'Deer',url: 'https://picsum.photos/250?image=1003',
description: 'this is a deer', tag: 'deer'),
];
Let me know if anything is unclear :)

Flutter - material design 2 semi transparent appbar

I want to get effect like this - when scrolled up, appbar is transparent with listview visible below it:
And scrolled down, only white color - first item below appbar:
My window layout:
return Container(
color: AppTheme.nearlyWhite,
child: SafeArea(
top: false,
bottom: false,
child: Scaffold(
backgroundColor: AppTheme.nearlyWhite,
body: Stack(
children: <Widget>[
DrawerUserController(
screenIndex: _drawerIndex,
drawerWidth: MediaQuery.of(context).size.width * 0.75,
animationController: (AnimationController animationController) => _sliderAnimationController = animationController,
onDrawerCall: (DrawerIndex drawerIndexdata) => _onDrawerCall(drawerIndexdata, _forceRefresh),
onDrawerTap:(DrawerIndex drawerIndexdata) => _onDrawerTap(drawerIndexdata),
screenView: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.fromLTRB(8, MediaQuery.of(context).padding.top + 8, 8, 8),
child: _createAppBar(),
),
Expanded(
child:
Container(
color: Colors.white,
child: _screenView,
)
),
],
),
),
new FabDialer(_fabMiniMenuItemList, Colors.blue, new Icon(Icons.add))
],
),
),
),
);
}
_screenView is simple Listview().builder() and it shows InkWell widget for each item. My appbar is custom, defined like this:
_createAppBar() {
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: Column(
children: <Widget>[
Text(
_menuSelected,
style: TextStyle(
fontSize: 22,
color: AppTheme.darkText,
fontWeight: FontWeight.w400,
),
),
Text(
globals.cityName,
style: TextStyle(
fontSize: 15,
color: AppTheme.darkerText,
fontWeight: FontWeight.w400,
),
),
],
),
),
),
),
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(Icons.refresh, color: AppTheme.dark_grey,),
onTap: () => setState(() => _forceRefresh = true),
),
),
),
),
],
),
);
}
That's how it looks now with first list item visible:
So, almost there, but when scrolled down, appbar won't be transparent:
I tried to mess around with setting my appbar backround to color with transparency, without success. Also I need to get my widgets actually overlapped (ListView needs to overlap my appbar) and it generates error messages from Flutter.
Any ideas how to do that properly?
set extendBodyBehindAppBar: true in Scaffold widget. Then use Opacity widget like this,
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(home: Home()));
}
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
#override
Widget build(BuildContext context) {
return Scaffold(
extendBodyBehindAppBar: true,
appBar: PreferredSize(
preferredSize: const Size.fromHeight(kToolbarHeight),
child: Opacity( //Wrap your `AppBar`
opacity: 0.8,
child: AppBar(
title: Text("Demo"),
),
),
),
body: ListView.builder(
itemCount: 30,
itemBuilder: (context, index) {
return ListTile(
title: Text("Tile: $index"),
);
},
),
);
}
}
#override
Widget build(BuildContext context) {
return Container(
child: Stack(
children:[
Container(
color:Colors.white,
padding:EdgeInsets.all(10),
child:ListView.builder(
itemCount:25+1,
//length + 1 is beacause to show 1st item at the beginning
shrinkWrap:true,
itemBuilder:(con,ind){
return ind==0 ?
Container(height:70)
:ListTile(
title:Text('Item $ind',
style:TextStyle(color:Colors.black,))
);
}
)
),
Container(
height:70,
color:Colors.transparent,
child:Card(
color:Colors.white.withAlpha(80),
child: Row(
children:[
Expanded(
flex:1,
child: IconButton(
icon:Icon(Icons.list,color:Colors.black,size:25),
onPressed:(){
//todo
}
),
),
Expanded(
flex:3,
child: Text('Title',
style:TextStyle(color:Colors.black,)),
),
Expanded(
flex:1,
child: IconButton(
icon:Icon(Icons.search,color:Colors.black,size:25),
onPressed:(){
//todo
}
),
),
Expanded(
flex:1,
child: IconButton(
icon:Icon(Icons.more_vert,color:Colors.black,size:25),
onPressed:(){
//todo
}
),
)
]
),
)
)
]
)
);
}