Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Xamarin Forms XAML Label Rotation

I've got a problem with Xamarin.Forms and Label. I'm trying to set a label on a grid column.

The first image here shows the expected result, which is written in AXML on Android.

Right

The second image here is written in XAML in Xamarin.Forms.

Wrong

The code in the XAML file is as follows:

<Grid 
    VerticalOptions="FillAndExpand"
    HorizontalOptions="FillAndExpand">
    <Grid.ColumnDefinitions>
            <ColumnDefinition Width="400*"/>
            <ColumnDefinition Width="75*"/>
        </Grid.ColumnDefinitions>
        <WebView Source="{Binding ContentSource}" />
        <!--<ProgressBar IsVisible="{Binding IsLoading}" 
                    Progress="{Binding Progress}"/>-->

        <Grid Grid.Column="1"
            BackgroundColor="#EE7F00" 
            VerticalOptions="FillAndExpand"
            HorizontalOptions="FillAndExpand">
            <Label
                Text="{Binding DocumentIndex}"
                LineBreakMode="NoWrap"
                HorizontalOptions="Center"
                Rotation="-90"
                VerticalOptions="Center" />
            </Grid>
        </Grid>

How can I expand the height or width of the label to equal to the text length?

Thank you so far

like image 226
MBZ Avatar asked Sep 17 '15 07:09

MBZ


2 Answers

Remove the Grid container for label and place a Box view instead, and set the Grid Row and Column same for both the box view and label. like this

<Grid 
VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand">
    <Grid.RowDefinitions>
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="80*"/>
        <ColumnDefinition Width="20*"/>
    </Grid.ColumnDefinitions>

    <WebView Grid.Row="0" Grid.Column="0" Source="{Binding ContentSource}" />
    <!--<ProgressBar IsVisible="{Binding IsLoading}" 
                Progress="{Binding Progress}"/>-->
    <BoxView Grid.Row="0" Grid.Column="1" BackgroundColor="#EE7F00" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand"/>
    <Label  Grid.Row="0" Grid.Column="1" Text="{Binding DocumentIndex}"
            LineBreakMode="NoWrap"
            HorizontalOptions="Center"
            Rotation="-90"
            VerticalOptions="Center" />

</Grid>

I hope this will solve your label length problem after rotation.

like image 106
Gowtham S Avatar answered Nov 05 '22 14:11

Gowtham S


I solved this with a custom renderer. In your Forms project:

public class RotatedText : View
{
    public static BindableProperty TitleValueProperty = BindableProperty.Create(nameof(TitleValue), typeof(string), typeof(string), null, BindingMode.TwoWay, null,
                                                             (bindable, oldValue, newValue) =>
                                                             {

                                                             });

    public string TitleValue
    {
        get => (string)GetValue(TitleValueProperty);
        set => SetValue(TitleValueProperty, value);
    }
}

And in your Android project:

[assembly: ExportRenderer(typeof(RotatedText), typeof(RotatedTextRenderer))]
namespace MyNamespace
{
    public class RotatedTextRenderer : ViewRenderer
    {
        private Context _context;

        public RotatedTextRenderer(Context c) : base(c)
        {
            _context = c;
        }

        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.View> e)
        {
            base.OnElementChanged(e);

            if (e.NewElement is RotatedText)
            {
                string title = ((RotatedText)e.NewElement).TitleValue;
                SetNativeControl(new RotatedTextView(_context, title));
            }
        }
    }

    public class RotatedTextView : Android.Views.View
    {
        private int DEFAULT_TEXT_SIZE = 30;
        private string _text;
        private TextPaint _textPaint;

        public RotatedTextView(Context c, string title) : base(c)
        {
            _text = title;
            initLabelView();
        }

        private void initLabelView()
        {
            this._textPaint = new TextPaint();
            this._textPaint.AntiAlias = true;
            this._textPaint.TextAlign = Paint.Align.Center;
            this._textPaint.TextSize = DEFAULT_TEXT_SIZE;
            this._textPaint.Color = new Android.Graphics.Color(0, 0, 0);
        }

        public override void Draw(Canvas canvas)
        {
            base.Draw(canvas);

            if (!string.IsNullOrEmpty(this._text))
            {
                float x = (Width / 2) - DEFAULT_TEXT_SIZE/3;
                float y = (Height / 2);

                canvas.Rotate(90);
                canvas.DrawText(this._text, y, -x, this._textPaint);
            }
        }
    }
}

Then just set TitleValue where ever you use RotatedText. It's a little ugly but I couldn't find a better way.

like image 1
Drake Avatar answered Nov 05 '22 12:11

Drake