1
00:00:03,740 --> 00:00:09,770
G'day everyone, welcome back. At the moment,
our About dialogue can only be dismissed

2
00:00:09,770 --> 00:00:14,750
by tapping away from it on the device
screen. But it's also usual to dismiss

3
00:00:14,750 --> 00:00:20,029
this type of dialogue by allowing the
user to tap the dialogue itself, or by

4
00:00:20,029 --> 00:00:26,020
providing an OK button. We'll look at
both ways to implement that, in this video.

5
00:00:26,020 --> 00:00:30,739
I'm going to do both, one after the
other, because there's a reason why

6
00:00:30,739 --> 00:00:36,230
tapping the dialogue to dismiss it isn't
really appropriate in this case. In fact,

7
00:00:36,230 --> 00:00:41,390
there are two reasons. So we're not going
to dismiss the dialogue by tapping on it

8
00:00:41,390 --> 00:00:46,120
in this app, but we'll have a quick look
at how to implement that behavior.

9
00:00:46,120 --> 00:00:51,640
We just have to set an onClick listener to
the dialogue's view. We've set on click

10
00:00:51,649 --> 00:00:56,210
listeners on buttons and ListView items,
but you can add them to any View in

11
00:00:56,210 --> 00:01:01,760
Android. Anything you can display on the
screen can be made clickable.

12
00:01:01,760 --> 00:01:07,480
In MainActivity, I'll delete that commented out
code that didn't work, because you've got

13
00:01:07,480 --> 00:01:16,700
the source in the last two videos if you need it.

14
00:01:16,700 --> 00:01:20,320
We'll take this line out too,

15
00:01:24,240 --> 00:01:27,439
and then we'll add our listener.

16
00:01:39,750 --> 00:01:44,460
We've seen code like this lots of times
now. The difference is that we're setting

17
00:01:44,460 --> 00:01:49,590
a listener on a View this time, rather
than a button. That's one way of allowing

18
00:01:49,590 --> 00:01:54,570
the user another way to dismiss the
dialogue, but in our particular case, it's

19
00:01:54,570 --> 00:01:59,430
got a couple of problems. I'll run the
app to make sure it works and then we'll

20
00:01:59,430 --> 00:02:02,720
look at what those problems are.

21
00:02:10,220 --> 00:02:14,630
With the about dialogue showing, I can
click somewhere near the copyright

22
00:02:14,630 --> 00:02:23,170
message and the dialogue's dismissed. We
also get the message in logcat;

23
00:02:29,580 --> 00:02:32,780
entering message view dot onClick.

24
00:02:32,780 --> 00:02:35,480
So that's working fine and shows you can

25
00:02:35,490 --> 00:02:41,610
attach onClick listeners to any type of
View. The first problem is, that our icon

26
00:02:41,610 --> 00:02:47,370
and title aren't part of our View. They
were added by the dialog builder. If we

27
00:02:47,370 --> 00:02:57,340
launch the About dialogue again, and
tap near the icon or title,

28
00:02:57,340 --> 00:02:59,060
nothing happens.

29
00:02:59,060 --> 00:03:03,980
The version number's part of our layout,
so tapping that will dismiss the dialogue,

30
00:03:03,980 --> 00:03:09,930
but from our user's point of view, it's a
bit hit or miss. If you include the title

31
00:03:09,930 --> 00:03:15,780
and icon in the layout, everything would
work fine. In that case, this would be a

32
00:03:15,780 --> 00:03:21,660
suitable approach, except for the second
problem. We've made the links in the text

33
00:03:21,660 --> 00:03:27,060
clickable. The way that works, is that
Android intercepts taps on the entire

34
00:03:27,060 --> 00:03:34,170
line of text, not just on the link itself.
If I tap level with the URL, but away to

35
00:03:34,170 --> 00:03:41,260
the right, it's still part of the TextView
and we've enabled autoLink on the TextView.

36
00:03:41,260 --> 00:03:45,510
So, I'd suggest that dismissing the
dialogue by tapping it, when you're

37
00:03:45,510 --> 00:03:51,040
also showing autoLink text, isn't an
ideal way to handle things.

38
00:03:51,040 --> 00:03:56,720
If you're not showing autoLink text and your layout
covers the entire dialogue, then the code

39
00:03:56,720 --> 00:03:58,860
you've got will work fine.

40
00:03:58,860 --> 00:04:03,320
OK, let's see how to add a button
to the dialogue instead.

41
00:04:03,320 --> 00:04:08,560
I want to leave the current code in, so
it's available in the code you can download.

42
00:04:08,560 --> 00:04:15,080
I'll copy the entire function and comment
one copy out so it's still available.

43
00:04:15,080 --> 00:04:19,820
Android Studio has a neat
feature to make that a lot easier.

44
00:04:19,820 --> 00:04:25,400
Select the entire function, including the
annotation at the top, and use ctrl D,

45
00:04:25,410 --> 00:04:28,820
command D on a Mac.

46
00:04:32,400 --> 00:04:37,420
That works better if you also include
the blank line after the function.

47
00:04:37,420 --> 00:04:43,800
The copy remains highlighted, so we can use
control / (command / on the Mac)

48
00:04:43,800 --> 00:04:49,300
to comment the copy out. We can get the
Builder to add a new button to the dialogue.

49
00:04:49,300 --> 00:04:53,260
Just like we had to do with the
title and the icon. Though we have to add

50
00:04:53,260 --> 00:04:58,840
the button call before the call to builder.create,
otherwise the button won't

51
00:04:58,840 --> 00:05:01,650
appear in the dialogue.

52
00:05:26,440 --> 00:05:32,420
We've seen the setPositive button
function before, in our AppDialog class,

53
00:05:32,420 --> 00:05:37,780
and this is doing the same thing. Run the
app, and our users can now dismiss the dialogue,

54
00:05:37,780 --> 00:05:43,360
by tapping away from it or
tapping the OK button.

55
00:05:58,240 --> 00:06:03,080
So, that's dialogues in a nutshell.
They've turned into a large nut, though.

56
00:06:03,080 --> 00:06:07,280
I'm going to finish this video with a
comment about that last bit of code.

57
00:06:07,280 --> 00:06:11,920
Looking at the code in the setPositiveButton
function that we just

58
00:06:11,920 --> 00:06:18,430
created, we perform a null check and also
check that the dialogue is showing,

59
00:06:18,430 --> 00:06:23,919
before calling it's dismiss function. Because
Kotlin can't be sure that aboutDialogue

60
00:06:23,920 --> 00:06:29,620
hasn't been changed on another thread, we
need to use a safe call operator.

61
00:06:29,620 --> 00:06:33,900
You may be wondering why it's necessary to check
that the dialogue's showing before

62
00:06:33,910 --> 00:06:38,110
dismissing it.
If the dialogue's not showing, it's going to

63
00:06:38,110 --> 00:06:43,240
be very hard for the user to tap the
button. That may be true, but in an

64
00:06:43,240 --> 00:06:48,430
event-driven system like Android, you can
never be completely sure about the order

65
00:06:48,430 --> 00:06:53,889
that events happen. If the device is
rotated, and the user accidentally taps

66
00:06:53,889 --> 00:06:58,900
the button at just the wrong time, it may
be possible for our code to be called,

67
00:06:58,900 --> 00:07:04,840
very slightly after the system's removed
the dialogue. We can't be sure that an

68
00:07:04,840 --> 00:07:10,060
event such as garbage collection, or an
incoming phone call, won't slow things

69
00:07:10,060 --> 00:07:15,300
down just enough, to give a delay before
our function's called.

70
00:07:15,300 --> 00:07:21,480
Trying to duplicate a series of events like that, so you can
test it and be completely sure that it

71
00:07:21,490 --> 00:07:26,979
will never happen, is not going to be
easy. If an event happens, though, you can

72
00:07:26,979 --> 00:07:31,900
be sure that you've handled it correctly.
If something doesn't happen, you can't be

73
00:07:31,900 --> 00:07:35,500
sure that it never will. Just because you
can't get it to happen,

74
00:07:35,500 --> 00:07:41,169
doesn't guarantee that it won't. So, I
prefer to program very defensively in

75
00:07:41,169 --> 00:07:46,330
these situations. The safe call operator
makes sure we don't try to call a

76
00:07:46,330 --> 00:07:53,920
function on a null object. At the moment,
the check for isShowing isn't strictly necessary.

77
00:07:53,920 --> 00:07:57,460
If you look at the code for
the dismiss function, and follow it back

78
00:07:57,460 --> 00:08:02,320
to the dialogue class dismiss dialogue
function, you'll see that there's a check

79
00:08:02,320 --> 00:08:06,849
that the dialogue is showing in there.
We're not writing a time critical bit of

80
00:08:06,849 --> 00:08:11,680
code here, and I prefer to be safe, rather
than find that Google has

81
00:08:11,680 --> 00:08:17,400
changed something and my code crashes.
Alright, I'll accept Android Studio's

82
00:08:17,400 --> 00:08:23,110
suggestion that we can replace the
dialogue and the which arguments with an

83
00:08:23,110 --> 00:08:28,500
underscore. In fact, I'll get the light
bulb to do that.

84
00:08:35,980 --> 00:08:41,539
You have to get the light bulb to appear
twice, once for each argument.

85
00:08:41,539 --> 00:08:46,300
The compiler can optimize the code, if it
knows that the arguments aren't used,

86
00:08:46,300 --> 00:08:52,390
and using underscore for the name is how you
tell it that. In the next video, we'll see

87
00:08:52,390 --> 00:08:56,720
how to make the links clickable on older
Android versions.

88
00:08:56,720 --> 00:08:59,840
See you in the next one.

