The Solution: Creating the UI16:05 with Ben Deitch
In this video we'll create the UI for our note-taking app.
All right, let´s make a note taking app. 0:00 In this video, we'll create the project and make the UI for the app, and 0:02 in the next video, we´ll create all of the Room elements that tie the app together. 0:07 So if you´d like to jump ahead and 0:13 see all of the Room part of the solution, go ahead and click on to the next video. 0:15 Okay, let's get started by creating a new project. 0:20 I'll name mine Note Pad, And include Kotlin support. 0:29 Accept the defaults, and hit Finish. 0:38 Now that we've got the app, let's click over into activity_main and 0:44 set up the layout. 0:48 Let's click on the Design tab and we can hide the project paint for now. 0:51 And I'll make this a little easier to see. 0:57 To get started, lets delete the hello world text view, 1:02 and then start from the bottom right with our button. 1:06 Let's grab a button end from the pallet, put it in the bottom right, and 1:10 remember since this is a constraint layout, We need to add constraints, 1:14 so let's constrain it to the bottom right, and 1:20 we can leave those as 8 DPs with padding that's fine. 1:23 And for the text, let's change it to say ok. 1:27 Then we need the edit text that goes next to it, so let's click on Text. 1:32 And we can go with Multiline Text, drag that down here. 1:37 Give it constraints to the bottom left side, and on the right to the button. 1:49 Give it a size of match_constraints for the layout width. 1:56 Also for the text size which we can find in the all attributes section. 2:02 Let's start with 18sp. 2:12 Okay, now to add the RecyclerView. 2:18 RecyclerView doesn't come downloaded by default, so by clicking it and 2:24 dragging it out, it'll prompt us to add the project as a dependency. 2:28 Let's click OK here, And now we can use RecyclerViews. 2:32 Just like the other views, we should constrain the RecyclerView to the edges 2:44 of the screen and the other views in the layout. 2:47 It looks like the constraints are here on the screen, but maybe not over here on 2:57 the right, let's check this text and find out what's real here. 3:01 RecyclerView, Is constrained, okay. 3:07 Not sure what's going on there. 3:15 There we go, okay, it is constrained. 3:19 Another thing we wanna be careful of when placing views in a constraint layout, 3:22 is the layout width and layout height being set somewhat arbitrarily. 3:27 It looks like this happened with our RecyclerView, let's go ahead and 3:31 set these to match_constraints. 3:35 Perfect, also our edit text has an Id of editText, our button has an Id of button, 3:38 and our RecyclerView doesn't have an Id yet, so let's call it recyclerView. 3:44 Okay, that should be good for the layout for now, 3:54 if it's not we'll find out when we run the app and fix it at that time. 3:57 The other layout we'll need to create is the layout that goes 4:01 inside the RecyclerView representing one row. 4:04 Let's create that layout now, let's open the project pane, 4:07 go into the res directory> layouts> create a New> Layout 4:13 constraint layout is fine, and let's call it note_row. 4:17 It's a constraint layout and right now it's set to fill the space it inhabits. 4:24 Which is not quite what we want. 4:31 We do want it to be as wide as the parent but not as tall as the parent. 4:33 So for the layout height, let's set this to 80dp. 4:38 So each row will be 80dp tall. 4:43 Inside this row, let's start by putting a divider at the very bottom. 4:46 Let's pick Horizontal Divider and drag it out to the screen. 4:50 Then let's put it on the bottom with no padding, And 4:56 let's also center it by adding constraints to the right and left. 5:02 We can leave a padding for each of those. 5:06 Then we need to add a text view to show the text of the note. 5:11 Let's drag out a textView, And constrain it, 5:15 To the middle of our constraint layout. 5:25 Then we'll change the layout width and height to let it use all of the space. 5:28 Next, to make the textView be centered, 5:36 let's go into All Attributes, and under gravity, 5:39 let's check the box for, let's see if we can see this a little better, 5:43 center_vertical to move the text to be centered vertically. 5:48 Notice how before upper_left, center_vertical and the middle. 5:54 And we can leave this as an Id of textView, awesome. 6:01 Now that we've got our views, let's flip back to main activity and 6:05 start writing some code. 6:08 Inside the onCreate statement let's create three variables to represent each of 6:11 our views in the activity main layout. 6:16 Let's get one for the editText. 6:20 We'll findViewById, and we'll bring back an EditText, the R.id.editText. 6:25 And let's do val button = findViewById, 6:32 it'll give us a button, and the id is R.id.button. 6:36 And finally, we've got the recyclerView. 6:44 I'm gonna need to import that, and the new ID is R.id.recyclerView. 6:54 Once we've got these, we'll need an adapter for our recyclerView. 7:01 So, let's create a new class, And give our recyclerView an adapter. 7:06 Whenever I'm not sure what to call it, I usually just default to my adapter. 7:14 If I come up with a better name later, I can always change it. 7:18 So let's call this MyAdapter and 7:22 make it extend from RecycleView.Adapter. 7:26 And it'll want us to specify our ViewHolder class, With the adapter. 7:30 But it doesn't exist yet, so let's create that first. 7:37 That'll be an inner class and we'll call it ViewHolder. 7:41 And it extends from RecyclerView.ViewHolder. 7:48 Then we can auto complete to add the constructor call, and 7:57 looks like we need to pass in a view, so we'll pass in a view. 8:02 And we'll need to import the View class. 8:08 And now that we have our ViewHolder class, let's use it up on the class line, so 8:13 MyAdapter.ViewHolder. 8:18 And let's use Alt + Enter to add the constructor call, and 8:20 then we need to implement the class members. 8:23 And if you go into the settings, 8:29 you can make it not give you these to do lines if you'd rather. 8:32 Okay, now inside our adaptor, 8:41 let's start by creating a list to represent the data in the RecyclerView. 8:44 And it'll be just a mutable list of strings, and it'll start empty. 8:51 And then in onCreateViewHolder, let's create a view first, and so 8:57 that'll be LayoutInflater.from and to get the context, we can use the parent, 9:02 Then we need to call inflate, pass in the resource ID. 9:11 So, R.layout.noterow, 9:14 then we need to pass the view group which is parent, and 9:17 whether we need to attach it to that route, which is false. 9:22 Now that we've got the view, we need to return a view holder. 9:28 So just return a new view holder object while passing in the view for 9:31 the constructor, awesome. 9:37 getItemCount and let's move this over so we can see that a little better. 9:39 For getItemCount we can just set that equal to list.size. 9:44 And for onBindViewHolder we'll call a function in our ViewHolder class to update 9:51 the ViewHolder, so let's create that function first. 9:56 Since our note row only contains on view that we need to do anything with, 9:59 the text view, let's start by grabbing that textView. 10:04 Let's do val textView and instead of view.findViewbyId, 10:09 and this is gonna be a textView, and 10:14 we'll pass in after we import textViewr.id.textView. 10:17 Then let's add an update function, so fun update and 10:23 this will take in the index of the list which is an int. 10:28 And inside this function, we'll just do textView.text = list, at position index. 10:33 Finally, in onBindViewHolder(), we just need to call holder.update(), and 10:41 pass in the position variable, awesome, that should do it for our adaptor. 10:48 Back in the activity, let's create a new instance of our adaptor, 10:53 And then finish setting up our recyclerView. 11:02 So first, we concept the layout manager = LinearLayoutManager. 11:06 We're gonna pass on the context, the orientation which is vertical, 11:15 And then reverse layout which is false. 11:22 And after setting the layout manager, 11:27 we need to add the adapter, recycleView.adapter = adapter. 11:30 All right, and we've got access to each of our views. 11:35 Let's add a couple lines and start adding the code that ties it all together. 11:39 When we click the button, we need to take the text that's in the edit text and 11:45 add it to the recyclerView. 11:50 We'll make this work with the database in the next video. 11:51 But let's just hook things together for 11:54 the moment to make sure everything's working. 11:56 So let's take our button and call setOnClickListener and 12:00 pick the version with the brackets. 12:05 Then inside the brackets we need to get access to the note. 12:08 Let's create a new variable called note, and set it equal to editText.text, 12:12 and then .toString() to turn it into a string. 12:19 Then let's verify that our note isn't blank, so if note, 12:24 .isNotBlank(), and then we'll do something with it. 12:30 So let's take our adapter.list, And add the note to it. 12:35 Then we'll invalidate our adapter, or 12:46 rather notifyDataSetChanged, and that should update the UI. 12:49 Though if you run the app here, we should see a couple little issues. 12:57 So if we run it, and we add a message, 13:11 And click OK, so there's a couple things to notice here. 13:17 One, it looks like our Hello World text is indented, not quite as far as the divider. 13:21 Ideally, they'd be indented the same distance. 13:28 Let's check out what's going on there by heading into our activity_main.xml, 13:31 Or rather the node_row. 13:37 And let's bring in the Attributes pane, 13:40 see the textView is at 8, and the divider is also at 8. 13:44 But the divider is tricking us here again by setting a specific layout width 13:49 let's change this to match constraint, and that should fix that issue. 13:53 So let's run the app again, we'll come up, put in some text, hit OK and there it is. 13:59 It's over the same amount as the divider, also the text looks a little small, 14:04 so I'm gonna head back in here, change the textView itself from 14:10 down the text size and lets change that to 18sp, as well. 14:15 Okay, then we can run this again. 14:22 Verify that's fixed, good that looks better. 14:28 Another issue, the keyboard is not going away and 14:30 the keyboard text is not being cleared. 14:33 So to clear the keyboard text that one's actually pretty easy. 14:35 Just come in here and we just set editText, 14:38 .setText, and set it to nothing. 14:45 But to close the keyboard is actually a little bit harder. 14:49 And if you Google for it, 14:52 You're almost guaranteed to find this page describing how to solve the issue. 15:00 It's not pretty, but it does work. 15:04 So, with over 4,000 upvotes on Stack Overflow, 15:07 let's just copy this code and paste it into our OnClickListener. 15:12 And we can hit OK to make it automatically convert from Java to Kotlin. 15:23 Then we'll need to use Alt + Enter to add a couple of imports, and 15:28 we should add a comment saying, close the keyboard. 15:32 Okay, let's run this one more time. 15:38 And then if we add a note, Hit OK, 15:45 the note gets added, it lines up with the divider, the text is big enough, 15:50 the keyboard went away and the text is cleared of the edit text. 15:55 All right, 15:59 in the next video we'll finish this up by integrating room behind the scenes. 16:00
You need to sign up for Treehouse in order to download course files.Sign up