summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Platform.Android/Renderers/LabelRenderer.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Xamarin.Forms.Platform.Android/Renderers/LabelRenderer.cs')
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/LabelRenderer.cs213
1 files changed, 213 insertions, 0 deletions
diff --git a/Xamarin.Forms.Platform.Android/Renderers/LabelRenderer.cs b/Xamarin.Forms.Platform.Android/Renderers/LabelRenderer.cs
new file mode 100644
index 00000000..45068838
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/LabelRenderer.cs
@@ -0,0 +1,213 @@
+using System;
+using System.ComponentModel;
+using Android.Content.Res;
+using Android.Graphics;
+using Android.Text;
+using Android.Util;
+using Android.Widget;
+using AColor = Android.Graphics.Color;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class LabelRenderer : ViewRenderer<Label, TextView>
+ {
+ ColorStateList _labelTextColorDefault;
+ int _lastConstraintHeight;
+ int _lastConstraintWidth;
+
+ SizeRequest? _lastSizeRequest;
+ float _lastTextSize = -1f;
+ Typeface _lastTypeface;
+
+ Color _lastUpdateColor = Color.Default;
+ FormsTextView _view;
+ bool _wasFormatted;
+
+ public LabelRenderer()
+ {
+ AutoPackage = false;
+ }
+
+ public override SizeRequest GetDesiredSize(int widthConstraint, int heightConstraint)
+ {
+ if (_lastSizeRequest.HasValue)
+ {
+ // if we are measuring the same thing, no need to waste the time
+ bool canRecycleLast = widthConstraint == _lastConstraintWidth && heightConstraint == _lastConstraintHeight;
+
+ if (!canRecycleLast)
+ {
+ // if the last time we measured the returned size was all around smaller than the passed constraint
+ // and the constraint is bigger than the last size request, we can assume the newly measured size request
+ // will not change either.
+ int lastConstraintWidthSize = MeasureSpecFactory.GetSize(_lastConstraintWidth);
+ int lastConstraintHeightSize = MeasureSpecFactory.GetSize(_lastConstraintHeight);
+
+ int currentConstraintWidthSize = MeasureSpecFactory.GetSize(widthConstraint);
+ int currentConstraintHeightSize = MeasureSpecFactory.GetSize(heightConstraint);
+
+ bool lastWasSmallerThanConstraints = _lastSizeRequest.Value.Request.Width < lastConstraintWidthSize && _lastSizeRequest.Value.Request.Height < lastConstraintHeightSize;
+
+ bool currentConstraintsBiggerThanLastRequest = currentConstraintWidthSize >= _lastSizeRequest.Value.Request.Width && currentConstraintHeightSize >= _lastSizeRequest.Value.Request.Height;
+
+ canRecycleLast = lastWasSmallerThanConstraints && currentConstraintsBiggerThanLastRequest;
+ }
+
+ if (canRecycleLast)
+ return _lastSizeRequest.Value;
+ }
+
+ SizeRequest result = base.GetDesiredSize(widthConstraint, heightConstraint);
+ result.Minimum = new Size(Math.Min(Context.ToPixels(10), result.Request.Width), result.Request.Height);
+
+ _lastConstraintWidth = widthConstraint;
+ _lastConstraintHeight = heightConstraint;
+ _lastSizeRequest = result;
+
+ return result;
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
+ {
+ base.OnElementChanged(e);
+ if (_view == null)
+ {
+ _view = new FormsTextView(Context);
+ _labelTextColorDefault = _view.TextColors;
+ SetNativeControl(_view);
+ }
+
+ if (e.OldElement == null)
+ {
+ UpdateText();
+ UpdateLineBreakMode();
+ UpdateGravity();
+ }
+ else
+ {
+ _view.SkipNextInvalidate();
+ UpdateText();
+ if (e.OldElement.LineBreakMode != e.NewElement.LineBreakMode)
+ UpdateLineBreakMode();
+ if (e.OldElement.HorizontalTextAlignment != e.NewElement.HorizontalTextAlignment || e.OldElement.VerticalTextAlignment != e.NewElement.VerticalTextAlignment)
+ UpdateGravity();
+ }
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == Label.HorizontalTextAlignmentProperty.PropertyName || e.PropertyName == Label.VerticalTextAlignmentProperty.PropertyName)
+ UpdateGravity();
+ else if (e.PropertyName == Label.TextColorProperty.PropertyName)
+ UpdateText();
+ else if (e.PropertyName == Label.FontProperty.PropertyName)
+ UpdateText();
+ else if (e.PropertyName == Label.LineBreakModeProperty.PropertyName)
+ UpdateLineBreakMode();
+ else if (e.PropertyName == Label.TextProperty.PropertyName || e.PropertyName == Label.FormattedTextProperty.PropertyName)
+ UpdateText();
+ }
+
+ void UpdateColor()
+ {
+ Color c = Element.TextColor;
+ if (c == _lastUpdateColor)
+ return;
+ _lastUpdateColor = c;
+
+ if (c.IsDefault)
+ _view.SetTextColor(_labelTextColorDefault);
+ else
+ _view.SetTextColor(c.ToAndroid());
+ }
+
+ void UpdateFont()
+ {
+ Font f = Element.Font;
+
+ Typeface newTypeface = f.ToTypeface();
+ if (newTypeface != _lastTypeface)
+ {
+ _view.Typeface = newTypeface;
+ _lastTypeface = newTypeface;
+ }
+
+ float newTextSize = f.ToScaledPixel();
+ if (newTextSize != _lastTextSize)
+ {
+ _view.SetTextSize(ComplexUnitType.Sp, newTextSize);
+ _lastTextSize = newTextSize;
+ }
+ }
+
+ void UpdateGravity()
+ {
+ Label label = Element;
+
+ _view.Gravity = label.HorizontalTextAlignment.ToHorizontalGravityFlags() | label.VerticalTextAlignment.ToVerticalGravityFlags();
+
+ _lastSizeRequest = null;
+ }
+
+ void UpdateLineBreakMode()
+ {
+ switch (Element.LineBreakMode)
+ {
+ case LineBreakMode.NoWrap:
+ _view.SetSingleLine(true);
+ _view.Ellipsize = null;
+ break;
+ case LineBreakMode.WordWrap:
+ _view.SetSingleLine(false);
+ _view.Ellipsize = null;
+ _view.SetMaxLines(100);
+ break;
+ case LineBreakMode.CharacterWrap:
+ _view.SetSingleLine(false);
+ _view.Ellipsize = null;
+ _view.SetMaxLines(100);
+ break;
+ case LineBreakMode.HeadTruncation:
+ _view.SetSingleLine(true);
+ _view.Ellipsize = TextUtils.TruncateAt.Start;
+ break;
+ case LineBreakMode.TailTruncation:
+ _view.SetSingleLine(true);
+ _view.Ellipsize = TextUtils.TruncateAt.End;
+ break;
+ case LineBreakMode.MiddleTruncation:
+ _view.SetSingleLine(true);
+ _view.Ellipsize = TextUtils.TruncateAt.Middle;
+ break;
+ }
+ _lastSizeRequest = null;
+ }
+
+ void UpdateText()
+ {
+ if (Element.FormattedText != null)
+ {
+ FormattedString formattedText = Element.FormattedText ?? Element.Text;
+ _view.TextFormatted = formattedText.ToAttributed(Element.Font, Element.TextColor, _view);
+ _wasFormatted = true;
+ }
+ else
+ {
+ if (_wasFormatted)
+ {
+ _view.SetTextColor(_labelTextColorDefault);
+ _lastUpdateColor = Color.Default;
+ }
+ _view.Text = Element.Text;
+ UpdateColor();
+ UpdateFont();
+
+ _wasFormatted = false;
+ }
+
+ _lastSizeRequest = null;
+ }
+ }
+} \ No newline at end of file