Size LabelF9pSize(double widthConstraint, double fontSize) { if (_currentDrawState == null || _currentDrawState.IsEmpty || Control == null || Element == null || _disposed) { return(Size.Zero); } var displayScale = (float)Resources.DisplayMetrics.DensityDpi / (float)Android.Util.DisplayMetricsDensity.Default; _currentMeasureState = new TextControlState(_currentDrawState) { AvailWidth = (int)System.Math.Floor(System.Math.Min(widthConstraint * displayScale, int.MaxValue / 3)), AvailHeight = int.MaxValue / 3, TextSize = (float)fontSize, }; _measureControl = _measureControl ?? new F9PTextView(Settings.Context); _lastMeasureResult = InternalLayout(_measureControl, _currentMeasureState); _lastMeasureState = new TextControlState(_currentMeasureState); return(new Size(_lastMeasureResult.Value.Request.Width / displayScale, _lastMeasureResult.Value.Request.Height / displayScale)); }
SizeRequest DrawLabel(double width, double height) { if (_currentDrawState == null || _currentDrawState.IsEmpty || Control == null || Element == null || _disposed || width < 0 || height < 0 ) { return(new SizeRequest(Size.Zero)); } if (double.IsInfinity(width)) { width = int.MaxValue / 3; } if (double.IsInfinity(height)) { height = int.MaxValue / 3; } var displayScale = (float)Resources.DisplayMetrics.DensityDpi / (float)Android.Util.DisplayMetricsDensity.Default; _currentDrawState.AvailWidth = (int)System.Math.Floor(width * displayScale); _currentDrawState.AvailHeight = (int)System.Math.Floor(height * displayScale); _lastDrawResult = InternalLayout(Control, _currentDrawState); _lastDrawState = new TextControlState(_currentDrawState); return(_lastDrawResult.Value); }
/// <summary> /// Raises the element changed event. /// </summary> /// <param name="e">E.</param> protected override void OnElementChanged(ElementChangedEventArgs <Label> e) { base.OnElementChanged(e); _lastMeasureState = null; _lastDrawResult = null; _lastMeasureResult = null; _measureControl?.Dispose(); _measureControl = null; _currentDrawState = new TextControlState { Lines = e.NewElement.Lines, AutoFit = e.NewElement.AutoFit, LineBreakMode = e.NewElement.LineBreakMode, SyncFontSize = (float)e.NewElement.SynchronizedFontSize, }; if (e.OldElement != null) { e.OldElement.RendererIndexAtPoint -= IndexAtPoint; e.OldElement.RendererSizeForWidthAndFontSize -= LabelF9pSize; e.OldElement.Draw -= DrawLabel; Control?.SkipNextInvalidate(); } if (e.NewElement != null) { if (Control == null) { var view = new F9PTextView(Context); InitControl(view); SetNativeControl(view); } else { InitControl(Control); } Control.IsNativeDrawEnabled = false; e.NewElement.RendererIndexAtPoint += IndexAtPoint; e.NewElement.RendererSizeForWidthAndFontSize += LabelF9pSize; e.NewElement.Draw += DrawLabel; if (e.NewElement.Width > 0 && e.NewElement.Height > 0) { var displayScale = (float)Resources.DisplayMetrics.DensityDpi / (float)Android.Util.DisplayMetricsDensity.Default; DrawLabel(e.NewElement.Width * displayScale, e.NewElement.Height * displayScale); } Control.IsNativeDrawEnabled = true; } }
protected override void Dispose(bool disposing) { if (!_disposed && disposing) { _disposed = true; if (Element is Forms9Patch.Label element) { try // incase it has been garbage collected { element.RendererIndexAtPoint -= IndexAtPoint; element.RendererSizeForWidthAndFontSize -= LabelF9pSize; element.Draw -= DrawLabel; } #pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body catch (System.Exception) { } #pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body } _currentDrawState = null; _measureControl?.Dispose(); _measureControl = null; } base.Dispose(disposing); }
SizeRequest InternalLayout(F9PTextView control, TextControlState state) { if (Element is Forms9Patch.Label element && control != null) { ICharSequence text = state.JavaText; var tmpFontSize = BoundTextSize(element.FontSize); control.Typeface = state.Typeface; //control.SetTextColor(state.TextColor.ToAndroid()); UpdateColor(control); control.TextSize = tmpFontSize; control.IsNativeDrawEnabled = false; control.SetSingleLine(false); control.SetMaxLines(int.MaxValue / 2); control.SetIncludeFontPadding(false); control.Ellipsize = null; double tmpHt = -1; double tmpWd = -1; var fontMetrics = control.Paint.GetFontMetrics(); var fontLineHeight = fontMetrics.Descent - fontMetrics.Ascent; var fontLeading = System.Math.Abs(fontMetrics.Bottom - fontMetrics.Descent); if (state.Lines == 0) { if (state.AvailHeight < int.MaxValue / 3) { tmpFontSize = TextPaintExtensions.ZeroLinesFit(state.JavaText, new TextPaint(control.Paint), ModelMinFontSize, tmpFontSize, state.AvailWidth, state.AvailHeight); } } else { if (state.AutoFit == AutoFit.Lines) { if (state.AvailHeight > int.MaxValue / 3) { tmpHt = System.Math.Round(state.Lines * fontLineHeight + (state.Lines - 1) * fontLeading); } else { var fontPointSize = tmpFontSize; var lineHeightRatio = fontLineHeight / fontPointSize; var leadingRatio = fontLeading / fontPointSize; tmpFontSize = ((state.AvailHeight / (state.Lines + leadingRatio * (state.Lines - 1))) / lineHeightRatio - 0.1f); } } else if (state.AutoFit == AutoFit.Width) { tmpFontSize = TextPaintExtensions.WidthFit(state.JavaText, new TextPaint(control.Paint), state.Lines, ModelMinFontSize, tmpFontSize, state.AvailWidth, state.AvailHeight); } } tmpFontSize = BoundTextSize(tmpFontSize); // this is the optimal font size. Let it be known! if (System.Math.Abs(tmpFontSize - element.FittedFontSize) > 0.1) { if (System.Math.Abs(tmpFontSize - element.FontSize) < 0.1 || (element.FontSize < 0 && System.Math.Abs(tmpFontSize - F9PTextView.DefaultTextSize) < 0.1)) { element.FittedFontSize = -1; } else { element.FittedFontSize = tmpFontSize; } } var syncFontSize = (float)((ILabel)element).SynchronizedFontSize; if (syncFontSize >= 0 && System.Math.Abs(tmpFontSize - syncFontSize) > 0.1) { tmpFontSize = syncFontSize; } control.TextSize = tmpFontSize; state.RenderedFontSize = tmpFontSize; var layout = TextExtensions.StaticLayout(state.JavaText, new TextPaint(control.Paint), state.AvailWidth, Android.Text.Layout.Alignment.AlignNormal, 1.0f, 0.0f, true); int lines = state.Lines; if (lines == 0 && state.AutoFit == AutoFit.None) { for (int i = 0; i < layout.LineCount; i++) { if (layout.GetLineBottom(i) <= state.AvailHeight - layout.TopPadding - layout.BottomPadding) { lines++; } else { break; } } } if (layout.Height > state.AvailHeight || (lines > 0 && layout.LineCount > lines)) { if (state.Lines == 1) { control.SetSingleLine(true); control.SetMaxLines(1); control.Ellipsize = state.LineBreakMode.ToEllipsize(); } else { layout = TextPaintExtensions.Truncate(state.Text, element.F9PFormattedString, new TextPaint(control.Paint), state.AvailWidth, state.AvailHeight, element.AutoFit, element.LineBreakMode, ref lines, ref text); } } lines = lines > 0 ? System.Math.Min(lines, layout.LineCount) : layout.LineCount; for (int i = 0; i < lines; i++) { tmpHt = layout.GetLineBottom(i); var width = layout.GetLineWidth(i); if (width > tmpWd) { tmpWd = System.Math.Ceiling(width); } } if (state.AutoFit == AutoFit.None && state.Lines > 0) { control.SetMaxLines(state.Lines); } if (element.IsDynamicallySized && state.Lines > 0 && state.AutoFit == AutoFit.Lines) { fontMetrics = control.Paint.GetFontMetrics(); fontLineHeight = fontMetrics.Descent - fontMetrics.Ascent; fontLeading = System.Math.Abs(fontMetrics.Bottom - fontMetrics.Descent); tmpHt = fontLineHeight * state.Lines + fontLeading * (state.Lines - 1); } control.Gravity = element.HorizontalTextAlignment.ToHorizontalGravityFlags() | element.VerticalTextAlignment.ToVerticalGravityFlags(); if (element.Text != null) { control.Text = text.ToString(); } else { control.TextFormatted = text; } var result = new SizeRequest(new Size(System.Math.Ceiling(tmpWd), System.Math.Ceiling(tmpHt)), new Size(10, System.Math.Ceiling(tmpHt))); if (element.LineBreakMode == LineBreakMode.NoWrap) { control.SetSingleLine(true); } control.IsNativeDrawEnabled = true; if (control == Control) { //P42.Utils.Debug.Message(Element?.HtmlText, "!!!~~~~~~~ REQUEST LAYOUT~~~~~~~~~!!!"); // none of the below seems to help the issue where the label is not apparing in ConnectionCalc cells //Control.RequestLayout(); ////P42.Utils.Debug.Message(Element?.HtmlText, "Control.Invalidate()"); //Control.Invalidate(); //Invalidate(); //var widthSpec = MeasureSpec.MakeMeasureSpec(tmpWd, Android.Views.MeasureSpecMode.Exactly); //var heightSpec = MeasureSpec.MakeMeasureSpec(tmpHt, Android.Views.MeasureSpecMode.Exactly); //Control.Measure(widthSpec, heightSpec); //Control.RequestLayout(); //Control.Layout(0, 0, (int)System.Math.Ceiling(tmpWd), (int)System.Math.Ceiling(tmpHt)); //Control } return(result); } return(new SizeRequest(Size.Zero)); }
/// <summary> /// Gets the size of the desired. /// </summary> /// <returns>The desired size.</returns> /// <param name="widthConstraint">Width constraint.</param> /// <param name="heightConstraint">Height constraint.</param> public override SizeRequest GetDesiredSize(int widthConstraint, int heightConstraint) { if (_currentDrawState == null || _currentDrawState.IsEmpty || Control == null || Element == null || _disposed) { return(new SizeRequest(Size.Zero)); } var width = MeasureSpec.GetSize(widthConstraint); if (MeasureSpec.GetMode(widthConstraint) == Android.Views.MeasureSpecMode.Unspecified) { width = int.MaxValue / 2; } var height = MeasureSpec.GetSize(heightConstraint); if (MeasureSpec.GetMode(heightConstraint) == Android.Views.MeasureSpecMode.Unspecified) { height = int.MaxValue / 2; } if (width <= 0 || height <= 0) { return(new SizeRequest(Size.Zero)); } _currentMeasureState = new TextControlState(_currentDrawState) { AvailWidth = width, AvailHeight = height }; if (_lastMeasureResult != null && _lastMeasureResult.HasValue && _lastMeasureState == _currentMeasureState && _lastMeasureResult.Value.Request.Width > 0 && _lastMeasureResult.Value.Request.Height > 0 && _lastMeasureState.RenderedFontSize >= _currentMeasureState.TextSize && _lastMeasureResult.Value.Request.Width <= _currentMeasureState.AvailWidth && _lastMeasureResult.Value.Request.Height <= _currentMeasureState.AvailHeight ) { return(_lastMeasureResult.Value); } if (_lastDrawResult != null && _lastDrawResult.HasValue && _lastDrawState == _currentMeasureState && _lastDrawResult.Value.Request.Width > 0 && _lastDrawResult.Value.Request.Height > 0 && _lastDrawState.RenderedFontSize >= _currentDrawState.TextSize && _lastDrawResult.Value.Request.Width <= _currentMeasureState.AvailWidth && _lastDrawResult.Value.Request.Height <= _currentMeasureState.AvailWidth) { return(_lastDrawResult.Value); } _measureControl = _measureControl ?? new F9PTextView(Settings.Context); _lastMeasureResult = InternalLayout(_measureControl, _currentMeasureState); _lastMeasureState = new TextControlState(_currentMeasureState); return(_lastMeasureResult.Value); }