Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0bf88594 authored by Romain Guy's avatar Romain Guy
Browse files

Make sure all list items know they are in a window.

Bug #2476671

If you had a ListView with a layout_height equals to WRAP_CONTENT, you would
get list children with a parent but not attached to the window. This was caused
by the onMeasure() code: that code was obtaining views from the adapter to
measure them and putting them in the recyler for later reuse. Unfortunately
the recycler assumes that views have been attached to the window but detached
from the parent, thus causing much grief. The fix simply forces measured views
to be added to the window the first time they come out of the recycler.

ListView, bow before me for I am your master!
parent db204c23
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -4032,6 +4032,17 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
        @ViewDebug.ExportedProperty
        boolean recycledHeaderFooter;

        /**
         * When an AbsListView is measured with an AT_MOST measure spec, it needs
         * to obtain children views to measure itself. When doing so, the children
         * are not attached to the window, but put in the recycler which assumes
         * they've been attached before. Setting this flag will force the reused
         * view to be attached to the window rather than just attached to the
         * parent.
         */
        @ViewDebug.ExportedProperty
        boolean forceAdd;

        public LayoutParams(Context c, AttributeSet attrs) {
            super(c, attrs);
        }
+3 −1
Original line number Diff line number Diff line
@@ -938,6 +938,7 @@ public class GridView extends AbsListView {
                child.setLayoutParams(p);
            }
            p.viewType = mAdapter.getItemViewType(0);
            p.forceAdd = true;

            int childHeightSpec = getChildMeasureSpec(
                    MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), 0, p.height);
@@ -1257,9 +1258,10 @@ public class GridView extends AbsListView {
        }
        p.viewType = mAdapter.getItemViewType(position);

        if (recycled) {
        if (recycled && !p.forceAdd) {
            attachViewToParent(child, where, p);
        } else {
            p.forceAdd = false;
            addViewInLayout(child, where, p, true);
        }

+3 −1
Original line number Diff line number Diff line
@@ -1109,6 +1109,7 @@ public class ListView extends AbsListView {
            child.setLayoutParams(p);
        }
        p.viewType = mAdapter.getItemViewType(position);
        p.forceAdd = true;

        int childWidthSpec = ViewGroup.getChildMeasureSpec(widthMeasureSpec,
                mListPadding.left + mListPadding.right, p.width);
@@ -1743,10 +1744,11 @@ public class ListView extends AbsListView {
        }
        p.viewType = mAdapter.getItemViewType(position);

        if (recycled || (p.recycledHeaderFooter &&
        if ((recycled && !p.forceAdd) || (p.recycledHeaderFooter &&
                p.viewType == AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER)) {
            attachViewToParent(child, flowDown ? -1 : 0, p);
        } else {
            p.forceAdd = false;
            if (p.viewType == AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER) {
                p.recycledHeaderFooter = true;
            }