Reputation: 131
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:
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
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