MBZ
MBZ

Reputation: 91

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

Upvotes: 9

Views: 9863

Answers (2)

Drake
Drake

Reputation: 2713

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.

Upvotes: 1

Gowtham
Gowtham

Reputation: 941

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.

Upvotes: 2

Related Questions