Xamarin 自定义渲染器:圆形按钮的自定义渲染器

Xamarin 自定义渲染器:圆形按钮的自定义渲染器,xamarin,xamarin.forms,portable-class-library,custom-renderer,Xamarin,Xamarin.forms,Portable Class Library,Custom Renderer,我正在使用PCL Xamarin表单项目开发一个跨平台应用程序。我的应用程序将在ios、android、windows 10和windows 8.1桌面上运行 我想为xamarin表单中的按钮控件创建一个自定义呈现程序,在这个呈现程序中,我可以从xaml页面和代码隐藏中指定以下属性- 边框颜色 边框宽度 边界半径 背景色 文本颜色 文本字体大小、颜色、属性(如粗体) 按钮的高度和宽度 我尝试过xamarin窗体的普通按钮控件,但在android和Windows10的悬停按钮颜色更改中,边框半径不

我正在使用PCL Xamarin表单项目开发一个跨平台应用程序。我的应用程序将在ios、android、windows 10和windows 8.1桌面上运行

我想为xamarin表单中的按钮控件创建一个自定义呈现程序,在这个呈现程序中,我可以从xaml页面和代码隐藏中指定以下属性-

  • 边框颜色
  • 边框宽度
  • 边界半径
  • 背景色
  • 文本颜色
  • 文本字体大小、颜色、属性(如粗体)
  • 按钮的高度和宽度

  • 我尝试过xamarin窗体的普通按钮控件,但在android和Windows10的悬停按钮颜色更改中,边框半径不起作用。
    那么我如何才能做到这一点呢?

    在Android中,
    radiuproperty
    停止仅使用
    AppCompat
    它是一个

    AppCompat 如果您想同时使用普通按钮和AppCompat,则需要继承按钮并注册
    CustomRenderer

    [assembly: ExportRenderer(typeof(RoundButton), typeof(RoundButtonRenderer))]
    namespace Project.Droid.Renderers
    {
        public class RoundButtonRenderer : Xamarin.Forms.Platform.Android.AppCompat.ButtonRenderer
        {
            ButtonDrawable _backgroundDrawable;
            Drawable _defaultDrawable;
            bool _drawableEnabled;
    
            protected override void Dispose(bool disposing)
            {
                if (disposing)
                {
                    if (_backgroundDrawable != null)
                    {
                        _backgroundDrawable.Dispose();
                        _backgroundDrawable = null;
                    }
                }
    
                base.Dispose(disposing);
            }
    
    
            protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Button> e)
            {
                base.OnElementChanged(e);
    
                if (e.OldElement != null && _drawableEnabled)
                {
                    _drawableEnabled = false;
                    _backgroundDrawable.Reset();
                    _backgroundDrawable = null;
                }
                UpdateDrawable();
            }
    
    
    
            protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
            {
                if (_drawableEnabled &&
                    (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName || e.PropertyName == Xamarin.Forms.Button.BorderColorProperty.PropertyName || e.PropertyName == Xamarin.Forms.Button.BorderRadiusProperty.PropertyName ||
                    e.PropertyName == Xamarin.Forms.Button.BorderWidthProperty.PropertyName))
                {
                    _backgroundDrawable.Reset();
                    Control.Invalidate();
                }
    
                base.OnElementPropertyChanged(sender, e);
            }
    
            private void UpdateDrawable()
            {
                if (Element.BackgroundColor == Color.Default)
                {
                    if (!_drawableEnabled)
                        return;
    
                    if (_defaultDrawable != null)
                        Control.SetBackground(_defaultDrawable);
    
                    _drawableEnabled = false;
                }
                else
                {
                    if (_backgroundDrawable == null)
                        _backgroundDrawable = new ButtonDrawable();
    
                    _backgroundDrawable.Button = Element;
    
                    if (_drawableEnabled)
                        return;
    
                    if (_defaultDrawable == null)
                        _defaultDrawable = Control.Background;
    
                    Control.SetBackground(_backgroundDrawable.GetDrawable());
                    _drawableEnabled = true;
                }
    
                Control.Invalidate();
            }
        }
    
    
        public class ButtonDrawable : IDisposable
        {
            object _backgroundDrawable;
    
            PropertyInfo ButtonProperty;
            public Xamarin.Forms.Button Button
            {
                get
                {
                    return (Xamarin.Forms.Button)ButtonProperty.GetMethod.Invoke(_backgroundDrawable, null);
                }
                set
                {
                    ButtonProperty.SetMethod.Invoke(_backgroundDrawable, new object[] { value });
                }
            }
    
            public ButtonDrawable()
            {
                _backgroundDrawable = typeof(Xamarin.Forms.Platform.Android.ButtonRenderer).Assembly.CreateInstance("Xamarin.Forms.Platform.Android.ButtonDrawable");
                this.ResetMethod = _backgroundDrawable.GetType().GetMethod("Reset", BindingFlags.Instance | BindingFlags.Public);
                this.DisposeMethod = _backgroundDrawable.GetType().GetMethod("Dispose", BindingFlags.Instance | BindingFlags.Public);
                this.ButtonProperty = _backgroundDrawable.GetType().GetProperty("Button", BindingFlags.Instance | BindingFlags.Public);
            }
    
            MethodInfo ResetMethod;
            public void Reset()
            {
                ResetMethod.Invoke(_backgroundDrawable, null);
            }
    
            MethodInfo DisposeMethod;
            public void Dispose()
            {
                DisposeMethod.Invoke(_backgroundDrawable, null);
            }
    
            public Android.Graphics.Drawables.Drawable GetDrawable()
            {
                return _backgroundDrawable as Android.Graphics.Drawables.Drawable;
            }
        }
    }
    

    我在我的应用程序上使用这些属性,对我来说效果很好。 我将这些属性与“样式”一起使用

    例如:

    <Style x:Key="buttonStyle" TargetType="Button">
        <Setter Property="BackgroundColor" Value="{DynamicResource Snow}"/>
        <Setter Property="TextColor" Value="{DynamicResource LightBlue}" />
        <Setter Property="BorderColor" Value="{DynamicResource LightBlue}"/>
        <Setter Property="BorderRadius" Value="15"/>
        <Setter Property="BorderWidth" Value="1"/>
        <Setter Property="FontAttributes" Value="Bold" />
      </Style>
    
    
    
    我的按钮:

    <Button Text="Login" Command="{Binding LoginCommand}" Style="{DynamicResource buttonStyle}" />
    
    
    

  • 在内容页资源中创建样式,并在按钮中添加此样式
  • 拐角半径必须是HeightRequest和WidthRequest的一半
  • 这是针对Xamarin的。表单>=3.4。现在将边界半径转换为拐角半径
  • 
    
    你的问题是什么?@Jason你还不清楚我的问题吗?“我需要…”不是问题。Border radius在IOS上有效吗?我还没有试过。从来没有遇到过问题,但是没有在任何windows平台上试过。我在Windows10和8.1中试过普通的按钮控件,效果很好@Sonali如果你在
    BorderRadius
    上加了一个不正确的量,超过了它的一半高度,那就有点错误了好吧,我会记住这一点,所以为android定制渲染器只能解决我的问题,对吧?我已经尝试过了,但在android上不起作用。按钮没有边框,也没有圆角,可以清除项目并重新编译。也许只是文件上的垃圾。我在我当前的项目中使用这个,我没有遇到任何问题。我尝试了这个,得到了一个错误:没有定义名称空间前缀“x”
    <Button Text="Login" Command="{Binding LoginCommand}" Style="{DynamicResource buttonStyle}" />
    
    <ContentPage.Resources>
        <ResourceDictionary>
            <Style x:Key="myRoundbutton" TargetType="Button">
                <Setter Property="BackgroundColor" Value="Green"/>
                <Setter Property="TextColor" Value="White" />
                <Setter Property="BorderColor" Value="Blue"/>
                 <Setter Property="CornerRadius" Value="35"/>
                <Setter Property="HeightRequest" Value="70" />
                <Setter Property="WidthRequest" Value="70"/>
                <Setter Property="BorderWidth" Value="2"/>
                <Setter Property="FontAttributes" Value="Bold" />
            </Style>
        </ResourceDictionary>
    </ContentPage.Resources>
    
    <ContentPage.Content>
          <StackLayout HorizontalOptions="Fill" 
                       VerticalOptions="Fill">
    
              <Button Image="myBtn3.png" 
                      Command="{Binding LoginCommand}" 
                      Style="{DynamicResource myRoundbutton}" />
    
          </StackLayout>
    </ContentPage.Content>