Skip to content

Instantly share code, notes, and snippets.

@wcoder
Last active July 14, 2021 15:35
Show Gist options
  • Save wcoder/91aa1141a60c5d8430fc13c9aa3e5fdb to your computer and use it in GitHub Desktop.
Save wcoder/91aa1141a60c5d8430fc13c9aa3e5fdb to your computer and use it in GitHub Desktop.
Simple AutoScroll UILabel for Xamarin.iOS
using CoreGraphics;
using Foundation;
using System;
using UIKit;
namespace YPControls.iOS
{
[Register("AutoScrollLabel")]
public class AutoScrollLabel : UIScrollView
{
private const int _animationDuration = 10;
private readonly nfloat _labelHeight = 50;
private readonly string _separator = " ";
private UILabel _label;
private nfloat _separatorWidth;
private nfloat _originalTextWidth;
public AutoScrollLabel(IntPtr handle) : base(handle)
{
}
public AutoScrollLabel(CGRect frame) : base(frame)
{
Initialize();
}
public override void AwakeFromNib()
{
base.AwakeFromNib();
Initialize();
}
public string Text { get; set; }
public UIFont Font { get; set; } = UIFont.SystemFontOfSize(18);
public nfloat AnimationDuration { get; set; } = _animationDuration;
public void EnableAutoScroll()
{
_label.Text = Text;
_label.Font = Font;
UpdateSizes();
}
public void StopAnimation()
{
Layer.RemoveAllAnimations();
// TODO YP: stop - start ... - don't work
}
private void Initialize()
{
SetupScrollView();
_label = new UILabel();
SetupLabel(_label);
AddSubview(_label);
}
protected virtual void SetupScrollView()
{
ShowsHorizontalScrollIndicator = false;
ShowsVerticalScrollIndicator = false;
ScrollEnabled = false;
ClipsToBounds = true;
}
protected virtual void SetupLabel(UILabel label)
{
label.BackgroundColor = UIColor.Clear;
label.Lines = 1;
}
private void UpdateSizes()
{
var textWidth = GetLabelTextWidth();
_originalTextWidth = textWidth;
var needAutoScroll = textWidth > Bounds.Width;
if (needAutoScroll)
{
_separatorWidth = GetTextWidth(_separator, _label.Font);
_label.Text = _label.Text + _separator + _label.Text;
textWidth = GetLabelTextWidth();
}
ContentSize = new CGSize(textWidth + 20, _labelHeight);
_label.Frame = new CGRect(0, 0, textWidth, _labelHeight);
if (needAutoScroll)
{
StartAnimation();
}
}
private void StartAnimation()
{
var duration = CalculateAnimationDuration();
UIView.Animate(duration, 1,
UIViewAnimationOptions.Repeat | UIViewAnimationOptions.CurveLinear,
() =>
{
ContentOffset = new CGPoint(_originalTextWidth + _separatorWidth, 0);
LayoutIfNeeded();
},
() => { });
}
private double CalculateAnimationDuration()
{
var speed = ContentSize.Width / Bounds.Width;
return speed * AnimationDuration;
}
private nfloat GetLabelTextWidth()
{
return GetTextWidth(_label.Text, _label.Font);
}
private nfloat GetTextWidth(string text, UIFont font)
{
return new NSString(text).GetBoundingRect(
new CGSize(9999, _labelHeight),
NSStringDrawingOptions.UsesLineFragmentOrigin,
new UIStringAttributes { Font = font }, null).Width;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment