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

Commit b742b87a authored by Yigit Boyar's avatar Yigit Boyar
Browse files

Remove detached headers

ListView was leaving header and footer views
in the detached state, which is a problem because
no view should be left in that state after a layout
calculation. This was also causing the view to never
received detached-from-window callback if
the ListView is detached while the header is not
visible.

This CL fixes an issue by traversing fixed views
and removing the ones that match the criteria.
To keep the behavior as similar as possible,
we still do not call startTmpDispatch on
fixed views unless we'll remove them.

Bug: 24490656
Change-Id: I8acfbd1a9d9b8b24c1c4b7692ef82cfe0f4d43a8
parent f970410a
Loading
Loading
Loading
Loading
+37 −0
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ import android.view.accessibility.AccessibilityNodeProvider;
import android.widget.RemoteViews.RemoteView;

import java.util.ArrayList;
import java.util.List;

/*
 * Implementation Notes:
@@ -1763,6 +1764,10 @@ public class ListView extends AbsListView {
            // Flush any cached views that did not get reused above
            recycleBin.scrapActiveViews();

            // remove any header/footer that has been temp detached and not re-attached
            removeUnusedFixedViews(mHeaderViewInfos);
            removeUnusedFixedViews(mFooterViewInfos);

            if (sel != null) {
                // The current selected item should get focus if items are
                // focusable.
@@ -1879,6 +1884,36 @@ public class ListView extends AbsListView {
        }
    }

    @Override
    boolean trackMotionScroll(int deltaY, int incrementalDeltaY) {
        final boolean result = super.trackMotionScroll(deltaY, incrementalDeltaY);
        removeUnusedFixedViews(mHeaderViewInfos);
        removeUnusedFixedViews(mFooterViewInfos);
        return result;
    }

    /**
     * Header and Footer views are not scrapped / recycled like other views but they are still
     * detached from the ViewGroup. After a layout operation, call this method to remove such views.
     *
     * @param infoList The info list to be traversed
     */
    private void removeUnusedFixedViews(@Nullable List<FixedViewInfo> infoList) {
        if (infoList == null) {
            return;
        }
        for (int i = infoList.size() - 1; i >= 0; i--) {
            final FixedViewInfo fixedViewInfo = infoList.get(i);
            final View view = fixedViewInfo.view;
            final LayoutParams lp = (LayoutParams) view.getLayoutParams();
            if (view.getParent() == null && lp != null && lp.recycledHeaderFooter) {
                removeDetachedView(view, false);
                lp.recycledHeaderFooter = false;
            }

        }
    }

    /**
     * @param child a direct child of this list.
     * @return Whether child is a header or footer view.
@@ -3179,6 +3214,8 @@ public class ListView extends AbsListView {
                last = getChildAt(--lastIndex);
            }
        }
        removeUnusedFixedViews(mHeaderViewInfos);
        removeUnusedFixedViews(mFooterViewInfos);
    }

    private View addViewAbove(View theView, int position) {