In this video we're going to create the
last layout we need to use for our tasks.
We've got the layouts that'll just
display the list of tasks in a Recycler
View, but at the moment there's no way to
create new tasks. So what we need is a
layout called fragment_
add_edit. So don't worry
about the strange names starting with
fragment at the moment. The reason for
that will become clear later. The layout's
going to contain three EditText widgets,
one below the other, and there's also
going to be a button as well. So why am
I telling you this?
Well you've guessed it - this video's
starting off with a challenge. Alright, so
we want to create a new layout, as I
mentioned, called fragment_
add_edit that contains three
EditText widgets, one below the other
and a button below them.
Now the IDs for the EditTexts are, in
order from top to bottom;
first one, addedit_name,
then addedit_description,
then addedit_sortorder,
and the ID for the Button should be add
edit_save. Now the first two
EditText widgets should fill the full
width of the screen, and automatically
extend vertically to accommodate several
lines of text. Now there's no need for
the sort order widget to extend
vertically, as it'll only accept numbers,
but it can fill the full width of the
screen. You may want to google the Edit
TextinputType property, to find out
what the effects of the various settings
are. So if you add hints to the widgets
using the hint property, then I suggest
you store any strings for that property
as String Resources rather than hard-
coding them into the layout. The names of
your String Resources aren't important,
but you should try to be consistent in
naming things. In fact, all text should be
stored in String Resources, rather than
hard-coded into the layout. Any property
not specified above can be left at its
default value, except for the maxLength
property. I'll be explaining why shortly,
but the EditText widgets need the
following values for maxLength; so add
edit_name - maxLength 64, add
edit_description - maxLength
256, then addedit_sortorder -
maxLength of 9.
Now don't be tempted to do anything
fancy with the layout in landscape mode.
If you remember from the demo of the app
earlier, we've got plans for the extra
screen width at landscape mode that
tablets provide. Now, of course, your
layout will fill the width of the screen
in landscape but that's fine. What I
don't want you to do is place things
next to each other, so that your layout
relies on the full width in landscape.
Now I should maybe include an image or
diagram of the expected layout, but quite
often you'll find that the specs you get
from your customer are pretty vague. That
can be a good thing because it gives you
a lot of freedom when designing your app.
Sometimes the specification will come
from programmers working on other parts
of the system, and they won't care what
you produce as long as it actually works
with their system, or their part of the
system. So if the layout you produce
meets the above criteria, then it should
work fine in this app. Alright so that's
the challenge. Pause the video now and
see if you can complete that challenge,
and I'll see you when you get back and
we'll go through the solution. Pause the
video now. Alright so welcome back. So
from my solution to the challenge I'm
going to use a linear layout. Now if you
haven't used the linear layout but you
perhaps used the constraint layout
then that's fine. The important thing
here is still that your layout allows
the data to be entered, and it has the
correct IDs. Now speaking of IDs, normally
you'd be free to use whatever you wanted,
but I specified them so that you could
concentrate on the code later, rather
than having to compare your IDs to mine.
It just makes it easier to use the same
ones. The same goes for the name of the
layout. Alright so let's go ahead and
create our layout. So I'm going to call this
one, as mentioned in the challenge notes,
fragment_add_edit.
Now I could change the layout type
before clicking OK, but I want to show
you a new feature in Android Studio. So
if I leave it set to ConstraintLayout
and click OK, even though that's not what
I want - I'll do that now - I can actually adjust
this later. So I can come over here to
the component tree. I'll close down the
Project pane first, right-click the
ConstraintLayout and I can select
Convert view,
and that actually lets you change one
view type to another. Now because we
right-clicked a view group - the layout - the
dialog only shows other layouts, but you
could type TextView in the box if that's
what you wanted. But we want a Linear
Layout so I'm going to select that and
click on apply, and you can see over there
at the component tree to the left
hand side, we've now got a LinearLayout.
So that's pretty cool, and if you want to
change a button, for example, to be an
image button, then you can convert it now
instead of editing the XML directly.
Alright, so a LinearLayout is a
perfectly adequate layout to use here,
but again it's fine if you used a
different layout. But when placing all
widgets where they're stacked up
vertically or next to each other, then a
linear layout is preferable because it's
so simple to use. So we need to make sure
that linear layout's selected over here,
and the first thing we want to do is
change the orientation to vertical which
will place the widgets one above the
other.
Alright so next we're going to drag
three EditText widgets and a Button
onto the layout. So I'm going to come over
here first and select Text. So the
first two are going to be used to enter
text. So I'm going to use the Plain Text
version over here, so I'm going to select those.
The third one is going to be used to
enter the sort order which is numeric, so
a Number EditText will be appropriate
here so I'll select that, or drag that
rather. And then lastly we just want a
regular Button, so I'm going to go back to
Common under the groups and select a
Button and drag that onto our layout. Al
right so from top down, the first Edit
Text should have the ID. I'll select that
and it's going to be addedit_
name. Again that was as per the
instructions in the challenge notes, so
addedit - I can spell - underscore name. Now
the layout_width and layout_height are
already set to match_parent and wrap_
content as you can see, and there's no
need to change them, but it's always a
good idea to check these two properties
to make sure they are set as you want.
The next property over here is input
type, so I'm going to switch to a browser.
So let's just have a quick look at input
type. So specifically I'm going to type
in edittext input type -
that's a search in Google - and you can see
that two of the top results are from
developer.android.com so that's always a
good place to start. One, as you can see
at the top one in my case, is a reference
doc, but there's also one of Google's
training docs just below that, and
that's probably a better place to start.
Now there's also a guide but it doesn't
always appear in the list of results, but
I'll come back to that when we've had a
look at the training doc. So I'm going to
select the training doc, click on that
one, and you can see that this is
actually quite interesting. The input
type property doesn't just restrict the
type of data that can be entered, it's
also used to decide which keyboard to
give the user. Now the example shows the
keyboard that appears if you set the
input type to phone and password, and
there's also an example of adding text
auto-correct in the input type. So I've
got some good examples showing on there
as you can see. So this is input -
this is a quite an important property
for EditText widgets. So a bit further
down as I scroll down, we've got this
Specify the input method action section.
There's a description here of a special
action button that can appear on the
keyboard, and there's even sample code, as
you can see there, showing how to add
your own listener to that key if you
want to do that, and that can be very
useful when displaying a form on a phone
in landscape. So in landscape there's not
a lot of height on the screen, and a soft
keyboard would probably obscure our Save
button. So it may be worth adding the
same functionality to a Done action
button. There's a lot of useful
information in this training doc so it's
definitely worth having a good read, and
then following the next links at the
bottom of each page. So you can basically
go through and there's lots of
information you can actually find here,
following this through to the next section
and sort of just reading through the
various pages there. If you provide the
users with the correct keyboard and the
behavior they expect, then your apps will
look far more polished and your users
will enjoy using them. Alright let's just go back
to Android Studio. Alright so what we
want to do here is select input type.
Firstly I'm going to uncheck the text
PersonName which was selected by default,
and I want to set this first EditText
input to text
NoSuggestions. So I'm going to click on that,
check that box. Now the user will most
likely use things like project names in
this field, such as TaskTimer for
example, so any suggestions are probably
unlikely to be much use. One thing we
certainly don't want to add here is text
autocorrect, as that would just be
annoying in use. Alright so I'm going to
click OK for that. Now for the hint
property I'm going to create a new
string resource, and we'll call this one
addedit_name_hint,
and for the Resource value we'll put Task
name colon required, enter there. Now we
can clear the text property so we'll do
that now, and that's got the added
advantage of enabling the hint to show
in the designer, and you can see over to
the left-hand side
that's now showing. Alright so
that's the first EditText. The next one,
let's move ahead and do that one. This is
going to be our description. So the ID
is going to be addedit_
description. The layout width and height
should still be set correctly, match_
parent and wrap_content respectively, and
for the input type we're going to click on
that. Now we want to allow the user to
insert line breaks by selecting text
MultiLine here, so I'm going to de-select
textPersonName and select text
MultiLine. Now suggestions might be
useful here, as this field may contain a
normal text description of the task, so I
won't add textNoSuggestions. If text
PersonName was added automatically,
which it was, and you saw when I first
went into this field,
remove that, which I've done. Alright so
let's click OK to that, now that text
MultiLine's selected, and same deal there
with the hint. I'm going to come over
here. We're going to create a new string
resource for the hint, and we're going to
go with the name here - addedit_
description_hint. And
the resource value we're going to go
with will be Task description
parentheses optional.
Alright, and once again as we did for the
name we're going to clear the text field,
and we can now see the hint appearing in
the left-hand side. Alright so the third
EditText will only allow numeric
input, and start by changing the ID for
that, and it's going to go addedit
_sort_hint. That's
going to be the name we assign to it.
The layout width and height, we'll leave
as the default there, match_parent and
wrap_content again, and I'm going to
click on the input type again. This time,
because we selected the number EditText,
it's already set to number, so we don't
need to make any changes to that. And for
the hint, let's create a new
string resource again. We'll call this
one addedit_sort_
hint, and we'll go with the resource
value name of Order: sorts low to
high. And we didn't have any value in
the text property so we didn't need to
clear that, and we can see the hint showing on
the left hand side again. Alright so at this
point now that just leaves the Button, so
let's work on that. The name, the ID
rather, we're going to call this one is
addedit_save. The layout width
and height here should both be set to
wrap_content. So I'm going to change the
layout width so it's wrap_content. Now
the text for the Button will be stored
in a string resource, so let's go ahead
and create that string resource And the
resource name, we're going to go with add
edit_save_text, and the
resource value is going to go with Save.
Now we're almost done at this point, but
there are a couple of things I want to
do to this button though. Firstly, I want
to give it a margin, a top margin of 8
dp just to move it away from the text,
the EditText just above it. So I'm going
to go into extended attributes for that.
I'm going to extend layout_margin, I'm going to
click into top here, in it
at 8dp, and you can see that the Button's
now moved down. We've now got a margin of
8dp. Now there's another thing we can do
and this isn't part of the challenge, but
it can be a nice touch on Buttons that
provide recognized functions like saving.
So
as well as the label Save on the Button, we
can also add an icon. And to do that if we
scroll down a bit, we're looking for a extended
attribute, and if we scroll we'll see
there's a number of them here; the drawable
Bottom, End etc. But the one I'm looking
for is drawableStart. So I'm going to come
into here, and as you click on the
ellipsis, and I want to set that to ic
_menu_save. And I can
do that by just typing in the word save,
expanding Android, and you can see we've
got this ic_menu_save pops up
for us. Click on OK, and you can see now
to the left hand side we've got
like a picture - an image there - of a Save
icon now added in addition to the text.
Alright, the specification in
the challenge also mentioned setting the
max length properties for the EditText
widgets. Now the reason for this is that
we're going to be storing whatever's
entered into those boxes, in our database,
and we really don't want to store huge
task names. The display will also look
very untidy if the names are very long,
and the idea is that a task should be
very easy to find in the list so that
users can quickly start the timer
without wasting too much time. So I'm
going to set the max length properties
to these values in the specification, and
it's actually easier to do these all at
once so that it avoids having to hunt
through the attributes to find max
length each time. Now an easy way to find max
length is just to come up here and just
search for maxLength. I can click on that
now, and come over here and click on the
value, but before I enter a value I need
to specify which fields. I'm going to
start with Task name: required.
I'm going to do a search again for maxLength, and
I'm going to set the value for the first
one for our name - the maxLength was 64.
Then I'm going to choose the next one, the
description, and again if I wanted to I
could go through and just search it each
time. It may also be easier just to come
down here, and
just come down to maxLength here so it
stays on the screen. Enter 256 - this time
for description, and then when I go and click
on the next one, notice that's
still there and I can come over here and
select the value, in this case of 9.
Alright and if I go back and click on another
one these properties I've already set,
notice that maxLength seems to
disappear from here.
So what actually happens is, if we
scroll back to the top - so up here you can
see that it now shows maxLength 256 under
inputType. So if you're hunting for
it, that's where it's gone. Okay so of
those three that we've set, and again we
can see them by clicking on them, we've
got 64 for addedit_name, addedit
underscores description of 256. And I
made a typo there, addedit
_sort_hint, but anyway
that one was set to 9. I'll just talk
about what they are. The really crucial
one out of these three is the value of
9 for the sort order. So that's a
numeric field, and if we allow too many
digits to be entered then our app will
crash when we try to convert the input
into a number. So we're being very
generous allowing nine digits. Really,
most users only really need one or two
digits to keep their tasks sorted how
they want. Alright so that's the
challenge done, but what I'll do is I'll
come up here and change the ID, because
the ID should have actually been add
edit_sortorder not hint,
sortorder. If you go back to our regular
attributes, I'll just check here we've
actually got that correctly set for the
string resource for hint, so that's okay.
But we'll also change the name to what
it should have been - addedit_
sortorder - and we've got our addedit
_description and addedit
_name correctly specified as
well as the Button. Alright so that's the
challenge completed. So I'm going to end
the video here, then in the next one we want
to change tact and start talking about
creating a data class to make all this
happen - in other words, to implement the
interface so that it actually does
something. So I'll see you in the next
video.