#xaml #xamarin.forms #xamarin.ios
#xaml #xamarin.forms #xamarin.ios
Вопрос:
У меня есть следующий код 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 кнопки выглядят так, как показано на рисунке ниже :
Комментарии:
1. Работает ли это сейчас?
Ответ №1:
Осторожно: в iOS, если вы хотите добиться эффекта, подобного приведенному выше изображению, которое вы получаете в Android, вам нужно установить cornerRadius как половину его HeightRequest .
Решение
Вариант 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 :
Если размер кнопки изменится во время выполнения, вы можете использовать пользовательский рендерер для настройки CornerRadius
на платформе iOS.
в формах
создайте пользовательскую кнопку
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;
}
}
}
}
в xaml
<local:MyButton
x:Name="SignInButton"
Visual="Material"
Padding="5"
Margin="10,0,0,0"
Style="{DynamicResource ButtonSecondary}"
HorizontalOptions="FillAndExpand"
Text="Sign In"
/>
Комментарии:
1. @George Вы могли бы проверить мой ответ.
Ответ №2:
Хотя я не вижу точной проблемы, которую вы видите с искажением, я вижу несоответствие между платформами. В конечном итоге это сводится к тому, как отдельные платформы отображают 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);
}
}
}
}
Затем просто прикрепите в своем стиле:
<Setter Property="roundButton:RoundCornerBehavior.AttachBehavior" Value="true" />
Я бы предложил написать какой Behavior
-нибудь способ обеспечения разумного CornerRadius
, который, по сути, использовал бы свойства Width
и Height
элемента управления и просто установил значение 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;
}
}
Комментарии:
1. Я не уверен, почему этот ответ был отмечен, и я просто пытаюсь обдумать ваш ответ
2. @George я тоже, я ценю, что не привел пример, но сейчас я добавил 2 🙂