0

I've populated the data into a multi column ListView from firebase database.

I've extended BaseAdapter class for getting getting this view as shown in below figures.

Why does the item positions change while scrolling ?

Rows are getting aligned up and down when scrolled. This is the scenario:

enter image description here

Scrolled a bit down... ( Looks fine! )

enter image description here

Scrolling...

( The records were not displayed in the order, as you can see they are getting changed every time I scroll through the list. )

enter image description here

What can be the reason for this? Can anyone explain?

Code for Adapter class:

    public class ReportAdapter extends BaseAdapter {

    public ArrayList<HashMap<String, String>> list;
    Activity activity;
    TextView childOneNameColumn, childTwoNameColumn, childThreeNameColumn;
    TextView checkInColumn;
    TextView parentCheckInColumn;
    TextView checkOutColumn;
    TextView parentCheckOutColumn;
    TextView familyNameColumn;


    public ReportAdapter(Activity activity, ArrayList<HashMap<String, String>> list) {
        super();
        this.activity = activity;
        this.list = list;
    }

    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return list.size();
    }

    @Override
    public Object getItem(int position) {
        // TODO Auto-generated method stub
        return list.get(position);
    }

    @Override
    public long getItemId(int position) {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        ViewHolder viewHolder;

        LayoutInflater inflater = activity.getLayoutInflater();

        if (convertView == null) {
            convertView = inflater.inflate(R.layout.column_row, parent, false);
            viewHolder = new ViewHolder(convertView);
            convertView.setTag(viewHolder);

        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }

        HashMap<String, String> map = list.get(position);
        familyNameColumn.setText(map.get(FAMILY_NAME_COLUMN));
        childOneNameColumn.setText(map.get(CHILD_ONE_NAME_COLUMN));
        childTwoNameColumn.setText(map.get(CHILD_TWO_NAME_COLUMN));
        childThreeNameColumn.setText(map.get(CHILD_THREE_NAME_COLUMN));
        checkInColumn.setText(map.get(CHECKIN_COLUMN));
        parentCheckInColumn.setText(map.get(PARENT_CHECKIN_COLUMN));
        checkOutColumn.setText(map.get(CHECKOUT_COLUMN));
        parentCheckOutColumn.setText(map.get(PARENT_CHECKOUT_COLUMN));

        return convertView;
    }

    private class ViewHolder {

        public ViewHolder(View view) {
            childOneNameColumn = (TextView) view.findViewById(R.id.child1NameColumn);
            childTwoNameColumn = (TextView) view.findViewById(R.id.child2NameColumn);
            childThreeNameColumn = (TextView) view.findViewById(R.id.child3NameColumn);
            checkInColumn = (TextView) view.findViewById(R.id.checkInColumn);
            parentCheckInColumn = (TextView) view.findViewById(R.id.parentCheckInColumn);
            checkOutColumn = (TextView) view.findViewById(R.id.checkOutColumn);
            parentCheckOutColumn = (TextView) view.findViewById(R.id.parentCheckOutColumn);
            familyNameColumn = (TextView) view.findViewById(R.id.familyNameColumn);
        }
    }
}

Layout column_row.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="match_parent"
    android:padding="10dp">


    <LinearLayout
        android:id="@+id/linearLayout5"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="30dp"
        android:orientation="horizontal">

        <TextView
            android:id="@+id/familyNameColumn"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="0.8"
            android:textColor="@color/colorBlack" />

        <TextView
            android:id="@+id/child1NameColumn"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="0.5" />

        <TextView
            android:id="@+id/child2NameColumn"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="0.5" />

        <TextView
            android:id="@+id/child3NameColumn"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="0.5" />

        <TextView
            android:id="@+id/checkInColumn"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:textColor="@color/colorGreen" />

        <TextView
            android:id="@+id/parentCheckInColumn"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="0.7" />

        <TextView
            android:id="@+id/checkOutColumn"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:textColor="@color/colorGreen" />

        <TextView
            android:id="@+id/parentCheckOutColumn"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="0.7" />

    </LinearLayout>
</RelativeLayout>

ListView properties:

<ListView
    android:id="@+id/reportListView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:layout_marginTop="40dp"
    android:transcriptMode="alwaysScroll" />
coderpc
  • 4,119
  • 6
  • 51
  • 93
  • This is hard to know without the code in your `BaseAdapter`. – Peike Jun 06 '17 at 16:46
  • I added code. Please see the above updated question. @Col – coderpc Jun 06 '17 at 16:53
  • 1
    It looks like not only the order has changed, the texts on each row has changed as well. Can you add the `R.layout.column_row`? Also `ViewHolder` is the recommended pattern for list adapter. Try that and see what will happen. https://guides.codepath.com/android/Using-a-BaseAdapter-with-ListView#optimization-using-the-viewholder-pattern – Peike Jun 06 '17 at 18:00
  • Yes exactly. even the texts on each row also changed. Added Layout code too. Meanwhile, I'd refer the link which you provided. @Col – coderpc Jun 06 '17 at 18:01

2 Answers2

1

Better use a ViewHolder for long lists.

Anyway, you wrongly set views. In a ListView you should manage both branches, whether convertView == null or not. When convertView != null you also have to set views.

So, if you don't want to create a ViewHolder, write:

if (convertView == null) {
    convertView = inflater.inflate(R.layout.column_row, parent, false);
}
childOneNameColumn = (TextView) convertView.findViewById(R.id.child1NameColumn);
childTwoNameColumn = (TextView) convertView.findViewById(R.id.child2NameColumn);
...

Also try to name variables with lowercase.

CoolMind
  • 26,736
  • 15
  • 188
  • 224
  • Please can you see my updated question. Added XML properties of my `ListView` I've modified my Adapter class code using `ViewHolder`. Even after changing, I feel like I'm having the same problem but as per loading point of view using `ViewHolder` it is pretty fast. – coderpc Jun 06 '17 at 18:39
  • 1
    Glad that you added VH. But all fields must be written inside ViewHolder, not in adapter. I mean `TextView childOneNameColumn, childTwoNameColumn, childThreeNameColumn;`, etc. should be written in `private class ViewHolder`. So, in `getView()` you can access them with `viewHolder.childOneNameColumn.setText(...);`. – CoolMind Jun 06 '17 at 19:10
  • 1
    Yes got it! Appreciate it for your time and support. – coderpc Jun 06 '17 at 19:13
  • Hey. Can you please check this [post](https://stackoverflow.com/questions/44447813/populating-a-video-url-from-firebase-and-display-that-video-in-a-videoview-in-an). I'm stuck there. Can you please guide me. – coderpc Jun 09 '17 at 02:01
1

The main reason for messed up rows are that you are not setting the text at the correct TextView objects.

You have 8 TextViews each row. That means, for all the rows showing on the screen, they each has 8 TextView objects.

For example, if you have 10 rows on screen, then you will have 10 individual copies of those 8 TextView.

You can use ViewHolder. The main purpose for the View Holder Pattern is to eliminate the need to call findViewById every time and that will give you better performance.

Peike
  • 727
  • 4
  • 15
  • I've set it right now. Even after setting I feel like it is the same. I've implemented `ViewHolder`. Please see the above updated question. Did i do it right ? – coderpc Jun 06 '17 at 18:36
  • I've added my `ListView` xml properties. Please have a look. Is that right ? – coderpc Jun 06 '17 at 18:41
  • 1
    No it's not. You should move those `TextView` fields into the holder. That is why it's called `ViewHolder`. This is a good tutorial: https://guides.codepath.com/android/Using-a-BaseAdapter-with-ListView#optimization-using-the-viewholder-pattern – Peike Jun 06 '17 at 18:53
  • Perfect. Now i get it. Flawlessly worked !! Appreciate it. – coderpc Jun 06 '17 at 19:12
  • Hey col, can you please check this [post](https://stackoverflow.com/questions/44447813/populating-a-video-url-from-firebase-and-display-that-video-in-a-videoview-in-an). I'm stuck there. Can you please guide me. – coderpc Jun 09 '17 at 02:00