Search code examples
c#xamlxamarinxamarin.formsxamarin.android

justify text without custom render


I wanted to know if there is no way other than custom rendering to arrange the ends of the texts in xamarinforms?

Because the modification does not support Android 7 and below.

Thanks to those who respond!

This code is related to my CustomRendering , which in Android 7, my app crashes:



[assembly: ExportRenderer(typeof(CustomLabel), typeof(CustomLabelRender))]

namespace Liko.Droid
{

    public class CustomLabelRender : LabelRenderer
    {
        public CustomLabelRender(Context context) : base(context)
        {

        }

        protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
        {

            base.OnElementChanged(e);


            if (Control != null)
            {
                Control.JustificationMode = JustificationMode.InterWord;
            }

        }

    }
}

Solution

  • On Android 7.0, it do not support JustificationMode. JustificationMode is added in API level 26. https://developer.android.com/reference/android/R.attr#justificationMode

    The customrenderer could justify text in Android 7.0 with ViewRenderer.

    Custom control:

     public class JustifiedLabel : Label
    {
    }
    

    Csutom renderer:

    [assembly: ExportRenderer(typeof(JustifiedLabel), typeof(JustifiedLabelRenderer))]
    

    namespace Test.Droid { public class JustifiedLabelRenderer : ViewRenderer { public JustifiedLabelRenderer(Context context) : base(context) {

        }
        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.View> e)
        {
            base.OnElementChanged(e);
    
            //if we have a new forms element, we want to update text with font style (as specified in forms-pcl) on native control
            if (e.NewElement != null)
            {
                if (Control == null)
                {
                    //register webview as native control
                    var webView = new Android.Webkit.WebView(Context);
                    webView.VerticalScrollBarEnabled = false;
                    webView.HorizontalScrollBarEnabled = false;
    
                    webView.LoadData("<html><body>&nbsp;</body></html>", "text/html; charset=utf-8", "utf-8");
                    SetNativeControl(webView);
                }
    
                //if we have a new forms element, we want to update text with font style (as specified in forms-pcl) on native control
                UpdateTextOnControl();
            }
        }
    
        protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);
    
            //if there is change in text or font-style, trigger update to redraw control
            if (e.PropertyName == nameof(Label.Text)
               || e.PropertyName == nameof(Label.FontFamily)
               || e.PropertyName == nameof(Label.FontSize)
               || e.PropertyName == nameof(Label.TextColor)
               || e.PropertyName == nameof(Label.FontAttributes))
            {
                UpdateTextOnControl();
            }
        }
    
        void UpdateTextOnControl()
        {
            var webView = Control as Android.Webkit.WebView;
            var formsLabel = Element as Label;
    
            // create css style from font-style as specified
            var cssStyle = $"margin: 0px; padding: 0px; text-align: justify; color: {ToHexColor(formsLabel.TextColor)}; background-color: {ToHexColor(formsLabel.BackgroundColor)}; font-family: {formsLabel.FontFamily}; font-size: {formsLabel.FontSize}; font-weight: {formsLabel.FontAttributes}";
    
            // apply that to text 
            var strData =
                $"<html><body style=\"{cssStyle}\">{formsLabel?.Text}</body></html>";
    
            // and, refresh webview
            webView.LoadData(strData, "text/html; charset=utf-8", "utf-8");
            webView.Reload();
        }
    
        // helper method to convert forms-color to css-color
        string ToHexColor(Color color)
        {
            var red = (int)(color.R * 255);
            var green = (int)(color.G * 255);
            var blue = (int)(color.B * 255);
            var alpha = (int)(color.A * 255);
            var hex = $"#{red:X2}{green:X2}{blue:X2}";
    
            return hex;
        }
    }
    

    Usage:

     <StackLayout Margin="20">
            <Entry x:Name="InputEntry" />
    
            <Label
                Margin="0,10,0,0"
                BackgroundColor="Navy"
                FontSize="15"
                HorizontalOptions="CenterAndExpand"
                Text="Normal Text Label"
                TextColor="White" />
            <Label
                FontAttributes="Bold"
                FontSize="20"
                Text="{Binding Text, Source={x:Reference InputEntry}}" />
    
            <Label
                Margin="0,10,0,0"
                BackgroundColor="Navy"
                FontSize="15"
                HorizontalOptions="CenterAndExpand"
                Text="Justified Text Label"
                TextColor="White" />
            <local:JustifiedLabel
                BackgroundColor="Yellow"
                FontAttributes="Bold"
                FontSize="20"
                HorizontalOptions="FillAndExpand"
                Text="{Binding Text, Source={x:Reference InputEntry}}"
                TextColor="Green"
                VerticalOptions="FillAndExpand" />
    
        </StackLayout>
    

    Screenshot:

    enter image description here

    Updated:

     public class JustifiedLabelRenderer : ViewRenderer
    {
        Context _context;
        Android.Webkit.WebView webView;
        public JustifiedLabelRenderer(Context context) : base(context)
        {
            _context = context;
        }
        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.View> e)
        {
            base.OnElementChanged(e);
    
            //if we have a new forms element, we want to update text with font style (as specified in forms-pcl) on native control
            if (e.NewElement != null)
            {
                if (Control == null)
                {
                    //register webview as native control
                    webView = new Android.Webkit.WebView(_context);
                    webView.VerticalScrollBarEnabled = false;
                    webView.HorizontalScrollBarEnabled = false;
    
                    var formsLabel = Element as Label;
    
                    // create css style from font-style as specified
                    var cssStyle = $"margin: 0px; padding: 0px; text-align: justify; color: {ToHexColor(formsLabel.TextColor)}; background-color: {ToHexColor(formsLabel.BackgroundColor)}; font-family: {formsLabel.FontFamily}; font-size: {formsLabel.FontSize}; font-weight: {formsLabel.FontAttributes}";
                    
                    // apply that to text 
                    var strData = $"<html><body style=\"{cssStyle}\">{formsLabel?.Text}</body></html>";
    
                    webView.LoadDataWithBaseURL("", strData, "text/html; charset=utf-8", "utf-8", "");
    
                    SetNativeControl(webView);
    
                }
    
            }
     string ToHexColor(Color color)
        {
            var red = (int)(color.R * 255);
            var green = (int)(color.G * 255);
            var blue = (int)(color.B * 255);
            var alpha = (int)(color.A * 255);
            var hex = $"#{red:X2}{green:X2}{blue:X2}";
    
            return hex;
        }
        }
    

    xaml:

       <local:JustifiedLabel
                BackgroundColor="Yellow"
                FontAttributes="Bold"
                FontSize="20"
                WidthRequest="500"
                HeightRequest="500"
                HorizontalOptions="FillAndExpand"
                Text="I wanted to know if there is no way other than custom rendering to arrange the ends of the texts in xamarinforms? Because the modification does not support Android 7 and below. Thanks to those who respond! This code is related to my CustomRendering , which in Android 7, my app crashes:"
                TextColor="Green"
                VerticalOptions="FillAndExpand" />
    

    Screenshot:

    enter image description here