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

Android Chat Screen

Miroslav Smukov edited this page Jun 26, 2016 · 18 revisions

Chat Activity

Now that we have the Contact screen ready, it's only natural to continue with a Chat screen that we'll use to communicate with our contacts.

Creating a new Activity

We'll start by creating a basic activity using the Android Studio's wizard. If we go to File > New > Activity > Basic Activity we'll be presented with a screen similar to the one below.

Create Chat Activity

After we specify the name of the new activity, we can also specify something called a Hierarchical Parent. This will tell Android Studio to automatically provide the default implementation for the "Up" button for this activity. We are setting this value to our NavigationActivity, which means that when a users presses the "Up" or "Back" button, he'll be taken to NavigationActivity screen.

All that this feature really does is adding the below meta-data to the new activity in AndroidManifest.xml.

<meta-data
  android:name="android.support.PARENT_ACTIVITY"
  android:value="com.thesis.smukov.anative.NavigationActivity" />

Chat Activity Implementation

As I usually do with everything I need to implement for the first time, I searched the web a little bit for existing ideas and solutions on how to create the Chat Activity in Android. After going through a few resources, I got really lucky by finding the following post created by JoCodes on CodeProject. His sample code gave me a great start for this activity, and he has provided everything you might need, even the NinePatch resources for the chat bubbles.

As this application continues to grow I'll certainly make a lot of changes to the code provided in the CodeProject's post that I mentioned, but for now, I'll use a lot of the code as is. Firstly, I added the two NinePatch images (in_message_bg and out_message_bg) to my drawable folder. Then I added the ChatMessage.java, and list_item_chat_message.xml code without making any changes to them. To the ChatActivity I made minimal changes, only changing the extended class from the deprecated ActionBarActivity to the AppCompatActivity, and changing the type of sendBtn from Button to ImageButton, as I also changed the chat layout quite a bit. Below you can see the new version of the activity_chat.xml file:

Source Code

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="20dp">

    <LinearLayout
        android:id="@+id/chatControls"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true">

        <EditText
            android:id="@+id/messageEdit"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:inputType="textMultiLine"
            android:hint="@string/typeMessage"
            android:layout_weight="0.8"/>

        <ImageButton
            android:id="@+id/chatSendButton"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:src="@drawable/ic_menu_send"
            android:background="@android:color/transparent"
            android:layout_weight="0.2"/>

    </LinearLayout>

    <ListView
        android:id="@+id/messagesContainer"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentLeft="false"
        android:layout_alignParentTop="false"
        android:layout_marginBottom="20dp"
        android:layout_above="@+id/chatControls"
        android:layout_marginTop="10dp"
        android:listSelector="@android:color/transparent"
        android:transcriptMode="alwaysScroll"
        android:divider="@null" />

</RelativeLayout>

The key thing inside this new layout file is the grouping of EditText and ImageButton inside a single LinearLayout parent, which allowed me to grow the height of my button as new lines of text are added to EditText. I also used the android:layout_weight attribute to set the EditText to 80%, and the ImageButton to 20% of the full layout width.

Finally, I made some minimal changes to the ChatAdapter as I wanted my chat bubbles to be on the right, and my correspondent's on the left side. All the changes made were inside the setAlignment method, where I swapped the two drawables for chat bubbles, and switched the Gravity and RelativeLayout alignment.

NinePatch

I've used the term NinePatch a few times in the section above. Let's explain what this really is by using the official Android documentation:

A NinePatchDrawable graphic is a stretchable bitmap image, which Android will automatically resize to accommodate the contents of the View in which you have placed it as the background. An example use of a NinePatch is the backgrounds used by standard Android buttons — buttons must stretch to accommodate strings of various lengths. A NinePatch drawable is a standard PNG image that includes an extra 1-pixel-wide border. It must be saved with the extension .9.png, and saved into the res/drawable/ directory of your project.

The border is used to define the stretchable and static areas of the image. You indicate a stretchable section by drawing one (or more) 1-pixel-wide black line(s) in the left and top part of the border (the other border pixels should be fully transparent or white).

You can also define an optional drawable section of the image (effectively, the padding lines) by drawing a line on the right and bottom lines. If a View object sets the NinePatch as its background and then specifies the View's text, it will stretch itself so that all the text fits inside only the area designated by the right and bottom lines (if included). If the padding lines are not included, Android uses the left and top lines to define this drawable area.

Here is a sample NinePatch file used to define a button:

NinePatch Sample

Navigating to Chat

Now let's implement a way for our users to navigate to this Chat activity.

We implemented a BaseNavigationFragment class that is a base class for all of our fragments that should appear inside the main NavigationActivity. This BaseNavigationFragment has an abstract method called prepareFloatingActionButton() that all extending classes must implement. Inside this method we are changing the icon and the function of the FloatingActionButton inside the NavigationActivity, so that it matches the context of the displayed fragment. We are using this method to handle the navigation from Contact to Chat screen. Below you can see the implementation of this method for ContactFragment class:

Source Code

@Override
protected void prepareFloatingActionButton(){
    if(fab == null){
        fab = (FloatingActionButton) getActivity().findViewById(R.id.fab);
    }

    fab.show();
    fab.setImageDrawable(ContextCompat.getDrawable(getActivity(), R.drawable.ic_forum_black_24dp));
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent intent = new Intent(getActivity(), ChatActivity.class);
            startActivity(intent);
        }
    });
}

Enabling the Action Bar

To complete the Chat screen we will enable the Action Bar that was hidden by default by Android Studio when it generated the initial Activity classes. We will also set the title of the activity dynamically to the name of the contact that we are chatting with.

If we delete the following android:theme="@style/AppTheme.NoActionBar" line from our ChatActivity in AndroidManifest.xml the Action Bar will appear.

Now we just need to set the appropriate title for the ChatActivity. For this we'll use the setTitle(..) method that we'll add to onCreate(..) inside the ChatActivity class.

Source Code

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_chat);
    setTitle("Dr. Gregory House");//hard-coded for now
    initControls();
}

Conclusion

It took me less than 2 hours to implement all of this. I was very lucky that I found this great CodeProject post which got me started fast. However, that's the benefit of working on a pretty mature platform that is Android. There are lots of resources online, and you don't have to reinvent the wheel every time. We'll see how the Ionic2 Chat implementation will compare.

Chat Activity

References

Commits

Direct:

Related:

Clone this wiki locally