"Specified cast is not valid" when using SetOnItemSelectedListener of NavigationBarView
genis-bosch-ypsomed opened this issue · comments
Android application type
Android for .NET (net6.0-android, etc.)
Affected platform version
.NET 6.0.100
Description
When setting an OnItemSelectedListener for a NavigationBarView, the execution fails with the following error:
System.InvalidCastException: Specified cast is not valid.
at Google.Android.Material.Navigation.NavigationBarView.SetOnItemSelectedListener(IOnItemSelectedListener listener) in C:\a\_work\1\s\generated\com.google.android.material.material\obj\Release\net6.0-android\generated\src\Google.Android.Material.Navigation.NavigationBarView.cs:line 1916
at Droid.Components.CoreFeatures.BaseNavigation.AppPresenter.SetBottomNavigationViewAsync(MvxTabItemPresentationAttribute attribute) in Droid/Components/CoreFeatures/BaseNavigation/AppPresenter.cs:line 330
at Droid.Components.CoreFeatures.BaseNavigation.AppPresenter.AddToBottomNavigationOrShowFragment(Type viewType, IMvxPresentationAttribute attribute, MvxViewModelRequest request) in .Droid/Components/CoreFeatures/BaseNavigation/AppPresenter.cs:line 415
at MvvmCross.Base.MvxMainThreadAsyncDispatcher.<>c__DisplayClass1_0.<<ExecuteOnMainThreadAsync>b__0>d.MoveNext() in /_/MvvmCross/Base/MvxMainThreadAsyncDispatcher.cs:line 34
--- End of stack trace from previous location ---
at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__128_0(Object state)
at Android.App.SyncContext.<>c__DisplayClass2_0.<Post>b__0()
at Java.Lang.Thread.RunnableImplementor.Run()
at Java.Lang.IRunnableInvoker.n_Run(IntPtr jnienv, IntPtr native__this)
at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PP_V(_JniMarshal_PP_V callback, IntPtr jnienv, IntPtr klazz)
The same method worked for .NET Standard 2.1.
Steps to Reproduce
1 - Create a NavigationBarView, with .NET 6 and Xamarin.Google.Android.Material 1.10.0.3.
2 - Create an implementation of NavigationBarView.IOnItemSelectedListener.
3 - Set the OnItemSelectedListener by calling the _navigationBarView.SetOnItemSelectedListener(...)
Did you find any workaround?
No
Relevant log output
System.InvalidCastException: Specified cast is not valid.
at Google.Android.Material.Navigation.NavigationBarView.SetOnItemSelectedListener(IOnItemSelectedListener listener) in C:\a\_work\1\s\generated\com.google.android.material.material\obj\Release\net6.0-android\generated\src\Google.Android.Material.Navigation.NavigationBarView.cs:line 1916
at Droid.Components.CoreFeatures.BaseNavigation.AppPresenter.SetBottomNavigationViewAsync(MvxTabItemPresentationAttribute attribute) in Droid/Components/CoreFeatures/BaseNavigation/AppPresenter.cs:line 330
at Droid.Components.CoreFeatures.BaseNavigation.AppPresenter.AddToBottomNavigationOrShowFragment(Type viewType, IMvxPresentationAttribute attribute, MvxViewModelRequest request) in .Droid/Components/CoreFeatures/BaseNavigation/AppPresenter.cs:line 415
at MvvmCross.Base.MvxMainThreadAsyncDispatcher.<>c__DisplayClass1_0.<<ExecuteOnMainThreadAsync>b__0>d.MoveNext() in /_/MvvmCross/Base/MvxMainThreadAsyncDispatcher.cs:line 34
--- End of stack trace from previous location ---
at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__128_0(Object state)
at Android.App.SyncContext.<>c__DisplayClass2_0.<Post>b__0()
at Java.Lang.Thread.RunnableImplementor.Run()
at Java.Lang.IRunnableInvoker.n_Run(IntPtr jnienv, IntPtr native__this)
at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PP_V(_JniMarshal_PP_V callback, IntPtr jnienv, IntPtr klazz)
This looks like the line that is causing the InvalidCastException
:
__args [0] = new JniArgumentValue ((listener == null) ? IntPtr.Zero : ((global::Java.Lang.Object) listener).Handle);
My guess is your implementation of NavigationBarView.IOnItemSelectedListener
does not inherit from Java.Lang.Object
, which is required.
The following is a cut-down version that I’ve been using with X.A, Net7 and Net8. See any of the NavigationGraph examples at https://github.com/gmck for more details. I'm using Xamarin.Google.Android.Material 1.10.0.3.
I'm pretty sure it changed from the original implementation a couple of years back, but I now can't remember what the old way was.
NavigationBarView.IOnItemSelectedListener
bottomNavigationView!.ItemSelected += BottomNavigationView_ItemSelected!;
private void BottomNavigationView_ItemSelected(object sender, NavigationBarView.ItemSelectedEventArgs e)
{
…
... navController!.Navigate(e.Item.ItemId, null, navOptions);
}
Thank you for your helpful answers. From what I see, we weren't using the Java.Lang.Object which should be the issue. I will try this one and come back for feedback.
What do you get when you right-click NavigationView.IOnNavigationItemSelectedListener and then go to Definition
Mine has JavaObject.
public interface IOnNavigationItemSelectedListener : IJavaObject, IDisposable, IJavaPeerable
{
[Register("onNavigationItemSelected", "(Landroid/view/MenuItem;)Z", "GetOnNavigationItemSelected_Landroid_view_MenuItem_Handler:Google.Android.Material.Navigation.NavigationView/IOnNavigationItemSelectedListenerInvoker, Xamarin.Google.Android.Material")]
bool OnNavigationItemSelected(IMenuItem menuItem);
}
Does your main activity inherit from AppCompatActivity?
I had a bit of a brain fade last night when I posted the above. The above should have been about NavigationBarView.IOnItemSelectedListener, not NavigationView.
It should have read right-click on NavigationBarView.IOnItemSelectedListener
[Register("com/google/android/material/navigation/NavigationBarView$OnItemSelectedListener", "", "Google.Android.Material.Navigation.NavigationBarView/IOnItemSelectedListenerInvoker")]
public interface IOnItemSelectedListener : IJavaObject, IDisposable, IJavaPeerable
{
[Register("onNavigationItemSelected", "(Landroid/view/MenuItem;)Z", "GetOnNavigationItemSelected_Landroid_view_MenuItem_Handler:Google.Android.Material.Navigation.NavigationBarView/IOnItemSelectedListenerInvoker, Xamarin.Google.Android.Material")]
bool OnNavigationItemSelected(IMenuItem p0);
}
If you look at the IOnItemSelectedListenerInvoker below that, you'll see it inherits from Java.Lang.Object. If I remember correctly the change I referred to was introduced in Material 1.4.0