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.

Leave a rating/review
Save for later
Share
You are currently viewing page 2 of 7 of this article. Click here to view the first page.

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.

layout_alignParentBottom

Example 2: You can use layout_toRightOf and the analogous attributes for left, above and below to position one View relative to another.

layout_toRightOf

Example 3: You can use layout_alignRight and the analogous attributes to align a side of one View with another.

layout_alignRight

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.

layout_weight

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:

layout_gravity

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 LinearLayouts 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 LinearLayouts and layout_weights — all those extra tiny calculations could add up.

Note: There are also performance reasons for considering a simple layout design. Layout weights require the layout inflater — the class which turns the XML into real 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 LinearLayouts and layout_weights — 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.

refactor

Then, type in textview and click Refactor.

rename_textview

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:
import warning

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!

dynamic_text

The text set via Java code now appears on screen. What are the steps you just took to make that happen?

  1. You added an id attribute to the View in XML.
  2. You used the id to access the View via your code.
  3. 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.