Last active
July 14, 2021 15:35
-
-
Save wcoder/91aa1141a60c5d8430fc13c9aa3e5fdb to your computer and use it in GitHub Desktop.
Simple AutoScroll UILabel for Xamarin.iOS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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