如何将CornerRadius设置为包含元素的框架(Xamarin.Forms)

时间:2018-05-14 14:44:46

标签: xamarin xamarin.forms frame rounded-corners cornerradius

我需要将框架的角设置为圆角,但我的代码不起作用。我认为问题是我有两个带BackgroundColor的StackLayout。为什么使用IsClippedToBounds =" True"不起作用吗?

This is how it should be

This is what i get

这是代码:

    <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>

2 个答案:

答案 0 :(得分:1)

您可以为框架上的角半径创建自定义渲染器。首先,创建一个自定义控件,该控件从便携式项目中的框架继承为:

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;
    }
}

答案 1 :(得分:0)

使用Shaw的代码我找到了解决方案!

我删除了框架,我用两个不同的CustomRenderer替换了网格内的两个stacklayout,一个用于围绕左角,一个用于右角。

word

在Android渲染器中删除构造函数并替换:

<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>

使用:

gi.SetCornerRadius(origFrame.CornerRadius);

在IOS Renderer(我还没有测试过)之后:

//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 });

放:

Layer.CornerRadius = cornerRadius;