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

时间:2017-01-24 16:53:09

标签: xamarin xamarin.forms portable-class-library custom-renderer

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

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

  1. 边框颜色
  2. 边框宽度
  3. 边界半径
  4. 背景颜色
  5. 文字颜色
  6. 文字字体大小,颜色,粗体等属性。
  7. 按钮的高度和宽度
  8. 我已经尝试了xamarin表单的正常按钮控件,但是在边框半径不能在android和Windows 10中的悬停按钮颜色更改中工作。 那我怎么能实现这个呢?

3 个答案:

答案 0 :(得分:1)

在Android中,RadiusProperty仅停止使用AppCompat known issue

程序兼容性

如果您想同时使用普通按钮和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中的样式必须继承自非{App(1)}等非AppCompat样式

android:Theme.Material

答案 1 :(得分:1)

我在我的应用程序上使用这些属性,对我来说工作正常。 我正在使用这些属性&#34;样式&#34;。

示例:

<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

答案 2 :(得分:0)

  
      
  1. 在“内容页面”资源中创建样式,然后在按钮中添加此样式。
  2.   
  3. CornerRadius必须是HeightRequest和WidthRequest的一半。
  4.   
  5. 这是针对Xamarin.Forms> = 3.4的。现在BorderRadius转换为CornerRadius。
  6.   
function my_widget_title($title, $instance, $id_base) 
{

    global $post;
    if ( is_singular() && 'text' == $id_base) {
        return get_the_title($post->ID).__(' Custom Tour Inquiry');
    }
    else 
    {
        return $title;
    }

}
add_filter ( 'widget_title' , 'my_widget_title', 10, 3);