SearchBar completed
This commit is contained in:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user