In the previous video, we copied the code
from a blank project to add a Snackbar
to our app. In this video, we're going to
look at Snackbars in more detail, and
see how we can make our app a little bit
easier to use. Snackbars were introduced
with Material Design, and are intended as
an alternative to the Toast messages.
Now both Snackbars and Toast
messages can be used to notify the user
of something, in an unobtrusive way. The
user gets to see the message, but the
messages don't interrupt their flow,
and that's unlike a dialogue that has to
be dismissed before you can continue. In
the case of Toast messages and Snack
bars, they appear on the screen, but
shouldn't get in the way and thus can be
ignored. Snackbars are a lot more
versatile than Toast messages. One
problem, actually, with a Toast message is
that they may be easy to miss. There are
only two options for how long a Toast
can stay on the screen; LENGTH
_SHORT and LENGTH
_LONG. Once the specified period has
expired, then the Toast message will
automatically disappear from the screen.
Now in the case of Snackbars, we've got
another value we can use; LENGTH
_INDEFINITE. So what I'm going
to do is change the code, in our
Floating Action Button's onClick method,
and then we're going to have a look at
what this LENGTH_INDEFINITE
does. So I'm down here now - the code here
on line 62.
I'm going to change that to LENGTH_
INDEFINITE. Now I can bring up the
documentation for our LENGTH_INDEFINITE to
take a look at that. And you've seen this
before with Ctrl_Alt. I can go and
have a check, I can click and select the
source code and we can see the comments
above there, talking about what it is - how it
shows the Snackbar, unsurprisingly,
indefinitely. And basically, the Snackbar
will be displayed, from the time that
it's shown until either it's dismissed,
or another Snackbar is shown, which will
then replace it. So in this case, that's
very good. It's going to allow us to
leave that message on the screen until
the user dismisses it, or there's another
Snackbar message shown. And you've
probably worked this out by now, but
notice that the comments - when we go into
the source code - appear above the code
they refer to. So make sure you do read
the right comment. Otherwise, things can
get confusing if you're looking down
here, for example,
and wandering Does that apply to LENGTH
_INDEFINITE? which is not the case.
Alright, so I'm going to close down
that Snackbar.java code now. By the way,
we could have got a similar result by
just opening the documentation, and
getting the information up that way,
which you've seen in previous videos as
well. Alright, so let's run the app, and
see what happens now we've got this
indefinite setting, LENGTH_
INDEFINITE set. Alright, so I'm gonna
click on DENY here this time. This time
now when I open, or click on
the FAB, notice now that the Snackbar
message doesn't disappear automatically.
But if you do want to dismiss a Snack
bar, just swipe it right and it'll
vanish from the screen, and you can see me
doing that now. So that's pretty cool, but
they can get even better. So instead of
just showing the user a message, I think
it'd be nice if we could provide them
with a way to grant the access at the
same time rather, than just telling them
that they need to grant that access. The
good news here is that Snackbars can
contain a clickable link. So as well as
displaying the message, they can also
behave like a button and allow us to
provide some extra functionality. So to
do that, going back to our code, what we need
to do is add some code here, in the
listener, and you can see we've currently
got that set to null. So I'm just going
to delete that, and enter a left curly
brace, which adds the right one
automatically. Press ENTER, and I'm going
to type in some code now. So this would
be the code that we executed, if the
Snackbar button itself is tapped. So I'm
going to just put a Toast message in
there. So Toast.makeText parenthesis
it.context comma, and I'm just
going to put a message there; Snackbar
action clicked comma. And it's going to be Toast
dot LENGTH_SHORT and right
parenthesis and dot show. Now I'm
not suggesting that you should show a
Toast message from a Snackbar here. I'm
only doing that here so we can see the
action being called. We'll actually do
something more useful with the action, in
a moment.
So let's actually run this, though, just
to see what it does - make sure that it
works.
So I can click on DENY, click on the
Floating Action Button, and that stays
there because we've using the LENGTH
_INDEFINITE. And now if I click
on the action button, you can see we've
got our Toast message showing up on the
screen there. So clearly, the action was
invoked after we clicked it. Now I actually
had a reason for showing you that, and
the reason was that when we create a
Toast message, we have to provide a
Context to the makeText function. You
can see that code there, on line 65. The
onClick method gets passed a reference
to the View that was clicked. But because
we're using Kotlin rather than Java, and
implementing the onClick method with a
lambda, Kotlin allows us to admit the
parameter declaration. So instead of us
explicitly declaring the parameter,
Kotlin does it for us, and uses the
symbol it - you can see I've typed it.
context there. So basically, that's why we
can refer to it.context as an argument
to makeText. Now the other thing that
may not be obvious, is that a View has a
Context, and that's the other thing I
wanted to demonstrate by using a Toast
message here. Sometimes you might
struggle to get a Context easily - in an
Adapter, for example. Now if you find you
need one in a ClickListener, you can
often use the Context of the view
argument, just like we're doing here. And
again, just to confirm - run it again. Click
on Deny,
and this time you can see over here,
there's an Action - Action text is
appearing on the right-hand side there.
Now that text comes from the text
specified in the setAction method, and
when I tap it, you can see we
get our Toast message showing on
the screen there. Now one common error
that that people often make, is to forget
to call the dot show at the end of
Toast.makeText, and that applies when
displaying Snackbar and Toast messages.
Now Android Studio does warn you if you
do that, but if you don't see the Toast
message, make sure you've got dot show at
the end there, in parentheses, as I've got. So
the code for displaying Snackbars and
Toast messages look very similar. You
make a Snackbar or a Toast and then
call the show method. Now there's really
not a great deal more to say about Snack
bars. We can check the documentation by
clicking on Snackbar, which I can do
over here. And you can see it says that Snack
bars provide lightweight feedback about
an operation. They show a brief message
at the bottom of the screen on mobile,
and lower left on larger devices. Snack
bars appear above all other elements on
screen, and only one can be
displayed at a time. And also, they
automatically disappear after a timeout
or after using interaction elsewhere on
the screen, particularly after
interactions that summon a new surface
or activity. And as you saw, they can also
be swiped off the screen. Now it's also
possible to be called back when a Snack
bar is shown or dismissed, if you need to
check that. Alright, so we've got the
ability to respond when a user clicks
the Action link. What we can do, is
present the user with the dialogue to
grant access. And that's pretty easy - we
just call the requestPermission method
again - but what if they've permanently
denied access.
So in that case, calling request
Permissions won't pop up the dialogue
again. What we can do in that case, is
take them into the Settings for our app,
so that they can grant the access that
we need. Now unfortunately, Google doesn't
allow a way to go all the way into their
permissions, but we can get them as far
as our app's settings. So let's see how
that's going to work before we write the
code to do it. I'm going to switch over
and show you a finished version of this
app in my API 27 emulator,
just so that we can see what's it's
actually going to do.
Okay, so I'm running the final version, as
you can see on screen now, and we get the
normal dialogue to grant access - and that's
as we've already seen in our app. So I'm
gonna click on Deny access, and now when
I tap the Floating Action Button, we get
a Snackbar and there's now an option
here to grant access. So if I tap that
Action, you notice that the pop-up came
up again. And I can click on Allow, just
to confirm that that does work, and we
can now see our contacts when we run it.
So that's a definite improvement -
rather than just a message, the user can
grant access when they attempt to use
the functionality. As google
explain in the documentation, that
you'll be reading when we
finish this app, users sometimes refuse
access because they don't understand why
it's being requested. When they come to
use a feature that requires the access,
they're much more likely to understand
why they're being asked for it, and so
therefore, more likely to grant it. But
what happens if they refuse access, and
tick the box not to be bothered again? So
what I'm going to do now is go into
settings for this app - let's go and do that.
I'm gonna go into our Content Provider,
into Permissions, and I click, and turn this off.
So I'm going to revoke access, or revoke
that permission, so that when we want to
run it again now, we should find it'll
ask us for permission again. So it's
asking us for permission again, because
we've revoked access. So this time I
gonna click on the Don't ask again, and
I'm going to click on Deny. Now that I've
done that, when I'm gonna click on our Floating
Action Button. So we get the Snackbar as
before. This time, though, when I click
over here on Grant Access, notice that
it goes straight into the app Settings
for our Content Provider Example app. And
unfortunately, as I mentioned, this is as
far as we can get. But the user only has to
tap on the Permissions here, to get into
and grant access. So that might change in
the future as Google gets feedback from
users, but at the moment, that's the best
we can do. So with that said, now that
we've enabled the permission again,
does it
work? I'll go back now, keep going back -
we're back in our app, and you can see
we're accessing the contacts again. So
you can see that that clearly worked. So
that's how our app, ultimately, is going
to work, but obviously, at this point in
time we haven't implemented that code. So
let's stop the video here and in the
next video, we'll actually go ahead and
implement that functionality. So I'll see
you in the next video.