1 00:00:03,920 --> 00:00:10,440 G'day everyone, welcome back. Okay, let's have a look at plurals string resources. 2 00:00:10,440 --> 00:00:16,040 I created someone I pasted the resources into res slash values slash strings 3 00:00:16,059 --> 00:00:22,840 underscore settings.xml. In there we've got three sets of units; for seconds, 4 00:00:22,840 --> 00:00:29,950 minutes and hours. Each unit is inside a plurals resource and has the units when 5 00:00:29,950 --> 00:00:33,980 there's only one of it, and the units for zero or several. 6 00:00:33,980 --> 00:00:41,200 For example, the quantity equals one value for the little units is second, singular. 7 00:00:41,200 --> 00:00:48,800 The other value, when quantity equals other, is seconds, with the s on the end. 8 00:00:48,800 --> 00:00:53,440 Android takes care of choosing the appropriate string for us, and contains 9 00:00:53,440 --> 00:00:58,149 all the rules for every language that Android supports. You can find more 10 00:00:58,149 --> 00:01:12,000 information in the Google docs, at https:// developer.android.com/guide/topics/ resources/string-resource 11 00:01:12,000 --> 00:01:14,300 Scroll down a quarter of the way, 12 00:01:14,300 --> 00:01:19,980 and there's a section headed Quantity Strings Plurals. 13 00:01:20,070 --> 00:01:24,360 I won't read through that option, but it shows you all the options available to 14 00:01:24,360 --> 00:01:30,160 you. In the syntax box, you can see the quantity names that are available. 15 00:01:30,160 --> 00:01:34,710 Android will select the correct one, based on the user's language. Of course, 16 00:01:34,710 --> 00:01:38,160 you will have to provide a resource file for every language that your app will 17 00:01:38,160 --> 00:01:42,450 support, and you'll need someone to do the translations, unless you can speak 18 00:01:42,450 --> 00:01:47,620 all the languages yourself. Going back to our strings underscore settings file, 19 00:01:47,620 --> 00:01:52,950 I've set up quantity strings for the seconds, minutes and hours. We're not 20 00:01:52,950 --> 00:01:57,900 using hours, but you could easily extend the deltas array to do that. Be careful 21 00:01:57,900 --> 00:02:03,330 though. If you have too many values, then it can be very hard for your users to 22 00:02:03,330 --> 00:02:09,600 control the slider. Okay, that's how we create plural string resources. Let's see 23 00:02:09,600 --> 00:02:15,120 how to use them in our code. We set the seekBarValue initially, in the onView 24 00:02:15,120 --> 00:02:24,040 StateRestored function, 25 00:02:24,040 --> 00:02:29,900 and we need to check to see if we're displaying seconds or minutes. 26 00:02:37,080 --> 00:02:42,540 We get the correct quantity string by calling the resources dot get quantity 27 00:02:42,540 --> 00:02:48,210 string function. We have to provide it with the plurals resource ID, and also 28 00:02:48,210 --> 00:02:53,100 the value that we're trying to display. It's a bit clumsy, having to provide the 29 00:02:53,100 --> 00:02:57,630 ignoreLessThan value twice, but the get QuantityString needs to know the 30 00:02:57,630 --> 00:03:02,580 quantity. That lets it use the language rules to return the appropriate string. 31 00:03:02,580 --> 00:03:07,180 Alright, that deals with the seconds, if ignoreLessThan is less than 60. 32 00:03:07,180 --> 00:03:12,400 For larger values, the code's almost the same, but we use the big units instead. 33 00:03:12,400 --> 00:03:17,500 We also divide the seconds by 60, to get the minutes. 34 00:03:25,690 --> 00:03:35,890 Run the app again, and we get the correct number of seconds, and the singular or 35 00:03:35,890 --> 00:03:41,200 plural units appearing in the seek bar's title. The next step is to update that 36 00:03:41,200 --> 00:03:46,810 text, when the slide is dragged from side to side. To do that, we need to listen to 37 00:03:46,810 --> 00:03:52,450 changes to the seek bar. We've seen on ClickListeners a lot. The seek bar has 38 00:03:52,450 --> 00:03:58,450 an onSeekBarChangeListener. It works in the same way - we'll get call back, 39 00:03:58,450 --> 00:04:04,060 whenever the seekBarValue changes. I'll set the listener in the onViewCreated 40 00:04:04,060 --> 00:04:09,000 function, just before we set the button's listeners. 41 00:04:15,580 --> 00:04:21,579 The onSeekBarChangeListener interface contains three functions, which means we 42 00:04:21,579 --> 00:04:26,440 can't use a simple lambda here. Instead, we have to implement all three functions, 43 00:04:26,440 --> 00:04:31,540 even though we only need one of them. I'll get Android Studio to create the 44 00:04:31,540 --> 00:04:37,650 stubs, using ctrl i with the cursor, inside the control block. 45 00:04:51,580 --> 00:04:57,400 As I said, we have to implement all three, so select them all from the dialog. 46 00:04:57,400 --> 00:05:03,340 For the onstartTrackingTouch and onStop TrackingTouch functions, which we're 47 00:05:03,350 --> 00:05:08,380 not going to use, I'll just a replace the TODO with a comment. 48 00:05:32,690 --> 00:05:38,070 The code in onProgressChanged is very similar to the code we used in 49 00:05:38,070 --> 00:05:40,060 onViewStateRestored. 50 00:05:40,060 --> 00:05:42,280 Whenever the seekBar's value changes, 51 00:05:42,280 --> 00:05:46,320 we'll find the number of seconds that corresponds to the value, then display it 52 00:05:46,320 --> 00:05:50,090 along with the quantity string. 53 00:06:12,750 --> 00:06:17,820 There's another change I want to make. Google haven't yet got around to 54 00:06:17,820 --> 00:06:24,030 annotating the seekBar parameter, as not null. It can't be null - you can't get a 55 00:06:24,030 --> 00:06:29,310 notification from a null old seekBar - so I'll remove the nullable type marker from the 56 00:06:29,310 --> 00:06:38,550 seekBar parameter. If you're not comfortable doing things like that, then 57 00:06:38,550 --> 00:06:43,050 don't do it, but by the time you watch this video, you may find that the seek 58 00:06:43,050 --> 00:06:49,980 Bar's been annotated as non null, anyway. Okay, that should work. I'll run the app 59 00:06:49,980 --> 00:06:54,200 and drag the slider around to test that it does. 60 00:07:04,540 --> 00:07:10,000 That's looking good - well goodish. Be careful when displaying dynamic text 61 00:07:10,000 --> 00:07:15,010 like this in a dialog. It's very easy to have the dialog jumping around, 62 00:07:15,010 --> 00:07:20,650 as it's with changes. It's not the best user experience, and makes it hard to set the 63 00:07:20,650 --> 00:07:26,830 slider reliably. Fortunately, it's easy to fix. Let's have a look at our Settings 64 00:07:26,830 --> 00:07:44,230 Dialog layout. Select ignoreSecondsTitle in the component tree, and check 65 00:07:44,230 --> 00:07:50,110 the attributes and the constraints. It can take some careful thinking to work 66 00:07:50,110 --> 00:07:54,880 out what's going on here. I've got a dialog that resizes itself, based on 67 00:07:54,880 --> 00:08:00,310 its contents, because that's what dialogs do, and we've got a TextView 68 00:08:00,310 --> 00:08:07,140 whose contents change. That's why our dialog keeps resizing. To fix the problem, 69 00:08:07,140 --> 00:08:11,800 we need to set the width of the TextView. The tricky bit is working out what 70 00:08:11,800 --> 00:08:16,450 to set it to. The only thing we really know is the maximum number of characters 71 00:08:16,450 --> 00:08:23,050 we'll be displaying - that's 35 characters in this case. Fortunately, Android does 72 00:08:23,050 --> 00:08:30,400 provide a way to do that. In publishing, there's something called an em, spelt em. 73 00:08:30,400 --> 00:08:35,049 It's the width of the widest character, which is usually an uppercase M, hence 74 00:08:35,049 --> 00:08:42,909 the name, em. If we set the em's attribute to 35, then our textView can display 35 75 00:08:42,909 --> 00:08:51,340 characters without resizing. You'll find ems in the extended attributes. 76 00:08:51,340 --> 00:08:58,920 Set it to 35, and then run the app again. 77 00:09:08,900 --> 00:09:14,640 That's much better. That approach should work for all languages, because the TextView's 78 00:09:14,640 --> 00:09:18,980 height is set to wrap content. If there are more than 35 characters in 79 00:09:18,990 --> 00:09:24,510 some languages, the TextView will wrap onto another line. Alright, we'll finish 80 00:09:24,510 --> 00:09:28,620 the SettingsDialog in the next video, when we'll add a title to the Dialog. 81 00:09:28,620 --> 00:09:31,820 I'll see you then.