blavi
blavi

Reputation: 531

ListView messed up when scroll

I have a list of items. Some of them need to be purchased and some don't. For those that need to be purchased a price is displayed. I am using a BaseAdapter to populate the list view. At first glance prices are shown for the right items, but at scroll prices are shown also for other lessons. With each scroll, the list view changes.

    public View getView(int position, View convertView, ViewGroup parent)
    {
        Lesson lesson = (Lesson) getItem(position);

        if (convertView == null)
        {
            convertView = new LessonView(lesson);
        }
        else
        {
            ((LessonView) convertView).setLessonView(lesson);
        }

        return convertView;
    }

public class LessonView extends LinearLayout
{
    private TextView lessonTitle, cardsNr, percentageValue, percentageCompleted, purchasePrice;
    private ImageView progressImage, purchaseIcon;
    private DrawUIHelper drawUIHelper;
    private RelativeLayout lessonRow;

    public LessonView(Lesson lesson)
    {
        super(mContext);
        drawUIHelper = DrawUIHelper.getInstance(mContext);
        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(((WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getWidth(), (int) (((WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getHeight() * 0.14));
        addView(LayoutInflater.from(mContext).inflate(R.layout.lesson_item, null), params);

        setLessonView(lesson);
    }

    /**
     * @param lesson
     */
    private void setLessonView(Lesson lesson)
    {
        lessonTitle = (TextView) findViewById(R.id.lessonTitleTextView);
        lessonTitle.setText(lesson.getTitle());

        TypeFaceSetter.getInstance(mContext).setFontType(lessonTitle);
        cardsNr = (TextView) findViewById(R.id.cardsNrTextView);
        cardsNr.setText(String.valueOf(lesson.getCardCount()));

        progressImage = (ImageView) findViewById(R.id.learnProgressImageView);
        lessonRow = (RelativeLayout) findViewById(R.id.lessonItem);

        lessonTitle.setTextSize(TypedValue.COMPLEX_UNIT_PX, lessonRow.getLayoutParams().width / 20);
        percentageValue = (TextView) findViewById(R.id.percentageTextView);
        TypeFaceSetter.getInstance(mContext).setFontType(percentageValue);
        percentageValue.setTextSize(TypedValue.COMPLEX_UNIT_PX, lessonRow.getLayoutParams().width / 15);
        percentageValue.setText(String.valueOf(Math.round(lesson.getLearningProgress() * 100)) + "%");
        percentageCompleted = (TextView) findViewById(R.id.percentageCompleted);
        TypeFaceSetter.getInstance(mContext).setFontType(percentageCompleted);
        percentageCompleted.setTextSize(TypedValue.COMPLEX_UNIT_PX, lessonRow.getLayoutParams().width / 50);

        progressImage.setImageBitmap(drawUIHelper.drawLearnCircle(lessonRow.getLayoutParams().height + 40, lessonRow.getLayoutParams().height + 40, lesson.getLearningProgress() * 100));

        int lessonId = getResources().getIdentifier("lesson_" + String.valueOf(lesson.getId()), "string", mContext.getPackageName());
        if (lessonId != 0) {
            String sku = mContext.getString(lessonId);
            if (lessonsDetailsMap.containsKey(sku)) {
                purchaseIcon = (ImageView) findViewById(R.id.purchaseIcon);
                purchaseIcon.setVisibility(View.VISIBLE);
                purchasePrice = (TextView) findViewById(R.id.purchasePrice);
                purchasePrice.setVisibility(View.VISIBLE);
                purchasePrice.setText(lessonsDetailsMap.get(sku));
            } else {
                // no purchased items
            }
        }
    }
}

Upvotes: 0

Views: 593

Answers (2)

juanmeanwhile
juanmeanwhile

Reputation: 2634

When scrolling in ListView views are reused. When setting a view values (in your setLessonView method) be sure you are getting every view (with findViewById) and giving them all a value. If not, if the view have been previously used to hold a Lesson with price and you do not hide this price view (or set some kind of value) you will see the old value.

In your code:

purchaseIcon = (ImageView) findViewById(R.id.purchaseIcon); 
purchasePrice = (TextView) findViewById(R.id.purchasePrice);
if (lessonId != 0) {
            String sku = mContext.getString(lessonId);
            if (lessonsDetailsMap.containsKey(sku)) {                
                purchaseIcon.setVisibility(View.VISIBLE);               
                purchasePrice.setVisibility(View.VISIBLE);
                purchasePrice.setText(lessonsDetailsMap.get(sku));
            } else {
                // no purchased items
                purchaseIcon.setVisibility(View.INVISIBLE);               
                purchasePrice.setVisibility(View.INVISIBLE);
            }
}

}

Upvotes: 2

HexAndBugs
HexAndBugs

Reputation: 5789

The problem appears to be that you are not resetting your prices in your setLessonView() method.

When you scroll, getView() will reuse views and convertView will not be null, so the else branch of getView() will be executed. This calls setLessonView(), and when lessonsDetailsMap.containsKey(sku) returns false, you don't clear the purchaseIcon and purchasePrice, so it will retain the old purchaseIcon and purchasePrice from the view it is reusing.

To fix this, in your else branch of setLessonView() after the comment // no purchased items, you need to add

purchaseIcon.setVisibility(View.INVISIBLE);
purchasePrice.setVisibility(View.INVISIBLE);

You could alternatively use View.GONE, depending on your layout and whether you want it removed rather than hidden.

Upvotes: 1

Related Questions