Skip to content
This repository has been archived by the owner on Mar 3, 2023. It is now read-only.

Android Contacts Screen

Miroslav Smukov edited this page Jul 9, 2016 · 11 revisions

My Contacts Screen

In this page we'll talk about the My Contacts screen, what it will represent and how to implement it.

The My Contacts screen is a standard ListActivity that you can find in almost every Android application. These are screens that mainly consist of one ListView that takes all, or at least most of the screen real estate. My Contacts page will contain the list of all of our contacts that we added through our application.

As always, for now, we are just implementing the user interface part and the minimal logic to make it all run.

ListFragment vs ListActivity

My Contacts page will be a ListFragment, which is almost as same as ListActivity. The only key difference is that a Fragment, and also ListFragment, can be hosted inside of an Activity. We already covered fragments here.

All that I will talk about here can be applied to ListActivity. The reason why I went with ListFragment for my implementation is purely due to a fact that I want to host it inside my NavigationActivity and avoid creating a separate `Activity.

Basic Implementation

Official Android documentation covers the basics pretty well in this case:

A ListFragment is a fragment that displays a list of items by binding to a data source such as an array or Cursor, and exposes event handlers when the user selects an item.

Screen Layout

ListFragment has a default layout that consists of a single list view. However, if you desire, you can customize the fragment layout by returning your own view hierarchy from onCreateView(LayoutInflater, ViewGroup, Bundle). To do this, your view hierarchy must contain a ListView object with the id @android:id/list (or list if it's in code).

Optionally, your view hierarchy can contain another view object of any type to display when the list view is empty. This "empty list" notifier must have an id android:empty. Note that when an empty view is present, the list view will be hidden when there is no data to display.

Changing the Page Title

I wanted to quickly cover here this feature that I haven't mentioned before, but it's quite useful for improving user experience. You will find all the changes that I had to made to my project in this commit.

The key takeaway is that your Activity has a setTitle(..) method, that you can use to change the title of the current page. You'll see in the screenshot below that I changed the title to "My Contacts" for this screen.

Below you can see my implementation of the layout:

Source Code

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ListView android:id="@id/android:list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:drawSelectorOnTop="false"/>

</LinearLayout>

Row Layout

You can specify the layout of individual rows in the list. You do this by specifying a layout resource in the ListAdapter object hosted by the fragment (the ListAdapter binds the ListView to the data - more on this later).

Below you can see my implementation of the row layout:

Source Code

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:paddingTop="7dp"
    android:paddingBottom="7dp">

    <include layout="@layout/profile_header"/>

    <Space
        android:layout_width="20dp"
        android:layout_height="20dp" />

    <TextView
        android:id="@+id/txtEmployment"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="@string/hint_employment"
        android:textSize="16sp"
        android:ellipsize="middle"
        />


    <TextView
        android:id="@+id/txtEducation"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:layout_gravity="center_horizontal"
        android:text="@string/hint_faculty" />

</LinearLayout>

Binding to Data

You bind the ListFragment's ListView object to data using a class that implements the ListAdapter interface. Android provides two standard list adapters: SimpleAdapter for static data (Maps), and SimpleCursorAdapter for Cursor query results.

My ListAdapter is called ContactsAdapter, and you can see the full source code for it here.

The key thing from the adapter's source code to notice, is that a getView(..) method dictates how each individual row is going to look like. Potentially, you could use the position parameter to render different views based on it, or you could use information from the model itself, like we did when we implemented Chat Screen in its ChatAdapter.

Also, we are using our custom ViewHolder class as a simple wrapper around our row view, in order to be able to easily bind to appropriate widgets inside it.

Model

The model for our ChatAdapter will be a Contact class that will hold all the necessary information about the contacts. We are going to pull from this model information to display in our rows.

I added this class to new Models folder inside the base anative package, and I plan to add here additional models over time.

The hosting fragment

Now we finally came to the actual ListFragment that is going to host the ListView.

For this I created the ContactsFragment class, that is extending the BaseNavigationListFragment, which is my own base ListFragment implementation that I'm using to store the code that is in common across all my ListFragments hosted in the NavigationActivity - I'm expecting to be at least one more BaseNavigationListFragment implementation.

Then for the users to be able to open my new screen, I changed the onNavigationItemSelected(..) method of the NavigationActivity to create the ContactsFragment object instead of ContactFragment when a user clicks on My Contacts in the navigation drawer.

Clickable Rows

The final piece of the puzzle is allowing our users to navigate to individual contact screen by clicking on a row. To do this, we'll add the OnItemClickListener to our ListView. We will do it with the following code that is executing inside onViewCreated(..) method in ContactsFragment class:

Source Code

listView = getListView();
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
   @Override
   public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
       ContactFragment contactFragment = new ContactFragment();
       contactFragment.setContact(adapter.getItem(position));

       ((NavigationActivity)getActivity()).openNewFragment(contactFragment);
   }
});

Since our Contact Screen is already implemented as a Fragment, we have to rely on our hosting NavigationActivity to show it. This why we exposed the openNewFragment(INavigationFragment) method in our NavigationActivity:

Source Code

public void openNewFragment(INavigationFragment newFragment){
   fragmentManager.beginTransaction()
       .replace(R.id.content_frame, (Fragment) newFragment)
       .commit();
}

That's it, when a user clicks on a row the appropriate Contact Screen will open.

P.S. I also did some small changes to ContactFragment by adding the setContact(Contact) method and binding that information in the UI, you can see the additional code here.

Conclusion

Since I already implemented the Chat Screen, which is also a ListActivity, I was able to apply a very similar solution in this case as well. I created this code in about 30 minutes.

Contacts List

References

Commits

Clone this wiki locally