Fix labels, lists and other tweaks
This commit is contained in:
@@ -558,7 +558,7 @@ public class SkiaButton : SkiaView, IButtonController
|
||||
// This ensures buttons are visible even without explicit styling
|
||||
if (!hasExplicitBackground)
|
||||
{
|
||||
bgColor = SkiaTheme.Gray200SK; // Default button background
|
||||
bgColor = SkiaTheme.ButtonBackgroundSK; // Theme-aware default button background
|
||||
}
|
||||
|
||||
bool hasBackground = hasExplicitBackground ? bgColor.Alpha > 0 : true;
|
||||
@@ -688,8 +688,8 @@ public class SkiaButton : SkiaView, IButtonController
|
||||
}
|
||||
else
|
||||
{
|
||||
// Default button (gray background) - use dark text for contrast
|
||||
textColor = SkiaTheme.Gray800SK;
|
||||
// Default button - use theme-appropriate text color for contrast
|
||||
textColor = SkiaTheme.CurrentTextSK;
|
||||
}
|
||||
|
||||
if (!IsEnabled)
|
||||
|
||||
@@ -289,7 +289,10 @@ public class SkiaCheckBox : SkiaView
|
||||
// Get colors as SKColor
|
||||
var colorSK = ToSKColor(Color);
|
||||
var checkColorSK = ToSKColor(CheckColor);
|
||||
var uncheckedBoxColorSK = ToSKColor(UncheckedBoxColor);
|
||||
// Use theme-aware color for unchecked box if default white
|
||||
var uncheckedBoxColorSK = UncheckedBoxColor == Colors.White
|
||||
? SkiaTheme.CurrentSurfaceSK
|
||||
: ToSKColor(UncheckedBoxColor);
|
||||
var borderColorSK = ToSKColor(BorderColor);
|
||||
var disabledColorSK = ToSKColor(DisabledColor);
|
||||
var hoveredBorderColorSK = ToSKColor(HoveredBorderColor);
|
||||
|
||||
@@ -429,14 +429,19 @@ public class SkiaCollectionView : SkiaItemsView
|
||||
rawHeight = ItemHeight;
|
||||
}
|
||||
|
||||
var measuredHeight = Math.Max(rawHeight, ItemHeight);
|
||||
if (!_itemHeights.TryGetValue(index, out var cachedHeight) || Math.Abs(cachedHeight - measuredHeight) > 1f)
|
||||
// Store the actual measured height for row sizing
|
||||
var cellHeight = Math.Max(rawHeight, ItemHeight);
|
||||
if (!_itemHeights.TryGetValue(index, out var cachedHeight) || Math.Abs(cachedHeight - cellHeight) > 1f)
|
||||
{
|
||||
_itemHeights[index] = measuredHeight;
|
||||
_itemHeights[index] = cellHeight;
|
||||
_heightsChangedDuringDraw = true;
|
||||
}
|
||||
|
||||
var actualBounds = new SKRect(bounds.Left, bounds.Top, bounds.Right, bounds.Top + measuredHeight);
|
||||
// Vertically center the content within the cell bounds
|
||||
// Use rawHeight (actual content height) for centering, not cellHeight
|
||||
var contentHeight = Math.Min(rawHeight, bounds.Height);
|
||||
var verticalOffset = Math.Max(0, (bounds.Height - contentHeight) / 2);
|
||||
var actualBounds = new SKRect(bounds.Left, bounds.Top + verticalOffset, bounds.Right, bounds.Top + verticalOffset + contentHeight);
|
||||
itemView.Arrange(new Rect(actualBounds.Left, actualBounds.Top, actualBounds.Width, actualBounds.Height));
|
||||
itemView.Draw(canvas);
|
||||
|
||||
|
||||
@@ -149,10 +149,12 @@ public class SkiaItemsView : SkiaView
|
||||
|
||||
/// <summary>
|
||||
/// Gets the height for a specific item, using cached height or default.
|
||||
/// Always returns at least ItemHeight to allow vertical centering of smaller content.
|
||||
/// </summary>
|
||||
protected float GetItemHeight(int index)
|
||||
{
|
||||
return _itemHeights.TryGetValue(index, out var height) ? height : _itemHeight;
|
||||
var cached = _itemHeights.TryGetValue(index, out var height) ? height : _itemHeight;
|
||||
return Math.Max(cached, _itemHeight);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -711,10 +711,6 @@ public class SkiaLabel : SkiaView
|
||||
|
||||
if (needsMultiLine)
|
||||
{
|
||||
var textBoundsDbg = new SKRect();
|
||||
paint.MeasureText(displayText, ref textBoundsDbg);
|
||||
if (displayText.StartsWith("Full XAML") || displayText.StartsWith("Shell nav"))
|
||||
Console.WriteLine($"[Label OnDraw] '{displayText.Substring(0, Math.Min(15, displayText.Length))}' textW={textBoundsDbg.Width:F0} boundsW={contentBounds.Width:F0} LineBreakMode={LineBreakMode}");
|
||||
DrawMultiLineText(canvas, paint, font, contentBounds, displayText);
|
||||
}
|
||||
else
|
||||
@@ -1126,6 +1122,15 @@ public class SkiaLabel : SkiaView
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if the entire paragraph fits on one line - no need to wrap
|
||||
// Use small tolerance to account for floating point precision
|
||||
float paragraphWidth = paint.MeasureText(paragraph);
|
||||
if (paragraphWidth <= maxWidth + 1.0f)
|
||||
{
|
||||
lines.Add(paragraph);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (LineBreakMode == LineBreakMode.CharacterWrap)
|
||||
{
|
||||
WrapByCharacter(paragraph, paint, maxWidth, lines);
|
||||
@@ -1236,9 +1241,11 @@ public class SkiaLabel : SkiaView
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use advance width (paint.MeasureText return value) not bounding box width
|
||||
// This must match what WrapText uses for consistency
|
||||
var textBounds = new SKRect();
|
||||
paint.MeasureText(displayText, ref textBounds);
|
||||
width = textBounds.Width;
|
||||
width = paint.MeasureText(displayText); // Advance width, not textBounds.Width
|
||||
height = textBounds.Height;
|
||||
|
||||
// Account for character spacing
|
||||
|
||||
@@ -454,8 +454,6 @@ public class SkiaStackLayout : SkiaLayoutView
|
||||
// Horizontal stack: give each child its measured width
|
||||
// Don't constrain - let content overflow if needed (parent clips)
|
||||
var useWidth = childWidth;
|
||||
if (child is SkiaLabel lbl)
|
||||
Console.WriteLine($"[HStack Arrange] Label '{lbl.Text?.Substring(0, Math.Min(15, lbl.Text?.Length ?? 0))}' childWidth={childWidth:F0} contentWidth={contentWidth:F0} offset={offset:F0}");
|
||||
|
||||
// Respect child's VerticalOptions for horizontal layouts
|
||||
var useHeight = Math.Min(childHeight, contentHeight);
|
||||
|
||||
@@ -141,16 +141,24 @@ public class SkiaPage : SkiaView
|
||||
|
||||
protected override void OnDraw(SKCanvas canvas, SKRect bounds)
|
||||
{
|
||||
// Draw background color
|
||||
// Draw background color - use theme-aware default if not set
|
||||
SKColor bgColor;
|
||||
if (BackgroundColor != null && BackgroundColor != Colors.Transparent)
|
||||
{
|
||||
using var bgPaint = new SKPaint
|
||||
{
|
||||
Color = GetEffectiveBackgroundColor(),
|
||||
Style = SKPaintStyle.Fill
|
||||
};
|
||||
canvas.DrawRect(bounds, bgPaint);
|
||||
bgColor = GetEffectiveBackgroundColor();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use theme-aware page background when no explicit color is set
|
||||
bgColor = SkiaTheme.CurrentPageBackgroundSK;
|
||||
}
|
||||
|
||||
using var bgPaint = new SKPaint
|
||||
{
|
||||
Color = bgColor,
|
||||
Style = SKPaintStyle.Fill
|
||||
};
|
||||
canvas.DrawRect(bounds, bgPaint);
|
||||
|
||||
// Draw background image if set
|
||||
if (BackgroundImage != null)
|
||||
|
||||
@@ -143,10 +143,16 @@ public class SkiaSearchBar : SkiaView
|
||||
float cornerRadius = (float)CornerRadius;
|
||||
float iconSize = (float)IconSize;
|
||||
|
||||
// Draw background
|
||||
// Draw background - use theme-aware color if not explicitly set
|
||||
var bgColor = SearchBarBackgroundColor.ToSKColor();
|
||||
// If using default light color, check for dark mode
|
||||
if (SearchBarBackgroundColor.Red > 0.9f && SearchBarBackgroundColor.Green > 0.9f && SearchBarBackgroundColor.Blue > 0.9f)
|
||||
{
|
||||
bgColor = SkiaTheme.InputBackgroundSK;
|
||||
}
|
||||
using var bgPaint = new SKPaint
|
||||
{
|
||||
Color = SearchBarBackgroundColor.ToSKColor(),
|
||||
Color = bgColor,
|
||||
IsAntialias = true,
|
||||
Style = SKPaintStyle.Fill
|
||||
};
|
||||
|
||||
@@ -317,4 +317,43 @@ public static class SkiaTheme
|
||||
internal static readonly SKColor DarkHoverSK = DarkHover.ToSKColor();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Theme-Aware Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if dark mode is currently active.
|
||||
/// </summary>
|
||||
public static bool IsDarkMode => Application.Current?.UserAppTheme == AppTheme.Dark;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the appropriate button background color for the current theme.
|
||||
/// </summary>
|
||||
public static SKColor ButtonBackgroundSK => IsDarkMode ? DarkSurfaceSK : Gray200SK;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the appropriate text color for the current theme.
|
||||
/// </summary>
|
||||
public static SKColor CurrentTextSK => IsDarkMode ? DarkTextSK : TextPrimarySK;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the appropriate background color for input controls in the current theme.
|
||||
/// </summary>
|
||||
public static SKColor InputBackgroundSK => IsDarkMode ? DarkBackgroundSK : BackgroundWhiteSK;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the appropriate border color for the current theme.
|
||||
/// </summary>
|
||||
public static SKColor CurrentBorderSK => IsDarkMode ? Gray600SK : BorderLightSK;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the appropriate surface background for the current theme.
|
||||
/// </summary>
|
||||
public static SKColor CurrentSurfaceSK => IsDarkMode ? DarkSurfaceSK : BackgroundWhiteSK;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the appropriate page background for the current theme.
|
||||
/// </summary>
|
||||
public static SKColor CurrentPageBackgroundSK => IsDarkMode ? DarkBackgroundSK : BackgroundWhiteSK;
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user