Allowing the User to Click the Image and Go to the Website: The url_launcher Package

What if users want to see a comic on the XKCD website? Right now, the only way they could do that is by taking advantage of the comic number and title and searching the XKCD website themselves.

It wouldn’t be too hard to provide users with the ability to do that with a tap in the app, so let’s do it!

To launch URLs from Flutter apps, we’ll use a handy package on Pub called url_launcher.

Using the url_launcher Package

Let’s add the url_launcher package to the dependencies in pubspec.yaml:

 url_launcher: ​^5.0.2

and import it in our code in main.dart:

 import​ ​'package:url_launcher/url_launcher.dart'​;

The url_launcher package provides two functions: canLaunch(url) and launch(url). The first returns a bool wrapped in a Future, which will be true if there is an app that can handle the URL or false if there isn’t. The second actually launches the URL and returns the same value as the other function: if the launch was successfull, it returns true; if it wasn’t, it returns false.

So we know how to launch the URL, but we don’t actually get the comic URL when we fetch the comic’s JSON. That’s not actually a problem, since the URL for each comic is just https://xkcd.com/comic_number/: the URL to reach comic #2019 is https://xkcd.com/2019/.

This means that a method to launch comics, to be defined inside the ComicPage class, can be written in the following way:

 void​ ​_launchComic​(​int​ comicNumber) {
  launch(​"https://xkcd.com/​​$comicNumber​​/"​);
 }

Adding an onTap Event

We know how to launch an URL, but the Image’s constructors don’t provide an onTap argument, so we need to wrap it in a InkWell, which is a lot like wrapping an img HTML image tag in an a link tag: the InkWell needs two arguments: a child which, in this case, will be the Image, and the onTap argument we wanted, along with a bunch of options to customize the inksplash effect you can check out on the official Flutter documentation.[41]

All that’s left to do is to find the place where we show the comic image in ComicPage and wrap it in the InkWell:

 InkWell(
  onTap: () {_launchComic(widget.comic[​"num"​]);},
  child: Image.file(File(widget.comic[​"img"​])),
 ),

Showing Inksplash on the InkWell

images/aside-icons/info.png

One of InkWell’s features is that it can show an inksplash effect when the user taps on the area where it is located, but that will not work in our app because of how visual effects like the inksplash are applied on Flutter widgets.

A Flutter layout is made of widgets, but the inksplash is not applied to widgets: it is applied to Material, which is the class that is also responsible for clipping and elevation effects. An Image is drawn over a Material, so the inksplash will be applied to the Material below the image, which will make it invisible.

To show the inksplash effect you’d need to overlap the Image with a transparent Material widget. The Ink widget[42] makes that simpler: it provides a Ink.image method that allows you to set the InkWell as a child, making the image and the Material on top of it an ancestor of the InkWell.

A disadvantage of the Ink is that it requires setting a maximum width and height. For an example of code that correctly shows the inksplash over the image and that works when replacing the code we used above, take a look at this:

 Material(
  child: Ink.image(
  image: FileImage(File(widget.comic[​"img"​])),
  height: 300,
  width: 200,
  child: InkWell(
  onTap: () {_launchComic(widget.comic[​"num"​]);},
  ),
  ),
 ),

If you are not interested in the inskplash effect at all, you can use a GestureDetector instead of the InkWell. It works in the same way as the InkWell, with the same arguments, but without applying an inksplash effect on any kind of widget.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset