G'day, welcome back everyone.
So the challenge was to fix the app's About
dialogue, to make the web links clickable in all versions of Android from API 17 up.
I'm going to keep the layout changes to a minimum, and I won't be creating
complete versions of the layout for API 21. If you've done that, and your solution
works, then that's fine. If you have too many variants of your resource files, it
makes maintenance harder. In my solution, I'm going to minimize the duplication as
much as possible. I'll start with the string resources and we need to separate
the text from the URL, for the pre API 21 devices. Android Studio lets you
duplicate a line, using ctrl D, command D on a Mac, to create a duplicate
of the about_weblink string resource to start with.
The new string resource will be for
devices running Android versions before API 21, but the name about_weblink_pre_21, for example, is a bit clumsy.
So I'll rename the original to about_weblink_v21.
It doesn't really matter, but naming things like that fits in better with the way
Android deals with resources. The convention is to have a base version,
then create a new resource for later Android versions, so I'm following that
convention. We'll split our pre version 21 about_weblink into two parts.
Cut the URL
and then add another string resource.
You may not have noticed, but in the layout designer we can change a TextView's text
to be bold, but there's no option to underline it. I'm going to add
a tag around the text.
We saw that inan earlier video, and we used it in the
about_credit string resource to embolden just parts of the text.
One thing I haven't done, is added the https:// to the URL.
As I hinted in the challenge description, that's going to crash the program.
We could read through all the documentation to find out the exact exception that'll be
thrown, but it's easier to just let the app crash, and get the exception from logcat.
Okay, time to look at the about layout.
We've got five TextViews in there, and we're interested in the
about_weblink one. For API 21 and higher, that's fine as it is. For earlier
Android versions, we're going to use two TextViews instead of one.
The first TextView will contain the text: instructions available at, and the
second one will hold the URL. You could duplicate the entire layout and create a
v21 variant, and if you've done that, then that's fine. As I said, I prefer to keep
duplication to a minimum, so that maintenance is easier. We know that one
layout file can be included in another. That's what activity_main does,
to keep the toolbar and floating action button separate from your widgets.
It adds your widgets to the layout by including content_main.
What I'm going to do here, is create two new layouts; one for API 21 and above, and one
for the earlier versions. The API 21 layout will contain just a single
TextView, and the earlier one will have two TextViews. Create a new layout
resource file and call it about_web_url
Make sure that the root element is a LinearLayout, and click OK.
We could follow the normal steps of dragging TextViews onto the layout, then configuring
the properties. But we've already got a TextView with all the properties set,
in our About layout. I'll copy the XML for the about_weblink widget,
and paste it into the XML for our new layout. In fact, I'll paste it twice, then change
the ID of the second copy to about_url.
As long as you paste the widgets between the opening and closing LinearLayout
tags, this is much quicker than configuring all the properties again.
Back in the designer, and make sure that the LinearLayout's set to vertical, with the
layout_width as match_parent, and the layout_height set to wrap_content.
We need to remove all the margins and padding from both the widgets. It's obvious why
we don't want a top margin on the about_url widget. We want it to
appear directly below about_weblink, so that the text looks like
it's part of the same widget. What's not obvious, is why we're removing the top
margin from about_weblink, and I'll come back to that later.
I didn't discover that this was necessary, until after running the app for the
first time, but I'm changing it now to save us having to come back in here.
Both widgets also have the autoLink property set, so untick web.
On older devices, we're going to use an onClickListener
to launch the browser. That means we don't want autoLink. It doesn't work anyway,
that's why we're doing this. There's a couple of other changes to
make to about_url, which we can do in the reduced attributes pane.
The first thing is the text.
Use the symbol
to choose the string, about_url.
Next, is the textColor property. That should be our accent color, so that it's obviously clickable.
Set textColor to colorAccent.
You can use the symbol to choose the color,
rather than remembering that resource ID.
Notice that the text style lets us use bold, italic and small caps, but that there's
no underline. That's why I added the tag in the
string resource. There's a convention that links are underlined,
and their email and web links were underlined on the API 25 emulator.
We want to keep things consistent.
Okay, we want an API 21 version of this layout,
and Android Studio makes it very easy to create different versions of layouts.
The button to do this is currently the second one in the designers toolbar, the one that
looks like a device being rotated. It gives options to create a landscape
variant, a version for devices with extra-large screens, and the one we want,
Create Other. In the dialogue that appears, scroll down to Version,
and use the top button to add an Android version-specific variant. The platform API level
we want is 21, and click OK.
That's created a v21/about_web_url layout,
and we can check the name in the editor tab.
All we have to do to make things work, is delete the about_url TextView,
and change the resource string in about_weblink's text property
to about_weblink_v21. However, as
there's only going to be a single textView in this layout, we don't need to
wrap it all in a LinearLayout. We'll be including this file in about.xml,
which already has a LinearLayout as its root. If we use another one here,
then we're nesting layouts unnecessarily, and as we know, nesting layout should be
avoided for performance reasons. We had no choice with the first version of
about_web_url, because you can't have two widgets in a
layout, without putting them inside a single root.
But here, all we need is one textView.
It's worth pausing here and keeping things in perspective.
We're creating a layout to be used in an About dialogue. We're not attempting to show 60
of these every second, and if the user has to wait a few extra milliseconds for
the dialogue to appear, or even a few hundredths of a second, they won't even notice.
So, if you left a LinearLayout in and just deleted the second TextView,
about_url in my example, then congratulations on completing the challenge.
I'm going to make the layout as efficient as possible, so that if you
use this approach where performance does matter, you'll have seen how to do it to
avoid nesting where possible. It's also a chance to show you something you can do
in Android Studio, that may not be obvious. So just to be clear, generating
alternative variants of your layout, using that button, is fine most of the time.
Occasionally, you'll want to create the variant from scratch, and that's what
I'm going to do here. Close the layout file,
then delete the v21 layout that we've just generated.
Answer no if you're prompted to delete the alternative resource files for other
configurations, otherwise we'll remove the other web_url layout file as well.
Next, create a new layout resource file
and call it about_web_url.
That's the same name as we used
for the pre API 21 version of the layout. Scroll down and at the end of the
list of available qualifiers,
use the top button to add version. As we did before,
type 21 for the platform API level. Don't press Enter or you'll just create
another LinearLayout. The bit that isn't obvious. is that you can use any widget
as the root element. It doesn't have to be a layout. Change the root element
from LinearLayout to TextView.
Click OK
and an API 21 version of the layout is
created for us. This layout contains just a TextView, which is what we want.
We just need to configure the TextView to match the one that it will replace,
in the About dialogue.
The ID will be about_weblink,
and the layout_width should be match_parent. For the text property, use the symbol to choose our
new about_weblink_21 string resource.
The entire text is showing in the accent color, so we need to change text color to
colorPrimary.
We're just about done. The final change is to go into the
all attributes section and set the autoLink property to web.
Now we've got two versions of about_web_url;
one containing two textViews inside a linear layout,
and the other, the v21 version, just containing a
single textView.
Right, let's end this video here, and I'll see you in the next one.