Custom ButtonRenderer not called when my Activity inherits from FormsAppCompatActivity

OSDMobileOSDMobile NLUniversity ✭✭
edited October 2015 in Xamarin.Forms

My Custom ButtonRenderer does not get called since my Activity inherits from FormsAppCompatActivity instead of FormsApplicationActivity

Is this a known issue?

My custom renderer:

[assembly: ExportRenderer (typeof (Button), typeof (ButtonCustomRenderer))]
namespace MyApp.Droid
{
    public class ButtonCustomRenderer : ButtonRenderer
    {
        Android.Graphics.Typeface _typeFaceRegular = Android.Graphics.Typeface.CreateFromAsset (Android.App.Application.Context.Assets, "AbcTT-Regular_2_0.ttf");

        protected override void OnElementChanged (Xamarin.Forms.Platform.Android.ElementChangedEventArgs<Button> e)
        {
            base.OnElementChanged (e);

            Control.SetTypeface (_typeFaceRegular, Android.Graphics.TypefaceStyle.Normal);

            Control.StateListAnimator = null;
        }

        protected override void OnElementPropertyChanged (object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged (sender, e);
        }
    }
}

I already tried to change my usings from:
using Xamarin.Forms.Platform.Android;
to:
using Xamarin.Forms.Platform.Android.AppCompat;

Answers

  • HankBeasleyHankBeasley USMember

    I have the same issue

  • MichaelRumplerMichaelRumpler ATMember ✭✭✭✭✭
    edited January 2016

    @OSDMobile @HankBeasley
    According to this thread AppCompat uses a different ButtonRenderer. Try inheriting from that instead.

    If it still does not work, then you should file a bug at bugzilla.

  • T_ODT_OD FRUniversity ✭✭

    @OSDMobile @HankBeasley
    I don't really know why, but the "AppCompat" custom renderer don't seem to work directly with native control.
    A workaround that works for me, with Buttons and TabbedPages, is to create an inherited class of the native control.
    Here's an example with the Button:

    namespace Xamarin.Forms
    {
        /// <summary>
        /// Cette classe ne "sert à rien", c'est simplement un 'workaround' permettant de faire fonctionner le ButtonRenderer depuis l'implémentation de Android Materiel Design...
        /// </summary>
        public class CustomButton : Button  
        {
            public CustomButton():base()
            {   
            }
    
            protected override void OnParentSet()
            {
                base.OnParentSet();
            }
        }
    }
    

    And the custom renderer:

    [assembly: ExportRenderer(typeof(CustomButton), typeof(CustomButtonRenderer))]
    namespace CalculateurMadelin.Droid.Renderers
    {
            public class CustomButtonRenderer : Xamarin.Forms.Platform.Android.AppCompat.ButtonRenderer
        { ...
    

    Hope this help.
    Thomas

  • KellyAdamsKellyAdams USMember

    Look at the decompiled code for FormsAppCompatActivity.LoadApplication:

    protected void LoadApplication(Xamarin.Forms.Application application)
    {
      if (!this.renderersAdded)
      {
        this.RegisterHandlerForDefaultRenderer(typeof (NavigationPage), typeof (NavigationPageRenderer), typeof (NavigationRenderer));
        this.RegisterHandlerForDefaultRenderer(typeof (TabbedPage), typeof (TabbedPageRenderer), typeof (TabbedRenderer));
        this.RegisterHandlerForDefaultRenderer(typeof (MasterDetailPage), typeof (MasterDetailPageRenderer), typeof (MasterDetailRenderer));
        ***this.RegisterHandlerForDefaultRenderer(typeof (Xamarin.Forms.Button), typeof (Xamarin.Forms.Platform.Android.AppCompat.ButtonRenderer), typeof (ButtonRenderer));***
        this.RegisterHandlerForDefaultRenderer(typeof (Xamarin.Forms.Switch), typeof (Xamarin.Forms.Platform.Android.AppCompat.SwitchRenderer), typeof (SwitchRenderer));
        this.RegisterHandlerForDefaultRenderer(typeof (Picker), typeof (Xamarin.Forms.Platform.Android.AppCompat.PickerRenderer), typeof (PickerRenderer));
        this.RegisterHandlerForDefaultRenderer(typeof (Frame), typeof (Xamarin.Forms.Platform.Android.AppCompat.FrameRenderer), typeof (FrameRenderer));
        this.RegisterHandlerForDefaultRenderer(typeof (CarouselPage), typeof (Xamarin.Forms.Platform.Android.AppCompat.CarouselPageRenderer), typeof (CarouselPageRenderer));
      }
      ....
    

    It will always re-register it's renderers and over-write your own, just before it renders your main page, (unless you set the private field renderersAdded to true through reflection). On a side note, since renderersAdded never gets anything other than default(bool) ((false)), and is never set anywhere else in the class, it makes me wonder if Xamarin meant to expose it via a property but never did.

  • PabloBiagioliPabloBiagioli USMember ✭✭

    I agree with @KellyAdams

    A solution has been posted in https://bugzilla.xamarin.com/show_bug.cgi?id=38117

    Anyways, it's always a good practice to extend all the controls, even if they don't behave different than the generic ones.

    So, my approach would be to create a

    public class GenericButton : Button {}

    and then make a custom renderer of this generic button control.

    The elevation attribute isn't working either if you are using Xamarin Forms.
    Bugzilla = https://bugzilla.xamarin.com/show_bug.cgi?id=27797

Sign In or Register to comment.