【问题标题】:Xamarin forms IOS Buttons looking distortedXamarin 形成看起来扭曲的 IOS 按钮
【发布时间】:2021-03-18 13:28:30
【问题描述】:

我在下面有以下 XAML 代码:

    <StackLayout
        Grid.Row="2"
        Orientation="Horizontal"
        VerticalOptions="End"
        Margin="0,0,0,20"
        Spacing="28">

        <Button
            x:Name="SignInButton"
            Visual="Material"
            Padding="5"
            Margin="10,0,0,0"
            Style="{DynamicResource ButtonSecondary}"
            HorizontalOptions="FillAndExpand"              
            Text="Sign In"
            Clicked="SignInButton_Clicked"/>

        <Button
            x:Name="JoinUsButton"
            Visual="Material"
            Padding="5"
            Margin="0,0,10,0"
            Style="{DynamicResource ButtonPrimary}"
            HorizontalOptions="FillAndExpand"
            VerticalOptions="End"
            Text="Join Us"
            Clicked="JoinUsButton_Clicked"/>
    </StackLayout>

App.xaml文件中当前存储的动态资源如下:

<Style x:Name="ButtonSecondary" x:Key="ButtonSecondary" TargetType="Button" ApplyToDerivedTypes="True">
    <Setter Property="BackgroundColor"
            Value="{DynamicResource SecondaryColor}" />
    <Setter Property="TextColor"
            Value="{DynamicResource PrimaryTextColor}" />
    <Setter Property="BorderWidth"
            Value="1" />
    <Setter Property="BorderColor"
            Value="{DynamicResource SecondaryBorderColor}" />
    <Setter Property="CornerRadius"
            Value="50" />            
</Style>

但是,当我在 iOS 上运行应用程序时,按钮如下图所示。

但是,在 android 设备上,按钮如下图所示:

【问题讨论】:

  • 现在可以用了吗?

标签: xaml xamarin.forms xamarin.ios


【解决方案1】:

虽然我看不到您所看到的失真问题的确切问题,但我确实看到了平台之间的不一致。这最终归结为各个平台如何呈现CornerRadius 属性。 Android 会将其限制在明显合理的范围内(基本上是高度/宽度的一半,以较小者为准),而 iOS 会按照您的要求进行操作。

这张图片左边是我目前看到的,中间是我的第二个解决方案,右边是我的第一个解决方案。

我可能的解决方案是:

附加行为

public class RoundCornerBehavior : Behavior<Button>
{
    protected override void OnAttachedTo(Button button)
    {
        button.SizeChanged += OnSizeChanged;
        base.OnAttachedTo(button);
    }

    protected override void OnDetachingFrom(Button button)
    {
        button.SizeChanged -= OnSizeChanged;
        base.OnDetachingFrom(button);
    }

    private void OnSizeChanged(object sender, EventArgs e)
    {
        var button = (Button) sender;
        button.CornerRadius = (int)Math.Min(button.Width, button.Height) / 2;
    }

    public static readonly BindableProperty AttachBehaviorProperty =
            BindableProperty.CreateAttached("AttachBehavior", typeof(bool), typeof(RoundCornerBehavior), false, propertyChanged: OnAttachBehaviorChanged);

    public static bool GetAttachBehavior(BindableObject view)
    {
        return (bool)view.GetValue(AttachBehaviorProperty);
    }

    public static void SetAttachBehavior(BindableObject view, bool value)
    {
        view.SetValue(AttachBehaviorProperty, value);
    }

    static void OnAttachBehaviorChanged(BindableObject view, object oldValue, object newValue)
    {
        if (!(view is Button button))
        {
            return;
        }

        var attachBehavior = (bool)newValue;
        if (attachBehavior)
        {
            button.Behaviors.Add(new RoundCornerBehavior());
        }
        else
        {
            var toRemove = button.Behaviors.FirstOrDefault(b => b is RoundCornerBehavior);
            if (toRemove != null)
            {
                button.Behaviors.Remove(toRemove);
            }
        }
    }
}

然后简单地附上你的风格:

&lt;Setter Property="roundButton:RoundCornerBehavior.AttachBehavior" Value="true" /&gt;

我建议编写某种Behavior 来提供合理的CornerRadius,它基本上会采用控件的WidthHeight 属性,并将CornerRadius 设置为最小值的一半。我会看看我是否可以尽快提供一个具体的例子。

这种方法的好结果将允许您继续像以前一样定义控件,并将逻辑自我包含在附加的行为中。

子类按钮

另一种方法是子类Button 并创建您自己的RoundedButton,它可以与Behavior 方法相同。那么

public class RoundedButton : Button
{
    protected override void OnSizeAllocated(double width, double height)
    {
        base.OnSizeAllocated(width, height);

        this.CornerRadius = (int)Math.Min(width, height) / 2;
    }
}

【讨论】:

  • 我不知道为什么这个答案被标记了,我只是想围绕你的答案来思考
  • @George 我也没有,我很感激我没有提供一个例子,但我现在添加了 2 :)
【解决方案2】:

原因:在iOS中,如果想达到Android中的上图效果,需要将CornerRadius设置为CornerRadius的一半强>高度请求。

解决方案

选项 1

如果按钮的大小始终是固定值,则只需在样式中设置HeightRequest

<Style x:Name="ButtonSecondary" x:Key="ButtonSecondary" TargetType="Button" ApplyToDerivedTypes="True">
            <Setter Property="BackgroundColor"
            Value="{DynamicResource SecondaryColor}" />
            <Setter Property="TextColor"
            Value="{DynamicResource PrimaryTextColor}" />
            <Setter Property="BorderWidth"
            Value="1" />
            <Setter Property="BorderColor"
            Value="{DynamicResource SecondaryBorderColor}" />
            <Setter Property="CornerRadius"
            Value="25" />
            <Setter Property="HeightRequest"
            Value="50" />  // double of CornerRadius
        </Style>

选项 2:

如果Button的大小在运行时会发生变化,你可以在iOS平台使用Custom Renderer设置CornerRadius

在表单中

创建自定义按钮

public class MyButton:Button
{
}

在 iOS 中

using Foundation;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UIKit;

using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;

using App6;
using App6.iOS;
using System.ComponentModel;

[assembly:ExportRenderer(typeof(MyButton),typeof(MyButtonRenderer))]
namespace App6.iOS
{
    public  class MyButtonRenderer:ButtonRenderer
    {
       
        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);

            if(e.PropertyName=="Height")
            {
                var height = Element.Height;

                Control.Layer.MasksToBounds = true;
                Control.Layer.BorderColor = UIColor.Black.CGColor;
                Control.Layer.CornerRadius = (nfloat)(height / 2.0);
                Control.Layer.BorderWidth = (nfloat)0.5;

            }

        }
    }
}

在xml中

<local:MyButton
            x:Name="SignInButton"
            Visual="Material"
            Padding="5"
            Margin="10,0,0,0"
            Style="{DynamicResource ButtonSecondary}"
            HorizontalOptions="FillAndExpand"              
            Text="Sign In"
           />

【讨论】:

  • @George 你可以查看我的答案。
猜你喜欢
  • 2020-02-08
  • 2012-08-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-02
  • 2014-01-24
  • 2020-10-22
相关资源
最近更新 更多