Reputation: 9162
I have ListView
which contains items containing a View
and a TextView
:
chat_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="90dp"
android:id="@+id/chat_message_wrapper"
xmlns:pixlui="http://schemas.android.com/apk/com.neopixl.pixlui">
<View
android:id="@+id/message_indicator"
android:layout_width="10dp"
android:layout_height="90dp"/>
<com.neopixl.pixlui.components.textview.TextView
android:id="@+id/message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/midnight_blue"
android:padding="14dp"
android:layout_centerVertical="true"/>
</RelativeLayout>
And this is getView()
in my Adapter class:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if (view == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.chat_item, null);
}
ChatMessageItem item = getItem(position);
if(item != null) {
TextView messageTextView = (TextView) view.findViewById(R.id.message);
ViewGroup messageWrapper = (ViewGroup) view.findViewById(R.id.chat_message_wrapper);
View messageIndicatorView = view.findViewById(R.id.message_indicator);
if(messageTextView != null) {
messageTextView.setText(String.valueOf(item.getMessage()));
RelativeLayout.LayoutParams textParams = (RelativeLayout.LayoutParams)messageTextView.getLayoutParams();
RelativeLayout.LayoutParams indicatorParams = new RelativeLayout.LayoutParams(10, ViewGroup.LayoutParams.MATCH_PARENT);
RelativeLayout.LayoutParams messageWrapperParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 90);
if(item.getSender() == ChatMessageItem.Sender.ME) {
textParams.addRule(RelativeLayout.LEFT_OF, R.id.message_indicator);
indicatorParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
messageIndicatorView.setBackgroundColor(getContext().getResources().getColor(R.color.light_blue));
}
else if(item.getSender() == ChatMessageItem.Sender.OTHER) {
textParams.addRule(RelativeLayout.RIGHT_OF, R.id.message);
indicatorParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
messageIndicatorView.setBackgroundColor(getContext().getResources().getColor(R.color.silver));
}
messageTextView.setLayoutParams(textParams);
messageIndicatorView.setLayoutParams(indicatorParams);
messageWrapper.setLayoutParams(messageWrapperParams);
}
}
return view;
}
I added the following line to at least keep the height of the items constant, which used to also change (which will probably give me problems later, as the content is dynamic, but ok..)
RelativeLayout.LayoutParams messageWrapperParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 90);
The problem is when I scroll up and down more and more text disappears. messageIndicatorView
does not disappear though, only the text disappears. If I keep scrolling enough, all text will disappear. What am I doing wrong and how can I fix it? Thanks. (I know I must use a ViewHolder for better performance, but I will do that when this problem is fixed)
Upvotes: 3
Views: 1466
Reputation: 55350
The problem is that as the ListView recycles and reuses the views, conflicting rules are added to the RelativeLayout.LayoutParams
instances for the @id/message
TextView. In particular this happens whenever a view for a "ME" message is reused for an "OTHER" message, or vice-versa.
RelativeLayout.LayoutParams
keeps a list of rules (actually an array by verb, so that you cannot add, say, two LEFT_OF
rules -- but any other combination is possible, including problematic ones).
The easiest solution is to use a new RelativeLayout.LayoutParams
object each time, by changing this line:
RelativeLayout.LayoutParams textParams =
(RelativeLayout.LayoutParams)messageTextView.getLayoutParams();
into:
RelativeLayout.LayoutParams textParams =
new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
There are other solutions, such as having different actual layouts for each kind of ListView item (via getItemViewType()
) but it's probably overkill in this case. However if the differences between the two kinds of views were greater, it might be worth considering.
Upvotes: 1