Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Implementing Chat Bubble in ListView

I am in the process of writing a chat client on Android but I am having some issues with putting a chat bubble in my client. My chat screen consists of a ListView with a textbox and a Send button at bottom. For an outgoing message, the texts are left aligned in the ListView row. For an incoming message, the texts are right aligned in the ListView row. However, the chat bubble does not resize to the length of the incoming message texts. This issue does not happen for the left aligned outgoing message.

Here the screen shot is below.

Image

The chat message texts are stored in a database and are displayed in the ListView via a cursor adapter. The alignment of the chat texts are determined on-the-fly in the Java source code in MessageAdapter. Both chat bubbles are done using nine patch image of Android.

Below is my chat activity layout, the ListView with issue is messageHistoryList:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  android:orientation="vertical"
  android:padding="10dip" 
  android:layout_width="fill_parent"
  android:layout_height="fill_parent">

    <ListView
      android:id="@+id/messageHistoryList"
      android:layout_width="wrap_content" 
      android:layout_height="0px" 
      android:layout_weight="1"/>

    <LinearLayout 
      android:layout_width="fill_parent" 
      android:layout_height="wrap_content" >

      <EditText
        android:id="@+id/message"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="top"
        android:layout_weight="1"/>

      <Button 
          android:id="@+id/sendMessageButton"
          android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:layout_weight="4"
          android:text="Send"/>

    </LinearLayout>

</LinearLayout>

ListView row layout:

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

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/userAndMessage">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/textUser"
            android:textStyle="bold"
            android:textColor="@color/blue"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/textMessage"
            android:textColor="@color/blue"
            android:textStyle="bold"/>

    </RelativeLayout>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/textTime"
        android:textColor="@color/blue"/>

</RelativeLayout>

Message adapter:

public class MessageAdapter extends SimpleCursorAdapter {

    static final String[] FROM = { ChatHistoryManager.C_TIME };
    static final int[] TO = { R.id.textTime };

    static final int MESSAGE_INCOMING_DIR = 1;

    private String incomingMessageUserName;
    private String selfUserName;

    public MessageAdapter(Context context, Cursor cursor) {
        super(context, R.layout.message_list_item, cursor, FROM, TO);
    }

    @Override
    public void bindView(View row, Context context, Cursor cursor) {
        super.bindView(row, context, cursor);

        int messageDir = cursor.getInt(cursor.getColumnIndex(ChatHistoryManager.C_DIR));
        if(messageDir == MESSAGE_INCOMING_DIR) {

            RelativeLayout.LayoutParams userNameAndChatMessageParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
            userNameAndChatMessageParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE);

            RelativeLayout.LayoutParams userNameParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
            userNameParams.addRule(RelativeLayout.LEFT_OF, R.id.textMessage);

            RelativeLayout.LayoutParams chatMessageParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
            chatMessageParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, R.id.textUser);

            RelativeLayout.LayoutParams timeParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
            timeParams.addRule(RelativeLayout.ALIGN_RIGHT, R.id.userAndMessage);
            timeParams.addRule(RelativeLayout.BELOW, R.id.userAndMessage);

            row.setBackgroundResource(R.color.grey);

            // Set the chat message
            String chatMessage = cursor.getString(cursor.getColumnIndex(ChatHistoryManager.C_TEXT));
            TextView textMessage = (TextView) row.findViewById(R.id.textMessage);
            textMessage.setText(chatMessage.trim());
            textMessage.setLayoutParams(chatMessageParams);

            // Format the time stamp of the message
            long timestamp = cursor.getLong(cursor.getColumnIndex(ChatHistoryManager.C_TIME));
            TextView textTime = (TextView) row.findViewById(R.id.textTime);
            String readableTimeStamp = (String) DateUtils.getRelativeTimeSpanString(timestamp);
            textTime.setText(readableTimeStamp.trim());
            textTime.setLayoutParams(timeParams);

            // Format the message owner and the message
            TextView textUser = (TextView) row.findViewById(R.id.textUser);
            textUser.setText(incomingMessageUserName + ": ");
            textUser.setLayoutParams(userNameParams);
            row.setBackgroundResource(R.drawable.incoming_chat_bubble);
        }
        else {
            RelativeLayout.LayoutParams userNameAndChatMessageParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
            userNameAndChatMessageParams.addRule(RelativeLayout.RIGHT_OF, R.id.userImage);

            RelativeLayout.LayoutParams userImageParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
            userImageParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT, RelativeLayout.TRUE);

            RelativeLayout.LayoutParams userNameParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
            userNameParams.addRule(RelativeLayout.ALIGN_LEFT, R.id.userAndMessage);

            RelativeLayout.LayoutParams chatMessageParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
            chatMessageParams.addRule(RelativeLayout.RIGHT_OF, R.id.textUser);

            RelativeLayout.LayoutParams timeParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
            timeParams.addRule(RelativeLayout.ALIGN_LEFT, R.id.userAndMessage);
            timeParams.addRule(RelativeLayout.BELOW, R.id.userAndMessage);

            // Set the chat message
            String chatMessage = cursor.getString(cursor.getColumnIndex(ChatHistoryManager.C_TEXT));
            TextView textMessage = (TextView) row.findViewById(R.id.textMessage);
            textMessage.setText(chatMessage);
            textMessage.setLayoutParams(chatMessageParams);

            // Format the time stamp of the message
            long timestamp = cursor.getLong(cursor.getColumnIndex(ChatHistoryManager.C_TIME));
            TextView textTime = (TextView) row.findViewById(R.id.textTime);
            textTime.setText(DateUtils.getRelativeTimeSpanString(timestamp));
            textTime.setLayoutParams(timeParams);

            // Format the message owner and the message
            TextView textUser = (TextView) row.findViewById(R.id.textUser);
            textUser.setText(selfUserName + ": ");
            textUser.setLayoutParams(userNameParams);
            row.setBackgroundResource(R.drawable.outgoing_chat_bubble);
        }
    }

    public void setIncomingMessageUserName(String inputUserName) {
        this.incomingMessageUserName = inputUserName;
    }

    public void setSelfUserName(String inputUserName) {
        this.selfUserName = inputUserName;
    }
}
like image 773
user1125567 Avatar asked Jan 02 '12 19:01

user1125567


1 Answers

use LinearLayout instead of Relative layout. It will solve your problem. I had same issue. I solved it using LinearLayout

like image 172
Nayanesh Gupte Avatar answered Oct 23 '22 12:10

Nayanesh Gupte