Как получить текст для переноса и добавить еще одну строку ниже в пользовательском рендерере Xamarin Forms iOS? - PullRequest
0 голосов
/ 12 июня 2018

Я создаю пользовательский рендер для отображения заголовка и описания в полупрозрачном пустом пространстве на изображении.Заголовок должен переноситься на вторую строку, если он шире, чем изображение, и дополнительное описание может появиться ниже, если есть место.В Android я могу сделать это с помощью StaticLayout:

            // Create text rectangle
            var height = Height / 3;
            canvas.Save();
            canvas.ClipRect(0, Height - height, Width, Height);
            canvas.DrawARGB(191, 255, 255, 255);

            canvas.Restore();
            var item = ((ImageTile) Element).Item;
            var textSize = (height - 15) / 2;

            var textPaint = new TextPaint
            {
                StrokeWidth = 5,
                TextSize = textSize,
                FakeBoldText = true,
            };
            if (Build.VERSION.SdkInt >= BuildVersionCodes.Honeycomb)
                SetLayerType(LayerType.Software, textPaint);
            textPaint.SetStyle(Paint.Style.Fill);
            textPaint.Color = global::Android.Graphics.Color.Black;
            // init StaticLayout for text
            var titleLayout = new StaticLayout(
                item.Title, textPaint, Width - 10, Android.Text.Layout.Alignment.AlignNormal, 1.0f, 0.0f, false);
            canvas.Translate(5, Height - height + 5);
            titleLayout.Draw(canvas);
            canvas.Restore();

            textPaint = new TextPaint
            {
                StrokeWidth = 4,
                TextSize = textSize - 10,
            };
            if (Build.VERSION.SdkInt >= BuildVersionCodes.Honeycomb)
                SetLayerType(LayerType.Software, textPaint);
            var descLayout = new StaticLayout(
                item.Description, textPaint, Width - 10, Android.Text.Layout.Alignment.AlignNormal, 1.0f, 0.0f, false);
            canvas.Translate(5, Height - height + titleLayout.Height + 5);
            descLayout.Draw(canvas);
            canvas.Restore();

в iOS Я использую CATextLayers, но я не могу получить текст для переноса, даже если я определил рамку и установил для обоих Wrapped значение trueи TextTruncationMode to None.Я также не знаю, как получить фактическую высоту слоя тильте, так что я могу расположить слой вниз под ним.Это то, что я до сих пор, который рисует заголовок и описание друг на друге без переноса.

                var textLayer = new CALayer();
                var textRec = new CGRect(0, element.HeightRequest - textheight, element.WidthRequest,
                    textheight);
                textLayer.Frame = textRec;
                var backgroundcolor = Color.FromRgba(255, 255, 255, .25).ToCGColor();
                textLayer.BackgroundColor = backgroundcolor;
                Control.Layer.AddSublayer(textLayer);
                var titleLayer = new CATextLayer
                {
                    String = element.Item.Title,
                    ForegroundColor = Color.Black.ToCGColor(),
                    FontSize = 14,
                    Wrapped = true,
                    TextTruncationMode = CATextLayerTruncationMode.None,
                    TextAlignmentMode = CATextLayerAlignmentMode.Left,
                    //Bounds = new CGRect(2, element.HeightRequest - textheight + 2, element.WidthRequest - 4,
                    //    textheight - 4),
                };
                var titleRec = new CGRect(2, element.HeightRequest - textheight + 2, element.WidthRequest - 4,
                    textheight - 4);
                titleLayer.Frame = titleRec;
                Control.Layer.AddSublayer(titleLayer);
                var descLayer = new CATextLayer
                {
                    String = element.Item.Description,
                    ForegroundColor = Color.Black.ToCGColor(),
                    FontSize = 12,
                    Wrapped = true,
                    TextTruncationMode = CATextLayerTruncationMode.None,
                };
                var descRec = new CGRect(2, element.HeightRequest - textheight + 2, element.WidthRequest - 4,
                    textheight - 4);
                descLayer.ContentsRect = descRec;
                Control.Layer.AddSublayer(descLayer);

1 Ответ

0 голосов
/ 13 июня 2018

Почему бы не попробовать autoLayout?Вы хотите добавить фоновый вид и два типа текста на исходное изображение.CALayer может достичь вашего эффекта, но он не может использовать autoLayout, так что вам нужно использовать жесткий код (вычислить высоту текста и положение слоя) для его построения.Также вы сказали

Я не могу получить текст для переноса.И я также не знаю, как получить фактическую высоту tilteLayer, чтобы я мог расположить descLayer под ним.

В пользовательском рендерере изображения, так как этот элемент управления не был отображен, его Frame и HeightRequest также неизвестны.Тогда вы не получите правильный кадр и слой, поэтому текст не будет отображаться.Я думаю, что лучший способ сделать это - использовать AutoLayout :

// Create a view to hold content just like your textLayer 
UIView bgView = new UIView();
bgView.BackgroundColor = UIColor.FromRGBA(1, 1, 1, 0.25f);
bgView.TranslatesAutoresizingMaskIntoConstraints = false;
Control.AddSubview(bgView);

bgView.LeadingAnchor.ConstraintEqualTo(Control.LeadingAnchor).Active = true;
bgView.TopAnchor.ConstraintGreaterThanOrEqualTo(Control.TopAnchor).Active = true;
bgView.TrailingAnchor.ConstraintEqualTo(Control.TrailingAnchor).Active = true;
bgView.BottomAnchor.ConstraintEqualTo(Control.BottomAnchor).Active = true;

UILabel titleLabel = new UILabel();
bgView.AddSubview(titleLabel);
titleLabel.TranslatesAutoresizingMaskIntoConstraints = false;
// Set this property to 0, then your label will move to several lines if your text is too large.
titleLabel.Lines = 0;
titleLabel.Font = UIFont.SystemFontOfSize(14);
titleLabel.Text = Element.Item.Title;

titleLabel.LeadingAnchor.ConstraintEqualTo(bgView.LeadingAnchor).Active = true;
titleLabel.TopAnchor.ConstraintEqualTo(bgView.TopAnchor).Active = true;
titleLabel.TrailingAnchor.ConstraintEqualTo(bgView.TrailingAnchor).Active = true;
// This constraint will show the titleLabel's content at high priority. It means show the descLabel if the image has enough place.
titleLabel.SetContentHuggingPriority(249, UILayoutConstraintAxis.Vertical);

UILabel descLabel = new UILabel();
bgView.AddSubview(descLabel);
descLabel.TranslatesAutoresizingMaskIntoConstraints = false;
descLabel.Lines = 0;
descLabel.Text = Element.Item.Description;
descLabel.Font = UIFont.SystemFontOfSize(12);

descLabel.LeadingAnchor.ConstraintEqualTo(bgView.LeadingAnchor).Active = true;
descLabel.TopAnchor.ConstraintEqualTo(titleLabel.BottomAnchor).Active = true;
descLabel.TrailingAnchor.ConstraintEqualTo(bgView.TrailingAnchor).Active = true;
descLabel.BottomAnchor.ConstraintEqualTo(bgView.BottomAnchor).Active = true;

Таким образом, bgView увеличит свою высоту в зависимости от titleLabel и descLabel.Наибольшая высота будет высотой исходного изображения.Кроме того, titleLabel автоматически рассчитает его размер в зависимости от его содержимого.Также descLabel всегда будет находиться ниже titleLabel, если позволяет комната.

Вы можете настроить эти ограничения в соответствии со своими требованиями.

...