Why does the text in the ListView control disappear when scrolling?

I have ListView

one which contains elements containing 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 elements that were changing as well (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 that as you scroll up and down, more and more text disappears. messageIndicatorView

does not disappear, but only the text disappears. If I continue scrolling enough, all of the text disappears. What am I doing wrong and how can I fix it? Thank you. (I know I have to use ViewHolder to improve performance, but I will when this issue is fixed)

+3


source to share


1 answer


The problem is that because the ListView is recycling and reusing views, conflicting rules are being added to the instances RelativeLayout.LayoutParams

for the @id/message

TextView. In particular, this happens whenever the presentation for the "ME" message is reused for the "OTHER" message, or vice versa.

RelativeLayout.LayoutParams

stores a list of rules (in fact, an array by verb, so you can't add, say, two rules LEFT_OF

, but any other combination is possible, including problematic ones).

The simplest solution is to use a new object each time RelativeLayout.LayoutParams

, changing this line:

RelativeLayout.LayoutParams textParams = 
    (RelativeLayout.LayoutParams)messageTextView.getLayoutParams();

      



in

RelativeLayout.LayoutParams textParams = 
    new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);

      

There are other solutions as well, such as different actual layouts for each type of ListView item (through getItemViewType()

), but that probably overwhelms this case. However, if the differences between the two views were more significant, one might think.

+1


source







All Articles