Android:Exercises Adding views

From Juneday education
Jump to: navigation, search

Prepare

We need a cleaned up pproject. Either you create a new or clean up a previous one. The important things are:

  • your activity should have an empty LinearLayout
  • remove all methods - apart from the onCreate method.

Add a Button

How do we get a reference to a layout?

Suggested solution

Expand using link to the right to see the full content.

First of all we need to add an id to our layout. Do this in the Layout's XML file. We will call it top_layout. Our Layout file looks like this:

<?xml version="1.0" encoding="utf-8"?>
<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:id="@+id/top_layout"
    tools:context="se.juneday.throwaway.addingviews.MainActivity">
</LinearLayout>

Since the Layout now have an id (defined in the XML file) we can find the layout by using the method:

  findViewById(R.id.button);

We can use it like this:

  LinearLayout layout  = (LinearLayout) findViewById(R.id.top_layout);

How do we create a Button

Or let's put it another way. How do we create an instance of Button? Think about how you usually create objects in Java.

Suggested solution

Expand using link to the right to see the full content.

By using the constructor in Button:

  Button(Context context)

We can use it like this:

  Button b  = new Button(this); 
  b.setText("Butoni");

Add the Button to the layout

Suggested solution

Expand using link to the right to see the full content.

By using the method:

   void addView (View child)

We can use it like this:

  layout.addView(b);

Wrapping it up

Let's now put the pieces together. If you want to see a more complete view of the code we've written so far:

Expand using link to the right to see the full content.


Here's our layout:

<?xml version="1.0" encoding="utf-8"?>
<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:id="@+id/top_layout"
    tools:context="se.juneday.throwaway.addingviews.MainActivity">
</LinearLayout>

and here's our Java code:

package se.juneday.throwaway.addingviews;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Button;
import android.widget.LinearLayout;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        LinearLayout layout  = (LinearLayout) findViewById(R.id.top_layout);
        Button b  = new Button(this);
        b.setText("Butoni");
        layout.addView(b);


    }
}

Add a listener

Add code that changes the text on the Button.

Suggested solution

Expand using link to the right to see the full content.

We can do this several ways. The two recommended ways are to use either an anonymous inner class or lambda expression. We're going to show how to do this using anonymous inner class since lambda is not available on all API levels.

        b.setOnClickListener(new OnClickListener() {
                                 @Override
                                 public void onClick(View view) {
                                     ((Button) view).setText("Butoni updated using anon inner class");
                                 }
                             });

Yet another Button

Add one more Button, with the text "ok".

Suggested solution

Expand using link to the right to see the full content.

        Button b  = new Button(this);
        b.setText("Butoni");
        layout.addView(b);

Yet another Listener

Add code to update the text in first Button when the ok Button is pressed. The text shall be updated to "Ok as well".

Suggested solution

Expand using link to the right to see the full content.

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        LinearLayout layout  = (LinearLayout) findViewById(R.id.top_layout);
        Button b  = new Button(this);
        b.setText("Butoni");
        b.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                ((Button) view).setText("Butoni clicked");
            }
        });
        Button okButton  = new Button(this);
        okButton.setText("Ok");
        okButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                b.setText("Ok as well");
            }
        });
        layout.addView(b);
        layout.addView(okButton);
    }

Add a LinearLayout inside the Layout

Suggested solution

Expand using link to the right to see the full content.

        LinearLayout buttonLayout = new LinearLayout(this);
        layout.addView(buttonLayout);

Add a TextView to the new Layout

Suggested solution

Expand using link to the right to see the full content.

        LinearLayout buttonLayout = new LinearLayout(this);
        TextView tv = new TextView(this);
        layout.addView(tv);
        layout.addView(buttonLayout);

The text in the TextView shall be a string resource

Add a string resource, info_text, to use instead of the hard coded string in MainActivity.java.

Suggested solution

Expand using link to the right to see the full content.

Add a string to res/values/strings.xml:

<resources>
    <string name="app_name">AddingViews</string>
    <string name="info_text">Just some text</string>
</resources>

And here the Java code (MainActivity.java) to use the newly created string resource:

        tv.setText(R.string.info_text);

Create a Swedish (or other language) translation

Add a swedish translation to the newly created string resource (info_text).

Suggested solution

Expand using link to the right to see the full content.

Add a string to res/values-sv/strings.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">AddingViews</string>
    <string name="info_text">Bara lite text</string>
</resources>

Add an int resource, nr_buttons

Add an integer resource, nr_buttons and assign it the value 5. Use the value to set the text in the first Button to "Butoni clicked (5)" where 5 should not be hardcoded but the integer resource we just added.

Hint: Using the id R.integer.nr_buttons directly, without using the getInteger method, wil not work. But try it :)

Suggested solution

Expand using link to the right to see the full content.

Add a string to res/values/integers.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <integer name="nr_buttons">5</integer>
</resources>

Change the onClick method to:

        Button b  = new Button(this);
        b.setText("Butoni");
        b.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                ((Button) view).setText("Butoni clicked (" + getResources().getInteger(R.integer.nr_buttons) + ")");
            }
        });

Create and add nr_buttons Buttons in to the Layout

Read the integer resource nr_buttons and create that many Buttons. The Button should be placed in the Layout created dynamically in our Java code.

Here's a screenshot of the Layout

Android-AddingViews-1.png

Hint: Now we're creating rather many Views in the method onCreate so we suggest putting this code in a separate method Hint: If you can't see al the Buttons you may have to change theLayout's orientation

Suggested solution

Expand using link to the right to see the full content.

    private final static String LOG_TAG = MainActivity.class.getSimpleName();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // The code to create Views has been put in a separate method createViews
        createViews();
    }


    private void createViews() {
        int nr_buttons = getResources().getInteger(R.integer.nr_buttons);

        LinearLayout layout  = (LinearLayout) findViewById(R.id.top_layout);

        // Butoni button
        Button b  = new Button(this);
        b.setText("Butoni");
        b.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                // We could use the reference variable b in our method
                // but we stick to using view to show that the View we get
                // is the View that was clicked

                //        ((Button) view).setText("Butoni clicked (" + getResources().getInteger(R.integer.nr_buttons) + ")");
                ((Button) view).setText("Butoni clicked (" + nr_buttons + ")");
            }
        });

        // Ok button
        Button okButton  = new Button(this);
        okButton.setText("Ok");
        okButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                b.setText("Ok as well");
            }
        });

        layout.addView(b);
        layout.addView(okButton);

        LinearLayout buttonLayout = new LinearLayout(this);
        buttonLayout.setOrientation(LinearLayout.VERTICAL);
        TextView tv = new TextView(this);
        tv.setText(R.string.info_text);
        layout.addView(tv);
        layout.addView(buttonLayout);

        // Add nr_buttons Buttons to the buttonLayout
        for (int i=0; i<nr_buttons; i++) {
            Log.d(LOG_TAG, "Adding Button " + i);
            Button localButton = new Button(this);
            localButton.setText("Button " + i);
            localButton.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View view) {
                    Log.d(LOG_TAG, "Click");
                }
            });
            buttonLayout.addView(localButton);
        }
    }

Note: we have added a bit of sample code to handle the

Add a method to each Button above

Add a method to each of the Button you just created. The method shall set the text in the TextView to the text in Button that was clicked.

Suggested solution

Expand using link to the right to see the full content.

Add a string to res/values/integers.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <integer name="nr_buttons">5</integer>
</resources>

Change the onClick method for the Buttons to:

            localButton.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View view) {
                    Log.d(LOG_TAG, "Click " + ((Button) view).getText());
                    tv.setText(((Button) view).getText());
                }
            });

Chapter links

Source code

Android - the practical way

Book TOC | previous chapter | next chapter