Search code examples
javaandroidandroid-layoutandroid-listviewandroid-arrayadapter

Confusion with adapter holder, how can I prevent getView method from modifying inappropriate ListView rows?


I haven't got an idea of custom adapters used in ListViews. Especially I mean holder class, which is appropriate for holding specified row data. I have an ArrayList which has NewsItem objects. NewsItem object has some string fields, such as title, timestamp, etc. This class has boolean called page_separator_flag, and this question is around this particular variable. Depending on this value row item in ListView changes its background and hides some information.

I have read that when I use holder for my adapter I will prevent unwanted changes of rows. So I created the holder called NewsItemHolder which has some fields to keep Views from particular row, and it has similar "page_separator_flag" too. According to my research, I thought that I can control row apperance by if statement.

Unfortunately some rows which I didn't want to change has been changed (especially when I scroll my ListView object fast).

My getView method:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View rowView = convertView;
    NewsItemHolder holder = new NewsItemHolder();

    if(rowView == null) {
        LayoutInflater inflater = ((Activity)context).getLayoutInflater();
        rowView = inflater.inflate(layoutResourceId, parent, false);

        holder.newsPicture = (ImageView)rowView.findViewById(R.id.newsPicture);
        holder.newsTimestamp = (TextView)rowView.findViewById(R.id.newsTimestamp);
        holder.newsTitle = (TextView)rowView.findViewById(R.id.newsTitle);
        holder.newsItemLayout = (LinearLayout)rowView.findViewById(R.id.newsLayout);

        // Setting font
        holder.newsTimestamp.setTypeface(typeface);
        holder.newsTitle.setTypeface(typeface);

        rowView.setTag(holder);
    }
    else {
        holder = (NewsItemHolder) rowView.getTag();
    }

        String tests = (String)holder.newsTitle.getText();

        NewsItem single_item = items.get(position);
        holder.newsTimestamp.setText(single_item.getTimestamp());
        holder.newsTitle.setText(single_item.getTitle());
        holder.page_separator_flag = single_item.page_separator_flag;

        // For page headers there is a special treatment
       // if (holder.page_separator_flag == true) {
        if(holder.newsTitle.getText().toString().contains("Page") && holder.page_separator_flag == true) {
            holder.newsPicture.setVisibility(View.GONE);
            holder.newsTimestamp.setVisibility(View.GONE);
            holder.newsItemLayout.setBackground(context.getResources().getDrawable(R.drawable.background_card_page));
            holder.newsTitle.setTextSize(Float.valueOf(holder.newsTitle.getTextSize()) * 0.50f);
            holder.newsTitle.setTextColor(Color.WHITE);
        }
        // Load picture using Picasso (we haven't to focus on caching and preventing re-download)
        Picasso.with(context).load(single_item.getImgURL()).placeholder(R.mipmap.ic_empty_news).into(holder.newsPicture);


    return rowView;
}

My NewsItemHolder class:

static class NewsItemHolder {
    boolean page_separator_flag;

    ImageView newsPicture;
    TextView newsTimestamp;
    TextView newsTitle;
    LinearLayout newsItemLayout;
}

As you can see in the if statement mentioned above, row appearance will change when title View will contain "Page" word (it's about separating one set of data from another). Unfortunately as I said, it affects on rows which are not page separators and contain needed data.

How can I handle this properly when holder fails? What am I doing wrong?


Solution

  • you have to handle else case too otherwise it wont work

    if(holder.newsTitle.getText().toString().contains("Page ") && holder.page_separator_flag == true) {
            holder.newsPicture.setVisibility(View.GONE);
            holder.newsTimestamp.setVisibility(View.GONE);
            holder.newsItemLayout.setBackground(context.getResources().getDrawable(R.drawable.background_card_page));
            holder.newsTitle.setTextSize(Float.valueOf(holder.newsTitle.getTextSize()) * 0.50f);
            holder.newsTitle.setTextColor(Color.WHITE);
        }
    else {
    YOUR DEFAULT VALUES WHEN BOOLEAN IS FALSE
    }