Android Tutorial for Beginners: Part 2
An Android Tutorial that shows you how to make your first app app step-by-step, using Android Studio! By Darryl Bayliss.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Android Tutorial for Beginners: Part 2
55 mins
- Getting Started
- XML Layout Basics
- Relative Layouts
- Linear Layouts
- Accessing Views From Within Java
- Buttons and Listeners
- Adding a Visual and Nested Layouts
- Involving the Keyboard
- The ListView
- Detecting List Selections
- The Action Bar
- Sharing
- Remembering Your Name
- Displaying the Name Dialog
- Where to Go From Here?
Relative Layouts
The layouts in iOS apps used to be in purely absolute terms, like: “Place View X at pixels (x,y)”, but now iOS developers have AutoLayout. Android developers have always needed to keep device screen sizes in mind. Layout files are very well-suited for this consideration.
The default project Studio created for you sets you up with a useful layout: a RelativeLayout
. It is currently the parent layout and the TextView
element is its child.
A RelativeLayout is an intuitive and powerful thing. It holds a bunch of child views and positions them in relation to each other. Here are three examples of what you can easily do with a RelativeLayout
:
Example 1: Use layout_alignParentBottom
and the similar attributes for top, left and right to line up a view’s edge with the corresponding edge of the RelativeLayout
, which may or may not also be the edge of the screen.
Example 2: You can use layout_toRightOf
and the analogous attributes for left, above and below to position one View
relative to another.
Example 3: You can use layout_alignRight
and the analogous attributes to align a side of one View
with another.
You can see how that could be useful! For now, though, let’s move on to the layout type you’ll be using for this tutorial.
Linear Layouts
A LinearLayout needs to have an orientation specified, either horizontal
or vertical
. Then it lines up its children in that orientation, in the order in which they are specified in your XML.
The children of LinearLayouts
don’t respond to attributes like layout_toRightOf
, but they do respond to two other attributes: layout_weight
and layout_gravity
.
Specifying a layout_weight
expands the view to a proportion of its parent so that the parent weight is the sum of all child view weights.
The layout_weight
of View
X
———————————————————————-
The sum of all weights of View
X and its siblings
The layout_weight
of View
X
———————————————————————-
The sum of all weights of View
X and its siblings
Confused? Perhaps the following image might help explain it better.
Notice how the full height of the parent view is split up between the child views based on the layout weight assigned to each child view.
Assigning a layout_gravity
to a view sets its horizontal and vertical positions within its parent LinearLayout
. For example, a view might have a layout_gravity
attribute with a value like left
, right
, and center_vertical
. The previous values can also be combined, like this: top|center_horizontal
.
Then, there’s gravity
, not to be confused with layout_gravity
. While layout_gravity
is about where you place the view itself, the gravity
attribute defines how you place the content of a view within itself. If you want your text to be left or center justified, use gravity
.
The following example shows how layout_gravity
and gravity
work in a vertical LinearLayout
. Note that the top three have a layout_width
of wrap_content
while for the bottom three it’s set to match_parent
:
One handy trick, which you’ll see in just a bit, is that you can nest layouts inside each other. Cue the theme music from Inception!
You don’t want your layouts to be as multi-layered as a Christopher Nolan movie, though. So, if you start to see your nested LinearLayout
s scheme getting out of hand, consider switching to a RelativeLayout
.
Now, modern devices won’t have any trouble rendering your basic layouts. But if you were to make an indefinitely long ListView
— for instance, one full of cells making copious use of nested LinearLayout
s and layout_weight
s — all those extra tiny calculations could add up.
Views
— to do a tiny calculation to put the view together.
Now, modern devices won’t have any trouble rendering your basic layouts. But if you were to make an indefinitely long ListView
— for instance, one full of cells making copious use of nested LinearLayout
s and layout_weight
s — all those extra tiny calculations could add up.
Before you move on to the next section, open res/layout/activity_main.xml and change the root node from a RelativeLayout
— what Android Studio gave you as a default — to a LinearLayout
.
To do that, you should replace these lines:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
And this one at the very end of the file:
</RelativeLayout>
With This:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
And this:
</LinearLayout>
Accessing Views From Within Java
Layouts are primarily the domain of your XML. But there are plenty of visual elements you will want to create, destroy, change, and trigger from within your Java code!
So first, edit the TextView
in activity_main.xml to match the following:
<TextView
android:id="@+id/main_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:text="@string/hello_world"/>
Notice the addition of the id
attribute. Using this tag (or attribute, if you prefer) allows you to access that specific View
from within your code, so you can thereafter manipulate the View
via code.
There’s also a change to make in the text
tag. The name of the string resource hello_world
is a bit outdated now, don’t you think? Right-click on the @string/hello_world part of the line and then choose Refactor > Rename.
Then, type in textview
and click Refactor.
This not only changes the name of the resource ID in your layout file, it also changes the original resource ID in your strings.xml
file. It also renames the resource ID wherever else it might be used in the project. This is a useful trick to remember when renaming something that appears all over your project!
Now open MainActivity.java and add the following line above the onCreate
method but below the MainActivity class declaration:
TextView mainTextView;
Android Studio will throw an error at you when you leave your cursor on this line that will look like this:
The TextView
class hasn’t been imported into MainActivity.java yet so it doesn’t know what a TextView
is. Android Studio can quickly fix that for you. Just tap Alt-Enter on your keyboard while this error popup is present to automatically import TextView
.
Note: It can get tiresome very quickly having to manually import every single component of an Android App you want to use in a class. Fortunately you can automate this in the IDE settings window, which you can access by going to Android Studio > Preferences (for Mac) or File > Settings (for Windows & Linux) and then clicking Editor > Auto Import and ticking Optimize imports on the fly and Add unambiguous imports on the fly.
Note: It can get tiresome very quickly having to manually import every single component of an Android App you want to use in a class. Fortunately you can automate this in the IDE settings window, which you can access by going to Android Studio > Preferences (for Mac) or File > Settings (for Windows & Linux) and then clicking Editor > Auto Import and ticking Optimize imports on the fly and Add unambiguous imports on the fly.
Next, add the following code to onCreate
after the two existing lines of code:
// 1. Access the TextView defined in layout XML
// and then set its text
mainTextView = (TextView) findViewById(R.id.main_textview);
mainTextView.setText("Set in Java!");
Your MainActivity.java file should now look like this:
public class MainActivity extends ActionBarActivity {
TextView mainTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 1. Access the TextView defined in layout XML
// and then set its text
mainTextView = (TextView) findViewById(R.id.main_textview);
mainTextView.setText("Set in Java!");
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
}
Finally, run your app and look at the results!
The text set via Java code now appears on screen. What are the steps you just took to make that happen?
- You added an
id
attribute to theView
in XML. - You used the
id
to access theView
via your code. - You called a method on the
View
to change its text value.
Note: You added the code to access and set the text of your TextView
in the onCreate
method of your Activity
, meaning that the app runs all the code in that block right away when it first creates the Activity
. Activities have strict lifecycles they must follow and it’s thanks to this that you can write code that runs at specific points of an Activities life. You can read more about the Activity
lifecycle here.
Note: You added the code to access and set the text of your TextView
in the onCreate
method of your Activity
, meaning that the app runs all the code in that block right away when it first creates the Activity
. Activities have strict lifecycles they must follow and it’s thanks to this that you can write code that runs at specific points of an Activities life. You can read more about the Activity
lifecycle here.