1 00:00:05,300 --> 00:00:10,060 Alright so there's something else we can do with string resources, and we can have a look at that by making 2 00:00:10,060 --> 00:00:13,730 a couple of changes in PhotoDetailsActivity. 3 00:00:13,740 --> 00:00:15,400 dot Kotlin, so let's actually have a look at that. 4 00:00:15,400 --> 00:00:24,010 So I'm going to open our file, PhotoDetailsActivity. Now something that you'll often want to do, is display 5 00:00:24,010 --> 00:00:27,140 values with a heading to show what the value is. 6 00:00:27,140 --> 00:00:31,510 Now I'm going to demonstrate that by showing the obvious way you might do it, and then we'll put things 7 00:00:31,510 --> 00:00:32,100 right. 8 00:00:32,180 --> 00:00:33,520 Then we come down here to photo 9 00:00:33,580 --> 00:00:34,860 underscore title dot text, 10 00:00:34,870 --> 00:00:42,030 and before the photo dot title I'm going to add double quotes title colon space 11 00:00:42,030 --> 00:00:45,160 plus, and obviously I've got a closing double quote there. 12 00:00:45,320 --> 00:00:48,590 And on the next line for tags, we're going to do the same thing, or similar thing, 13 00:00:48,680 --> 00:00:56,530 double quotes and tags colon in the middle of that, and a space, then plus photo dot tags. 14 00:00:56,530 --> 00:01:01,330 Now that was obviously a very simple change, but Android Studio is highlighting those two lines and giving 15 00:01:01,330 --> 00:01:08,320 a warning. If we hover over that, we can see that it says "Do not concatenate text displayed with setText. 16 00:01:08,320 --> 00:01:14,670 Use resource string with placeholders", and then moving on, "String literal in setText cannot be translated. 17 00:01:14,750 --> 00:01:16,990 Use Android resources instead". 18 00:01:17,160 --> 00:01:22,570 And we get the same warning for both the title and the tags, similar warning, or same warning, and the suggestion 19 00:01:22,570 --> 00:01:27,110 again is to use a string resource instead of hardcoding the text. 20 00:01:27,130 --> 00:01:31,990 Now that's fine. We know how to do that now, but the warning's also talking about a resource string 21 00:01:32,050 --> 00:01:33,230 with placeholders. 22 00:01:33,430 --> 00:01:39,160 So let's actually see how they work, and this'll also let us see how to access string resources in code, 23 00:01:39,580 --> 00:01:41,300 rather than just in the layouts. 24 00:01:41,560 --> 00:01:47,490 So we're going to open up our strings.xml file again. We're going to create a new string resource called photo 25 00:01:47,490 --> 00:01:52,490 underscore title underscore text, and I'll add that just before the closing resources tag. 26 00:01:52,780 --> 00:02:00,050 So less than sign to start off, string space name equals double quotes, and this one's going to be called photo 27 00:02:00,050 --> 00:02:06,130 underscore title underscore text, and we've got a greater than sign to close off the tag, and in the middle there we're going 28 00:02:06,130 --> 00:02:11,590 to type in title colon space percent sign lower case s. 29 00:02:11,890 --> 00:02:13,060 So here the percent 30 00:02:13,060 --> 00:02:18,140 s is a place holder that can be replaced with the required value when the app's running. 31 00:02:18,370 --> 00:02:21,390 The s in that specifies that it can be replaced with a string. 32 00:02:21,700 --> 00:02:26,120 If we'd used a present d instead, then it could be replaced with a decimal number. 33 00:02:26,410 --> 00:02:30,210 So let's add another one for the tags attribute as well. 34 00:02:30,260 --> 00:02:38,940 I'm going to copy that and paste that, and change the text to photo tags text for the name, and the value's going to be tags 35 00:02:38,950 --> 00:02:41,110 colon 36 00:02:42,040 --> 00:02:44,120 space percent s. Alright, 37 00:02:44,150 --> 00:02:46,540 so that's strings.xml updated. 38 00:02:46,810 --> 00:02:52,240 Let's see how to use those resources in code. So back to PhotoDetailsActivity. 39 00:02:52,260 --> 00:02:59,380 I'm going to comment that these two lines. We're going to replace those instead with, for the first one, for the title, it's going 40 00:02:59,930 --> 00:03:01,250 to be photo 41 00:03:01,830 --> 00:03:12,940 underscore title dot text is equal to resources dot getString, parentheses as you can see there, R.string dot 42 00:03:13,350 --> 00:03:16,470 photo underscore title underscore text comma 43 00:03:16,670 --> 00:03:18,870 photo dot title. 44 00:03:19,490 --> 00:03:25,840 That's the first one, and for tags we'll do a similar thing, photo underscore tags dot text is equal to 45 00:03:25,840 --> 00:03:27,200 resources 46 00:03:27,270 --> 00:03:32,450 dot getString parentheses R.string dot, 47 00:03:32,540 --> 00:03:37,140 this times it's going to be photo underscore tags dot text, tags underscore text I should say, 48 00:03:37,290 --> 00:03:42,160 comma photo dot tags. 49 00:03:42,910 --> 00:03:46,820 So we start off by getting the resources for the app, that's this resources part here. 50 00:03:47,210 --> 00:03:53,800 Now resources is a property of activities, and it lets us access the app's resources. So next we're using the get 51 00:03:53,800 --> 00:04:00,680 String function to get the string with the ID photo underscore title underscore text. 52 00:04:00,700 --> 00:04:03,970 Now that's the string we just created in the strings.xml resource file. 53 00:04:03,990 --> 00:04:09,730 Now the getString function will replace any placeholders with the appropriate value, and we get that 54 00:04:09,730 --> 00:04:11,340 by using the title field 55 00:04:11,380 --> 00:04:16,260 of our photo object, over here to the right. And the tags heading works exactly the same, 56 00:04:16,260 --> 00:04:22,240 using getString to get the string resource, this time called photo underscore tags underscore text, 57 00:04:22,720 --> 00:04:26,270 and it replaces the placeholder with the photo's tags field. 58 00:04:26,950 --> 00:04:30,310 So the getString function takes care of replacing the place 59 00:04:30,310 --> 00:04:35,530 holders with the values that we specify, and in this particular case there's only one placeholder to replace 60 00:04:35,530 --> 00:04:36,110 here. 61 00:04:36,220 --> 00:04:41,330 But you can replace several values at once, with a single call to the getString function 62 00:04:41,350 --> 00:04:46,330 if you need to, and it's the same mechanism as the string.format function that we used in the top 63 00:04:46,330 --> 00:04:51,820 10 downloader app, to display whether we were showing the top 10 or top 25 results. 64 00:04:51,820 --> 00:04:56,740 Now that's slightly harder than how we did it in the layout, because Android Studio takes care of 65 00:04:56,740 --> 00:05:02,440 retrieving the string resources for us when it inflates the xml layout. It does give more flexibility 66 00:05:02,440 --> 00:05:08,070 here though, because it allows the use of placeholders to include different text while the app's running. 67 00:05:08,080 --> 00:05:09,750 Of course you can't do that with a layout. 68 00:05:10,050 --> 00:05:14,980 Now there is one other thing you should consider, and that's the fact that words can appear in different 69 00:05:15,070 --> 00:05:17,390 orders in different languages. 70 00:05:17,470 --> 00:05:25,620 Now as an example, my red car would translate to ma voiture rouge in French, and apologies to anyone 71 00:05:25,620 --> 00:05:27,010 speaking French out there. 72 00:05:27,090 --> 00:05:33,840 That was my interpretation anyway. In the English version, the adjective red comes before the noun car, 73 00:05:33,990 --> 00:05:36,800 but in French the word for car comes first. 74 00:05:36,840 --> 00:05:41,020 So a literal translation back to English would be my car red. 75 00:05:41,050 --> 00:05:46,450 Now that means that you may need to apply the values in different orders, in different languages. 76 00:05:46,730 --> 00:05:51,120 Now to cater for that, it's a good idea to actually number the placeholders. 77 00:05:51,410 --> 00:05:56,750 Now to see what I mean, we're going to change the strings.xml file to include placeholder numbers. 78 00:05:57,090 --> 00:06:02,480 So I'll go back to strings.xml, and let's create another entry for the resource. 79 00:06:02,510 --> 00:06:09,100 So less than sign then string to get started, name equals two double quotes, and it's going to be photo underscore 80 00:06:09,150 --> 00:06:13,080 author underscore text, then close that tag. 81 00:06:13,320 --> 00:06:17,280 And this time the new resource is going to contain three placeholders, 82 00:06:17,430 --> 00:06:24,650 but these are going to be numbered, and to number them, percent 1 dollar s space, 83 00:06:24,850 --> 00:06:29,950 percent 2 dollar s space, and percent 84 00:06:30,210 --> 00:06:32,510 3 dollar s, 85 00:06:32,840 --> 00:06:34,080 as you can see. 86 00:06:34,140 --> 00:06:39,840 So we've added three place holders there that are numbered, and we'll just go back to PhotoDetailsActivity, and 87 00:06:39,990 --> 00:06:46,040 what we'll do is we'll replace the text for the photo author in PhotoDetailsActivity. So I'll comment that line out, 88 00:06:46,710 --> 00:06:48,410 and it'll be photo 89 00:06:48,970 --> 00:07:00,560 underscore author dot text is equal to resources.getString parentheses. It's going to be R.string dot 90 00:07:00,610 --> 00:07:04,240 photo underscore author underscore text comma 91 00:07:04,650 --> 00:07:08,280 and let's just try in double quotes, my. Now 92 00:07:08,490 --> 00:07:09,200 one nice touch 93 00:07:09,200 --> 00:07:15,570 here is that Android Studio's picked up on the fact that the resource string has got three placeholders, but we're 94 00:07:15,570 --> 00:07:17,960 only supplying one, so we're getting a value, 95 00:07:18,000 --> 00:07:19,040 we're getting an error. 96 00:07:19,230 --> 00:07:23,760 And if I hover over that we can see that, "requires 3 but format call supplies 1. 97 00:07:24,120 --> 00:07:29,000 So what this does is it prevents us from accidentally providing the wrong number of values when calling 98 00:07:29,010 --> 00:07:30,690 the getString function. 99 00:07:30,690 --> 00:07:31,840 So I'd better fix that. 100 00:07:31,850 --> 00:07:33,460 We'll go back and add the other two. 101 00:07:33,840 --> 00:07:40,800 So I'm going to add a comma space, in double quotes red, double quote, closing the double quote that is, comma and the last 102 00:07:40,800 --> 00:07:41,270 one, double quotes 103 00:07:41,760 --> 00:07:45,460 car, and you can see when I do that the error then disappears. 104 00:07:47,630 --> 00:07:52,020 Now I'm supplying the three strings, my, red and car here, 105 00:07:52,310 --> 00:07:56,040 but obviously in a real app, these would be values that change when the app runs. 106 00:07:56,060 --> 00:08:01,070 This is just to demonstrate how to use placeholder numbering, to change the order of the words for different 107 00:08:01,070 --> 00:08:01,600 languages 108 00:08:01,610 --> 00:08:02,690 if you need to. 109 00:08:02,840 --> 00:08:04,350 So when I run this app, let's do that now. 110 00:08:17,960 --> 00:08:18,710 OK we'll just go into a photo, and 111 00:08:22,510 --> 00:08:24,550 you can see at the top here, my red car. 112 00:08:24,800 --> 00:08:27,700 So basically getting that text for the author. 113 00:08:27,860 --> 00:08:33,400 Now if we needed the words in a different order for another language, we can actually position the numbered 114 00:08:33,409 --> 00:08:38,450 placeholders in any order we want, in that language's strings.xml file. 115 00:08:38,480 --> 00:08:40,650 So as an example, if I go into this one, 116 00:08:40,650 --> 00:08:48,830 and change this and we'll move the third place holder, paste it in and change the order like so. So that's now placeholder one, 117 00:08:48,830 --> 00:08:50,020 three then two. 118 00:08:50,180 --> 00:08:51,230 And now when I run the app again, and load it up, 119 00:08:57,560 --> 00:09:05,190 and you can see over here now we've got the text my car red, and that would then work fine in French. 120 00:09:05,730 --> 00:09:08,140 And we haven't changed the code to do that. 121 00:09:08,190 --> 00:09:14,400 Android would automatically use the French resource file if we'd created one on a French device. 122 00:09:14,400 --> 00:09:19,090 Now the French resource would have the placeholders listed in a different order, like I did when I swapped 123 00:09:19,220 --> 00:09:23,050 the second placeholder, the percent 2 dollar s 124 00:09:23,170 --> 00:09:26,880 with the percent 3 dollar s. And if you're using more than one placeholder, 125 00:09:27,030 --> 00:09:32,200 it's a good idea to always number them, so that your string resources are as flexible as possible. 126 00:09:32,250 --> 00:09:36,540 Alright so I'm going to put the PhotoDetailsActivity back to how it should be. 127 00:09:36,580 --> 00:09:41,850 And basically what I'm going to do is leave the photo author text tag in a string resources, 128 00:09:41,850 --> 00:09:48,660 so it's available if you want to download my source code. So I'm just going to undo that basically, comment this one out, and we'll go back 129 00:09:48,660 --> 00:09:50,100 to the original author name. 130 00:09:50,670 --> 00:09:55,650 And again as I mentioned I've going to leave this in the strings xml file, but as we're not going 131 00:09:55,650 --> 00:09:56,100 to use it 132 00:09:56,100 --> 00:09:57,480 I should really delete it. 133 00:09:57,680 --> 00:10:02,470 And it is a good idea to be tidy and not normally leave unused resources in the xml files. 134 00:10:02,490 --> 00:10:03,810 But as I said I'll leave it in there, 135 00:10:03,930 --> 00:10:08,130 so that's available if you want to download my source code, but it's a good habit to get into, to delete 136 00:10:08,190 --> 00:10:09,770 any unused resources. 137 00:10:10,010 --> 00:10:10,320 Alright. 138 00:10:10,320 --> 00:10:15,390 So at this point we've got a pretty cool looking app for displaying flickr photos, but it does have one 139 00:10:15,390 --> 00:10:21,430 serious shortcoming, and that is that it can only display photos that are tagged with Android and Oreo. 140 00:10:21,570 --> 00:10:22,900 That's pretty boring, 141 00:10:23,100 --> 00:10:28,140 so the last bit of functionality we need to provide, is a search feature to allow users to search on 142 00:10:28,140 --> 00:10:29,280 different tags. 143 00:10:29,280 --> 00:10:31,430 So we'll make a start on that in the next video.