S21st
S21st

Reputation: 131

Alternate chat bubble widths

I am developing a chat type application. I am using two different nine patches for chat bubble main message and responses. The problem I am facing is to automatically wrapping the widths of the bubbles according to the message length. Following is my main layout:

<RelativeLayout
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="0dp"
    android:layout_weight="1"
    >

 <ListView android:id="@+id/list"
    android:layout_width="wrap_content"
    android:layout_height="fill_parent"
    android:stackFromBottom="true"
    android:transcriptMode="alwaysScroll"
    android:cacheColorHint="#00000000"
    android:listSelector="@android:color/transparent"
    android:divider="@null"
    />
 </RelativeLayout>

<LinearLayout android:id="@+id/footer" android:layout_width="fill_parent"
    android:layout_height="wrap_content" android:orientation="horizontal"
    android:gravity="bottom" style="@android:style/ButtonBar">
    <Button
        android:id="@+id/stt_button"
        android:layout_width="45dp"
        android:layout_height="50dp"
        android:background="@drawable/microphone"
    />   

    <EditText android:id="@+id/chat_msg"
        android:inputType="text" 
        android:layout_width="0dp"
        android:layout_height="40dp"
        android:layout_weight="1" />

    <Button android:id="@+id/send_button"
        android:layout_width="wrap_content"
        android:layout_height="40dp"
        android:layout_gravity="center_vertical"
        android:text="@string/send_button" />
</LinearLayout>
</LinearLayout>

This is my list_item layout:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="wrap_content" android:weightSum="1.0"
android:layout_weight="1" android:layout_height="wrap_content">
<LinearLayout         
    android:id="@+id/linearLayoutLeft" 
    android:layout_width="0dp"
    android:layout_weight="0.8"
    android:layout_height="wrap_content">
    <RelativeLayout 
        android:id="@+id/relativeLayoutLeft" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content">
        <TextView 
            android:id="@+id/lefttext" 
            android:layout_width="wrap_content" 
            android:gravity="top" 
            android:layout_height="wrap_content" 
            android:paddingLeft="10dip" 
            android:paddingRight="10dip" 
            android:paddingTop="5dip" 
            android:layout_alignParentLeft="true">
        </TextView>
    </RelativeLayout>
</LinearLayout>
<LinearLayout         
    android:id="@+id/linearLayoutRight"
    android:layout_width="0dp"         
    android:layout_weight="0.8"
    android:layout_height="wrap_content">
    <RelativeLayout 
        android:id="@+id/relativeLayoutRight" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content">
        <TextView 
            android:id="@+id/righttext" 
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content" 
            android:paddingLeft="10dip" 
            android:paddingRight="10dip" 
            android:paddingTop="5dip" 
            android:layout_alignParentRight="true" 
            android:layout_alignParentTop="true">
        </TextView>
    </RelativeLayout>
</LinearLayout>

This is the code inside the getView method of my custom array adapter:

    View view = convertView;
    if(view == null){
        view = mInflater.inflate(R.layout.list_item, null);
    }

    Resources res = getContext().getResources();
    Drawable bubblesChat = res.getDrawable(R.drawable.bubbles_chat);
    Drawable bubblesResponse = res.getDrawable(R.drawable.bubbles_response);
    TextView left = (TextView) view.findViewById(R.id.lefttext);
    TextView right = (TextView) view.findViewById(R.id.righttext);
    View leftLayout = view.findViewById(R.id.relativeLayoutLeft);
    View rightLayout = view.findViewById(R.id.relativeLayoutRight); 
    LinearLayout linearLeft = (LinearLayout) view.findViewById(R.id.linearLayoutLeft);
    LinearLayout linearRight = (LinearLayout) view.findViewById(R.id.linearLayoutRight);

    LayoutParams leftParams = (LayoutParams) linearLeft.getLayoutParams();
    LayoutParams rightParams = (LayoutParams) linearRight.getLayoutParams();

    String txt = super.getItem(position);
    if(txt.startsWith("s:")) {
        left.setText(getItem(position));
        leftLayout.setBackgroundDrawable(bubblesChat);
        leftParams.weight = 0.8f;
        linearLeft.setLayoutParams(leftParams);
        rightParams.weight = 0.2f;
        linearRight.setLayoutParams(rightParams);
        right.setText("");
        rightLayout.setBackgroundDrawable(null);
    } else {
        right.setText(getItem(position));
        rightLayout.setBackgroundDrawable(bubblesResponse);
        rightParams.weight = 0.8f;
        linearRight.setLayoutParams(rightParams);           
        leftParams.weight = 0.2f;
        linearLeft.setLayoutParams(leftParams);
        left.setText("");
        leftLayout.setBackgroundDrawable(null);
    }
    return view;

All I am getting from this setup is like the following (note the empty spaces in front of the right bubbles:

enter image description here

You can see that the right hand side bubbles are not wrapping the width according to the text size. I understand why this is happening - I am assigning weight of 0.8 to the current chat message bubble (may be left of right) and 0.2 to the rest. When the current message is from left bubble it works fine as it is draw first as 0.8 weight with wrap_content. But when the right bubble is the current message, the left bubble got drawn first and have a fixed width of 0.2, hence the right one always gets 0.8 irrespective of wrap_content. How can I fix this? All I want is to get the bubbles according to the text width and aligned either left or right. I can ditch my current way altogether if you can suggest a better way to do this correctly.

Upvotes: 3

Views: 8164

Answers (1)

S21st
S21st

Reputation: 131

When I first posted this question, I just started Android programming. The problem was I overly complicated my layout definitions and code. Now that I simplified my layout hierarchy, I have achieved what I wanted and without using any layout weight and with a lot simple code/configuration. Here I am posting my updated code snippets.

My Main layout now:

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="fill_parent">

    <ListView android:id="@+id/list"
        android:layout_width="fill_parent"
        android:layout_height="0dip"
        android:layout_weight="1"
        android:stackFromBottom="true"
        android:transcriptMode="alwaysScroll"
        android:cacheColorHint="#00000000"
        android:listSelector="@android:color/transparent"
        android:divider="@null"/>

    <LinearLayout android:id="@+id/footer" android:layout_width="fill_parent"
        android:layout_height="wrap_content" android:orientation="horizontal"
        android:gravity="bottom" style="@android:style/ButtonBar">
        <Button android:id="@+id/stt_button"
            android:layout_width="45dp"
            android:layout_height="50dp"
            android:background="@drawable/microphone"/>   

        <EditText android:id="@+id/chat_msg"
            android:inputType="text" 
            android:layout_width="0dp"
            android:layout_height="40dp"
            android:layout_weight="1" />

        <Button android:id="@+id/send_button"
            android:layout_width="wrap_content"
            android:layout_height="40dp"
            android:layout_gravity="center_vertical"
            android:text="@string/send_button" />
    </LinearLayout>
</LinearLayout>

List item layout:

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

    <TextView android:id="@+id/lefttext" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:layout_marginLeft="10dip" 
        android:layout_marginRight="10dip" 
        android:layout_marginTop="10dip"
        android:layout_marginBottom="5dip"
        android:layout_alignParentLeft="true"
        android:maxWidth="250dip"/>

    <TextView 
        android:id="@+id/righttext" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dip" 
        android:layout_marginRight="10dip" 
        android:layout_marginTop="10dip"
        android:layout_marginBottom="5dip"
        android:layout_alignParentRight="true"
        android:maxWidth="250dip"/>
</RelativeLayout>

This is the code inside the getView method of my custom array adapter:

    View view = convertView;
    if(view == null){
         view = mInflater.inflate(R.layout.list_item, null);
    }

    Resources res = getContext().getResources();
    Drawable bubblesChat = res.getDrawable(R.drawable.bubbles_chat);
    Drawable bubblesResponse = res.getDrawable(R.drawable.bubbles_response);
    TextView left = (TextView) view.findViewById(R.id.lefttext);
    TextView right = (TextView) view.findViewById(R.id.righttext);

    String txt = super.getItem(position);
    if(txt.startsWith("s:")) {
        left.setText(getItem(position));
        left.setBackgroundDrawable(bubblesChat);
        right.setText("");
        right.setBackgroundDrawable(null);
    } else {
        right.setText(getItem(position));
        right.setBackgroundDrawable(bubblesResponse);
        left.setText("");
        left.setBackgroundDrawable(null);
    }
    return view;

Upvotes: 5

Related Questions