Skip to content

Instantly share code, notes, and snippets.

@kevinmutlow
Created November 17, 2017 02:39
Show Gist options
  • Save kevinmutlow/af7e5105e00c762863ec4517825b0bce to your computer and use it in GitHub Desktop.
Save kevinmutlow/af7e5105e00c762863ec4517825b0bce to your computer and use it in GitHub Desktop.
4 ways to create rounded Labels in Xamarin.Forms.
using App.Droid.Effects;
using App.Core.Effects;
using System;
using System.ComponentModel;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using Android.Graphics.Drawables;
using Android.Util;
using Android.Content;
[assembly: ExportEffect(typeof(CornerRadiusEffect_Droid), "CornerRadiusEffect")]
namespace App.Droid.Effects
{
public class CornerRadiusEffect_Droid : PlatformEffect
{
Drawable orig_Background;
protected override void OnAttached()
{
AddCornerRadius();
}
protected override void OnDetached()
{
RemoveCornerRadius();
}
protected override void OnElementPropertyChanged(PropertyChangedEventArgs args)
{
base.OnElementPropertyChanged(args);
if (args.PropertyName == RoundLabelEffect.CornerRadiusProperty.PropertyName)
{
UpdateCornerRadius();
}
}
private void AddCornerRadius()
{
var view = (View)Element;
if (view == null) return;
orig_Background = Control.Background;
SetBackgroundOnControl();
}
private void UpdateCornerRadius()
{
SetBackgroundOnControl();
}
private void RemoveCornerRadius()
{
Control.SetBackground(orig_Background);
}
private void SetBackgroundOnControl()
{
var radius = (float)RoundLabelEffect.GetCornerRadius(Element);
var radiusPixels = DpToPixels(Android.App.Application.Context, radius);
var view = (View)Element;
var backgroundColor = view.BackgroundColor;
view.BackgroundColor = Color.Transparent;
GradientDrawable _gradientBackground = new GradientDrawable();
_gradientBackground.SetShape(ShapeType.Rectangle);
_gradientBackground.SetColor(backgroundColor.ToAndroid());
_gradientBackground.SetCornerRadius(radiusPixels);
Control.SetBackground(_gradientBackground);
}
static float DpToPixels(Context context, float valueInDp)
{
DisplayMetrics metrics = context.Resources.DisplayMetrics;
return TypedValue.ApplyDimension(ComplexUnitType.Dip, valueInDp, metrics);
}
}
}
using App.Core.Effects;
using App.iOS.Effects;
using System;
using System.ComponentModel;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportEffect(typeof(CornerRadiusEffect_iOS), "CornerRadiusEffect")]
namespace App.iOS.Effects
{
public class CornerRadiusEffect_iOS : PlatformEffect
{
private nfloat origCornerRadius = 0;
protected override void OnAttached()
{
AddCornerRadius();
}
protected override void OnDetached()
{
RemoveCornerRadius();
}
protected override void OnElementPropertyChanged(PropertyChangedEventArgs args)
{
base.OnElementPropertyChanged(args);
if (args.PropertyName == RoundLabelEffect.CornerRadiusProperty.PropertyName)
{
UpdateCornerRadius();
}
}
private void AddCornerRadius()
{
origCornerRadius = this.Container.Layer.CornerRadius;
this.Container.Layer.CornerRadius = (nfloat)RoundLabelEffect.GetCornerRadius(Element);
}
private void UpdateCornerRadius()
{
this.Container.Layer.CornerRadius = (nfloat)RoundLabelEffect.GetCornerRadius(Element);
}
private void RemoveCornerRadius()
{
this.Container.Layer.CornerRadius = origCornerRadius;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Xamarin.Forms.Platform.Android;
using Xamarin.Forms;
using Android.Graphics;
using App.Droid.Renderers;
[assembly: ExportRenderer(typeof(Xamarin.Forms.Label), typeof(IconFontLabelRenderer_Droid))]
namespace App.Droid.Renderers
{
public class IconFontLabelRenderer_Droid : Xamarin.Forms.Platform.Android.LabelRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
if (Element == null || Element.Text == null || Element.Text.Length == 0)
return;
Typeface tf = null;
if (IconFontUtils.GetTypeFaceForFontFamily(Element.FontFamily, out tf))
Control.Typeface = tf;
}
static class IconFontUtils
{
private static readonly Tuple<string, string>[] CustomFonts = new Tuple<string, string>[]
{
new Tuple<string, string>("fontawesome", "Fonts/fontawesome-webfont.ttf"),
};
public static bool GetTypeFaceForFontFamily(string fontFamily, out Typeface tf)
{
foreach (Tuple<string, string> customFont in CustomFonts)
{
if (fontFamily == customFont.Item1)
{
tf = Typeface.CreateFromAsset(Xamarin.Forms.Forms.Context.ApplicationContext.Assets, customFont.Item2);
return true;
}
}
tf = null;
return false;
}
}
}
}
using Xamarin.Forms;
namespace App.Core.Controls
{
public class RoundLabel : Label
{
public float CornerRadius { get; set; }
}
}
using System.Linq;
using Xamarin.Forms;
namespace App.Core.Effects
{
public static class RoundLabelEffect
{
public static readonly BindableProperty CornerRadiusProperty =
BindableProperty.CreateAttached("CornerRadius", typeof(double), typeof(RoundLabelEffect), 0.0, propertyChanged: OnCornerRadiusChanged);
private static void OnCornerRadiusChanged(BindableObject bindable, object oldValue, object newValue)
{
var view = bindable as View;
if (view == null)
return;
var radius = (double)newValue;
if (radius > 0)
{
view.Effects.Add(new CornerRadiusEffect());
}
else
{
var toRemove = view.Effects.FirstOrDefault(e => e is CornerRadiusEffect);
if (toRemove != null)
view.Effects.Remove(toRemove);
}
}
public static void SetCornerRadius(BindableObject view, double radius)
{
view.SetValue(CornerRadiusProperty, radius);
}
public static double GetCornerRadius(BindableObject view)
{
return (double)view.GetValue(CornerRadiusProperty);
}
class CornerRadiusEffect : RoutingEffect
{
public CornerRadiusEffect() : base("kvntech.CornerRadiusEffect")
{
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Xamarin.Forms;
using App.Core.Controls;
using Xamarin.Forms.Platform.Android;
using App.Droid.Renderers;
using Android.Graphics.Drawables;
using Android.Util;
[assembly: ExportRenderer(typeof(RoundLabel), typeof(RoundLabelRenderer_Droid))]
namespace App.Droid.Renderers
{
public class RoundLabelRenderer_Droid : LabelRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
if(e.NewElement != null)
{
var label = e.NewElement as RoundLabel;
if (label != null)
{
SetBackgroundOnControl(label, label.CornerRadius);
}
}
}
private void SetBackgroundOnControl(RoundLabel view, float radius)
{
var radiusPixels = DpToPixels(this.Context, radius);
var backgroundColor = view.BackgroundColor;
view.BackgroundColor = Color.Transparent;
GradientDrawable _gradientBackground = new GradientDrawable();
_gradientBackground.SetShape(ShapeType.Rectangle);
_gradientBackground.SetColor(backgroundColor.ToAndroid());
_gradientBackground.SetCornerRadius(radiusPixels);
Control.SetBackground(_gradientBackground);
}
static float DpToPixels(Context context, float valueInDp)
{
DisplayMetrics metrics = context.Resources.DisplayMetrics;
return TypedValue.ApplyDimension(ComplexUnitType.Dip, valueInDp, metrics);
}
}
}
using App.Core.Controls;
using App.iOS.Renderers;
using System;
using System.Collections.Generic;
using System.Text;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(RoundLabel), typeof(RoundLabelRenderer_iOS))]
namespace App.iOS.Renderers
{
public class RoundLabelRenderer_iOS : LabelRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
var label = e.NewElement as RoundLabel;
if(label != null)
{
SetCornerRadius((nfloat)label.CornerRadius);
}
}
}
private void SetCornerRadius(nfloat radius)
{
Layer.MasksToBounds = true;
Layer.CornerRadius = radius;
}
}
}
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace App.Core.Pages.Other
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class RoundThingsPage : ContentPage
{
public RoundThingsPage ()
{
InitializeComponent ();
}
}
}
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:App.Core.Controls"
xmlns:ef="clr-namespace:App.Core.Effects"
x:Class="App.Core.Pages.Other.RoundThingsPage"
Title="Round all the things">
<StackLayout
VerticalOptions="Center"
Spacing="20">
<controls:RoundLabel
Text="Control"
WidthRequest="80"
HeightRequest="80"
CornerRadius="40"
VerticalOptions="Center"
HorizontalOptions="Center"
VerticalTextAlignment="Center"
HorizontalTextAlignment="Center"
BackgroundColor="Coral" />
<Label
Text="Label Effect"
TextColor="White"
WidthRequest="80"
HeightRequest="80"
ef:RoundLabelEffect.CornerRadius="40"
VerticalOptions="Center"
HorizontalOptions="Center"
VerticalTextAlignment="Center"
HorizontalTextAlignment="Center"
BackgroundColor="Aqua" />
<Frame
WidthRequest="80"
HeightRequest="80"
CornerRadius="40"
Padding="0"
VerticalOptions="Center"
HorizontalOptions="Center"
BackgroundColor="Red"
HasShadow="False">
<Label
Text="Framed"
TextColor="White"
VerticalOptions="Center"
HorizontalOptions="Center" />
</Frame>
<Grid
WidthRequest="90"
HeightRequest="100"
VerticalOptions="Center"
HorizontalOptions="Center">
<Label
Text="&#xf111;"
TextColor="Green"
FontSize="95"
FontFamily="fontawesome"
VerticalOptions="Center"
HorizontalOptions="Center"
VerticalTextAlignment="Center"
HorizontalTextAlignment="Center" />
<!-- &#xa; ==> LINE FEED character -->
<Label
Text="Font Icon&#xa;in Grid"
TextColor="White"
VerticalOptions="Center"
HorizontalOptions="Center"
VerticalTextAlignment="Center"
HorizontalTextAlignment="Center"
LineBreakMode="WordWrap" />
</Grid>
</StackLayout>
</ContentPage>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment