Residence List Deletion & ViewPager

We introduce a facility to select and delete a subset of residences in the list view. The selected items need not be contiguous. The Android MultiChoiceModeListener interface is key to the implementation of this feature.

Preview

Figure 1: Long press to engage contextual menu to delete selection from list

Resources (Contextual Menu)

Continue building the MyRent app that you developed in the previous lab.

This string resource is required:

  <string name="delete_residence">Delete Residence</string>

Add a new context menu resource.

Filename: res/menu/residence_list_context.xml

<menu
  xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/menu_item_delete_residence"
    android:icon="@android:drawable/ic_menu_delete"
    android:title="@string/delete_residence" />
</menu>

We would like the selected residences to appear highlighted for ease of identification.

  • Create a new folder (directory) in res named drawable.

Add the following xml file to drawable:

Filename: res/drawable/background_activated.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
  <item
    android:state_activated="true"
    android:drawable="@android:color/darker_gray"
    />
</selector>

Activate the background_activated state by adding the following attribute to res/layout/list_item_residence.xml.

  • Failure to introduce this line of code will result in selected residence in the list remaining highlighted only as long as the mouse button is pressed.
    android:background="@drawable/background_activated"

Here is the complete file:

Filename: list_item_residence.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/background_activated"
    android:orientation="vertical">

    <CheckBox
        android:id="@+id/residence_list_item_isrented"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:layout_alignParentRight="true"
        android:enabled="false"
        android:focusable="false"
        android:padding="4dp"
         />

    <TextView
        android:id="@+id/residence_list_item_geolocation"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_toLeftOf="@id/residence_list_item_isrented"
        android:textStyle="bold"
        android:paddingLeft="4dp"
        android:paddingRight="4dp"
        />

    <TextView
        android:id="@+id/residence_list_item_dateTextView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/residence_list_item_geolocation"
        android:layout_toLeftOf="@id/residence_list_item_isrented"
        android:paddingLeft="4dp"
        android:paddingRight="4dp"
        android:paddingTop="4dp"/>

</RelativeLayout>

Implement step 3 before attempting to launch the contextual action bar.

Press and hold trash can to display menu label

ResidenceListFragment

Add import statements:

import android.widget.AbsListView;
import android.view.ActionMode;

Change class signature by implementing MultiChoiceModeListener:

public class ResidenceListFragment extends ListFragment implements OnItemClickListener, AbsListView.MultiChoiceModeListener

Add a ListView field:

private ListView listView;

In onCreateView initialize the listView and set listener:

    listView = (ListView) v.findViewById(android.R.id.list);
    listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
    listView.setMultiChoiceModeListener(this);

Implement MultiChoiceModeListener methods:

  /* ************ MultiChoiceModeListener methods (begin) *********** */
  @Override
  public boolean onCreateActionMode(ActionMode actionMode, Menu menu)
  {
    MenuInflater inflater = actionMode.getMenuInflater();
    inflater.inflate(R.menu.residence_list_context, menu);
    return true;
  }

  @Override
  public boolean onPrepareActionMode(ActionMode actionMode, Menu menu)
  {
    return false;
  }

  @Override
  public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem)
  {
    switch (menuItem.getItemId())
    {
    case R.id.menu_item_delete_residence:
      deleteResidence(actionMode);
      return true;
    default:
      return false;
    }

  }

  private void deleteResidence(ActionMode actionMode)
  {
    for (int i = adapter.getCount() - 1; i >= 0; i--)
    {
      if (listView.isItemChecked(i))
      {
        portfolio.deleteResidence(adapter.getItem(i));
      }
    }
    actionMode.finish();
    adapter.notifyDataSetChanged();
  }

  @Override
  public void onDestroyActionMode(ActionMode actionMode)
  {
  }

  @Override
  public void onItemCheckedStateChanged(ActionMode actionMode, int position, long id, boolean checked)
  {
  }

  /* ************ MultiChoiceModeListener methods (end) *********** */

Portfolio requires a method to delete a residence:

  public void deleteResidence(Residence residence)
  {
    residences.remove(residence);
    saveResidences();
  }

Test your work by creating a number of residences and exercising a range of deletion options, for example:

  • create a single residence and delete it
  • create three residences and delete the first and last
  • add some more residences and delete all.

The application at the end of this lab is available for reference here: myrent-08