Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
… into fix_auto_alignment
  • Loading branch information
rubensousa committed Dec 27, 2023
2 parents cfe46a5 + 2c76fd3 commit 36a348a
Show file tree
Hide file tree
Showing 5 changed files with 192 additions and 164 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -416,4 +416,32 @@ class HorizontalAlignmentTest : DpadRecyclerViewTest() {
}
assertThat(getItemViewBounds(position = 0)).isEqualTo(childBounds)
}

@Test
fun testFirstItemIsAlignedCorrectlyWhenScrollingBack() {
launchFragment(
layoutConfiguration = getDefaultLayoutConfiguration().copy(
parentAlignment = ParentAlignment(
edge = Edge.MAX,
offset = 200,
fraction = 0f,
preferKeylineOverEdge = false
),
childAlignment = ChildAlignment(
offset = 0,
fraction = 0f
)
),
adapterConfiguration = getDefaultAdapterConfiguration()
)

val childBounds = getItemViewBounds(position = 0)
assertThat(childBounds.left).isEqualTo(200)
KeyEvents.pressRight()
waitForIdleScrollState()
KeyEvents.pressLeft()
waitForIdleScrollState()
waitForIdleScrollState()
assertThat(getItemViewBounds(position = 0)).isEqualTo(childBounds)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -251,14 +251,15 @@ class VerticalAlignmentTest : DpadRecyclerViewTest() {
fraction = 0f
)
)
KeyEvents.pressDown(times = 5)
val recyclerViewBounds = getRecyclerViewBounds()
val startPosition = 5
selectPosition(startPosition)
repeat(5) {
val viewBounds = getItemViewBounds(position = startPosition + it)
assertThat(viewBounds.top)
.isEqualTo(recyclerViewBounds.top + containerOffset + abs(itemOffset))
KeyEvents.pressDown()
waitForIdleScrollState()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import kotlin.math.sign

internal class LayoutAlignment(
private val layoutManager: LayoutManager,
private val layoutInfo: LayoutInfo
private val layoutInfo: LayoutInfo,
) {

companion object {
Expand Down Expand Up @@ -242,40 +242,41 @@ internal class LayoutAlignment(
startViewAnchor = Int.MIN_VALUE
}
if (!reverseLayout) {
parentAlignmentCalculator.updateScrollLimits(
startEdge = startEdge,
endEdge = endEdge,
startViewAnchor = startViewAnchor,
endViewAnchor = endViewAnchor,
alignment = parentAlignment
)
if (layoutInfo.isLoopingAllowed) {
// If we're looping, there's no end scroll limit
parentAlignmentCalculator.invalidateEndLimit()
} else {
parentAlignmentCalculator.updateEndLimit(endEdge, endViewAnchor, parentAlignment)
}
if (layoutInfo.isLoopingStart) {
parentAlignmentCalculator.invalidateStartLimit()
} else {
parentAlignmentCalculator.updateStartLimit(
startEdge, startViewAnchor, parentAlignment
)
}
} else {
parentAlignmentCalculator.updateScrollLimits(
startEdge = endEdge,
endEdge = startEdge,
startViewAnchor = endViewAnchor,
endViewAnchor = startViewAnchor,
alignment = parentAlignment
)
if (layoutInfo.isLoopingAllowed) {
parentAlignmentCalculator.invalidateStartLimit()
} else {
parentAlignmentCalculator.updateStartLimit(endEdge, endViewAnchor, parentAlignment)
}
if (layoutInfo.isLoopingStart) {
parentAlignmentCalculator.invalidateEndLimit()
} else {
parentAlignmentCalculator.updateEndLimit(
startEdge, startViewAnchor, parentAlignment
)
}

}
}

private fun isEndAvailable(
adapterPosition: Int,
maxLayoutPosition: Int,
minLayoutPosition: Int
minLayoutPosition: Int,
): Boolean {
return if (!reverseLayout) {
adapterPosition == maxLayoutPosition
Expand All @@ -287,7 +288,7 @@ internal class LayoutAlignment(
private fun isStartAvailable(
adapterPosition: Int,
maxLayoutPosition: Int,
minLayoutPosition: Int
minLayoutPosition: Int,
): Boolean {
return if (!reverseLayout) {
adapterPosition == minLayoutPosition
Expand Down Expand Up @@ -343,7 +344,7 @@ internal class LayoutAlignment(
private fun calculateAdjustedAlignedScrollDistance(
offset: Int,
view: View,
childView: View
childView: View,
): Int {
var scrollValue = offset
val subPosition = getSubPositionOfView(view, childView)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,58 +82,56 @@ internal class ParentAlignmentCalculator {
endScrollLimit = Int.MAX_VALUE
}

fun updateStartLimit(
edge: Int,
viewAnchor: Int,
fun updateScrollLimits(
startEdge: Int,
endEdge: Int,
startViewAnchor: Int,
endViewAnchor: Int,
alignment: ParentAlignment,
) {
startEdge = edge
if (isStartUnknown) {
startScrollLimit = Int.MIN_VALUE
return
this.startEdge = startEdge
this.endEdge = endEdge
val keyline = calculateKeyline(alignment)
startScrollLimit = when {
isStartUnknown -> Int.MIN_VALUE
shouldAlignViewToStart(startViewAnchor, keyline, alignment) -> {
calculateScrollOffsetToStartEdge(startEdge)
}

shouldAlignStartToKeyline(alignment) -> {
calculateScrollOffsetToKeyline(startViewAnchor, keyline)
}

else -> 0
}
val keyLine = calculateKeyline(alignment)
startScrollLimit = if (shouldAlignViewToStart(viewAnchor, keyLine, alignment)) {
calculateScrollOffsetToStartEdge(edge)
} else if (isLayoutComplete()
|| alignment.preferKeylineOverEdge
|| alignment.edge == Edge.NONE
) {
calculateScrollOffsetToKeyline(viewAnchor, keyLine)
} else {
0
endScrollLimit = when {
isEndUnknown -> Int.MAX_VALUE
shouldAlignViewToEnd(endViewAnchor, keyline, alignment) -> {
calculateScrollOffsetToEndEdge(endEdge)
}

shouldAlignEndToKeyline(alignment) -> {
calculateScrollOffsetToKeyline(endViewAnchor, keyline)
}

else -> 0
}
}

fun updateEndLimit(
edge: Int,
viewAnchor: Int,
alignment: ParentAlignment,
) {
endEdge = edge
if (isEndUnknown) {
endScrollLimit = Int.MAX_VALUE
return
}
val keyline = calculateKeyline(alignment)
endScrollLimit = if (shouldAlignViewToEnd(viewAnchor, keyline, alignment)) {
calculateScrollOffsetToEndEdge(edge)
} else if (isLayoutComplete()
|| alignment.preferKeylineOverEdge
|| alignment.edge == Edge.NONE
) {
calculateScrollOffsetToKeyline(viewAnchor, keyline)
} else {
0
}
private fun shouldAlignStartToKeyline(alignment: ParentAlignment): Boolean {
return !shouldAlignToStartEdge(alignment.edge) || preferKeylineOverEdge(alignment)
}

private fun calculateScrollOffsetToEndEdge(edge: Int): Int {
return edge - getLayoutEndEdge()
private fun shouldAlignEndToKeyline(alignment: ParentAlignment): Boolean {
return !shouldAlignToEndEdge(alignment.edge) || preferKeylineOverEdge(alignment)
}

private fun calculateScrollOffsetToStartEdge(edge: Int): Int {
return edge - getLayoutStartEdge()
private fun calculateScrollOffsetToEndEdge(anchor: Int): Int {
return anchor - getLayoutAbsoluteEnd()
}

private fun calculateScrollOffsetToStartEdge(anchor: Int): Int {
return anchor - getLayoutAbsoluteStart()
}

/**
Expand Down Expand Up @@ -192,10 +190,10 @@ internal class ParentAlignmentCalculator {
if (isStartUnknown || !shouldAlignToStartEdge(alignment.edge)) {
return false
}
if (!isLayoutIncomplete()) {
return viewAnchor + getLayoutStartEdge() <= startEdge + keyline
if (isLayoutComplete()) {
return viewAnchor + getLayoutAbsoluteStart() <= startEdge + keyline
}
return isLayoutIncomplete() && !alignment.preferKeylineOverEdge
return isLayoutStartKnown() && !preferKeylineOverEdge(alignment)
}

private fun shouldAlignViewToEnd(
Expand All @@ -206,41 +204,46 @@ internal class ParentAlignmentCalculator {
if (isEndUnknown || !shouldAlignToEndEdge(alignment.edge)) {
return false
}
if (!isLayoutIncomplete()) {
return viewAnchor + getLayoutEndEdge() >= endEdge + keyline
if (isLayoutComplete()) {
return viewAnchor + getLayoutAbsoluteEnd() >= endEdge + keyline
}
return isLayoutIncomplete() && !alignment.preferKeylineOverEdge
return isLayoutStartKnown() && !preferKeylineOverEdge(alignment)
}

private fun calculateScrollOffsetToKeyline(anchor: Int, keyline: Int): Int {
return anchor - keyline
}

private fun getLayoutEndEdge(): Int {
private fun getLayoutAbsoluteEnd(): Int {
return size - paddingEnd
}

private fun getLayoutStartEdge(): Int {
private fun getLayoutAbsoluteStart(): Int {
return paddingStart
}

private fun isLayoutComplete(): Boolean {
if (isEndUnknown || isStartUnknown) {
return false
if (isEndUnknown && isStartUnknown) {
return true
}
return if (!reverseLayout) {
(startEdge <= getLayoutAbsoluteStart()
&& (endEdge >= getLayoutAbsoluteEnd() || isEndUnknown))
} else {
(endEdge >= getLayoutAbsoluteEnd()
&& (startEdge <= getLayoutAbsoluteStart() || isStartUnknown))
}
return endEdge - startEdge >= size - paddingEnd - paddingStart
&& endEdge <= size - paddingEnd
&& startEdge >= paddingStart
}

private fun isLayoutIncomplete(): Boolean {
if (isEndUnknown || isStartUnknown) {
return false
}
private fun preferKeylineOverEdge(alignment: ParentAlignment): Boolean {
return alignment.preferKeylineOverEdge || alignment.edge == Edge.NONE
}

private fun isLayoutStartKnown(): Boolean {
return if (!reverseLayout) {
endEdge < size - paddingEnd
!isStartUnknown
} else {
startEdge > paddingStart
!isEndUnknown
}
}

Expand Down
Loading

0 comments on commit 36a348a

Please sign in to comment.