From 7056ab7e4e715d8202799e7955e1ea45d0ad58c6 Mon Sep 17 00:00:00 2001 From: logikonline Date: Fri, 16 Jan 2026 05:31:38 +0000 Subject: [PATCH] SearchBar completed --- Handlers/SearchBarHandler.cs | 2 +- Views/SkiaSearchBar.cs | 140 ++++++++++++++++++++++++++++++----- 2 files changed, 122 insertions(+), 20 deletions(-) diff --git a/Handlers/SearchBarHandler.cs b/Handlers/SearchBarHandler.cs index e5118b2..7f56930 100644 --- a/Handlers/SearchBarHandler.cs +++ b/Handlers/SearchBarHandler.cs @@ -119,7 +119,7 @@ public partial class SearchBarHandler : ViewHandler // CancelButtonColor maps to ClearButtonColor if (searchBar.CancelButtonColor is not null) - handler.PlatformView.ClearButtonColor = searchBar.CancelButtonColor.ToSKColor(); + handler.PlatformView.ClearButtonColor = searchBar.CancelButtonColor; } diff --git a/Views/SkiaSearchBar.cs b/Views/SkiaSearchBar.cs index 3678580..763337a 100644 --- a/Views/SkiaSearchBar.cs +++ b/Views/SkiaSearchBar.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Windows.Input; +using Microsoft.Maui.Controls; using Microsoft.Maui.Graphics; using Microsoft.Maui.Platform.Linux.Rendering; using SkiaSharp; @@ -9,12 +11,19 @@ namespace Microsoft.Maui.Platform; /// /// Skia-rendered search bar control. +/// Implements MAUI ISearchBar interface patterns. /// public class SkiaSearchBar : SkiaView { + #region Fields + private readonly SkiaEntry _entry; private bool _showClearButton; + #endregion + + #region Properties + public string Text { get => _entry.Text; @@ -39,18 +48,58 @@ public class SkiaSearchBar : SkiaView set => _entry.PlaceholderColor = value; } - public new SKColor BackgroundColor { get; set; } = new SKColor(0xF5, 0xF5, 0xF5); - public SKColor IconColor { get; set; } = new SKColor(0x75, 0x75, 0x75); - public SKColor ClearButtonColor { get; set; } = new SKColor(0x9E, 0x9E, 0x9E); - public SKColor FocusedBorderColor { get; set; } = new SKColor(0x21, 0x96, 0xF3); - public string FontFamily { get; set; } = "Sans"; - public float FontSize { get; set; } = 14; - public float CornerRadius { get; set; } = 8; - public float IconSize { get; set; } = 20; + public Color SearchBarBackgroundColor { get; set; } = Color.FromRgb(245, 245, 245); + public Color IconColor { get; set; } = Color.FromRgb(117, 117, 117); + public Color ClearButtonColor { get; set; } = Color.FromRgb(158, 158, 158); + public Color FocusedBorderColor { get; set; } = Color.FromRgb(33, 150, 243); + + public string FontFamily + { + get => _entry.FontFamily; + set => _entry.FontFamily = value; + } + + public double FontSize + { + get => _entry.FontSize; + set => _entry.FontSize = value; + } + + public FontAttributes FontAttributes + { + get => _entry.FontAttributes; + set => _entry.FontAttributes = value; + } + + public double CharacterSpacing + { + get => _entry.CharacterSpacing; + set => _entry.CharacterSpacing = value; + } + + public TextAlignment HorizontalTextAlignment + { + get => _entry.HorizontalTextAlignment; + set => _entry.HorizontalTextAlignment = value; + } + + public double CornerRadius { get; set; } = 8.0; + public double IconSize { get; set; } = 20.0; + + public ICommand? SearchCommand { get; set; } + public object? SearchCommandParameter { get; set; } + + #endregion + + #region Events public event EventHandler? TextChanged; public event EventHandler? SearchButtonPressed; + #endregion + + #region Constructor + public SkiaSearchBar() { _entry = new SkiaEntry @@ -70,25 +119,68 @@ public class SkiaSearchBar : SkiaView Invalidate(); }; - _entry.Completed += (s, e) => SearchButtonPressed?.Invoke(this, EventArgs.Empty); + _entry.Completed += (s, e) => + { + SearchButtonPressed?.Invoke(this, EventArgs.Empty); + if (SearchCommand?.CanExecute(SearchCommandParameter) == true) + { + SearchCommand.Execute(SearchCommandParameter); + } + }; IsFocusable = true; } + #endregion + + #region Helper Methods + + /// + /// Converts a MAUI Color to SkiaSharp SKColor. + /// + private static SKColor ToSKColor(Color? color) + { + if (color == null) return SKColors.Transparent; + return new SKColor( + (byte)(color.Red * 255), + (byte)(color.Green * 255), + (byte)(color.Blue * 255), + (byte)(color.Alpha * 255)); + } + + /// + /// Converts a MAUI Color to SKColor with modified alpha. + /// + private static SKColor ToSKColorWithAlpha(Color? color, byte alpha) + { + if (color == null) return SKColors.Transparent; + return new SKColor( + (byte)(color.Red * 255), + (byte)(color.Green * 255), + (byte)(color.Blue * 255), + alpha); + } + + #endregion + + #region Drawing + protected override void OnDraw(SKCanvas canvas, SKRect bounds) { - var iconPadding = 12f; - var clearButtonSize = 20f; + float iconPadding = 12f; + float clearButtonSize = 20f; + float cornerRadius = (float)CornerRadius; + float iconSize = (float)IconSize; // Draw background using var bgPaint = new SKPaint { - Color = BackgroundColor, + Color = ToSKColor(SearchBarBackgroundColor), IsAntialias = true, Style = SKPaintStyle.Fill }; - var bgRect = new SKRoundRect(bounds, CornerRadius); + var bgRect = new SKRoundRect(bounds, cornerRadius); canvas.DrawRoundRect(bgRect, bgPaint); // Draw focus border @@ -96,7 +188,7 @@ public class SkiaSearchBar : SkiaView { using var borderPaint = new SKPaint { - Color = FocusedBorderColor, + Color = ToSKColor(FocusedBorderColor), IsAntialias = true, Style = SKPaintStyle.Stroke, StrokeWidth = 2 @@ -107,10 +199,10 @@ public class SkiaSearchBar : SkiaView // Draw search icon var iconX = bounds.Left + iconPadding; var iconY = bounds.MidY; - DrawSearchIcon(canvas, iconX, iconY, IconSize); + DrawSearchIcon(canvas, iconX, iconY, iconSize); // Calculate entry bounds - leave space for clear button - var entryLeft = iconX + IconSize + iconPadding; + var entryLeft = iconX + iconSize + iconPadding; var entryRight = _showClearButton ? bounds.Right - clearButtonSize - iconPadding * 2 : bounds.Right - iconPadding; @@ -132,7 +224,7 @@ public class SkiaSearchBar : SkiaView { using var paint = new SKPaint { - Color = IconColor, + Color = ToSKColor(IconColor), IsAntialias = true, Style = SKPaintStyle.Stroke, StrokeWidth = 2, @@ -160,7 +252,7 @@ public class SkiaSearchBar : SkiaView // Draw circle background using var bgPaint = new SKPaint { - Color = ClearButtonColor.WithAlpha(80), + Color = ToSKColorWithAlpha(ClearButtonColor, 80), IsAntialias = true, Style = SKPaintStyle.Fill }; @@ -169,7 +261,7 @@ public class SkiaSearchBar : SkiaView // Draw X using var paint = new SKPaint { - Color = ClearButtonColor, + Color = ToSKColor(ClearButtonColor), IsAntialias = true, Style = SKPaintStyle.Stroke, StrokeWidth = 2, @@ -181,6 +273,10 @@ public class SkiaSearchBar : SkiaView canvas.DrawLine(x + offset, y - offset, x - offset, y + offset, paint); } + #endregion + + #region Input Handling + public override void OnPointerPressed(PointerEventArgs e) { if (!IsEnabled) return; @@ -236,8 +332,14 @@ public class SkiaSearchBar : SkiaView _entry.OnKeyUp(e); } + #endregion + + #region Measurement + protected override SKSize MeasureOverride(SKSize availableSize) { return new SKSize(250, 40); } + + #endregion }