locked
is it possible to bold UITextView text RRS feed

  • Question

  • User244067 posted

    I am using Xamarin forms application. I have created label renderer with Textview and MarkdownSharp nuget its working for android without any issue. This is the sample i have used.

    https://forums.xamarin.com/discussion/comment/415646#Comment_415646

    Now i am stuck with iOS part. Its using UITextView. If you have any idea please suggest.

    Wednesday, July 1, 2020 6:40 AM

Answers

  • User369979 posted

    Helped you change the code. It works fine now. And please notice Label renders to UILabel in iOS, not UITextView: Attached the sample here.

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Thursday, July 2, 2020 8:22 AM

All replies

  • User369979 posted

    TextView control in Android is something like UILabel in iOS. If you want to convert strings to attributed string in iOS, here is the workaround. Try to create a class like:

    public static class HtmlExtension
    {
        #region MARKDOWN STYLES
        private const string ORIGINAL_PATTERN_BEGIN = "<code>";
        private const string ORIGINAL_PATTERN_END = "</code>";
        private const string PARSED_PATTERN_BEGIN = "<font color=\"#888888\" face=\"monospace\"><tt>";
        private const string PARSED_PATTERN_END = "</tt></font>";
    
        #endregion
    
        public static string ToHtml(this string markdownText)
        {
            var markdownOptions = new MarkdownOptions
            {
                AutoHyperlink = true,
                AutoNewlines = false,
                LinkEmails = true,
                StrictBoldItalic = true
            };
            var markdown = new Markdown(markdownOptions);
            var htmlContent = markdown.Transform(markdownText);
            var regex = new Regex("\n");
            htmlContent = regex.Replace(htmlContent, "<br/>");
    
            var html = htmlContent.HtmlWrapped();
            var regex2 = new Regex("\r");
            html = regex.Replace(html, string.Empty);
            html = regex2.Replace(html, string.Empty);
            return html;
        }
    
        ///
        //<summary>
        /// Wrap html with a full html tag
        /// </summary>
        /// <param name="html"></param>
        /// <returns></returns>
        public static string HtmlWrapped(this string html)
        {
            if (!html.StartsWith("<html>") || !html.EndsWith("</html>"))
            {
                html = $"<html><body>{html}</body></html>";
            }
            return html;
        }
    
        ///<summary>
        /// Parses html with code or pre tags and gives them proper
        /// styled spans so that Android can parse it properly
        /// </summary>
        /// <param name="htmlText">The html string</param>
        /// <returns>The html string with parsed code tags</returns>
        public static string ParseCodeTags(this string htmlText)
        {
            if (htmlText.IndexOf(ORIGINAL_PATTERN_BEGIN) < 0) return htmlText;
            var regex = new Regex(ORIGINAL_PATTERN_BEGIN);
            var regex2 = new Regex(ORIGINAL_PATTERN_END);
    
            htmlText = regex.Replace(htmlText, PARSED_PATTERN_BEGIN);
            htmlText = regex2.Replace(htmlText, PARSED_PATTERN_END);
            htmlText = htmlText.TrimLines();
            return htmlText;
        }
    
        public static bool EqualsIgnoreCase(this string text, string text2)
        {
            return text.Equals(text2, StringComparison.CurrentCultureIgnoreCase);
        }
    
        public static string ReplaceBreaks(this string html)
        {
            var regex = new Regex("<br/>");
            html = regex.Replace(html, "\n");
            return html;
        }
    
        public static string ReplaceBreaksWithSpace(this string html)
        {
            var regex = new Regex("<br/>");
            html = regex.Replace(html, " ");
            return html;
        }
    
        public static string TrimLines(this string originalString)
        {
            originalString = originalString.Trim('\n');
            return originalString;
        }
    
        public static NSAttributedString MarkdownToHtml(this string markdown)
        {
            return markdown.ToHtml().ToAttributedString();
        }
    
        public static NSAttributedString ToAttributedString(this string html)
        {
            NSError error = new NSError();
            try
            {
                var htmlData = NSData.FromString(html);
                if (htmlData != null && htmlData.Length > 0)
                {
                    NSAttributedString attributedString = null;
                    attributedString = new NSAttributedString(htmlData, ref error);
                    return attributedString;
                }
                return null;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                return null;
            }
        }
    }
    

    And then use it like:

    UILabel label = new UILabel(new CGRect(0, 200, 200, 44));
    var markdown = "# Hello *World*";
    label.AttributedText = markdown.MarkdownToHtml();
    View.AddSubview(label);
    

    If you do need a UITextView control, here it is:

    UITextView textView = new UITextView(new CGRect(0, 200, 200, 44));
    var markdown = "# Hello *World*";
    textView.AttributedText = markdown.MarkdownToHtml();
    View.AddSubview(textView);
    
    Wednesday, July 1, 2020 8:43 AM
  • User244067 posted

    @LandLu I have added your code and its runing without errors. its adding tag correctly but all text are same.

    I have added bold part only for World.

    Wednesday, July 1, 2020 9:56 AM
  • User244067 posted

    font bold is not adding correctly.

    Thursday, July 2, 2020 3:21 AM
  • User369979 posted

    This is because you changed the FontSize. It messed up the attributed string. If you want to change the size of the strings, try to achieve it in this method:

    public static NSAttributedString ToAttributedString(this string html)
    {
        NSError error = new NSError();
        try
        {
            var htmlData = NSData.FromString(html + "<style>body{font-size: 42px;}</style>");
            if (htmlData != null && htmlData.Length > 0)
            {
                NSAttributedString attributedString = null;
                attributedString = new NSAttributedString(htmlData, new NSAttributedStringDocumentAttributes { DocumentType = NSDocumentType.HTML, StringEncoding = NSStringEncoding.UTF8 }, ref error);
    
                return attributedString;
            }
            return null;
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
            return null;
        }
    }
    

    Here is the effect: Here is a dynamical approach:

    var htmlData = NSData.FromString(html + $"<style>body{{font-size: {fontSize}px;}}</style>");
    
    Thursday, July 2, 2020 7:19 AM
  • User244067 posted

    @LandLu Thanks for replying me. I have change font size because bold is not visible for me. i have removed it. but still same. are you checking this simulator or device?

    Thursday, July 2, 2020 7:30 AM
  • User369979 posted

    Both work properly. I saw you used it in Forms. What does your custom renderer look like? Could you please share your sample here? If you want to use it in Forms, here is a forms plugin: https://github.com/SuavePirate/MarkdownTextView You could utilize it directly in Forms.

    Thursday, July 2, 2020 7:37 AM
  • User244067 posted

    @LandLu this is my sample

    https://drive.google.com/file/d/1qHfnJXZl745c8p2U8LLNA7TC1QuKHDj2/view?usp=sharing

    Thursday, July 2, 2020 8:04 AM
  • User244067 posted

    @LandLu this is my custom renderer. i am using this xamarin forms.

    using System; using CoreGraphics; using Foundation; using Label.iOS; using SelectableLabelApp.CustomControls; using test.iOS.Renderers; using UIKit; using Xamarin.Forms; using Xamarin.Forms.Platform.iOS;

    [assembly: ExportRenderer(typeof(SelectableLabel), typeof(SelectableLabelRenderer))]
    namespace test.iOS.Renderers
    {  
    
    public class SelectableLabelRenderer : ViewRenderer<SelectableLabel, UITextView>
    {
        UITextView uiTextView;
    
        protected override void OnElementChanged(ElementChangedEventArgs<SelectableLabel> e)
        {
            base.OnElementChanged(e);
    
            var label = (SelectableLabel)Element;
            if (label == null)
                return;
    
            if (Control == null)
            {
                uiTextView = new UITextView(new CGRect(0, 200, 200, 44));
            }
    
            uiTextView.Selectable = true;
            uiTextView.Editable = false;
            uiTextView.ScrollEnabled = false;
            uiTextView.TextContainerInset = UIEdgeInsets.Zero;
            uiTextView.TextContainer.LineFragmentPadding = 0;
            uiTextView.BackgroundColor = UIColor.Clear;
    
            // Initial properties Set
            uiTextView.Text = label.Text;
            uiTextView.TextColor = label.TextColor.ToUIColor();
            var markdown = uiTextView.Text; 
            uiTextView.AttributedText = markdown.MarkdownToHtml(); 
    
    
            switch (label.FontAttributes)
            {
                case FontAttributes.None:
                    uiTextView.Font = UIFont.SystemFontOfSize(new nfloat(label.FontSize));
                    break;
                case FontAttributes.Bold:
                    uiTextView.Font = UIFont.BoldSystemFontOfSize(new nfloat(label.FontSize));
                    break;
                case FontAttributes.Italic:
                    uiTextView.Font = UIFont.ItalicSystemFontOfSize(new nfloat(label.FontSize));
                    break;
                default:
                    uiTextView.Font = UIFont.BoldSystemFontOfSize(new nfloat(label.FontSize));
                    break;
            }
    
            SetNativeControl(uiTextView);
        }
    }
    

    }

    Thursday, July 2, 2020 8:05 AM
  • User369979 posted

    Helped you change the code. It works fine now. And please notice Label renders to UILabel in iOS, not UITextView: Attached the sample here.

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Thursday, July 2, 2020 8:22 AM
  • User244067 posted

    @LandLu Thank you very much! It works now

    Thursday, July 2, 2020 8:24 AM