File IO & Menu Up Navigation
We continue to evolve navigation support in the app, providing an 'up' button in the action bar to allow navigation from the ResidenceActivity to the ResidenceListActivity.
Up Button
All screens should offer a navigation route to their parent screens by pressing on the Up button located in the action bar as shown, for example, here in Figure 1.
Pressing the Up button should route one to the logical parent screen. The parent screen is declared in the manifest file.
In the case of MyRent, a call to setDisplayHomeAsUpEnabled() in the ResidenceFragment facilitates switching to the ResidenceListFragment screen when the Up button is pressed.
The following steps describe the process in detail.
IntentHelper
In order to support enhanced navigation, we define an additional Helper method in the IntentHelper class:
public static void navigateUp(Activity parent)
{
Intent upIntent = NavUtils.getParentActivityIntent(parent);
NavUtils.navigateUpTo(parent, upIntent);
}
Add an import statement for NavUtils:
import android.support.v4.app.NavUtils;
Here, for reference purposes, is the complete class:
package org.wit.android.helpers;
import java.io.Serializable;
import android.app.Activity;
import android.content.Intent;
import android.support.v4.app.NavUtils;
public class IntentHelper
{
public static void startActivity (Activity parent, Class classname)
{
Intent intent = new Intent(parent, classname);
parent.startActivity(intent);
}
public static void startActivityWithData (Activity parent, Class classname, String extraID, Serializable extraData)
{
Intent intent = new Intent(parent, classname);
intent.putExtra(extraID, extraData);
parent.startActivity(intent);
}
public static void startActivityWithDataForResult (Activity parent, Class classname, String extraID, Serializable extraData, int idForResult)
{
Intent intent = new Intent(parent, classname);
intent.putExtra(extraID, extraData);
parent.startActivityForResult(intent, idForResult);
}
public static void navigateUp(Activity parent)
{
Intent upIntent = NavUtils.getParentActivityIntent(parent);
NavUtils.navigateUpTo(parent, upIntent);
}
}
ResidenceActivity
New we can make use of the helper we just introduced. We wish to support the 'up' style navigation:
First introduce the helper method into ResidenceActivity:
import static org.wit.android.helpers.IntentHelper.navigateUp;
Add the statement:
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
to onCreate following setContentView(...) as indicated in the following code extract:
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_residence);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
...
}
Now we override the onOptionsItemSelected method:
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case android.R.id.home: navigateUp(this);
return true;
}
return super.onOptionsItemSelected(item);
}
This import statement is required:
import android.view.MenuItem;
For naming consistency we have changed the layout name from activity_myrent to activity_residence.
- Use the menu refactor command to change the name of the layout in res/layout.
Try this now - does it work as in Figure 1 above. Not Yet! - we need one more step...
Full class to this point for reference purposes:
package org.wit.myrent.activities;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.MenuItem;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.DatePicker;
import android.widget.EditText;
import org.wit.myrent.R;
import org.wit.myrent.app.MyRentApp;
import org.wit.myrent.models.Portfolio;
import org.wit.myrent.models.Residence;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import android.app.DatePickerDialog;
import android.view.View;
import static org.wit.android.helpers.IntentHelper.navigateUp;
public class ResidenceActivity extends AppCompatActivity implements TextWatcher,
CompoundButton.OnCheckedChangeListener,
View.OnClickListener,
DatePickerDialog.OnDateSetListener
{
private EditText geolocation;
private Residence residence;
private CheckBox rented;
private Button dateButton;
private Portfolio portfolio;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_residence);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
geolocation = (EditText) findViewById(R.id.geolocation);
residence = new Residence();
// Register a TextWatcher in the EditText geolocation object
geolocation.addTextChangedListener(this);
dateButton = (Button) findViewById(R.id.registration_date);
dateButton .setOnClickListener(this);
rented = (CheckBox) findViewById(R.id.isrented);
MyRentApp app = (MyRentApp) getApplication();
portfolio = app.portfolio;
Long resId = (Long) getIntent().getExtras().getSerializable("RESIDENCE_ID");
residence = portfolio.getResidence(resId);
if (residence != null) {
updateControls(residence);
}
}
public void updateControls(Residence residence) {
geolocation.setText(residence.geolocation);
rented.setOnCheckedChangeListener(this);
dateButton.setText(residence.getDateString());
}
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void afterTextChanged(Editable editable) {
residence.setGeolocation(editable.toString());
}
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
Log.i(this.getClass().getSimpleName(), "rented Checked");
residence.rented = isChecked;
}
@Override
public void onClick(View view) {
switch (view.getId())
{
case R.id.registration_date : Calendar c = Calendar.getInstance();
DatePickerDialog dpd = new DatePickerDialog (this, this, c.get(Calendar.YEAR), c.get(Calendar.MONTH), c.get(Calendar.DAY_OF_MONTH));
dpd.show();
break;
}
}
@Override
public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
Date date = new GregorianCalendar(year, monthOfYear, dayOfMonth).getTime();
residence.date = date.getTime();
dateButton.setText(residence.getDateString());
}
@Override
public void onPause()
{
super.onPause();
portfolio.saveResidences();
}
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case android.R.id.home: navigateUp(this);
return true;
}
return super.onOptionsItemSelected(item);
}
}
AndroidManifest
The final piece of the puzzle is the layout in the manifest the parent/child relationship between the ResidenceListActivity and ResidenceActivity classes:
<activity
android:name=".activities.ResidenceActivity"
android:label="@string/app_name" >
<meta-data android:name="android.support.PARENT_ACTIVITY"
android:value=".activities.ResidenceListActivity"/>
</activity>
In the above we are establishing this relationship. The navigation mechanism should work as expected now.
Here is the complete manifest file for reference purposes:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.wit.myrent">
<application
android:name=".app.MyRentApp"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity
android:name=".activities.ResidenceListActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".activities.ResidenceActivity"
android:label="@string/app_name">
<meta-data android:name="android.support.PARENT_ACTIVITY"
android:value=".activities.ResidenceListActivity"/>
</activity>
</application>
</manifest>
Test the back button as indicated in Figure 1.
The application at the end of this lab is available for reference here: myrent-05