1

我正在使用 PCL Xamarin Forms Project 开发跨平台应用程序。我的应用程序将在 ios、android、windows 10 和 windows 8.1 桌面上运行。

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

  1. 边框颜色
  2. 边框宽度
  3. 边界半径
  4. 背景颜色
  5. 文字颜色
  6. 文本字体大小、颜色、粗体等属性。
  7. 按钮的高度和宽度

我已经尝试过 xamarin 表单的普通按钮控制,但在该边框半径中,android 和 Windows 10 中的悬停按钮颜色更改不起作用。那么我该如何实现呢?

4

3 回答 3

1

在 Android 中,RadiusProperty停止工作仅适用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>
于 2017-01-24T17:08:30.957 回答
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 样式

于 2017-01-24T17:25:16.920 回答
0
  1. 在内容页面资源中创建一个样式,并将此样式添加到按钮中。
  2. CornerRadius 必须是 HeightRequest 和 WidthRequest 的一半。
  3. 这适用于 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>
于 2019-01-11T06:50:02.403 回答