Presentation is loading. Please wait.

Presentation is loading. Please wait.

several communicating screens

Similar presentations


Presentation on theme: "several communicating screens"— Presentation transcript:

1 several communicating screens
David Sutton

2 What we will cover in this lecture
ArrayLists (for the benefit of those who have not taken Data Structures). Intents and Multiple Screens Adapter Views

3 this week’s task In week 2 we created an application that selected a random scale for a students to practice. However it was selecting the scale from a predetermined list hard coded as an array in its one and only Activity This week we will develop the application so that a separate screen (Activity) is displayed in which the user can select the set of scales (s)he is working on.

4 design of the application
Click here to return to main screen Choose a scale from list to be practiced Shuffle the list To add a scale, write it here, and then click on the D-Pad Scale to be practised Launches the second screen List of scales to practice. Clicking on a scale deletes it from list

5 problems we have to solve
We need a data structure to which we can easily add data and from which we can easily remove data. We need to make on screen launch another. We need to transfer data from one screen to another, We need to display lists of data (the scales) whose content can change as we run the application.

6 Storing data Arrays are of fixed size and so are not ideal for representing lists whose content and size can change as we run an application. Fortunately the Java API contains many classes that represents lists which can dynamically change their size. The list implementation that we will use is called the ArrayList.

7 Lists Lists are flexible-length data structures where the data is ordered in a linear fashion. Each element of the list holds some data.

8 Arrays vs Lists Lists can grow or shrink in length as a program runs.
Data structures that can change in size whilst a program runs are known as dynamic data structures Arrays are fixed-length: once memory is assigned, the length of the array remains fixed. Data structures that are fixed-size are known as static data structures.

9 ArrayList The Java implementation of lists we will look at is called ArrayList. An ArrayList is flexible in length, like a list, but also offers some of the direct-access advantages of an array. For further reading on the ArrayList class, see Chapter 4 of Horstmann: “Java Concepts” (5th edition) Chapter 7.2 of Hubbard: “Schaum's Outline of Data Structures with Java” (2nd edition)

10 Declaring ArrayList objects
When using ArrayList s, at the top of the class, we need to import the Java utilities package (which is where the ArrayList class lives): import java.util.*; When declaring an ArrayList object, we have to say what type of objects we want in our ArrayList, e.g. ArrayList<String> myStrings; ArrayList<Balloon> myBalloons; type of the elements in the ArrayList type variable name

11 ArrayList<String> myStrings = new ArrayList<String>();
As with other variables, it is also possible to declare an ArrayList object and initialise it in the same statement, e.g. ArrayList<String> myStrings = new ArrayList<String>(); ArrayList<Balloon> myBalloons = new ArrayList<Balloon>(); initialises to an empty list with no elements

12 Useful ArrayList methods
There are many methods, but some of the most useful are add(E e) - appends the given element to the end of the list. get(int index) - returns the element at the given position in this list. clear() - removes all of the elements from this list. remove(int index)           Removes the element at the specified position in this list. size()           Returns the number of elements in this list. Full details can be found at the Java API documentation Here, E is just referring to the type of elements in the ArrayList

13 main activity layout (slide 1)
We will use a vertical LinearLayout for this, but a RelativeLayout would work too. <LinearLayout xmlns:android= " xmlns:tools=" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > ....

14 main activity layout (slide 2)
We learnt how to add buttons and externalise strings in earlier lectures. <Button android:layout_width="match_parent" android:layout_height="wrap_content" /> />

15 main activity layout (slide 3)
A “hint” is displayed in a text box before any real text is entered. <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" tools:context=".ScalePractice" /> <Button android:layout_width="match_parent" /> </LinearLayout>

16 What we should see at this point
Running the application should display a main activity with the widgets that we added to the layout. But there will be no response from the buttons yet.

17 Storing the list of scales
Lines we have added are in bold import java.util.ArrayList; public class ScalePractice extends Activity { private final String[] defaultKeys = {"C","D","E","F Sharp", “B Flat","A Flat"}; private ArrayList<String> scales = new ArrayList<String>(); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_scale_practice); setDefaultScales(); } private void setDefaultScales() { for (int i=0;i<defaultKeys.length;i++) { scales.add(defaultKeys[i] + " Major"); We will store the list of scales in this ArrayList Method to set up initial content of ArrayList

18 making the choose scale button respond
public class ScalePractice extends Activity ... int scaleIdx=0; Button chooseScaleButton; TextView practiceScale; @Override public void onCreate(Bundle savedInstanceState) { .... chooseScaleButton = (Button) findViewById(R.id.choose_scales_button); practiceScale = (TextView) findViewById(R.id.practice_scale_text); chooseScaleButton.setOnClickListener(new OnClickListener() { public void onClick(View view) { if (scaleIdx>=scales.size()) {scaleIdx=0;} practiceScale.setText(scales.get(scaleIdx)); scaleIdx++; } }); We will get an error here, if the ArrayList is empty. We will fix that later!

19 What we should see at this point
Clicking on the “Choose Scale” button causes us to cycle through the scales, but in a predetermined order. There is no response from the other buttons yet.

20 making the shuffle button respond
public class ScalePractice extends Activity { .... private ArrayList<String> scales = new ArrayList<String>(); int scaleIdx=0; ... private Button shuffleButton; @Override public void onCreate(Bundle savedInstanceState) { shuffleButton = (Button) findViewById(R.id.shuffle_button); shuffleButton.setOnClickListener( new OnClickListener() { public void onClick(View v) { Collections.shuffle(scales); scaleIdx = 0; } }); Collections is a class in the java.util package containing a set of static methods that do useful things with ArrayLists

21 What we should see at this point
Clicking on the “Choose Scale” button causes us to cycle through the scales. Clicking on the “Shuffle” button changes the order in which scales are presented. There is no response from the “Set Scales” button yet.

22 intents and activities
Android Activities are “loosely coupled”. Activities do not normally access each others methods or fields (not even public methods). Intent data extras Intent data extras One activity invokes another by sending a message called an Intent. The Intent may include information that will be used by the invoked Activity

23 Explicit and implicit intents
There are two types of Intent: Explicit Intents specify that some named Activity should be launched. Implicit Intents specify that some particular action should be performed, for example dialling a specified number. It is up to Android to find an Activity capable of performing that action. In this case, we know what Activity we want to invoke, so we will use an explicit Intent. But first we need to create a skeleton implementation of the Activity we wish to invoke...

24 SCale Set Activity layout
You can create a new XML Layout file by right clicking on the “res/layout” folder and select “New” and then “Android XML File”. A ListView can be dragged in from the “Composite” section of the palette. When we write the code for this Activity we will arrange for the ListView to be populated by Strings drawn from an ArrayList

25 SCale Set Activity layout (SLIDE 1)
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android =" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <Button android:layout_height="wrap_content" />

26 SCale Set Activity layout (SLIDE 2)
<EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:ems="10" > <requestFocus /> </EditText> <ListView android:layout_height="wrap_content" > </ListView> </LinearLayout>

27 Scale set activity code
package uk.ac.brookes.scalesv2; import android.app.Activity; import android.os.Bundle; public class ScaleSetActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.scale_set_layout); } You can create a new class by right clicking on a package node in the package explorer and selecting “New” then “Class”. Inflate the layout file for the scale set activity

28 starting an activity To start an Activity we must
Create an Intent object that specifies the Activity to be started (or the action to be performed in the case of an implicit Intent). Pass that intent to the startActivity or startActivityForResult method of the Activity class. The startActivityForResult method is used when you expect the invoked Activity to return data to the invoking Activity. We will want to do that eventually, but for the time being we will just use startActivity method. N.B this code should be placed in the main Activity, not in the Activity we wish to start. Intent intent = new Intent( getApplicationContext(), ScaleSetActivity.class); startActivity(intent); This is the Activity we wish to start.

29 starting the scale set activity
public class ScalePractice extends Activity { .... private Button setScalesButton; @Override public void onCreate(Bundle savedInstanceState) { ... setScalesButton = (Button) findViewById(R.id.set_scales_button); setScalesButton.setOnClickListener(new OnClickListener() { public void onClick(View v) { Intent intent = new Intent( getApplicationContext(), ScaleSetActivity.class); startActivity(intent); } });

30 The android manifest In order for our new Activity to be invoked, we will need to add it to the Android manifest. The manifest is contained in a file called AndroidManifest.xml and describes essential information about the application such as its permissions and the Activities that it contains. You can find the AndroidManifest file towards the bottom of the Package Explorer panel.

31 editing the manifest There is a custom editor for the manifest file. To add a new Activity to the manifest, go to the Application tab, click on Add... and then specify the name of the Scale Set Activity you just created (that is to say the name of the class). You can also create a label for the Activity that will appear in the title bar when it starts.

32 The android manifest (ONLY THE APPLICATION NODE SHOWN HERE)
> <activity android:name=".ScalePractice" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name="ScaleSetActivity" </application>

33 What we should see at this point
Clicking on the Set Scales button should now launch the Set Scales Activity. However clicking on the “Finish” button of that Activity does nothing.

34 returning control from the scale set activity
public class ScaleSetActivity extends Activity { private Button finishButton; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.scale_set_layout); finishButton = (Button) findViewById(R.id.finish_button); finishButton.setOnClickListener(new OnClickListener() { public void onClick(View view) { finish(); } }); To return control to the invoking Activity we simply call the Activity’s finish method.

35 What we should see at this point
Clicking on the Set Scales button should now launch the Set Scales Activity. Clicking on the Finish button should return control to the main Activity.

36 exchanging information between activities.
There are several ways in which Activities can exchange information. The easiest way is to add data to the “extras” bundle that is attached to an intent. This isn’t actually the best solution, but we shall adopt it for the time being because it is relatively simple. Intent data extras

37 exchanging information between activities
Here are the modifications that we need to make in order for the list of scales to be passed between the main activity and the scale set activity. The list of scales must be attached as an extra to the Intent sent by the main activity. We must use the startActivityForResult method, because we now expect to get information back from the scale set Activity The Scale Set Activity must retrieve the information from the Intent The Scale Set Activity must pass an Intent back to the main Activity, and must attach the list of scales as an extra. The main Activity class must override the onActivityResult method in order to retrieve the Intent created by the scale set Activity.

38 sending information to the scale set activity
public class ScalePractice extends Activity { private ArrayList<String> scales = new ArrayList<String>(); private final int SCALE_SET_REQUEST=1; ... @Override public void onCreate(Bundle savedInstanceState) { setScalesButton = (Button) findViewById(R.id.set_scales_button); setScalesButton.setOnClickListener(new OnClickListener() { public void onClick(View v) { Intent intent = new Intent( getApplicationContext(), ScaleSetActivity.class); intent.putStringArrayListExtra("Scales", scales); startActivityForResult(intent, SCALE_SET_REQUEST); } }); This value will be returned by Scale Set Activity. We are now using startActivityForResult

39 Retrieving information in the scale set activity
public class ScaleSetActivity extends Activity { private ArrayList<String> scales; private Button finishButton; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.scale_set_layout); Intent intent = getIntent(); scales = intent.getStringArrayListExtra("Scales");

40 returning information from the scale set activity
public class ScaleSetActivity extends Activity { private ArrayList<String> scales; private Button finishButton; @Override public void onCreate(Bundle savedInstanceState) { ... Intent intent = getIntent(); scales = intent.getStringArrayListExtra("Scales"); finishButton.setOnClickListener(new OnClickListener() { public void onClick(View view) { Intent result = new Intent(); result.putStringArrayListExtra("Scales", scales); setResult(RESULT_OK, result); finish(); } });

41 Retrieving information in the main activity
public class ScalePractice extends Activity { private ArrayList<String> scales = new ArrayList<String>(); private final int SCALE_SET_REQUEST=1; ... @Override public void onActivityResult(int requestCode, int resultCode, Intent data){ if (resultCode == RESULT_OK) { if (requestCode == SCALE_SET_REQUEST) { scales = data.getStringArrayListExtra("Scales"); scaleIdx = 0; }

42 adapters and adapter views
We want the Scale Set Activity’s ListVire to display a list of the currently chosen scales. The ListView is an example of an Adapter View. These are views that can be dynamically bound to a data structure such as an ArrayList. In order to link the ListView to the scales ArrayList, we need to supply an Adapter. We will use a very simple kind of adapter known as an ArrayAdapter

43 setting up the adapter public class ScaleSetActivity extends Activity { private ArrayList<String> scales; private ArrayAdapter<String> scaleAdapter; private ListView scaleList; @Override public void onCreate(Bundle savedInstanceState) { ... scaleAdapter = new ArrayAdapter<String> (this, android.R.layout.simple_list_item_1, scales); scaleList = (ListView) findViewById(R.id.scale_list_view); scaleList.setAdapter(scaleAdapter); .... } The adapter binds our ListView to the scales ArrayList. Each element of that ArrayList appears as a separate element in the ListView

44 what we should see now When the Set Scales Activity is launched, we should now see a list of the currently selected scales.

45 other adapter views In addition to the ListView the Android API includes a GridView that dynamically binds to a 2D data structure.

46 adding scales We now want to add code so that if the user enters a Scale into the “Scale to Add” EditText and then clicks on the D Pad, the scale will be added to our list In order to do this we must attach an OnKeyListener to the EditText

47 adding scales public class ScaleSetActivity extends Activity { ...
@Override public void onCreate(Bundle savedInstanceState) { enterScaleEdit = (EditText) findViewById(R.id.enter_scale_edit); enterScaleEdit.setOnKeyListener(new OnKeyListener() { public boolean onKey(View view, int keyCode, KeyEvent event) { boolean result = false; if (event.getAction() == KeyEvent.ACTION_DOWN) if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) { scales.add(0, enterScaleEdit.getText().toString()); scaleAdapter.notifyDataSetChanged(); enterScaleEdit.setText(""); result = true; } return result; }); The result returned should be true if the listener has “consumed” the event, which means that it does not want the event to passed to any other listener

48 what we should now see If the user types some text into the “Scale to Add” box, and then clicks the D Pad this will now be added to the list. When you click on the “Scale To Add” box, a virtual keyboard appears. You may need to hit the back button to hide the keyboard. We will fix this next week.

49 deleting scales We now want to add code so that if the user clicks on a Scale it is deleted from the list. In order to do this we must attach an OnItemClickListener to the ListView

50 deleting scales public class ScaleSetActivity extends Activity { ...
private ListView scaleList; @Override public void onCreate(Bundle savedInstanceState) { scaleList.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View view, int position, long id) { scales.remove(position); scaleAdapter.notifyDataSetChanged(); } });

51 what we should now see If the user clicks on a scale it is deleted from the list. If the user clicks on the “Finish” button they return to the main Activity, but now scales are picked from the modified list.

52 summary The ArrayList class is a dynamic data structure allowing elements to be easily added and deleted. One Activity can invoke another by passing an appropriate Intent. AdapterViews display the contents of data structures as lists of grids. They dynamically update as the content of the data structures changes.


Download ppt "several communicating screens"

Similar presentations


Ads by Google