G'day everyone, welcome back. Okay, let's have a look at plurals string resources.
I created someone I pasted the resources into res slash values slash strings
underscore settings.xml. In there we've got three sets of units; for seconds,
minutes and hours. Each unit is inside a plurals resource and has the units when
there's only one of it, and the units for zero or several.
For example, the quantity equals one value for the little units is second, singular.
The other value, when quantity equals other, is seconds, with the s on the end.
Android takes care of choosing the appropriate string for us, and contains
all the rules for every language that Android supports. You can find more
information in the Google docs, at https:// developer.android.com/guide/topics/ resources/string-resource
Scroll down a quarter of the way,
and there's a section headed Quantity Strings Plurals.
I won't read through that option, but it shows you all the options available to
you. In the syntax box, you can see the quantity names that are available.
Android will select the correct one, based on the user's language. Of course,
you will have to provide a resource file for every language that your app will
support, and you'll need someone to do the translations, unless you can speak
all the languages yourself. Going back to our strings underscore settings file,
I've set up quantity strings for the seconds, minutes and hours. We're not
using hours, but you could easily extend the deltas array to do that. Be careful
though. If you have too many values, then it can be very hard for your users to
control the slider. Okay, that's how we create plural string resources. Let's see
how to use them in our code. We set the seekBarValue initially, in the onView
StateRestored function,
and we need to check to see if we're displaying seconds or minutes.
We get the correct quantity string by calling the resources dot get quantity
string function. We have to provide it with the plurals resource ID, and also
the value that we're trying to display. It's a bit clumsy, having to provide the
ignoreLessThan value twice, but the get QuantityString needs to know the
quantity. That lets it use the language rules to return the appropriate string.
Alright, that deals with the seconds, if ignoreLessThan is less than 60.
For larger values, the code's almost the same, but we use the big units instead.
We also divide the seconds by 60, to get the minutes.
Run the app again, and we get the correct number of seconds, and the singular or
plural units appearing in the seek bar's title. The next step is to update that
text, when the slide is dragged from side to side. To do that, we need to listen to
changes to the seek bar. We've seen on ClickListeners a lot. The seek bar has
an onSeekBarChangeListener. It works in the same way - we'll get call back,
whenever the seekBarValue changes. I'll set the listener in the onViewCreated
function, just before we set the button's listeners.
The onSeekBarChangeListener interface contains three functions, which means we
can't use a simple lambda here. Instead, we have to implement all three functions,
even though we only need one of them. I'll get Android Studio to create the
stubs, using ctrl i with the cursor, inside the control block.
As I said, we have to implement all three, so select them all from the dialog.
For the onstartTrackingTouch and onStop TrackingTouch functions, which we're
not going to use, I'll just a replace the TODO with a comment.
The code in onProgressChanged is very similar to the code we used in
onViewStateRestored.
Whenever the seekBar's value changes,
we'll find the number of seconds that corresponds to the value, then display it
along with the quantity string.
There's another change I want to make. Google haven't yet got around to
annotating the seekBar parameter, as not null. It can't be null - you can't get a
notification from a null old seekBar - so I'll remove the nullable type marker from the
seekBar parameter. If you're not comfortable doing things like that, then
don't do it, but by the time you watch this video, you may find that the seek
Bar's been annotated as non null, anyway. Okay, that should work. I'll run the app
and drag the slider around to test that it does.
That's looking good - well goodish. Be careful when displaying dynamic text
like this in a dialog. It's very easy to have the dialog jumping around,
as it's with changes. It's not the best user experience, and makes it hard to set the
slider reliably. Fortunately, it's easy to fix. Let's have a look at our Settings
Dialog layout. Select ignoreSecondsTitle in the component tree, and check
the attributes and the constraints. It can take some careful thinking to work
out what's going on here. I've got a dialog that resizes itself, based on
its contents, because that's what dialogs do, and we've got a TextView
whose contents change. That's why our dialog keeps resizing. To fix the problem,
we need to set the width of the TextView. The tricky bit is working out what
to set it to. The only thing we really know is the maximum number of characters
we'll be displaying - that's 35 characters in this case. Fortunately, Android does
provide a way to do that. In publishing, there's something called an em, spelt em.
It's the width of the widest character, which is usually an uppercase M, hence
the name, em. If we set the em's attribute to 35, then our textView can display 35
characters without resizing. You'll find ems in the extended attributes.
Set it to 35, and then run the app again.
That's much better. That approach should work for all languages, because the TextView's
height is set to wrap content. If there are more than 35 characters in
some languages, the TextView will wrap onto another line. Alright, we'll finish
the SettingsDialog in the next video, when we'll add a title to the Dialog.
I'll see you then.