moonvader
moonvader

Reputation: 21091

Show fullscreen image onTap in Flutter

I have image shown using one of Flutter widgets

Image.network(....);

I want to add functionality that after tapping on image I can present this image in fullscreen mode. How it can be done?

Upvotes: 29

Views: 49918

Answers (5)

HoRiz
HoRiz

Reputation: 787

Use easy_image_viewer package. view

This example for Network image,

This package provides an easy-to-use and highly customizable image viewer. It allows you to display images in a full-screen view with zooming, panning, and rotation capabilities.

@Amfstacks shows how this works for image which is in your assets. This example for Network image,

        GestureDetector(
                onTap: () async {
                  final imageProvider =
                      Image.network("your url").image;
                  showImageViewer(context, imageProvider,
                      onViewerDismissed: () {
                    print("dismissed");
                  });
                },
                child: Container(
                    height: 150,
                    child: Image(
                      image: NetworkImage("your url"),
                    )),
              ),

Upvotes: 1

Amfstacks
Amfstacks

Reputation: 181

You can easily use this package easy_image_viewer

It worked perfectly without having to create a new screen to handle full screen. The package handles full screen, pinching, zooming in and out of image. Check this sample code below.


GestureDetector(
          onTap: () {
            showImageViewer(context, Image.asset("asset/image/myimage.jpg").image,
                swipeDismissible: false);
          },
          child: Container(
            height: 150,
            child: Image.asset(
             "asset/image/myimage.jpg",
              fit: BoxFit.cover,
            ),
          ),
        )

The Image opens in full screen, pinchable and zoomable.

Upvotes: 10

yobo zorle
yobo zorle

Reputation: 418

I simply found a library with just about what you are looking for and with animated Hero effects. full_screen_image by [email protected]

FullScreenWidget(
    child: Hero(
      tag: "customTag",
      child: ClipRRect(
        borderRadius: BorderRadius.circular(16),
        child: Image.asset(
          "assets/image2.jpg",
          fit: BoxFit.cover,
        ),
      ),
    ),
  );

Upvotes: 2

Arash Saatchi
Arash Saatchi

Reputation: 114

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

Upvotes: 4

shadowsheep
shadowsheep

Reputation: 15002

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

Upvotes: 66

Related Questions