2

I'm trying to create a custom ButtonRenderer for Xamarin.Forms. Here is a simple test I've been trying to put up together following some tutorials, but I can's seem to make it work.

Here is my .xaml page:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="TestProject.MainPage">
    <ContentPage.Content>
        <Button VerticalOptions="Center" HorizontalOptions="Center"></Button>
    </ContentPage.Content>
</ContentPage>

And here is my custom rendered: (it is placed in the Android project)

[assembly: ExportRenderer(typeof(Xamarin.Forms.Button), typeof(CustomButtonRenderer))]
namespace TestProject.Droid.CustomRenderers
{
    public class CustomButtonRenderer: ButtonRenderer
    {
        public CustomButtonRenderer(Context context) : base(context)
        {
        }

        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Button> e)
        {
            base.OnElementChanged(e);
            Control.SetBackgroundColor(Android.Graphics.Color.Red);
        }
    }
}

But it never gets called and my app crashes. My logcat shows:

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> Java.Lang.ClassNotFoundException: Didn't find class "md5dba8ede99752acada1f5ba384c7cf839.CustomButtonRenderer" on path: DexPathList[[zip file "/data/app/com.companyname.TestProject-1/base.apk"],nativeLibraryDirectories=[/data/app/com.companyname.GN.Mobile.TestProject-1/lib/arm, /data/app/com.companyname.GN.Mobile.TestProject-1/base.apk!/lib/armeabi-v7a, /vendor/lib, /system/lib]]

Am I missing something here?

LcSalazar
  • 16,524
  • 3
  • 37
  • 69
  • It looks pretty right. Have you tried the classic 'clean', delete obj and bin files, 'rebuild' and retry? – Diego Rafael Souza Dec 15 '17 at 19:15
  • @DiegoRafaelSouza - Yes, I have cleaned, deleted caches, etc... I have started a new clean project and tried to create just these classes... and nothing! :( – LcSalazar Dec 15 '17 at 19:18
  • What's your XF version? I'm using Xamarin 4.7.10.33, Xamarin.Android 8.0.2.1 and Xamarin.Forms 2.3.4.247... the `ButtonRenderer` constructor is parameterless – Diego Rafael Souza Dec 15 '17 at 19:41
  • Try to create new class wich inherits from button... es: MyButton : Button.... and in custom render place MyButton instead of button.. – purplesoft Dec 15 '17 at 19:47
  • Have you set up a breakpoint in the element changed method and checked if the method throws an exception? You should not just call something on the control without an antecedent null check. Watch [this presentation](https://youtu.be/pIZ8G47KPIM?t=17m11s) of jason smiths about custom renderers. at 17:12 he starts showing the pattern. – Csharpest Dec 17 '17 at 12:53
  • Thank you all for the time and effort. I still didn't solve the issue, but ended up running the same code in another machine, and it worked perfectly. I assume now it's some issue with my VS. Thanks. – LcSalazar Dec 18 '17 at 11:50
  • I had the exact same issue, I did a full clean and rebuild and it worked. – Ernesto Mar 18 '18 at 17:30

2 Answers2

2

I'm still investigating on this. Your class gets shrunk because it's not statically linked in your PCL. You avoid that by giving a name to your classes like this:

[Activity(Name = "somepackage.custombuttonrenderer")]
public class CustomButtonRenderer: ButtonRenderer
{ }

If you're able to target the minimum Android version to Android 5.0 (Api 21) this problem should disappear as another version of the Dex file is used.

IvanF.
  • 513
  • 10
  • 18
-1

replace CustomButtonRenderer code to below code.

[assembly: ExportRenderer(typeof(Xamarin.Forms.Button), typeof(CustomButtonRenderer))]
namespace TestProject.Droid.CustomRenderers
{
public class CustomButtonRenderer: ButtonRenderer
{
    public CustomButtonRenderer(Context context) : base(context)
    {
    }

    protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Button> e)
    {
        base.OnElementChanged(e);
        if (e.OldElement != null)
        {
            return;
        }
        var nativeButton = (Android.Widget.Button)this.Control;
        nativeButton.SetBackgroundColor(Android.Graphics.Color.Gray);

    }
}
}
ajaysinh rajput
  • 175
  • 2
  • 8