【问题标题】:Xamarin Frame only have a single rounded cornerXamarin Frame 只有一个圆角
【发布时间】:2020-01-07 10:58:54
【问题描述】:

简单的问题。我需要一个只有一个圆角的框架,而不是全部四个。我怎样才能只圆框架的一个角(在我的情况下是右上角)?

另一种表述方式:如何仅设置框架的一个角的圆角半径?

【问题讨论】:

    标签: xamarin xamarin.forms frame cornerradius


    【解决方案1】:

    简单的方法是使用Nuget PancakeView

    可以在每个顶点指定CornerRadius,达到想要的效果:

    例子:

    <yummy:PancakeView BackgroundColor="Orange"CornerRadius="60,0,0,60"/>
    

    您可以在official page.阅读更多内容

    【讨论】:

    • 嘿,我测试了 PancakeVIew,但是当我通过导航页返回时,当我尝试通过 C# 将cornerradius 设置为基值以外的值(即frame.CornerRadius = new CornerRadius(10,10,0,0))时,应用程序崩溃了。主页上有很长的 pancaceview 列表,单击其中一个会将您带到具有单个 pancakeview 的页面。返回主屏幕(使用导航)会中断应用程序。知道怎么做吗?
    • 此外,通过构造函数中的代码(如上)更改 CornerRadius 根本不会做任何事情。
    • 这里我必须补充一点,我正在为第二页创建一个新页面(因此是新的 PancakeView)。
    【解决方案2】:

    另一种使用自定义渲染框架的方式。

    1.创建类名CustomFrame,继承Frame类,在PCL中添加BindableProperty CornerRadiusProperty。

     public class CustomFrame: Frame
    {
        public static new readonly BindableProperty CornerRadiusProperty = BindableProperty.Create(nameof(CustomFrame), typeof(CornerRadius), typeof(CustomFrame));
        public CustomFrame()
        {
            // MK Clearing default values (e.g. on iOS it's 5)
            base.CornerRadius = 0;
        }
    
        public new CornerRadius CornerRadius
        {
            get => (CornerRadius)GetValue(CornerRadiusProperty);
            set => SetValue(CornerRadiusProperty, value);
        }
    
    }
    
    1. 在 Android 中创建 CustomFrameRender。

      using FrameRenderer = Xamarin.Forms.Platform.Android.AppCompat.FrameRenderer;
      
      [assembly: ExportRenderer(typeof(CustomFrame), typeof(CustomFrameRenderer))]
      namespace Demo1.Droid
      {
      class CustomFrameRenderer : FrameRenderer
       {
      public CustomFrameRenderer(Context context)
          : base(context)
      {
      }
      
      protected override void OnElementChanged(ElementChangedEventArgs<Frame> e)
      {
          base.OnElementChanged(e);
      
          if (e.NewElement != null && Control != null)
          {
              UpdateCornerRadius();
          }
      }
      
      protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
      {
          base.OnElementPropertyChanged(sender, e);
      
          if (e.PropertyName == nameof(CustomFrame.CornerRadius) ||
              e.PropertyName == nameof(CustomFrame))
          {
              UpdateCornerRadius();
          }
      }
      
      private void UpdateCornerRadius()
      {
          if (Control.Background is GradientDrawable backgroundGradient)
          {
              var cornerRadius = (Element as CustomFrame)?.CornerRadius;
              if (!cornerRadius.HasValue)
              {
                  return;
              }
      
              var topLeftCorner = Context.ToPixels(cornerRadius.Value.TopLeft);
              var topRightCorner = Context.ToPixels(cornerRadius.Value.TopRight);
              var bottomLeftCorner = Context.ToPixels(cornerRadius.Value.BottomLeft);
              var bottomRightCorner = Context.ToPixels(cornerRadius.Value.BottomRight);
      
              var cornerRadii = new[]
              {
                  topLeftCorner,
                  topLeftCorner,
      
                  topRightCorner,
                  topRightCorner,
      
                  bottomRightCorner,
                  bottomRightCorner,
      
                  bottomLeftCorner,
                  bottomLeftCorner,
              };
      
              backgroundGradient.SetCornerRadii(cornerRadii);
          }
      }
      
        }
       }
      

    3.在表单中使用自定义框架。

    <StackLayout>
            <controls:CustomFrame
                BackgroundColor="Red"
                CornerRadius="0,30,0,0"
                HeightRequest="100"
                HorizontalOptions="Center"
                VerticalOptions="Center"
                WidthRequest="100" />
        </StackLayout>
    

    更多详细信息,请参考:

    https://progrunning.net/customizing-corner-radius/

    【讨论】:

    • 这很好用,但我遇到了一个问题。与往常不同的是,框架的内容忽略了弯曲的角(它将内容绘制在框架角之外)。知道如何解决这个问题吗?
    • @Sander,我不明白你的意思,你能提供截图吗?
    • 我已经换成了 PancakeView (这也有一些我试图弄清楚的问题),但基本上会发生这种情况:当你添加一个框架时,框架的边缘是东西的限制可以画出来。如果添加圆角半径,它也会从可以绘制内容的“画布”上切开,例如生成圆形图像。使用此自定义框架,它会渲染角(向外),但不会编辑此“画布”,因此内容不会有圆角,而是与框架重叠(好像角半径设置为 0)。我希望这能很好地解释我的问题。
    • 该解决方案不适用于iOS,它确实通过自定义渲染器,但在设备上没有效果。
    【解决方案3】:

    使用 nuget 包 Xamarin.Forms.PancakeView。

    查看此答案是否有类似问题:

    https://stackoverflow.com/a/59650125/5869384

    【讨论】:

      【解决方案4】:

      这是用于 UWP 渲染器的

      我使用了 Cherry Bu - MSFT 的解决方案并将其更改为 UWP。在我的项目中,我在 Android、iOS 和 UWP 中使用它,并且运行良好。

      using System.ComponentModel;
      using Windows.UI.Xaml.Media;
      using Xamarin.Forms;
      using Xamarin.Forms.Platform.UWP;
      
      [assembly: ExportRenderer(typeof(CustomFrame), typeof(yourNamespace.UWP.CustomFrameRenderer))]
      namespace yourNamespace.UWP
      {
          public class CustomFrameRenderer : FrameRenderer
          {
              protected override void OnElementChanged(ElementChangedEventArgs<Frame> e)
              {
                  base.OnElementChanged(e);
      
                  if (e.NewElement != null && Control != null)
                  {
                      UpdateCornerRadius();
                  }
              }
      
              protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
              {
                  base.OnElementPropertyChanged(sender, e);
      
                  if (e.PropertyName == nameof(CustomFrame.CornerRadius) ||
                      e.PropertyName == nameof(CustomFrame))
                  {
                      UpdateCornerRadius();
                  }
              }
      
              private void UpdateCornerRadius()
              {
                  var radius = ((CustomFrame)this.Element).CornerRadius;
                  Control.CornerRadius = new Windows.UI.Xaml.CornerRadius(radius.TopLeft, radius.TopRight, radius.BottomRight, radius.BottomLeft);
              }
          }
      }
      

      【讨论】:

        【解决方案5】:

        我使用的简单解决方案是在圆形框架后面设置另一个框架,如下所示

        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="0.05*"/>
                <RowDefinition Height="0.05*"/>
                <RowDefinition Height="0.8*"/>
                <RowDefinition Height="0.05*"/>
                <RowDefinition Height="0.05*"/>
            </Grid.RowDefinitions>
        
        
            <Frame
                Grid.Row="4"
                Padding="0"
                BackgroundColor="Green"
                CornerRadius="0"/>
            
            <Frame
                Grid.Row="3"
                Grid.RowSpan="2"
                Padding="0"
                BackgroundColor="Green"
                HasShadow="True"
                CornerRadius="20">
            </Frame>
        
        </Grid>
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-04-02
          • 1970-01-01
          • 2011-02-03
          • 1970-01-01
          • 2011-06-18
          • 1970-01-01
          • 2022-11-10
          • 1970-01-01
          相关资源
          最近更新 更多