Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ class TitleAndButtonsContainer(context: Context) : ViewGroup(context) {
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
val titleComponent = getTitleComponent()
val isCenter = titleComponentAlignment == Alignment.Center
val isFill = titleComponentAlignment == Alignment.Fill
val containerWidth = r - l
val containerHeight = b - t
val isRTL = isRTL()
Expand All @@ -114,7 +115,7 @@ class TitleAndButtonsContainer(context: Context) : ViewGroup(context) {
val leftBarWidth = leftButtonBar.measuredWidth
val rightBarWidth = rightButtonBar.measuredWidth

val (titleLeft, titleRight) = resolveHorizontalTitleBoundsLimit(containerWidth, titleWidth, leftBarWidth, rightBarWidth, isCenter, isRTL)
val (titleLeft, titleRight) = resolveHorizontalTitleBoundsLimit(containerWidth, titleWidth, leftBarWidth, rightBarWidth, isCenter, isRTL, isFill)
val (titleTop, titleBottom) = resolveVerticalTitleBoundsLimit(containerHeight, titleHeight)
val (leftButtonsLeft, leftButtonsRight) = resolveLeftButtonsBounds(containerWidth, leftBarWidth, isRTL)
val (rightButtonsLeft, rightButtonsRight) = resolveRightButtonsBounds(containerWidth, rightButtonBar.measuredWidth, isRTL)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@ fun makeTitleAtMostWidthMeasureSpec(containerWidth: Int, rightBarWidth: Int, lef
return if (isCenter) {
val availableWidth = containerWidth - rightBarWidth - leftBarWidth
View.MeasureSpec.makeMeasureSpec(availableWidth, View.MeasureSpec.AT_MOST)
} else if (isFill) {
// Fill alignment must span the entire space between left and right button bars,
// so do not reserve the DEFAULT_LEFT_MARGIN_PX padding used for left-aligned titles.
val availableWidth = containerWidth - rightBarWidth - leftBarWidth
View.MeasureSpec.makeMeasureSpec(availableWidth, View.MeasureSpec.EXACTLY)
} else {
val availableWidth = containerWidth - rightBarWidth - leftBarWidth - 2 * DEFAULT_LEFT_MARGIN_PX
View.MeasureSpec.makeMeasureSpec(
availableWidth,
if (isFill) View.MeasureSpec.EXACTLY else View.MeasureSpec.AT_MOST
)
View.MeasureSpec.makeMeasureSpec(availableWidth, View.MeasureSpec.AT_MOST)
}
}

Expand All @@ -41,14 +43,22 @@ fun resolveHorizontalTitleBoundsLimit(
leftBarWidth: Int,
rightBarWidth: Int,
isCenter: Boolean,
isRTL: Boolean
isRTL: Boolean,
isFill: Boolean = false
): Pair<TitleLeft, TitleRight> {
val resolvedLeftBarWidth = if (isRTL) rightBarWidth else leftBarWidth
val resolvedRightBarWidth = if (isRTL) leftBarWidth else rightBarWidth
var suggestedLeft: TitleLeft
var suggestedRight: TitleRight

val rightLimit = parentWidth - resolvedRightBarWidth
if (isFill) {
// Fill alignment must span the entire space between the left and right
// button bars without the DEFAULT_LEFT_MARGIN_PX reservation used for
// left-aligned titles. Mirrors the measure spec produced by
// makeTitleAtMostWidthMeasureSpec when isFill = true.
return resolvedLeftBarWidth to rightLimit
}
if (isCenter) {
val availableSpace = parentWidth - resolvedLeftBarWidth - resolvedRightBarWidth
if (titleWidth >= availableSpace) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.reactnativenavigation.utils

import android.view.View
import com.reactnativenavigation.BaseRobolectricTest
import com.reactnativenavigation.views.stack.topbar.titlebar.DEFAULT_LEFT_MARGIN_PX
import com.reactnativenavigation.views.stack.topbar.titlebar.makeTitleAtMostWidthMeasureSpec
import com.reactnativenavigation.views.stack.topbar.titlebar.resolveHorizontalTitleBoundsLimit
import com.reactnativenavigation.views.stack.topbar.titlebar.resolveLeftButtonsBounds
import com.reactnativenavigation.views.stack.topbar.titlebar.resolveRightButtonsBounds
Expand Down Expand Up @@ -355,4 +357,82 @@ class TitleAndButtonsMeasurer : BaseRobolectricTest() {
assertEquals(parentWidth - leftButtons - DEFAULT_LEFT_MARGIN_PX - barWidth - DEFAULT_LEFT_MARGIN_PX, left)
assertEquals(parentWidth - leftButtons - DEFAULT_LEFT_MARGIN_PX, right)
}
}

// ----- makeTitleAtMostWidthMeasureSpec -----

@Test
fun `makeTitleAtMostWidthMeasureSpec - Fill - no buttons - EXACTLY full container width`() {
val spec = makeTitleAtMostWidthMeasureSpec(parentWidth, 0, 0, isCenter = false, isFill = true)
assertEquals(View.MeasureSpec.EXACTLY, View.MeasureSpec.getMode(spec))
assertEquals(parentWidth, View.MeasureSpec.getSize(spec))
}

@Test
fun `makeTitleAtMostWidthMeasureSpec - Fill - with buttons - EXACTLY width minus bars`() {
val leftBar = 120
val rightBar = 80
val spec = makeTitleAtMostWidthMeasureSpec(parentWidth, rightBar, leftBar, isCenter = false, isFill = true)
assertEquals(View.MeasureSpec.EXACTLY, View.MeasureSpec.getMode(spec))
assertEquals(parentWidth - leftBar - rightBar, View.MeasureSpec.getSize(spec))
}

@Test
fun `makeTitleAtMostWidthMeasureSpec - Center - AT_MOST full container width minus bars`() {
val leftBar = 100
val rightBar = 100
val spec = makeTitleAtMostWidthMeasureSpec(parentWidth, rightBar, leftBar, isCenter = true)
assertEquals(View.MeasureSpec.AT_MOST, View.MeasureSpec.getMode(spec))
assertEquals(parentWidth - leftBar - rightBar, View.MeasureSpec.getSize(spec))
}

@Test
fun `makeTitleAtMostWidthMeasureSpec - default (left-aligned) - keeps 2 x DEFAULT_LEFT_MARGIN_PX reservation`() {
val leftBar = 100
val rightBar = 100
val spec = makeTitleAtMostWidthMeasureSpec(parentWidth, rightBar, leftBar, isCenter = false, isFill = false)
assertEquals(View.MeasureSpec.AT_MOST, View.MeasureSpec.getMode(spec))
assertEquals(parentWidth - leftBar - rightBar - 2 * DEFAULT_LEFT_MARGIN_PX, View.MeasureSpec.getSize(spec))
}

// ----- resolveHorizontalTitleBoundsLimit - Fill alignment -----

@Test
fun `Fill - no buttons - Title should span full container width`() {
val barWidth = 200 // measured width of the title component
val leftButtons = 0
val rightButtons = 0
val isRTL = false
val center = false
val isFill = true
val (left, right) = resolveHorizontalTitleBoundsLimit(parentWidth, barWidth, leftButtons, rightButtons, center, isRTL, isFill)
assertEquals(0, left)
assertEquals(parentWidth, right)
}

@Test
fun `Fill - with buttons - Title should span between buttons without DEFAULT_LEFT_MARGIN_PX`() {
val barWidth = 200
val leftButtons = 120
val rightButtons = 80
val isRTL = false
val center = false
val isFill = true
val (left, right) = resolveHorizontalTitleBoundsLimit(parentWidth, barWidth, leftButtons, rightButtons, center, isRTL, isFill)
assertEquals(leftButtons, left)
assertEquals(parentWidth - rightButtons, right)
}

@Test
fun `RTL - Fill - with buttons - Title should span between buttons after RTL flip`() {
val barWidth = 200
val leftButtons = 120
val rightButtons = 80
val isRTL = true
val center = false
val isFill = true
val (left, right) = resolveHorizontalTitleBoundsLimit(parentWidth, barWidth, leftButtons, rightButtons, center, isRTL, isFill)
// RTL flips logical left/right: leftButtons render on the right edge, rightButtons on the left.
assertEquals(rightButtons, left)
assertEquals(parentWidth - leftButtons, right)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -352,8 +352,11 @@ class TitleAndButtonsContainerTest : BaseTest() {
)
component = uut.getTitleComponent()
idleMainLooper()
assertThat(component.left).isEqualTo(DEFAULT_LEFT_MARGIN_PX)
assertThat(component.right).isEqualTo(titleBarWidth + 2 * DEFAULT_LEFT_MARGIN_PX)
// Fill alignment must span the full container width between left and right
// button bars (zero-width here). The previous assertion that allowed the
// DEFAULT_LEFT_MARGIN_PX reservation matched left-aligned behaviour, not Fill.
assertThat(component.left).isEqualTo(0)
assertThat(component.right).isEqualTo(UUT_WIDTH)
}

@Test
Expand Down