Show fullscreen image onTap in Flutter
You say you want something like in this flutter cookbook?
import 'package:flutter/material.dart';
void main() => runApp(HeroApp());
class HeroApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Image/Detail Demo',
home: MainScreen(),
);
}
}
class MainScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Main Screen'),
),
body: GestureDetector(
child: Hero(
tag: 'imageHero',
child: Image.network(
'https://raw.githubusercontent.com/flutter/website/master/src/_includes/code/layout/lakes/images/lake.jpg',
),
),
onTap: () {
Navigator.push(context, MaterialPageRoute(builder: (_) {
return DetailScreen();
}));
},
),
);
}
}
class DetailScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: GestureDetector(
child: Center(
child: Hero(
tag: 'imageHero',
child: Image.network(
'https://raw.githubusercontent.com/flutter/website/master/src/_includes/code/layout/lakes/images/lake.jpg',
),
),
),
onTap: () {
Navigator.pop(context);
},
),
);
}
}
You can use the cache_network_image package to show the cached image without download it again.
import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';
void main() => runApp(HeroApp());
class HeroApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Image/Detail Demo',
home: MainScreen(),
);
}
}
class MainScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Main Screen'),
),
body: GestureDetector(
child: Hero(
tag: 'imageHero',
child: CachedNetworkImage(
imageUrl: 'https://raw.githubusercontent.com/flutter/website/master/src/_includes/code/layout/lakes/images/lake.jpg',
placeholder: new CircularProgressIndicator(),
errorWidget: new Icon(Icons.error),
)
),
onTap: () {
Navigator.push(context, MaterialPageRoute(builder: (_) {
return DetailScreen();
}));
},
),
);
}
}
class DetailScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: GestureDetector(
child: Center(
child: Hero(
tag: 'imageHero',
child: CachedNetworkImage(
imageUrl: 'https://raw.githubusercontent.com/flutter/website/master/src/_includes/code/layout/lakes/images/lake.jpg',
placeholder: new CircularProgressIndicator(),
errorWidget: new Icon(Icons.error),
),
),
),
onTap: () {
Navigator.pop(context);
},
),
);
}
}
My final release (with real fullscreen):
import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/services.dart';
void main() => runApp(HeroApp());
class HeroApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Image/Detail Demo',
home: MainScreen(),
);
}
}
class MainScreen extends StatefulWidget {
@override
_MainScreenState createState() => _MainScreenState();
}
class _MainScreenState extends State<MainScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Main Screen'),
),
body: GestureDetector(
child: Hero(
tag: 'imageHero',
child: CachedNetworkImage(
imageUrl:
'https://raw.githubusercontent.com/flutter/website/master/src/_includes/code/layout/lakes/images/lake.jpg',
placeholder: new CircularProgressIndicator(),
errorWidget: new Icon(Icons.error),
)),
onTap: () {
Navigator.push(context, MaterialPageRoute(builder: (_) {
return DetailScreen();
}));
},
),
);
}
}
class DetailScreen extends StatefulWidget {
@override
_DetailScreenState createState() => _DetailScreenState();
}
class _DetailScreenState extends State<DetailScreen> {
@override
initState() {
SystemChrome.setEnabledSystemUIOverlays([]);
super.initState();
}
@override
void dispose() {
//SystemChrome.restoreSystemUIOverlays();
SystemChrome.setEnabledSystemUIOverlays(SystemUiOverlay.values);
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: GestureDetector(
child: Center(
child: Hero(
tag: 'imageHero',
child: CachedNetworkImage(
imageUrl:
'https://raw.githubusercontent.com/flutter/website/master/src/_includes/code/layout/lakes/images/lake.jpg',
placeholder: new CircularProgressIndicator(),
errorWidget: new Icon(Icons.error),
),
),
),
onTap: () {
Navigator.pop(context);
},
),
);
}
}
Passing data from main to detail page
Just to complete my answer, I add some code showing how you could pass the image url from main to detail page.
import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/services.dart';
void main() => runApp(HeroApp());
class HeroApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Image/Detail Demo',
home: MainScreen(),
);
}
}
class MainScreen extends StatefulWidget {
@override
_MainScreenState createState() => _MainScreenState();
}
class _MainScreenState extends State<MainScreen> {
var _url = [
'https://raw.githubusercontent.com/flutter/website/master/src/_includes/code/layout/lakes/images/lake.jpg',
'https://github.com/flutter/plugins/raw/master/packages/video_player/doc/demo_ipod.gif?raw=true'
];
var _tag = ['imageHero', 'imageHero2'];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Main Screen'),
),
body: ListView(
children: <Widget>[
GestureDetector(
child: Hero(
tag: _tag[0],
child: CachedNetworkImage(
imageUrl: _url[0],
placeholder: Center(child: Container(width: 32, height: 32,child: new CircularProgressIndicator())),
errorWidget: new Icon(Icons.error),
)),
onTap: () {
Navigator.push(context, MaterialPageRoute(builder: (_) {
return DetailScreen(tag: _tag[0], url: _url[0]);
}));
},
),
GestureDetector(
child: Hero(
tag: _tag[1],
child: CachedNetworkImage(
imageUrl: _url[1],
placeholder: Center(child: Container(width: 32, height: 32,child: new CircularProgressIndicator())),
errorWidget: new Icon(Icons.error),
)),
onTap: () {
Navigator.push(context, MaterialPageRoute(builder: (_) {
return DetailScreen(tag: _tag[1], url: _url[1]);
}));
},
),
],
),
);
}
}
class DetailScreen extends StatefulWidget {
final String tag;
final String url;
DetailScreen({Key key, @required this.tag, @required this.url})
: assert(tag != null),
assert(url != null),
super(key: key);
@override
_DetailScreenState createState() => _DetailScreenState();
}
class _DetailScreenState extends State<DetailScreen> {
@override
initState() {
SystemChrome.setEnabledSystemUIOverlays([]);
super.initState();
}
@override
void dispose() {
//SystemChrome.restoreSystemUIOverlays();
SystemChrome.setEnabledSystemUIOverlays(SystemUiOverlay.values);
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: GestureDetector(
child: Center(
child: Hero(
tag: widget.tag,
child: CachedNetworkImage(
imageUrl: widget.url,
placeholder: Center(child: Container(width: 32, height: 32,child: new CircularProgressIndicator())),
errorWidget: new Icon(Icons.error),
),
),
),
onTap: () {
Navigator.pop(context);
},
),
);
}
}
UPDATE
In order to pop back tapping outside the image, bring outside the GestureDetector
in the Detail
widget.
class _DetailScreenState extends State<DetailScreen> {
@override
initState() {
SystemChrome.setEnabledSystemUIOverlays([]);
super.initState();
}
@override
void dispose() {
//SystemChrome.restoreSystemUIOverlays();
SystemChrome.setEnabledSystemUIOverlays(SystemUiOverlay.values);
super.dispose();
}
@override
Widget build(BuildContext context) {
return GestureDetector(
child: Scaffold (
body: Center(
child: Hero(
tag: widget.tag,
child: CachedNetworkImage(
imageUrl: widget.url,
placeholder: Center(child: Container(width: 32, height: 32,child: new CircularProgressIndicator())),
errorWidget: new Icon(Icons.error),
),
),
),
),
onTap: () {
Navigator.pop(context);
},
);
}
}
You can use this code to have full screen of image!
class DetailScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: GestureDetector(
child: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Hero(
tag: 'imageHero',
child: Image.network(
'https://picsum.photos/250?image=9',
),
),
),
onTap: () {
Navigator.pop(context);
},
),
);
}
}