SearchBar completed

This commit is contained in:
2026-01-16 05:31:38 +00:00
parent 1b1619de06
commit 7056ab7e4e
2 changed files with 122 additions and 20 deletions

View File

@@ -119,7 +119,7 @@ public partial class SearchBarHandler : ViewHandler<ISearchBar, SkiaSearchBar>
// CancelButtonColor maps to ClearButtonColor // CancelButtonColor maps to ClearButtonColor
if (searchBar.CancelButtonColor is not null) if (searchBar.CancelButtonColor is not null)
handler.PlatformView.ClearButtonColor = searchBar.CancelButtonColor.ToSKColor(); handler.PlatformView.ClearButtonColor = searchBar.CancelButtonColor;
} }

View File

@@ -1,6 +1,8 @@
// Licensed to the .NET Foundation under one or more agreements. // Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license. // 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.Graphics;
using Microsoft.Maui.Platform.Linux.Rendering; using Microsoft.Maui.Platform.Linux.Rendering;
using SkiaSharp; using SkiaSharp;
@@ -9,12 +11,19 @@ namespace Microsoft.Maui.Platform;
/// <summary> /// <summary>
/// Skia-rendered search bar control. /// Skia-rendered search bar control.
/// Implements MAUI ISearchBar interface patterns.
/// </summary> /// </summary>
public class SkiaSearchBar : SkiaView public class SkiaSearchBar : SkiaView
{ {
#region Fields
private readonly SkiaEntry _entry; private readonly SkiaEntry _entry;
private bool _showClearButton; private bool _showClearButton;
#endregion
#region Properties
public string Text public string Text
{ {
get => _entry.Text; get => _entry.Text;
@@ -39,18 +48,58 @@ public class SkiaSearchBar : SkiaView
set => _entry.PlaceholderColor = value; set => _entry.PlaceholderColor = value;
} }
public new SKColor BackgroundColor { get; set; } = new SKColor(0xF5, 0xF5, 0xF5); public Color SearchBarBackgroundColor { get; set; } = Color.FromRgb(245, 245, 245);
public SKColor IconColor { get; set; } = new SKColor(0x75, 0x75, 0x75); public Color IconColor { get; set; } = Color.FromRgb(117, 117, 117);
public SKColor ClearButtonColor { get; set; } = new SKColor(0x9E, 0x9E, 0x9E); public Color ClearButtonColor { get; set; } = Color.FromRgb(158, 158, 158);
public SKColor FocusedBorderColor { get; set; } = new SKColor(0x21, 0x96, 0xF3); public Color FocusedBorderColor { get; set; } = Color.FromRgb(33, 150, 243);
public string FontFamily { get; set; } = "Sans";
public float FontSize { get; set; } = 14; public string FontFamily
public float CornerRadius { get; set; } = 8; {
public float IconSize { get; set; } = 20; 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<TextChangedEventArgs>? TextChanged; public event EventHandler<TextChangedEventArgs>? TextChanged;
public event EventHandler? SearchButtonPressed; public event EventHandler? SearchButtonPressed;
#endregion
#region Constructor
public SkiaSearchBar() public SkiaSearchBar()
{ {
_entry = new SkiaEntry _entry = new SkiaEntry
@@ -70,25 +119,68 @@ public class SkiaSearchBar : SkiaView
Invalidate(); 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; IsFocusable = true;
} }
#endregion
#region Helper Methods
/// <summary>
/// Converts a MAUI Color to SkiaSharp SKColor.
/// </summary>
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));
}
/// <summary>
/// Converts a MAUI Color to SKColor with modified alpha.
/// </summary>
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) protected override void OnDraw(SKCanvas canvas, SKRect bounds)
{ {
var iconPadding = 12f; float iconPadding = 12f;
var clearButtonSize = 20f; float clearButtonSize = 20f;
float cornerRadius = (float)CornerRadius;
float iconSize = (float)IconSize;
// Draw background // Draw background
using var bgPaint = new SKPaint using var bgPaint = new SKPaint
{ {
Color = BackgroundColor, Color = ToSKColor(SearchBarBackgroundColor),
IsAntialias = true, IsAntialias = true,
Style = SKPaintStyle.Fill Style = SKPaintStyle.Fill
}; };
var bgRect = new SKRoundRect(bounds, CornerRadius); var bgRect = new SKRoundRect(bounds, cornerRadius);
canvas.DrawRoundRect(bgRect, bgPaint); canvas.DrawRoundRect(bgRect, bgPaint);
// Draw focus border // Draw focus border
@@ -96,7 +188,7 @@ public class SkiaSearchBar : SkiaView
{ {
using var borderPaint = new SKPaint using var borderPaint = new SKPaint
{ {
Color = FocusedBorderColor, Color = ToSKColor(FocusedBorderColor),
IsAntialias = true, IsAntialias = true,
Style = SKPaintStyle.Stroke, Style = SKPaintStyle.Stroke,
StrokeWidth = 2 StrokeWidth = 2
@@ -107,10 +199,10 @@ public class SkiaSearchBar : SkiaView
// Draw search icon // Draw search icon
var iconX = bounds.Left + iconPadding; var iconX = bounds.Left + iconPadding;
var iconY = bounds.MidY; var iconY = bounds.MidY;
DrawSearchIcon(canvas, iconX, iconY, IconSize); DrawSearchIcon(canvas, iconX, iconY, iconSize);
// Calculate entry bounds - leave space for clear button // Calculate entry bounds - leave space for clear button
var entryLeft = iconX + IconSize + iconPadding; var entryLeft = iconX + iconSize + iconPadding;
var entryRight = _showClearButton var entryRight = _showClearButton
? bounds.Right - clearButtonSize - iconPadding * 2 ? bounds.Right - clearButtonSize - iconPadding * 2
: bounds.Right - iconPadding; : bounds.Right - iconPadding;
@@ -132,7 +224,7 @@ public class SkiaSearchBar : SkiaView
{ {
using var paint = new SKPaint using var paint = new SKPaint
{ {
Color = IconColor, Color = ToSKColor(IconColor),
IsAntialias = true, IsAntialias = true,
Style = SKPaintStyle.Stroke, Style = SKPaintStyle.Stroke,
StrokeWidth = 2, StrokeWidth = 2,
@@ -160,7 +252,7 @@ public class SkiaSearchBar : SkiaView
// Draw circle background // Draw circle background
using var bgPaint = new SKPaint using var bgPaint = new SKPaint
{ {
Color = ClearButtonColor.WithAlpha(80), Color = ToSKColorWithAlpha(ClearButtonColor, 80),
IsAntialias = true, IsAntialias = true,
Style = SKPaintStyle.Fill Style = SKPaintStyle.Fill
}; };
@@ -169,7 +261,7 @@ public class SkiaSearchBar : SkiaView
// Draw X // Draw X
using var paint = new SKPaint using var paint = new SKPaint
{ {
Color = ClearButtonColor, Color = ToSKColor(ClearButtonColor),
IsAntialias = true, IsAntialias = true,
Style = SKPaintStyle.Stroke, Style = SKPaintStyle.Stroke,
StrokeWidth = 2, StrokeWidth = 2,
@@ -181,6 +273,10 @@ public class SkiaSearchBar : SkiaView
canvas.DrawLine(x + offset, y - offset, x - offset, y + offset, paint); canvas.DrawLine(x + offset, y - offset, x - offset, y + offset, paint);
} }
#endregion
#region Input Handling
public override void OnPointerPressed(PointerEventArgs e) public override void OnPointerPressed(PointerEventArgs e)
{ {
if (!IsEnabled) return; if (!IsEnabled) return;
@@ -236,8 +332,14 @@ public class SkiaSearchBar : SkiaView
_entry.OnKeyUp(e); _entry.OnKeyUp(e);
} }
#endregion
#region Measurement
protected override SKSize MeasureOverride(SKSize availableSize) protected override SKSize MeasureOverride(SKSize availableSize)
{ {
return new SKSize(250, 40); return new SKSize(250, 40);
} }
#endregion
} }