-
-
Save rudyryk/8cbe067a1363b45351f6 to your computer and use it in GitHub Desktop.
// | |
// Badge.cs | |
// Created by Alexey Kinev on 19 Jan 2015. | |
// | |
// Licensed under The MIT License (MIT) | |
// http://opensource.org/licenses/MIT | |
// | |
// Copyright (c) 2015 Alexey Kinev <[email protected]> | |
// | |
using System; | |
using Xamarin.Forms; | |
namespace ZeroFiveBit.Forms.Basic | |
{ | |
/// <summary> | |
/// Badge. | |
/// </summary> | |
public class Badge : AbsoluteLayout | |
{ | |
/// <summary> | |
/// The text property. | |
/// </summary> | |
public static readonly BindableProperty TextProperty = | |
BindableProperty.Create("Text", typeof(String), typeof(Badge), ""); | |
/// <summary> | |
/// The box color property. | |
/// </summary> | |
public static readonly BindableProperty BoxColorProperty = | |
BindableProperty.Create("BoxColor", typeof(Color), typeof(Badge), Color.Default); | |
/// <summary> | |
/// The text. | |
/// </summary> | |
public string Text | |
{ | |
get { return (string)GetValue(TextProperty); } | |
set { SetValue(TextProperty, value); } | |
} | |
/// <summary> | |
/// Gets or sets the color of the box. | |
/// </summary> | |
public Color BoxColor | |
{ | |
get { return (Color)GetValue(BoxColorProperty); } | |
set { SetValue(BoxColorProperty, value); } | |
} | |
/// <summary> | |
/// The box. | |
/// </summary> | |
protected RoundedBox Box; | |
/// <summary> | |
/// The label. | |
/// </summary> | |
protected Label Label; | |
/// <summary> | |
/// Initializes a new instance of the <see cref="ZeroFiveBit.Forms.Basic.Badge"/> class. | |
/// </summary> | |
public Badge(double size, double fontSize) | |
{ | |
HeightRequest = size; | |
WidthRequest = HeightRequest; | |
// Box | |
Box = new RoundedBox { | |
CornerRadius = HeightRequest / 2 | |
}; | |
Box.SetBinding(BackgroundColorProperty, new Binding("BoxColor", source: this)); | |
Children.Add(Box, new Rectangle(0, 0, 1.0, 1.0), AbsoluteLayoutFlags.All); | |
// Label | |
Label = new Label { | |
TextColor = Color.White, | |
FontSize = fontSize, | |
XAlign = TextAlignment.Center, | |
YAlign = TextAlignment.Center | |
}; | |
Label.SetBinding(Label.TextProperty, new Binding("Text", | |
BindingMode.OneWay, source: this)); | |
Children.Add(Label, new Rectangle(0, 0, 1.0, 1.0), AbsoluteLayoutFlags.All); | |
// Auto-width | |
SetBinding(WidthRequestProperty, new Binding("Text", BindingMode.OneWay, | |
new BadgeWidthConverter(WidthRequest), source: this)); | |
// Hide if no value | |
SetBinding(IsVisibleProperty, new Binding("Text", BindingMode.OneWay, | |
new BadgeVisibleValueConverter(), source: this)); | |
// Default color | |
BoxColor = Color.Red; | |
} | |
} | |
/// <summary> | |
/// Badge visible value converter. | |
/// </summary> | |
class BadgeVisibleValueConverter : IValueConverter | |
{ | |
#region IValueConverter implementation | |
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) | |
{ | |
var text = value as string; | |
return !String.IsNullOrEmpty(text); | |
} | |
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) | |
{ | |
throw new NotImplementedException(); | |
} | |
#endregion | |
} | |
/// <summary> | |
/// Badge width converter. | |
/// </summary> | |
class BadgeWidthConverter : IValueConverter | |
{ | |
/// <summary> | |
/// The width of the base. | |
/// </summary> | |
readonly double baseWidth; | |
/// <summary> | |
/// The width ratio. | |
/// </summary> | |
const double widthRatio = 0.33; | |
public BadgeWidthConverter(double baseWidth) | |
{ | |
this.baseWidth = baseWidth; | |
} | |
#region IValueConverter implementation | |
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) | |
{ | |
var text = value as string; | |
if ((text != null) && (text.Length > 1)) | |
{ | |
// We won't measure text length exactly here! | |
// May be we should, but it's too tricky. So, | |
// we'll just approximate new badge width as | |
// linear function from text legth. | |
return baseWidth * (1 + widthRatio * (text.Length - 1)); | |
} | |
return baseWidth; | |
} | |
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) | |
{ | |
throw new NotImplementedException(); | |
} | |
#endregion | |
} | |
} | |
// | |
// RoundedBox.cs | |
// Created by Alexey Kinev on 19 Jan 2015. | |
// | |
// Licensed under The MIT License (MIT) | |
// http://opensource.org/licenses/MIT | |
// | |
// Copyright (c) 2015 Alexey Kinev <[email protected]> | |
// | |
using System; | |
using Xamarin.Forms; | |
namespace ZeroFiveBit.Forms.Basic | |
{ | |
public class RoundedBox : BoxView | |
{ | |
/// <summary> | |
/// The corner radius property. | |
/// </summary> | |
public static readonly BindableProperty CornerRadiusProperty = | |
BindableProperty.Create("CornerRadius", typeof(double), typeof(RoundedBox), 0.0); | |
/// <summary> | |
/// Gets or sets the corner radius. | |
/// </summary> | |
public double CornerRadius | |
{ | |
get { return (double)GetValue(CornerRadiusProperty); } | |
set { SetValue(CornerRadiusProperty, value); } | |
} | |
} | |
} | |
// | |
// RoundedBoxRenderer_Droid.cs | |
// Created by Alexey Kinev on 26 Apr 2015. | |
// | |
// Licensed under The MIT License (MIT) | |
// http://opensource.org/licenses/MIT | |
// | |
// Copyright (c) 2015 Alexey Kinev <[email protected]> | |
// | |
using System; | |
using System.ComponentModel; | |
using Xamarin.Forms; | |
using Xamarin.Forms.Platform.Android; | |
using Android.Graphics; | |
using ZeroFiveBit.Forms.Basic; | |
using ZeroFiveBit.Forms.Basic.Droid; | |
[assembly: ExportRenderer(typeof(RoundedBox), typeof(RoundedBoxRenderer))] | |
namespace ZeroFiveBit.Forms.Basic.Droid | |
{ | |
public class RoundedBoxRenderer : BoxRenderer | |
{ | |
protected override void OnElementChanged(ElementChangedEventArgs<BoxView> e) | |
{ | |
base.OnElementChanged(e); | |
SetWillNotDraw(false); | |
Invalidate(); | |
} | |
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) | |
{ | |
base.OnElementPropertyChanged(sender, e); | |
if (e.PropertyName == RoundedBox.CornerRadiusProperty.PropertyName) | |
{ | |
Invalidate(); | |
} | |
} | |
public override void Draw(Canvas canvas) | |
{ | |
var box = Element as RoundedBox; | |
var rect = new Rect(); | |
var paint = new Paint() { | |
Color = box.BackgroundColor.ToAndroid(), | |
AntiAlias = true, | |
}; | |
GetDrawingRect(rect); | |
var radius = (float)(rect.Width() / box.Width * box.CornerRadius); | |
canvas.DrawRoundRect(new RectF(rect), radius, radius, paint); | |
} | |
} | |
} | |
// | |
// RoundedBoxRenderer_iOS.cs | |
// Created by Alexey Kinev on 19 Jan 2015. | |
// | |
// Licensed under The MIT License (MIT) | |
// http://opensource.org/licenses/MIT | |
// | |
// Copyright (c) 2015 Alexey Kinev <[email protected]> | |
// | |
using System; | |
using System.ComponentModel; | |
using Xamarin.Forms; | |
using Xamarin.Forms.Platform.iOS; | |
using ZeroFiveBit.Forms.Basic; | |
using ZeroFiveBit.Forms.Basic.iOS; | |
[assembly: ExportRenderer(typeof(RoundedBox), typeof(RoundedBoxRenderer))] | |
namespace ZeroFiveBit.Forms.Basic.iOS | |
{ | |
public class RoundedBoxRenderer : BoxRenderer | |
{ | |
protected override void OnElementChanged(ElementChangedEventArgs<BoxView> e) | |
{ | |
base.OnElementChanged(e); | |
if (Element != null) | |
{ | |
Layer.MasksToBounds = true; | |
UpdateCornerRadius(Element as RoundedBox); | |
} | |
} | |
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) | |
{ | |
base.OnElementPropertyChanged(sender, e); | |
if (e.PropertyName == RoundedBox.CornerRadiusProperty.PropertyName) | |
{ | |
UpdateCornerRadius(Element as RoundedBox); | |
} | |
} | |
void UpdateCornerRadius(RoundedBox box) | |
{ | |
Layer.CornerRadius = (float)box.CornerRadius; | |
} | |
} | |
} | |
@padhisandeepkumar @sportzbee Adding a badge to toolbar item can't be simply done with Xamarin.Forms. It has to be implemented per-platform and this component isn't really helpful for that case.
Actually, it's probably even easier :) Because iOS8+ natively supports UIBarButton.badgeValue
! Not sure about Android, though.
Xaml sample:
<badge:Badge Text="3" WidthRequest="25" HeightRequest="25" VerticalOptions="Center" HorizontalOptions="Center" BoxColor="Blue">
<x:Arguments>
<x:Double>30</x:Double>
<x:Double>12</x:Double>
</x:Arguments>
</badge:Badge>
@jaisont07: Do you have a fix already for the misalignment? I'm facing the same issue
How to use it? can someone show an example of implementation? I just learning xamarin forms.
@sportzbee I added the badge to the ToolbarItem for iOS using a custom renderer as explained in this blog post.
By the way, if anyone has been able to do the same for Android, I'm interested, I've googled for a solution without any luck.
How can i use it? I have grid and inside it i have 7 image(Grid.Row="0" Grid.Column="0" and so on) how can i do to show badge each cell? The values that will be shown comes from a method like this(the value to be show is resultado):
decimal realizado = 0;
decimal previsto = 0;
foreach (var item in indItem)
{
var val = item.Nome == "Previsto" ? previsto = item.Valor : realizado = item.Valor;
}
decimal desvio = Math.Abs(previsto - realizado);
if (desvio < 1000)
resultado = Math.Truncate(desvio).ToString();
else
while (desvio >= 1000 && siglas.Count > 0)
{
desvio /= 1000;
resultado = Math.Truncate(desvio) + siglas[0];
siglas.RemoveAt(0);
}
if (CorIndicador == "VERDE")
image.Source = ImageSource.FromResource("Estapar.AppOperacional.Images.faturamento caixa-28.png");
else
{
var pinta = CorIndicador == "VERMELHO" ? image.Source = ImageSource.FromResource("Estapar.AppOperacional.Images.faturamento caixa-26.png") : image.Source = ImageSource.FromResource("Estapar.AppOperacional.Images.faturamento caixa-27.png");
}
label.Text = resultado;
and my xaml is like this
<ContentPage.Content>
<StackLayout Padding="0" Spacing="0" Margin="0">
<Grid x:Name="grd" RowSpacing="1" ColumnSpacing="1" Padding="0" Margin="0" >
<Grid.RowDefinitions>
<RowDefinition Height="1" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image x:Name="imgDesvioFat" Grid.Row="0" Grid.Column="0" Grid.RowSpan="2" Source="{local:ImageResource Operacional.Images.faturamento caixa-28.png}" Aspect="AspectFill">
<Image.GestureRecognizers>
<TapGestureRecognizer Tapped="OnDesvioFaturamentoTapReconizerTapped" NumberOfTapsRequired="1"></TapGestureRecognizer>
</Image.GestureRecognizers>
</Image>
<!--<Label x:Name="lblFaturamento" Text="" Grid.Row="0" Grid.Column="0" TextColor="White" FontSize="9" FontAttributes="Bold" />-->
<!--</Grid>-->
<Image x:Name="imgTckCancelados" Grid.Row="1" Grid.Column="1" Source="{local:ImageResource Operacinal.Images.tickets cancelados-05.png}" Aspect="AspectFill">
<Image.GestureRecognizers>
<TapGestureRecognizer Tapped="OnTckCanceladosTapGestureReconizerTapped" NumberOfTapsRequired="1"></TapGestureRecognizer>
</Image.GestureRecognizers>
</Image>
i shown just two images, but i have 7 images and the code is such. How can i show the badge and the value inside with my code?
Hi Sandeep,
Have you able to added the badge to toolbar item?