Intro to Android

Lab: Add Buttons

In this lab we'll add the buttons to the view complete with tests.

Note: They won't be pretty and they won't do anything!

Testing

As I build each key, I write a test. Then I add the next key. I typically don't start laying out the views or making them pretty until they are all present in the view and the tests are passing. I commit after the views are present. Then I do a styling commit afterward (we'll do that as a separate step).

Add a test

Last we saw this file, we had all the initialization code in the the test that we wrote. Let's make a field for the fragment and move the initialization to the setUp() function:

private ButtonFragment buttonFragment;

@Before
public void setUp() throws Exception
{
    buttonFragment = new ButtonFragment();
    startFragment( buttonFragment );
}

Now we can add a new test.

We use getView() to get a reference to the view and then find the specific id.

@Test
public void shouldHaveOneKey() throws Exception
{
    assertViewIsVisible( buttonFragment.getView()
                                       .findViewById( R.id.key1 ) );
}

Add a button

Now we add the button to the view.

<!--1-->
<Button
    android:id="@+id/key1"
    android:layout_width="60dp"
    android:layout_height="60dp"
    android:layout_margin="5dp"
    android:text="@string/key1"/>

Add a string

It's best practice to move your strings to the strings.xml file instead of leaving them hard coded in the view. It also makes it easier to test that the correct string is configured for a view.

<string name="key1">1</string>

The lint tool will recommend this for you by showing yellow bars and a light bulb in the view.

Verify properties

Let's extend our test to ensure that the correct string is configured for the view. We'll use our ResourceLocator class to get the resource string and compare it to TextView's getText() return to ensure they are equal.

Our final test looks like this:

@Test
public void shouldHaveOneKey() throws Exception
{
    TextView key1 = (TextView) buttonFragment.getView().findViewById( R.id.key1 );
    assertViewIsVisible( key1 );
    assertThat( key1.getText().toString(),
                equalTo( ResourceLocator.getString( R.string.key1 ) ) );
}

Add all the buttons & commit

Add each number and operator key in turn and make sure the tests pass along the way. After you're done with the buttons, commit.

Make it pretty

Let's replace our parent LinearLayout with a RelativeLayout so that we can define the position of the buttons relative to the other buttons.

Please refer to the screenshot of the example project to determine where each button should be positioned.

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center">

    <!--1-->
    <Button
        android:id="@+id/key1"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:layout_margin="5dp"
        android:text="@string/key1"/>

    <!--2-->
    <Button
        android:id="@+id/key2"
        android:layout_toRightOf="@id/key1"
        android:layout_alignBaseline="@id/key1"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:layout_margin="5dp"
        android:text="@string/key2"/>

    <!--3-->
    <Button
        android:id="@+id/key3"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:layout_margin="5dp"
        android:layout_toRightOf="@id/key2"
        android:layout_alignBaseline="@id/key2"
        android:text="@string/key3"/>

    <!--4-->
    <Button
        android:id="@+id/key4"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:layout_margin="5dp"
        android:layout_below="@id/key1"
        android:text="@string/key4"/>
        ...
</RelativeLayout>

Note: There are many ways this view could be laid out. RelativeLayout isn't the most intuitive choice, but it is quite useful and mastery of it early in your Android career will lead to great things.