How can I position a FloatingActionButton spanning two widget in Flutter? - flutter

I trying to position a FloatingActionButton spanning two widget in flutter.
like this.
However, this is my app screen.
I can't stack the button on the center of two widget.
How can I solve my question :(? This is the sample code of my app. Thanks.
import 'package:flutter/material.dart';
class UserProfileBody extends StatelessWidget {
const UserProfileBody({
Key? key,
}) : super(key: key);
Widget _buildUserProfilePhoto(BuildContext context) {
return Container(
constraints: BoxConstraints(
maxHeight: MediaQuery.of(context).size.width,
),
width: MediaQuery.of(context).size.width,
child: const Image(
fit: BoxFit.contain,
image: NetworkImage(defaultUserProfileImage),
),
);
}
#override
Widget build(BuildContext context) {
return Column(
children: [
_buildUserProfilePhoto(context),
Stack(
children: [
Align(
alignment: Alignment.topRight,
child: FloatingActionButton(
onPressed: () {},
child: const Icon(Icons.photo_camera),
),
),
Column(
children: [
ListTile(
title: const Text('the title'),
subtitle: const Text('the subtitle'),
onTap: () {},
)
],
),
],
),
],
);
}
}

You can place image inside stack, in this case UI will be
class UserProfileBody extends StatelessWidget {
const UserProfileBody({
Key? key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return LayoutBuilder(builder: (context, constraints) {
final double imageHeight = constraints.maxHeight * .5;
debugPrint(imageHeight.toString());
return Column(
children: [
Stack(
clipBehavior: Clip.none,
children: [
// image
Align(
alignment: Alignment.topCenter,
child: Container(
height: imageHeight,
color: Colors.green,
)
// _buildUserProfilePhoto(context),
),
Positioned(
top: imageHeight - (64 / 2), //64 is default fab size
right: 24,
child: FloatingActionButton(
onPressed: () {},
child: const Icon(Icons.photo_camera),
),
),
// Column(
// children: [
// ListTile(
// title: const Text('the title'),
// subtitle: const Text('the subtitle'),
// onTap: () {},
// )
// ],
// )
],
),
],
);
});
}
}
Play with
Positioned(
top: imageHeight - (64 / 2), //64 is default fab size
right: 24,
child: FloatingActionButton(
Solution 2:
And if you like place image above stack
Positioned(
top: -(64 / 2),
class UserProfileBody extends StatelessWidget {
const UserProfileBody({
Key? key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return LayoutBuilder(builder: (context, constraints) {
final double imageHeight = constraints.maxHeight * .5;
debugPrint(imageHeight.toString());
return Column(
children: [
Container(
height: imageHeight,
color: Colors.green,
),
SizedBox(
height: constraints.maxHeight - imageHeight,
child: Stack(
clipBehavior: Clip.none,
children: [
Positioned(
top: -(64 / 2), //64 is default fab size
right: 24,
child: FloatingActionButton(
onPressed: () {},
child: const Icon(Icons.photo_camera),
),
),
Column(
children: [
ListTile(
title: const Text('the title'),
subtitle: const Text('the subtitle'),
onTap: () {},
)
],
)
],
),
),
],
);
});
}
}
Use clipBehavior: Clip.none, on stack

Related

Make Listeview work nested inside of column inside of a container in flutter

I am trying and make a Listeview work, which is nested inside of column that is nested inside of a container in flutter. The container is supposed to be a dialog. I think the problem is that the container has no defined hight (it is supposed to adapt to the screen size). With the current code I get a bottom overflow. Maybe because of the padding of the container?
I tried differen variants with expanded, flexible and singlechildscrollview but I can't make it work. The standard tip, wrap the ListView with Expanded seems not to work.
Thanks for your help!
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Dialog',
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: const Text('Welcome to Flutter'),
),
body: Center(
child: Column(
children: [
MaCard(mitarbeiterName: "Name"),
CustomDialogBoxRow(
title: "Sturmtruppler",
descriptions: "wird noch weichen",
text: "text")
],
),
),
),
);
}
}
class Constants {
Constants._();
static const double padding = 20;
static const double avatarRadius = 100;
static const double buttonHight = 100;
}
class CustomDialogBoxRow extends StatefulWidget {
final String title, descriptions, text;
const CustomDialogBoxRow({
Key? key,
required this.title,
required this.descriptions,
required this.text,
}) : super(key: key);
#override
_CustomDialogBoxRowState createState() => _CustomDialogBoxRowState();
}
class _CustomDialogBoxRowState extends State<CustomDialogBoxRow> {
#override
Widget build(BuildContext context) {
return Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(Constants.padding),
),
elevation: 0,
backgroundColor: Colors.transparent,
child: contentBox(context),
);
}
contentBox(context) {
return Stack(
children: <Widget>[
Container(
constraints: const BoxConstraints(minWidth: 400, maxWidth: 800),
padding: const EdgeInsets.only(
left: Constants.padding,
right: Constants.padding,
bottom: Constants.padding),
margin: const EdgeInsets.only(top: Constants.avatarRadius),
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: Colors.white,
borderRadius: BorderRadius.circular(Constants.padding),
boxShadow: [
const BoxShadow(
color: const Color.fromARGB(255, 79, 73, 73),
offset: const Offset(0, 5),
blurRadius: 5),
]),
child: Column(
children: [
SizedBox(
height: Constants.avatarRadius,
child: Row(
children: [
const SizedBox(
child: const Placeholder(),
),
const Expanded(
child: Placeholder(),
),
],
),
),
SingleChildScrollView(
child: Column(
children: [
SizedBox(
height: 50,
child: Text("bla"),
),
SizedBox(
height: 50,
child: Text("bla"),
),
SizedBox(
height: 50,
child: Text("bla"),
),
SizedBox(
height: 50,
child: Text("bla"),
)
],
),
)
],
),
),
Positioned(
left: Constants.padding,
right: Constants.padding,
child: Stack(
children: [
Container(
child: Align(
alignment: Alignment.topLeft,
child: Container(
width: Constants.avatarRadius * 2,
height: Constants.avatarRadius * 2,
child: const CircleAvatar(
radius: Constants.avatarRadius * 2,
backgroundImage: AssetImage('assets/images/SBE.jpg'),
),
),
),
),
],
),
),
],
);
}
}
class MaCard extends StatefulWidget {
MaCard({
Key? key,
required this.mitarbeiterName,
}) : super(key: key);
final String mitarbeiterName;
#override
State<MaCard> createState() => _MaCardState();
}
class _MaCardState extends State<MaCard> {
#override
Widget build(BuildContext context) {
return Card(
child: InkWell(
onTap: () {
print("card taped");
/*showDialog(context: context, builder: (BuildContext context) {
return
})*/
showDialog(
context: context,
builder: (BuildContext context) {
return CustomDialogBoxRow(
title: "Stormtrouper",
descriptions: "Jojo, this is card",
text: "Roger Roger",
);
});
},
child: SizedBox(
height: Constants.buttonHight,
width: 300,
child: Center(child: Text(widget.mitarbeiterName)),
),
));
}
}
Here is picture of what it should look like. My wonderful handdrawing is supposed to be the scrollable content.
Goal
It would be better using LayoutBuilder to get parent constraints and size the inner elements. Also You need to wrap with Expaned to get available spaces for infinite size widget.
I will highly recommend to check this video from Flutter.
Changes are made
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Dialog',
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: const Text('Welcome to Flutter'),
),
body: Center(
child: Column(
children: [
MaCard(mitarbeiterName: "Name"),
Expanded( //here
child: CustomDialogBoxRow(
title: "Sturmtruppler",
descriptions: "wird noch weichen",
text: "text"),
)
],
),
),
),
);
}
}
And on contentBox
contentBox(context) {
return LayoutBuilder(builder: (context, constraints) {
print(constraints);
return SizedBox(
width: constraints.maxWidth,
height: constraints.maxHeight,
child: Stack(
children: <Widget>[
Container(
constraints: const BoxConstraints(minWidth: 400, maxWidth: 800),
padding: const EdgeInsets.only(
left: Constants.padding,
right: Constants.padding,
bottom: Constants.padding),
margin: const EdgeInsets.only(top: Constants.avatarRadius),
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: Colors.white,
borderRadius: BorderRadius.circular(Constants.padding),
boxShadow: const [
BoxShadow(
color: Color.fromARGB(255, 79, 73, 73),
offset: Offset(0, 5),
blurRadius: 5),
]),
child: Column(
children: [
SizedBox(
height: Constants.avatarRadius,
child: Row(
children: [
const Expanded(
child: const Placeholder(),
),
const Expanded(
child: Placeholder(),
),
],
),
),
Expanded(
// or sizedBOx ( constraints.maxHeight- Constants.avatarRadius,)
child: SingleChildScrollView(
child: Column(
children: [
SizedBox(
height: 450,
child: Text("bla"),
),
SizedBox(
height: 50,
child: Text("bla"),
),
SizedBox(
height: 50,
child: Text("bla"),
),
SizedBox(
height: 50,
child: Text("bla"),
)
],
),
),
)
],
),
),
// Positioned(
// left: Constants.padding,
// right: Constants.padding,
// child: Stack(
// children: [
// Container(
// child: Align(
// alignment: Alignment.topLeft,
// child: Container(
// width: Constants.avatarRadius * 2,
// height: Constants.avatarRadius * 2,
// child: const CircleAvatar(
// radius: Constants.avatarRadius * 2,
// backgroundImage: AssetImage('assets/images/SBE.jpg'),
// ),
// ),
// ),
// ),
// ],
// ),
// ),
//
],
),
);
});
}

Flutter Navigation shows a black 404 screen when going back from a page

I'm facing this issue with Navigator in Flutter where when I go back from a page I get redirected to a black 404 page.
This is the navigation flow:
Login screen
HomePage screen
After being logged in, I am redirected to the Homepage and I shouldn't be able to go back to a previous screen, but if I swipe to the right I'm shown a black page with a 404 label and I can't move from there. Thank you in advance for any help!
Here I provide some code:
class SignInPage extends StatelessWidget {
static const routeName = '/signIn';
const SignInPage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Expanded(
child: Stack(
children: [
const Positioned(
left: -20,
top: -20,
child: AnimatedCircle(color: AppColors.lightBlue),
),
const Positioned(
right: -50, top: 150, child: AnimatedCircle(color: AppColors.lightOrange)),
const Positioned(
bottom: 60, left: -70, child: AnimatedCircle(color: AppColors.lightGreen)),
const Positioned(
right: -50, bottom: -60, child: AnimatedCircle(color: AppColors.lightRed)),
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset('assets/images/logo.png'),
Container(
width: MediaQuery.of(context).size.width * 8,
margin: const EdgeInsets.symmetric(horizontal: Dimens.SPACING_XL),
child: StyledButton.outlined(
title: 'Sign in with Google',
leading: Image.asset('assets/images/google.png', scale: 30),
onPressed: () async {
final res = await Authentication.signInWithGoogle();
await Authentication.userSetup(res.user!);
Navigator.of(context).popAndPushNamed(HomePage.routeName);
},
),
),
],
),
],
),
),
],
),
);
}
}
class HomePage extends StatelessWidget {
static const routeName = '/homepage';
static const _padding = EdgeInsets.symmetric(horizontal: 20.0, vertical: 6.0);
static const _dividerOptions = 30.0;
const HomePage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (_) => ItemsProvider(),
child: Consumer<ItemsProvider>(
builder: (_, provider, __) => Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
automaticallyImplyLeading: false,
actions: [
IconButton(
onPressed: () => Navigator.of(context).pushNamed('/user'),
icon: const Icon(Icons.person)),
],
),
floatingActionButton: Visibility(
visible: provider.buttonVisibility,
child: FloatingActionButton(
heroTag: "btn1",
backgroundColor: AppColors.red,
child: const Icon(Icons.add, color: AppColors.splashColor),
onPressed: () {
showModalBottomSheet(
context: context,
isScrollControlled: true,
builder: (context) => buildModal(context, provider),
);
}),
),
body: Padding(
padding: _padding,
child: Column(
children: [
TopCard(
itemCount: provider.itemsCount,
onPressed: () {
provider.deleteAllItem();
Navigator.of(context).pop();
},
),
const Divider(
height: _dividerOptions,
thickness: 1.0,
indent: _dividerOptions,
endIndent: _dividerOptions,
),
const Expanded(
child: ItemsList(),
),
],
),
),
),
),
);
}
SingleChildScrollView buildModal(
BuildContext context,
ItemsProvider provider,
) {
return SingleChildScrollView(
padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
child: Container(
decoration: const BoxDecoration(),
child: AddItemScreen(args: AddItemScreenArguments(provider.addItem)),
),
);
}
}

How to remove padding of MaterialBanner?

I want to remove the following blue padding from MaterialBanner widget, but it doesn't seem to be customizable. I want to insert an image in the red region.
I looked into MaterialBanner for using across Scaffold widgets because ScaffoldMessenger doesn't allow me to insert widgets other than MaterialBanner.
Is there any suggestion?
dartpad.
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(home: Scaffold(body: JustBanner())));
}
class JustBanner extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return _JustBannerState();
}
}
class _JustBannerState extends State<JustBanner> {
#override
Widget build(BuildContext context) {
return Column(
children: [
ElevatedButton(
onPressed: () {
final messenger = ScaffoldMessenger.of(context);
messenger.clearMaterialBanners();
messenger.showMaterialBanner(MaterialBanner(
padding: EdgeInsets.zero,
leadingPadding: EdgeInsets.zero,
leading: const SizedBox.shrink(),
backgroundColor: Colors.blue,
content: Container(
color: Colors.red,
width: 200,
height: 50,
),
actions: const [SizedBox.shrink()]));
},
child: const Text('Banner')),
],
);
}
}
Container(
width: MediaQuery.of(context).size.width,
child: MaterialBanner(
content: Text('Hello'),
actions: [
Icon(Icons.add),
],
),
),
Its no possible without copy and re-create the class, buttonBar always appear:
final Widget buttonBar = Container( // <-- problematic widget
alignment: AlignmentDirectional.centerEnd,
constraints: const BoxConstraints(minHeight: 52.0),
padding: const EdgeInsets.symmetric(horizontal: 8),
child: OverflowBar(
overflowAlignment: widget.overflowAlignment,
spacing: 8,
children: widget.actions,
),
);
final double elevation = widget.elevation ?? bannerTheme.elevation ?? 0.0;
final Color backgroundColor = widget.backgroundColor
?? bannerTheme.backgroundColor
?? theme.colorScheme.surface;
final TextStyle? textStyle = widget.contentTextStyle
?? bannerTheme.contentTextStyle
?? theme.textTheme.bodyText2;
Widget materialBanner = Container(
margin: EdgeInsets.only(bottom: elevation > 0 ? 10.0 : 0.0),
child: Material(
elevation: elevation,
color: backgroundColor,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Padding(
padding: padding,
child: Row(
children: <Widget>[
if (widget.leading != null)
Padding(
padding: leadingPadding,
child: widget.leading,
),
Expanded(
child: DefaultTextStyle(
style: textStyle!,
child: widget.content,
),
),
if (isSingleRow)
buttonBar, // <----- here
],
),
),
if (!isSingleRow)
buttonBar, // <----- here
if (elevation == 0)
const Divider(height: 0),
],
),
),
);

View behind Scaffold - Flutter/Dart

I tried a lot to get the behavior of the iOS project https://github.com/ivanvorobei/SPLarkController working in Flutter / Dart. I do not understand how to get another view behind the scaffold (holding also the bottom navigation bar). Any ideas how this can be achieved?
This could be achieved with the help of Stack.
First layer for the buttons on the bottom:
Second layer for the main content:
Then, you can wrap the BottomNavBar inside GestureDetector with onVerticalDragUpdate property.
Complete Code:
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Builder(
builder: (context) => MyChild(MediaQuery.of(context).size.height),
),
),
);
}
}
class MyChild extends StatefulWidget {
final double screenHeight;
const MyChild(this.screenHeight, {Key? key}) : super(key: key);
#override
_MyChildState createState() => _MyChildState();
}
class _MyChildState extends State<MyChild> {
double val = 1.0;
#override
Widget build(BuildContext context) {
return Stack(
children: [
Container(
padding: const EdgeInsets.only(bottom: 20.0),
color: const Color(0xFF303030),
child: Padding(
padding: const EdgeInsets.only(left: 20.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Row(
children: [
ElevatedButton(
onPressed: () {}, child: const Text('Button 1')),
const SizedBox(
width: 20.0,
),
ElevatedButton(
onPressed: () {}, child: const Text('Button 2'))
],
),
const SizedBox(
height: 20,
),
Row(
children: [
ElevatedButton(
onPressed: () {}, child: const Text('Button 3')),
const SizedBox(
width: 20.0,
),
ElevatedButton(
onPressed: () {}, child: const Text('Button 4'))
],
),
],
),
),
),
LayoutBuilder(
builder: (context, constraints) => AnimatedContainer(
duration: const Duration(milliseconds: 500),
curve: Curves.ease,
height: constraints.maxHeight * val,
color: Colors.white,
child: Column(
children: [
Expanded(
child: ListView.builder(
physics: const BouncingScrollPhysics(),
itemCount: 25,
itemBuilder: (context, index) => ListTile(
title: Text('ListTile $index'),
),
),
),
GestureDetector(
onVerticalDragUpdate: (details) {
if (details.delta.dy < 0) { // If the user drags upwards
setState(() {
val = 0.7;
});
} else if (details.delta.dy > 0) { // If the user drags downwards
setState(() {
val = 1.0;
});
}
},
// Create your bottom navigation bar here
// and not bottomNavigationBar property of Scaffold
child: Container(
color: Colors.green.shade100,
height: 80,
),
)
],
),
),
),
],
);
}
}

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