示例#1
0
        protected override Size MeasureOverride(Size size)
        {
            // Size used to compare with the previous one. We don't want to use this one for the calculation.
            var ceiledNewSize = new CGSize(Math.Ceiling(size.Width), Math.Ceiling(size.Height));

            var hasSameDesiredSize =
                !_measureInvalidated &&
                _previousAvailableSize != null &&
                _previousDesiredSize.Width == ceiledNewSize.Width &&
                _previousDesiredSize.Height == ceiledNewSize.Height;

            var isSingleLineNarrower =
                !_measureInvalidated &&
                _previousAvailableSize != null &&
                _previousDesiredSize.Width <= ceiledNewSize.Width &&
                _previousDesiredSize.Height == ceiledNewSize.Height;

            if (hasSameDesiredSize || isSingleLineNarrower)
            {
                return(_previousDesiredSize);
            }
            else
            {
                _previousAvailableSize = size;
                _measureInvalidated    = false;

                UpdateTypography();

                var padding = Padding;

                // available size considering padding
                size = size.Subtract(padding);

                var result = LayoutTypography(size);

                if (result.Height == 0)                 // this can happen when Text is null or empty
                {
                    // This measures the height correctly, even if the Text is null or empty
                    // This matches Windows where empty TextBlocks still have a height (especially useful when measuring ListView items with no DataContext)
                    var font = UIFontHelper.TryGetFont((float)FontSize, FontWeight, FontStyle, FontFamily);
                    result = (Text ?? NSString.Empty).StringSize(font, size);
                }

                result = result.Add(padding);

                return(_previousDesiredSize = new CGSize(Math.Ceiling(result.Width), Math.Ceiling(result.Height)));
            }
        }
示例#2
0
        protected override Size MeasureOverride(Size size)
        {
            // `size` is used to compare with the previous one `_previousDesiredSize`
            // We need to apply `Math.Ceiling` to compare them correctly
            var isSameOrNarrower =
                !_measureInvalidated &&
                _previousAvailableSize != null &&
                _previousDesiredSize.Width <= Math.Ceiling(size.Width) &&
                _previousDesiredSize.Height == Math.Ceiling(size.Height);

            if (isSameOrNarrower)
            {
                return(_previousDesiredSize);
            }
            else
            {
                _previousAvailableSize = size;
                _measureInvalidated    = false;

                UpdateTypography();

                var padding = Padding;

                // available size considering padding
                size = size.Subtract(padding);

                var result = LayoutTypography(size);

                if (result.Height == 0)                 // this can happen when Text is null or empty
                {
                    // This measures the height correctly, even if the Text is null or empty
                    // This matches Windows where empty TextBlocks still have a height (especially useful when measuring ListView items with no DataContext)
                    var font = UIFontHelper.TryGetFont((float)FontSize, FontWeight, FontStyle, FontFamily);

#pragma warning disable BI1234 // error BI1234: 'UIStringDrawing.StringSize(string, UIFont, CGSize)' is obsolete: 'Starting with ios7.0 use NSString.GetBoundingRect (CGSize, NSStringDrawingOptions, UIStringAttributes, NSStringDrawingContext) instead.'
                    result = (Text ?? NSString.Empty).StringSize(font, size);
#pragma warning restore BI1234
                }

                result = result.Add(padding);

                return(_previousDesiredSize = new Size(Math.Ceiling(result.Width), Math.Ceiling(result.Height)));
            }
        }
示例#3
0
        private UIStringAttributes GetAttributes()
        {
            var attributes = new UIStringAttributes();

            var font = UIFontHelper.TryGetFont((float)FontSize, FontWeight, FontStyle, FontFamily);

            attributes.Font            = font;
            attributes.ForegroundColor = (Foreground as SolidColorBrush)?.ColorWithOpacity;

            if (TextDecorations != TextDecorations.None)
            {
                attributes.UnderlineStyle = (TextDecorations & TextDecorations.Underline) == TextDecorations.Underline
                                        ? NSUnderlineStyle.Single
                                        : NSUnderlineStyle.None;

                attributes.StrikethroughStyle = (TextDecorations & TextDecorations.Strikethrough) == TextDecorations.Strikethrough
                                        ? NSUnderlineStyle.Single
                                        : NSUnderlineStyle.None;
            }

            var paragraphStyle = new NSMutableParagraphStyle()
            {
                MinimumLineHeight = (nfloat)LineHeight,
                Alignment         = TextAlignment.ToNativeTextAlignment(),
                LineBreakMode     = GetLineBreakMode(),
            };

            // For unknown reasons, the LineBreakMode must be set to WordWrap
            // when applied to a NSTextStorage for text to wrap.
            if (UseLayoutManager)
            {
                paragraphStyle.LineBreakMode = UILineBreakMode.WordWrap;
            }

            if (LineStackingStrategy != LineStackingStrategy.MaxHeight)
            {
                paragraphStyle.MaximumLineHeight = (nfloat)LineHeight;
            }
            attributes.ParagraphStyle = paragraphStyle;

            if (LineHeight != 0 && font != null)
            {
                // iOS puts text at the bottom of the line box, whereas Windows puts it at the top.
                // Empirically this offset gives similar positioning to Windows.
                // Note: Descender is typically a negative value.
                var verticalOffset = LineHeight - font.LineHeight + font.Descender;

                // Because we're trying to move the text up (toward the top of the line box),
                // we only set BaselineOffset to a positive value.
                // A negative value indicates that the the text is already bottom-aligned.
                attributes.BaselineOffset = Math.Max(0, (float)verticalOffset);
            }

            if (CharacterSpacing != 0)
            {
                //CharacterSpacing is in 1/1000 of an em, iOS KerningAdjustment is in points. 1 em = 12 points
                attributes.KerningAdjustment = (CharacterSpacing / 1000f) * 12;
            }

            return(attributes);
        }