Skip to content

Instantly share code, notes, and snippets.

@yuv4ik
Last active May 29, 2018 18:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yuv4ik/bf1bd8a82d1880f53825baf69d9fa1fe to your computer and use it in GitHub Desktop.
Save yuv4ik/bf1bd8a82d1880f53825baf69d9fa1fe to your computer and use it in GitHub Desktop.
Xamarin.Forms Android & iOS: LabelTextKerningEffect
using System.Linq;
using System.Text;
using Android.Text;
using Android.Text.Style;
using Android.Widget;
using MyNamespace.Effects;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using static Android.Widget.TextView;
[assembly: ResolutionGroupName("MyNamespace.Effects")]
[assembly: ExportEffect(typeof(MyNamespace.Droid.Effects.LabelTextKerningEffect), nameof(LabelTextKerningEffect))]
namespace MyNamespace.Droid.Effects
{
public class LabelTextKerningEffect : PlatformEffect
{
protected override void OnAttached()
{
var effect = (MyNamespace.Effects.LabelTextKerningEffect)Element.Effects.FirstOrDefault(e => e is MyNamespace.Effects.LabelTextKerningEffect);
ApplySpacing(effect.Kerning);
}
protected override void OnDetached() { }
void ApplySpacing(float letterSpacing)
{
var lbl = Control as TextView;
if (lbl == null || string.IsNullOrEmpty(lbl.Text)) return;
if (Build.VERSION.SdkInt >= BuildVersionCodes.Lollipop)
{
lbl.LetterSpacing = letterSpacing;
}
else
{
var originalText = lbl.Text;
var builder = new StringBuilder();
for (int i = 0; i < originalText.Length; i++)
{
builder.Append(originalText[i]);
if (i + 1 < originalText.Length)
builder.Append("\u00A0"); // 'NO-BREAK SPACE'
}
var finalText = new SpannableString(builder.ToString());
if (builder.ToString().Length > 1)
{
for (int i = 1; i < builder.ToString().Length; i += 2)
finalText.SetSpan(new ScaleXSpan(letterSpacing * 4), i, i + 1, SpanTypes.ExclusiveExclusive);
}
lbl.SetText(finalText, BufferType.Spannable);
}
}
}
}
using System.Linq;
using MyNamespace.Effects;
using Foundation;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ResolutionGroupName("MyNamespace.Effects")]
[assembly: ExportEffect(typeof(MyNamespace.iOS.Effects.LabelTextKerningEffect), nameof(LabelTextKerningEffect))]
namespace MyNamespace.iOS.Effects
{
public class LabelTextKerningEffect : PlatformEffect
{
protected override void OnAttached()
{
var effect = (MyNamespace.Effects.LabelTextKerningEffect)Element.Effects.FirstOrDefault(e => e is MyNamespace.Effects.LabelTextKerningEffect);
ApplySpacing(effect.Kerning);
}
protected override void OnDetached() { }
void ApplySpacing(float letterSpacing)
{
var lbl = Control as UILabel;
if (lbl == null || string.IsNullOrEmpty(lbl.Text)) return;
lbl.AttributedText = new NSAttributedString(lbl.Text, kerning: letterSpacing);
}
}
}
<?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:local="clr-namespace:XFLetterSpacing"
xmlns:effects="clr-namespace:XFLetterSpacing.Effects"
x:Class="XFLetterSpacing.MainPage">
<StackLayout>
<!-- Place new controls here -->
<Label Text="Welcome!" HorizontalOptions="Center" VerticalOptions="CenterAndExpand">
<Label.Effects>
<effects:LabelTextLetterSpacingEffect Kerning="5" />
</Label.Effects>
</Label>
</StackLayout>
</ContentPage>
public class LabelTextKerningEffect : RoutingEffect
{
public float Kerning { get; set; }
public LabelTextKerningEffect() : base($"MyNamespace.Effects.{nameof(LabelTextKerningEffect)}") { }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment