首页 文章

自定义渲染器:圆角按钮的自定义渲染器

提问于
浏览
1

我正在使用PCL Xamarin Forms Project开发一个跨平台的应用程序 . 我的应用程序将运行在ios,android,Windows 10和Windows 8.1桌面上 .

我想在xamarin表单中为按钮控件创建一个自定义渲染器,我可以在其中指定xaml页面中的以下属性以及后面的代码 -

  • 边框颜色

  • 边框宽度

  • 边界半径

  • 背景颜色

  • 文字颜色

  • 文本字体大小,颜色,粗体等属性 .

  • 按钮的高度和宽度

我已经尝试了xamarin表单的正常按钮控制,但是在边框半径不能在android和Windows 10中的悬停按钮颜色更改中工作 . 那么我该如何实现呢?

3 回答

  • 1

    我在我的应用程序上使用这些属性,对我来说工作正常 . 我将这些属性与“样式”一起使用 .

    例:

    <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}" />
    

    Xamarin Styles

  • 1

    在Android中, RadiusProperty 仅停止与 AppCompat 一起工作known issue

    AppCompat

    如果要同时使用普通按钮和AppCompat,则需要从Button继承并注册 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;
            }
        }
    }
    

    没有AppCompat

    如果你想删除AppCompat,你必须做两件事

    您的 MainActivity 必须现在从 global::Xamarin.Forms.Platform.Android.FormsApplicationActivity 继承,并且您的样式通常在 resources/values/styles.xml 中必须从非AppCompat样式继承,如 android:Theme.Material

    <resources>
      <!-- inherit from the material theme -->
      <style name="AppTheme" parent="android:Theme.Material">
        <!-- Main theme colors -->
        <!--   your app branding color for the app bar -->
        <item name="android:colorPrimary">@color/primary</item>
        <!--   darker variant for the status bar and contextual app bars -->
        <item name="android:colorPrimaryDark">@color/primary_dark</item>
        <!--   theme UI controls like checkboxes and text fields -->
        <item name="android:colorAccent">@color/accent</item>
      </style>
    </resources>
    
  • 0

    在“内容页面”资源中创建样式,然后在按钮中添加此样式 . CornerRadius必须是HeightRequest和WidthRequest的一半 . 这适用于Xamarin.Forms> = 3.4 . 现在BorderRadius转换为CornerRadius .

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

相关问题