Skip to content

2.2.0

Latest

Choose a tag to compare

@github-actions github-actions released this 17 Sep 13:35
· 20 commits to main since this release
ca55984

Added

  • smoothScrollToPosition(int), on all three views, animates the cell holding
    the position to parchment_snapPosition the way a fling gets there, where
    setSelection jumps. It runs at RecyclerView's programmatic speed, 25 ms
    per inch, four times a snap's: a cell already laid out is landed on with one
    decelerating scroll of exactly its snap distance; a cell that is not is
    sought at a constant speed by the distance extrapolated from the edge cell's
    size plus a viewport of runway, handed to the landing in the frame it is
    laid out, and sought again from wherever it is whenever less than a viewport
    of runway is left, so the motion stays even when the cells between were
    larger than the estimate assumed. The landing is not capped at half a
    second, so a long scroll decelerates from the seek's speed rather than
    snapping the rest of the way. It obeys every bound a fling obeys:
    android:padding*, parchment_scrollWithinContent, under which a cell the
    bound holds short of its snap point decelerates onto the bound and rests
    there, and parchment_isCircularScroll, under which it takes the shorter
    way round. A parchment_isViewPager view is crossed page by page rather
    than held to one, which needed the page clamp to learn that an animation is
    not a gesture. It reports settling then idle to the scroll listener, and
    under parchment_selectOnSnap selects the cell at the snap position when it
    comes to rest, once. The position is clamped to the adapter; before the first
    layout, on an empty adapter, or when the cell is already at its snap point
    nothing happens; it is ignored while a finger is down, and a touch cancels it
    like a fling. Under onScreen it scrolls the minimum that shows the cell
    whole. A position asked for before the first layout is not remembered; a
    pending target is a follow-up (#54, asked for in #19).

Changed

  • A jump ends a running animation. setSelection and a data set change now
    stop whatever was moving the content, a fling included, in the layout pass
    the jump asks for, snapping whatever residual the jump left, so the view
    rests with the incoming cell at its snap point and reports one idle; the
    fling used to carry on from the jumped offset. At rest nothing changes: no
    frame runs and nothing is reported.
  • Breaking: LayoutManager gains an abstract getCellBreadth, a cell's
    extent across the scroll axis, and measureBreadth, which
    AbstractAdapterView.onMeasure asks for the view's size across it;
    ScrollDirectionManager gains the cross-axis spec, padding and width/height
    mappings that serve them. All are implementation details the views build and
    call for themselves, so nothing outside the library should be subclassing or
    calling them.

Fixed

  • parchment_selectOnSnap reported the selection a stop made only on the next
    layout pass, so a fling that ended exactly on a snap point, with no residual
    snap to run a further frame, selected the cell but did not tell the
    OnItemSelectedListener until something else laid the view out. A frame
    that ends at rest now reports the selection its stop made, which is what
    every smoothScrollToPosition landing needs
    (aFlingThatEndsOnASnapPoint_withSelectOnSnap_reportsTheSelectionWithoutALayoutPass).
    Two consequences to know about: under parchment_selectOnSnap a data set
    change at rest that keeps or grows the count now reports its unchanged
    selection one layout pass earlier, the same cell in the same place, once;
    and a jump that lands mid-animation reports its selection where the cell is
    at the jump, after which the residual snap moves it the few pixels to its
    snap point, as it already did on main with the fling still running. Under
    parchment_isCircularScroll with parchment_selectOnSnap, a tap on a cell
    reports that cell and then the cell nearest the start edge, because the
    stop's snap selects the nearest cell to the onScreen position circular
    scrolling forces; main did the same silently, and this is now reported
    rather than fixed.
  • A fling, snap or smooth scroll that ran to rest within its first frame, as a
    short snap does and as any animation does when the main thread stalls for a
    frame, reported its displacement but no scroll state: the dispatcher reports
    a change at the end of a frame and the frame ended where it began, at
    idle. It now reports the state the frame ran in before the state it ended
    in, when the frame moved the content, so such a frame reports settling
    then idle after its onScrolled and a frame that moved nothing still
    reports nothing
    (aSmoothScrollThatEndsInItsFirstFrame_stillReportsSettlingThenIdle,
    aFlingThatEndsInItsFirstFrame_stillReportsSettlingThenIdle).
  • android:layout_height="wrap_content" on a horizontal view and
    android:layout_width="wrap_content" on a vertical one used to take every
    pixel the parent had left, pushing the next sibling of a LinearLayout off
    the screen: onMeasure set the measured size to the spec size whatever the
    spec's mode, so AT_MOST was treated as EXACTLY. Across the scroll axis a
    ListView now measures to its largest cell and a GridView to its largest
    row or column, the spacing between the views of the group included, plus
    android:padding*, capped at the size offered under AT_MOST and uncapped
    under UNSPECIFIED. EXACTLY is untouched, so match_parent and a fixed
    size lay out exactly as before. Along the scroll axis wrap_content still
    fills the parent, since wrapping there would mean measuring every item in the
    adapter, and GridPatternView, whose cells are sized from the view, still
    fills it on both axes. The size comes from the cells present at measure time:
    the cells laid out, or before the first layout the cells that fill the
    viewport from the start position, obtained through the recycler and handed
    back to it the way the platform ListView measures under AT_MOST. That
    first estimate cannot see a cell the layout back-fills before the start
    position, one the over-scroll correction pulls in, or one a scroll reveals
    later, so a layout that draws a cell larger than the size it was measured to
    asks the view for one more layout, and the next measure, which reads the
    drawn cells, grows the view to it. Cells of varying size across the scroll
    axis are therefore better served by a fixed size, because the view resizes
    as they come into view (#59, the remaining half of #10).
  • A horizontal ListView gave its children the mode of its own width spec as
    their height mode, and a GridView did the same for the views it obtains for
    a jump. They now take the mode of the height spec. Under wrap_content that
    is what lets a match_parent child measure to its content rather than to
    the whole height the parent offered; under a bounded width and an exact
    height, a horizontal list inside a HorizontalScrollView or a
    wrap_content-wide parent, a match_parent child is now given the exact
    height instead of a bound it measured itself to zero against. Under EXACTLY
    on both axes nothing changes.