Skip to content

Commit fa29e20

Browse files
Merge pull request #223 from Kamalesh-Periyasamy/Button-LineBreakMode-Issue
Resolved the button text does not wrap without explicit Widthrequest
2 parents 5720452 + d2ca309 commit fa29e20

File tree

3 files changed

+99
-11
lines changed

3 files changed

+99
-11
lines changed

maui/src/Button/SfButton.Methods.cs

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -540,15 +540,20 @@ double CalculateWidth(double widthConstraint)
540540
{
541541
if (widthConstraint == double.PositiveInfinity || widthConstraint < 0 || WidthRequest < 0)
542542
{
543+
double buttonContentWidth = 0;
543544
if (ShowIcon && ImageSource != null)
544545
{
545-
return ImageAlignment == Alignment.Top || ImageAlignment == Alignment.Bottom
546+
buttonContentWidth = ImageAlignment == Alignment.Top || ImageAlignment == Alignment.Bottom
546547
? Math.Max(ImageSize, TextSize.Width) + Padding.Left + Padding.Right + StrokeThickness + (_leftPadding * 2) + (_rightPadding * 2)
547548
: ImageSize + TextSize.Width + StrokeThickness + Padding.Left + Padding.Right + (_leftPadding * 2) + (_rightPadding * 2);
548549
}
549550
else
550551
{
551-
return TextSize.Width + Padding.Left + Padding.Right + StrokeThickness + (_leftPadding * 2) + (_rightPadding * 2);
552+
buttonContentWidth = TextSize.Width + Padding.Left + Padding.Right + StrokeThickness + (_leftPadding * 2) + (_rightPadding * 2);
553+
}
554+
if (buttonContentWidth <= widthConstraint)
555+
{
556+
return buttonContentWidth;
552557
}
553558
}
554559
return widthConstraint;
@@ -564,6 +569,7 @@ double CalculateHeight(double heightConstraint, double width)
564569
{
565570
if (heightConstraint == double.PositiveInfinity || heightConstraint < 0 || VerticalOptions != LayoutOptions.Fill)
566571
{
572+
width = CalculateAvailableTextWidth(width);
567573
if (LineBreakMode == LineBreakMode.WordWrap || LineBreakMode == LineBreakMode.CharacterWrap)
568574
{
569575
_numberOfLines = StringExtensions.GetLinesCount(Text, (float)width, this, LineBreakMode, out _);
@@ -587,6 +593,46 @@ double CalculateHeight(double heightConstraint, double width)
587593
return heightConstraint;
588594
}
589595

596+
/// <summary>
597+
/// Calculates the available width for the text area within the button.
598+
/// </summary>
599+
/// <param name="width"></param>
600+
/// <returns></returns>
601+
double CalculateAvailableTextWidth(double width)
602+
{
603+
if (ShowIcon && ImageSource != null)
604+
{
605+
if (ImageAlignment == Alignment.Start || ImageAlignment == Alignment.Left)
606+
{
607+
width = (ImageAlignment == Alignment.Start && _isRightToLeft) ? Math.Abs((float)(width - _textRectF.X - ImageSize - (_leftIconPadding * 2) - _textAreaPadding - (StrokeThickness / 2) - Padding.Right))
608+
: Math.Abs((float)(width - _textRectF.X - (StrokeThickness / 2) - _textAreaPadding - Padding.Right));
609+
610+
}
611+
else if (ImageAlignment == Alignment.End || ImageAlignment == Alignment.Right)
612+
{
613+
width = (ImageAlignment == Alignment.End && _isRightToLeft) ? Math.Abs((float)(width - _textRectF.X - (StrokeThickness / 2) - _textAreaPadding - Padding.Right))
614+
: Math.Abs((float)(width - _textRectF.X - ImageSize - _leftIconPadding - _leftIconPadding - _textAreaPadding - (StrokeThickness / 2) - Padding.Right));
615+
}
616+
else if (ImageAlignment == Alignment.Top)
617+
{
618+
width = Math.Abs((float)(width - _textAreaPadding - Padding.Left - Padding.Right - _textAreaPadding - (StrokeThickness / 2) - (StrokeThickness / 2)));
619+
}
620+
else if (ImageAlignment == Alignment.Bottom)
621+
{
622+
width = Math.Abs((float)(width - _textAreaPadding - Padding.Left - Padding.Right - _textAreaPadding - (StrokeThickness / 2) - (StrokeThickness / 2)));
623+
}
624+
else
625+
{
626+
width = Math.Abs((float)(width - _textRectF.X - (StrokeThickness / 2) - _textAreaPadding - Padding.Right));
627+
}
628+
}
629+
else
630+
{
631+
width = Math.Abs((float)(width - _textAreaPadding - Padding.Left - Padding.Right - _textAreaPadding - StrokeThickness));
632+
}
633+
return width;
634+
}
635+
590636
/// <summary>
591637
/// Measures the size of child elements if present and returns the size.
592638
/// </summary>
@@ -735,7 +781,10 @@ internal override void DrawText(ICanvas canvas, RectF dirtyRect)
735781
canvas.SaveState();
736782
float availableWidth = _textRectF.Width;
737783
#if ANDROID
738-
availableWidth-=AndroidTextMargin;
784+
if (LineBreakMode != LineBreakMode.WordWrap)
785+
{
786+
availableWidth -= AndroidTextMargin;
787+
}
739788
#endif
740789
var trimmedText = _isFontIconText ? Text : StringExtensions.GetTextBasedOnLineBreakMode(ApplyTextTransform(Text), this, availableWidth, _textRectF.Height, LineBreakMode);
741790
if (_textRectF.Width > 0 && _textRectF.Height > 0)

maui/src/Core/Extensions/StringExtensions.cs

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,15 @@ public static Size Measure(this string text, double availableWidth, ITextElement
4747
/// </summary>
4848
/// Note: It can be used from chart and sunbrust chart datalabels implement.
4949
public static string TrimTextToFit(this string inputText, ITextElement textElement, double availableWidth)
50-
{
51-
while (inputText.Measure(textElement).Width > availableWidth && inputText.Length > 0)
52-
{
53-
inputText = inputText.Substring(0, inputText.Length - 1);
54-
}
55-
return inputText;
56-
}
50+
{
51+
string trimmedText = inputText.TrimEnd();
52+
while (trimmedText.Measure(textElement).Width >= availableWidth && trimmedText.Length > 0)
53+
{
54+
trimmedText = trimmedText.Substring(0, trimmedText.Length - 1);
55+
trimmedText = trimmedText.TrimEnd();
56+
}
57+
return trimmedText;
58+
}
5759

5860
/// <summary>
5961
/// This method is utilized to get the total number of lines count from the text to fit within the available width.
@@ -171,13 +173,24 @@ public static string GetTextBasedOnLineBreakMode(this string text, ITextElement
171173
var leftTrimmedTextSize = leftTrimmedText.Measure((ITextElement)textElement);
172174
int leftLength = 0;
173175

174-
while (leftTrimmedTextSize.Width > charsToKeep && leftTrimmedText.Length > 0)
176+
while (leftTrimmedTextSize.Width >= charsToKeep && leftTrimmedText.Length > 0)
175177
{
176178
leftTrimmedText = leftTrimmedText.Substring(0, leftTrimmedText.Length - 1);
177179
leftTrimmedTextSize = leftTrimmedText.Measure((ITextElement)textElement);
178180
leftLength++;
179181
}
180182
string rightText = text.Substring(leftLength);
183+
184+
leftTrimmedText = leftTrimmedText.TrimEnd();
185+
rightText = rightText.TrimStart();
186+
187+
var rightTrimmedTextSize = rightText.Measure((ITextElement)textElement);
188+
while (rightTrimmedTextSize.Width >= charsToKeep && rightText.Length > 0)
189+
{
190+
leftLength++;
191+
rightText = text.Substring(leftLength).TrimStart();
192+
rightTrimmedTextSize = rightText.Measure((ITextElement)textElement);
193+
}
181194
string trimmedText = leftTrimmedText + "..." + rightText;
182195
return trimmedText;
183196

maui/tests/Syncfusion.Maui.Toolkit.UnitTest/Buttons/SfButtonUnitTests.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,32 @@ public void CalculateWidth_ShouldReturnWidth(double width, double expectedValue)
699699
Assert.Equal(expectedValue, actualValue);
700700
}
701701

702+
[Theory]
703+
[InlineData(150, 142, "SampleImage1.png", Alignment.Left)]
704+
[InlineData(150, 108, "SampleImage1.png", Alignment.Right)]
705+
[InlineData(180, 164, "SampleImage1.png", Alignment.Top)]
706+
[InlineData(250, 234, "SampleImage1.png", Alignment.Bottom)]
707+
[InlineData(200, 184, "SampleImage1.png", null)]
708+
public void CalculateAvailableTextWidth_ShouldReturnExpectedWidth(double width, double expectedValue, string imagePath, Alignment? alignment = null)
709+
{
710+
// Arrange
711+
var button = new SfButton();
712+
button.ImageSource = ImageSource.FromFile(imagePath);
713+
714+
if (alignment != null)
715+
{
716+
button.ShowIcon = true;
717+
button.ImageAlignment = (Alignment)alignment;
718+
}
719+
720+
// Set up as needed
721+
button.Padding = new Thickness(4, 4, 4, 4);
722+
723+
var actualValue = InvokePrivateMethod(button, "CalculateAvailableTextWidth", width);
724+
725+
Assert.Equal(expectedValue, actualValue);
726+
}
727+
702728
[Theory]
703729
[InlineData(true, false, false, false, "#000000")]
704730
[InlineData(true, true, false, false, "#FF0000")]

0 commit comments

Comments
 (0)