Android:Exercises Your own classes

From Juneday education
Jump to: navigation, search

Work in progress

Remove this section when the page is ready...

Create a small app with a ListView

Create a new Android app with:

  • a LinearLayout
  • an ArrayAdapter and ListView to display Strings
  • Add some Strings to a List of Strings

Here's a example picture:

ListView with String


Suggested solution

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

Layout (res/layout/activity_main.xml):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="se.juneday.examples.studentlist.MainActivity">


    <ListView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/student_list">
    </ListView>
</LinearLayout>

Java code (MainActivity.java):

package se.juneday.examples.studentlist;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private ListAdapter adapter;
    private List<String> students;


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

        createFakeStudentList();

        // Lookup ListView
        ListView listView = (ListView) findViewById(R.id.student_list);

        // Create Adapter
        adapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1,
                students);

        // Set listView's adapter to the new adapter
        listView.setAdapter(adapter);
    }

    private void createFakeStudentList() {
        students = new ArrayList<>();
        students.add("Ada");
        students.add("Burt");
        students.add("Cecilia");
        students.add("Dude");
        students.add("Emily");
        students.add("Federico");
        students.add("Gertrude");
        students.add("Hans");
        students.add("Ingrid");
        students.add("Jason");
        students.add("Kate");
        students.add("Leadbelly");
        students.add("Monica");
        students.add("Nico");
        students.add("Olivia");
        students.add("Peter");
        students.add("Q");
    }

}

Our first class

Add a class Student with the following instance variables:

  • String familyName
  • String givenName


Add a constructor which initializes the instance variables by using parameters passed to the constructors.

Note: use the same package as your other classes.

.... One more note: don't add a toString() method now;).

Suggested solution

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

Java code (Student.java):

package se.juneday.examples.studentlist;

public class Student {

    private String givenName;
    private String familyName;

    public Student(String givenName, String familyName) {
        this.givenName = givenName;
        this.familyName = familyName;
    }
}

Create one Student instance

In your Activity's onCreate method:

  • create a new Student instance (object)
  • add a TextView and set the Student object as text in the TextView

Note: you need to make sure both the TextView and the ListView can be seen.

Run your app. What text is seen in your TextView.


Suggested solution

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

Layout (res/layout/activity_main.xml):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="se.juneday.examples.studentlist.MainActivity">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="20px"
        android:id="@+id/student_name"/>

    <ListView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/student_list">
    </ListView>



</LinearLayout>

Java code (MainActivity.java):

package se.juneday.examples.studentlist;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private ListAdapter adapter;
    private List<String> students;


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

        createFakeStudentList();

        // Lookup ListView
        ListView listView = (ListView) findViewById(R.id.student_list);

        // Create Adapter
        adapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1,
                students);

        // Set listView's adapter to the new adapter
        listView.setAdapter(adapter);


        ((TextView)findViewById(R.id.student_name)).setText(new Student("Ada", "Lovelace").toString());
    }

    private void createFakeStudentList() {
        students = new ArrayList<>();
        students.add("Ada");
        students.add("Burt");
        students.add("Cecilia");
        students.add("Dude");
        students.add("Emily");
        students.add("Federico");
        students.add("Gertrude");
        students.add("Hans");
        students.add("Ingrid");
        students.add("Jason");
        students.add("Kate");
        students.add("Leadbelly");
        students.add("Monica");
        students.add("Nico");
        students.add("Olivia");
        students.add("Peter");
        students.add("Q");
    }

}

The text presenting the Student looks kind of bad: se.juneday.examples.studentlist.Student|46259f

Add a toString method

Add a toString method to your Student class.

Run your app. What text is seen in your TextView.


Suggested solution

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

Java code (Student.java):

    @Override
    public String toString() {
        return givenName + " " + familyName;
    }

The text presenting the Student looks better now: Ada Lovelace


Remove the TextView

Remove the TextView from the layout (xml) as well as the activity (Java). We asked you to add the TextView to see the need of a toString() method in Student.

Create and present a bunch of Members

Create a method that creates some fake Students (in a List<Student>). In a real app we would most likely get the List of Students from either a database or via some network, but in this app we want to focus on presenting data in a ListView so let's create local faked Students. The students shall be displayed in the ListView.

Suggested solution

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

Layout (activity_main.xml):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="se.juneday.examples.studentlist.MainActivity">

    <ListView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/student_list">
    </ListView>



</LinearLayout>

Java code (MainActivity.java):

package se.juneday.examples.studentlist;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private ListAdapter adapter;
    private List<Student> students;


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

        createFakeStudentList();

        // Lookup ListView
        ListView listView = (ListView) findViewById(R.id.student_list);

        // Create Adapter
        adapter = new ArrayAdapter<Student>(this,
                android.R.layout.simple_list_item_1,
                students);

        // Set listView's adapter to the new adapter
        listView.setAdapter(adapter);

    }

    private void createFakeStudentList() {
        students = new ArrayList<>();
        students.add(new Student("Ada", "Lovelace"));
        students.add(new Student("Burt", "Lovelace"));
        students.add(new Student("Cecilia", "Lovelace"));
        students.add(new Student("Dude", "Lovelace"));
        students.add(new Student("Emily", "Lovelace"));
        students.add(new Student("Federico", "Lovelace"));
        students.add(new Student("Gertrude", "Lovelace"));
        students.add(new Student("Hans", "Lovelace"));
        students.add(new Student("Ingrid", "Lovelace"));
        students.add(new Student("Jason", "Lovelace"));
        students.add(new Student("Kate", "Lovelace"));
        students.add(new Student("Leadbelly", "Lovelace"));
        students.add(new Student("Monica", "Lovelace"));
        students.add(new Student("Nico", "Lovelace"));
        students.add(new Student("Olivia", "Lovelace"));
        students.add(new Student("Peter", "Lovelace"));
        students.add(new Student("Q", "Lovelace"));
    }
}

Add a Toast when clicking on a Student

When clicking on a Student in the list of Students a Toast shall be displayed. The Toast shall contain the name of the Student.

Suggested solution

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

Add the following to the onCreate method in (MainActivity.java):

        listView.setOnItemClickListener(new ListView.OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent,
                                    final View view,
                                    int position /*The position of the view in the adapter.*/,
                                    long id /* The row id of the item that was clicked */) {
                Log.d(LOG_TAG, "Student clicked, pos:" + position + " id: " + id);

                Toast toast = Toast.makeText(getApplicationContext(),
                        students.get((int)id).toString(),
                        Toast.LENGTH_SHORT);
                toast.show();

            }
        });


Create a context menu for each Student

The menu shall present the user with the following options:

  • copy Student (which shall add a copy the Student to the list of Students)
  • remove Student (which shall remove the student from the list of Students)


Hint

Expand using link to the right to see a hint.

You need to:

onContextItemSelected]

Suggested solution

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

MainActivity.java:

package se.juneday.examples.studentlist;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.ContextMenu;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private static final String LOG_TAG = MainActivity.class.getSimpleName() ;
    private ListAdapter adapter;
    private List<Student> students;

    private static final int MENU_ENTRY_DELETE = 0 ;
    private static final int MENU_ENTRY_DUPLICATE = 1 ;

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

        createFakeStudentList();

        // Lookup ListView
        ListView listView = (ListView) findViewById(R.id.student_list);

        // Create Adapter
        adapter = new ArrayAdapter<Student>(this,
                android.R.layout.simple_list_item_1,
                students);

        // Set listView's adapter to the new adapter
        listView.setAdapter(adapter);

        listView.setOnItemClickListener(new ListView.OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent,
                                    final View view,
                                    int position /*The position of the view in the adapter.*/,
                                    long id /* The row id of the item that was clicked */) {
                Log.d(LOG_TAG, "Student clicked, pos:" + position + " id: " + id);

                Toast toast = Toast.makeText(getApplicationContext(),
                        students.get((int)id).toString(),
                        Toast.LENGTH_SHORT);
                toast.show();

            }
        });

        registerForContextMenu(listView);

    }

    @Override
    public boolean onContextItemSelected(MenuItem item) {
        // get extra information set by the View that added this menu item
        AdapterView.AdapterContextMenuInfo info =
                (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();

        Log.d(LOG_TAG, " itemId: " + item.getItemId());
        Log.d(LOG_TAG, " title:  " + item.getTitle());
        switch (item.getItemId()) {
            case MENU_ENTRY_DUPLICATE:
                Log.d(LOG_TAG, " student to duplicate: " + students.get(info.position));
                students.add(students.get(info.position));
                break;
            case MENU_ENTRY_DELETE:
                Log.d(LOG_TAG, " student to delete: " + students.get(info.position));
                students.remove(info.position);
                break;
            default:
                Log.d(LOG_TAG, " unknown action for student: " + students.get(info.position));
                break;
        }
        return true;
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
        ListView listView = (ListView) v;
        AdapterView.AdapterContextMenuInfo acMenuInfo = (AdapterView.AdapterContextMenuInfo) menuInfo;
        String student = listView.getItemAtPosition(acMenuInfo.position).toString();
        menu.setHeaderTitle("Manage " + student);
        menu.add(Menu.NONE, MENU_ENTRY_DELETE, Menu.NONE, "Delete");
        menu.add(Menu.NONE, MENU_ENTRY_DUPLICATE, Menu.NONE, "Duplicate");
    }

    private void createFakeStudentList() {
        students = new ArrayList<>();
        students.add(new Student("Ada", "Lovelace"));
        students.add(new Student("Burt", "Lovelace"));
        students.add(new Student("Cecilia", "Lovelace"));
        students.add(new Student("Dude", "Lovelace"));
        students.add(new Student("Emily", "Lovelace"));
        students.add(new Student("Federico", "Lovelace"));
        students.add(new Student("Gertrude", "Lovelace"));
        students.add(new Student("Hans", "Lovelace"));
        students.add(new Student("Ingrid", "Lovelace"));
        students.add(new Student("Jason", "Lovelace"));
        students.add(new Student("Kate", "Lovelace"));
        students.add(new Student("Leadbelly", "Lovelace"));
        students.add(new Student("Monica", "Lovelace"));
        students.add(new Student("Nico", "Lovelace"));
        students.add(new Student("Olivia", "Lovelace"));
        students.add(new Student("Peter", "Lovelace"));
        students.add(new Student("Q", "Lovelace"));
    }

}


Make sure your ListView is updated

If you tried (please do!) to delete a Student in the previous exercise the app most likely did not crash, but the Student was still present in the list. When trying again to delete the student the app will (most likely) crash since we can't remove a Student (which can still be seen in the ListView) which is not part of the Student List. So we need to update the ListView to present the actual list. This is the task for this exercise.

Note: when duplicating a Student, the new Student will appear at the end of the ListView.

Hint

Expand using link to the right to see a hint.

You need to invoke the method invalidateViews

Suggested solution

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

Adjust the code in onContextItemSelected method in (MainActivity.java) to:

    @Override
    public boolean onContextItemSelected(MenuItem item) {
        // get extra information set by the View that added this menu item
        AdapterView.AdapterContextMenuInfo info =
                (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();

        Log.d(LOG_TAG, " itemId: " + item.getItemId());
        Log.d(LOG_TAG, " title:  " + item.getTitle());
        switch (item.getItemId()) {
            case MENU_ENTRY_DUPLICATE:
                Log.d(LOG_TAG, " student to duplicate: " + students.get(info.position));
                students.add(students.get(info.position));
                break;
            case MENU_ENTRY_DELETE:
                Log.d(LOG_TAG, " student to delete: " + students.get(info.position));
                students.remove(info.position);
                break;
            default:
                Log.d(LOG_TAG, " unknown action for student: " + students.get(info.position));
                break;
        }
        ((ListView)findViewById(R.id.student_list)).invalidateViews();
        return true;
    }


Links

Source code available at github.com: StudentList

Books this chapter is a part of

Android - the practical way

Book TOC | previous chapter | next chapter