Как установить CornerRadius в рамку с элементами внутри (Xamarin.Формы)



Мне нужно скруглить углы рамки, но мой код не работает. Я думаю, что проблема в том, что у меня есть два StackLayout с BackgroundColor. Почему с IsClippedToBounds= "True" не работает?



Так и должно быть



Вот что я получаю



И это код:



    <Frame  CornerRadius="20"
Margin="15,7,15,7"
Padding="0"
IsClippedToBounds="True">
<Grid
IsClippedToBounds="True"
ColumnSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="50" />
</Grid.ColumnDefinitions>
<StackLayout Grid.Row="0"
Grid.Column="0"
BackgroundColor="{DynamicResource DarkGray}"
Padding="10">

<Label>...<Label>
</StackLayout>

<StackLayout Grid.Row="0"
Grid.Column="1"
BackgroundColor="{DynamicResource DarkGrayVariant}"
Padding="10">

<Image>...</Image>
</StackLayout>

</Grid>
</Frame>
454   2  

2 ответов:

Вы можете создать пользовательский визуализатор для углового радиуса на рамке. Прежде всего, создайте пользовательский элемент управления, который наследуется от фрейма в вашем переносимом проекте как:

public class ExtendedFrame : Frame
{
    public new Thickness Padding { get; set; } = 0;
    public int BorderThickness { get; set; } 
    public ExtendedFrame()
    {
        base.Padding = this.Padding;
    }
}

Затем вы можете реализовать визуализатор следующим образом:

Для Android:

public class ExtendedFrameRenderer : FrameRenderer
{
    GradientDrawable _gi;

    public ExtendedFrameRenderer(Context context) : base(context)
    {
    }

    protected override void OnElementChanged(ElementChangedEventArgs<Frame> e)
    {
        base.OnElementChanged(e);

        var origFrame = e.NewElement as ExtendedFrame;

        if(origFrame != null)
        {
            GradientDrawable gi = new GradientDrawable();

            _gi = gi;

            gi.SetStroke(origFrame.BorderThickness, origFrame.OutlineColor.ToAndroid());
            gi.SetColor(origFrame.BackgroundColor.ToAndroid());
            gi.SetCornerRadius(origFrame.CornerRadius);
#pragma warning disable CS0618 // Type or member is obsolete
            SetBackgroundDrawable(gi);
#pragma warning restore CS0618 // Type or member is obsolete
        }
    }

    protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (ChildCount > 0 && _gi != null)
        {
#pragma warning disable CS0618 // Type or member is obsolete
            SetBackgroundDrawable(_gi);
#pragma warning restore CS0618 // Type or member is obsolete
        }

        base.OnElementPropertyChanged(sender, e);
    }
}

Для IOS:

 public class ExtendedFrameRenderer : FrameRenderer
{


    private ExtendedFrame customFrame;

    protected override void OnElementChanged(ElementChangedEventArgs<Frame> e)
    {
        base.OnElementChanged(e);

        if (e.NewElement != null)
        {
            customFrame = e.NewElement as ExtendedFrame;
            SetupLayer();

        }
    }

    protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        base.OnElementPropertyChanged(sender, e);

        if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName ||
            e.PropertyName == Xamarin.Forms.Frame.OutlineColorProperty.PropertyName ||
            e.PropertyName == Xamarin.Forms.Frame.HasShadowProperty.PropertyName ||
            e.PropertyName == Xamarin.Forms.Frame.CornerRadiusProperty.PropertyName)
        {
            SetupLayer();
        }
    }

    void SetupLayer()
    {
        float cornerRadius = customFrame.CornerRadius;

        if (cornerRadius == -1f)
            cornerRadius = 5f; // default corner radius

        Layer.CornerRadius = cornerRadius;
        Layer.BackgroundColor = customFrame.BackgroundColor.ToCGColor();

        if (customFrame.HasShadow)
        {
            Layer.ShadowRadius = 2;
            Layer.ShadowColor = UIColor.Black.CGColor;
            Layer.ShadowOpacity = 0.3f;
            Layer.ShadowOffset = new SizeF();
        }
        else
            Layer.ShadowOpacity = 0;

        //if (customFrame.OutlineColor == Color.Default)
        //    Layer.BorderColor = UIColor.Clear.CGColor;
        //else
        //{
            Layer.BorderColor = customFrame.OutlineColor.ToCGColor();
            Layer.BorderWidth = customFrame.BorderThickness;
       // }

        Layer.RasterizationScale = UIScreen.MainScreen.Scale;
        Layer.ShouldRasterize = true;
    }
}

С помощью кода шоу я нашел решение!

Я удалил рамку и заменил два stacklayout внутри сетки двумя различными CustomRenderer, один для округления левых углов и один для правых углов.
<Grid   ColumnSpacing="0"
        Padding="15,7,15,7">
        <Grid.RowDefinitions>
            <RowDefinition Height="auto" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="50" />
        </Grid.ColumnDefinitions>
        <customRenders:LeftCornerRadiusFrame  CornerRadius="5"
                                                    Grid.Row="0"
                                                    Grid.Column="0"
                                                    Padding="10"
                                                    BackgroundColor="{DynamicResource DarkGray}">

            <Label>...</Label>

        </customRenders:LeftCornerRadiusFrame>

        <customRenders:RightCornerRadiusFrame Grid.Row="0"
                                                    Grid.Column="1"
                                                    CornerRadius="5"
                                                    Padding="10"
                                                    BackgroundColor="{DynamicResource DarkGrayVariant}">

            <Image>...</Image>

        </customRenders:RightCornerRadiusFrame>

    </Grid>

В рендере Android удалите конструктор и замените:

gi.SetCornerRadius(origFrame.CornerRadius);

С:

//in LeftCornerRadiusFrameRenderer
gi.SetCornerRadii(new float[] { origFrame.CornerRadius, origFrame.CornerRadius, 0, 0, 0, 0, origFrame.CornerRadius, origFrame.CornerRadius });

//in RightCornerRadiusFrameRenderer
gi.SetCornerRadii(new float[] { 0, 0, origFrame.CornerRadius, origFrame.CornerRadius, origFrame.CornerRadius, origFrame.CornerRadius, 0, 0 });

В рендере IOS (я его еще не тестировал) после:

Layer.CornerRadius = cornerRadius;

Поставить:

//in LeftCornerRadiusFrameRenderer
Layer.MaskedCorners = (CoreAnimation.CACornerMask)5;

//in RightCornerRadiusFrameRenderer
Layer.MaskedCorners = (CoreAnimation.CACornerMask)10;

Comments

    Ничего не найдено.