Rg.Plugins.Popup
Rg.Plugins.Popup copied to clipboard
Popup is not shown on Android in Xamarin Native app with Forms Page
Hello!
We are slowly transitioning our Xamarin Native app on Forms. Now we are making new pages on Forms and embedding them into app via integration according to official docs. Now we need to open popup page on pressing button in navigation bar (which is controlled by "native" part of application). On iOS all is working perfectly - popup is showing on button click, and behaves correctly.
But on Android popup is not shown and no error is raised. Next I'll show how we are integrating Forms page into Xamarin Android native app, and how i try to show popup:
This is main Activity with Forms and Popup plugin initialization code:
[Activity(Theme = "@style/theme_splash",
MainLauncher = true,
NoHistory = true,
ScreenOrientation = ScreenOrientation.Portrait)]
public class SplashScreenActivity : MvxSplashScreenActivity
{
public SplashScreenActivity() : base(Resource.Layout.splash)
{
}
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
Rg.Plugins.Popup.Popup.Init(this);
Forms.Init(this, bundle);
// Create app-level resource dictionary.
Xamarin.Forms.Application.Current = new Xamarin.Forms.Application();
Xamarin.Forms.Application.Current.Resources = new ApplicationResources();
}
}
According to docs, each Forms page must be inserted as Fragment into Activity. Here is our page, from which we are trying to open popup:
[MvxActivityPresentation]
[Activity(Label = "TaskRequestsFeedActivity", Icon = "@drawable/icon",
ScreenOrientation = ScreenOrientation.Portrait, WindowSoftInputMode = SoftInput.AdjustPan)]
public class TaskRequestFeedView: ViewWithMenuBase<TaskRequestsFeedViewModel>
{
protected override int ResourceId => Resource.Layout.task_requests_feed;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
var page = new TaskRequestsFeedPage()
{
Parent = Xamarin.Forms.Application.Current,
BindingContext = ViewModel
};
Xamarin.Forms.Application.Current.MainPage = page;
var pageFragment = page.CreateSupportFragment(this);
SupportFragmentManager
.BeginTransaction()
.Replace(Resource.Id.task_request_feed_container, pageFragment)
.Commit();
page.Parent = null;
}
}
Here is activity layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.drawerlayout.widget.DrawerLayout android:id="@+id/drawer_layout"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:layout_width="match_parent">
<LinearLayout android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/Toolbar" />
<FrameLayout **<<- Forms page is inserted here**
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/task_request_feed_container" />
</LinearLayout>
<com.google.android.material.navigation.NavigationView android:id="@+id/nav_view"
android:layout_width="@dimen/nav_view_width"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:itemTextColor="@android:color/black"
app:menu="@menu/menu"
app:headerLayout="@layout/menu_header"
app:MvxBind="NavigationItemSelected MenuItemClickCommand"
app:itemIconSize="@dimen/menu_item_icon_size"
android:theme="@style/NavigationTheme"
app:itemIconPadding="@dimen/menu_item_icon_padding"
app:itemIconTint="@android:color/black">
... menu content ...
</com.google.android.material.navigation.NavigationView>
</androidx.drawerlayout.widget.DrawerLayout>
</LinearLayout>
Here is the code which opens popup page on button click:
public Task OpenTaskRequestFilterPopupPageAsync(ITaskRequestFilterPopupParentViewModel parentViewModel)
{
var page = new TaskRequestFilterPopupPage(new TaskRequestFilterPopupPageViewModel(PopupNavigation.Instance,
parentViewModel,
logger));
PopupNavigation.Instance.Pushing -= InstanceOnPushing;
PopupNavigation.Instance.Pushing += InstanceOnPushing;
PopupNavigation.Instance.Pushed -= InstanceOnPushed;
PopupNavigation.Instance.Pushed += InstanceOnPushed;
return PopupNavigation.Instance.PushAsync(page);
}
private void InstanceOnPushing(object sender, PopupNavigationEventArgs e)
{
Debug.WriteLine($"{e.Page.GetType().Name}: pushing");
}
private void InstanceOnPushed(object sender, PopupNavigationEventArgs e)
{
Debug.WriteLine($"{e.Page.GetType().Name}: pushed");
}
This code is placed in common netstandard project and works well on iOS. On Android this code is being called, Pushing and Pushed events are firing, but poupup page is not shown.
Here is popup page:
<rg:PopupPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:rg="http://rotorgames.com"
xmlns:taskRequest="clr-namespace:Application.ViewModelsNew.TaskRequest;assembly=Application"
x:Class="Application.View.TaskRequestFilterPopupPage"
x:DataType="taskRequest:TaskRequestFilterPopupPageViewModel"
BackgroundColor="Transparent">
<Frame VerticalOptions="Start" HorizontalOptions="EndAndExpand" Margin="0,45,5,0">
<StackLayout VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<Button Text="Button 1"
Command="{Binding Path=ClickCommand}"
CommandParameter="{x:Static taskRequest:TaskRequestFilter.AssignedToMe}"/>
<Button Text="Button 2"
Command="{Binding Path=ClickCommand}"
CommandParameter="{x:Static taskRequest:TaskRequestFilter.UnderMyDirection}"/>
</StackLayout>
</Frame>
</rg:PopupPage>
And this is code behind of page with debugging methods:
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class TaskRequestFilterPopupPage : PopupPage
{
public TaskRequestFilterPopupPage(TaskRequestFilterPopupPageViewModel viewModel)
{
BindingContext = viewModel;
InitializeComponent();
}
protected override void OnAppearing()
{
Debug.WriteLine("Appearing");
base.OnAppearing();
}
protected override void OnDisappearing()
{
Debug.WriteLine("Disappearing");
base.OnDisappearing();
}
}
When page is opened on Android - OnAppearing is fired, but no page is shown.
Xamarin Forms version that we use is 5.0.0.2012. Also (i don't know whenether this is important) in Android we use MVVMCross for navigation between pages, while iOS app uses native navigation (for historical reasons).
I've tried to replace our TaskRequestFilterPopupPage with simple new PopupPage() containing label with some test text and colored backgroud - but this not helped.
Also I looked into plugin source code to find out what can cause this issue. I've found PopupPlatformDroid.AddAsync method.
At first I saw this code:
page.Parent = XApplication.Current.MainPage;
I've checked that we set MainPage property of Application class to our Forms page (see TaskRequestFeedView code fragment above).
Then i found this:
decoreView?.AddView(renderer.View);
where decoreView is:
var decoreView = DecoreView;
private static FrameLayout? DecoreView => (FrameLayout?)((Activity?)Popup.Context)?.Window?.DecorView;
I've checked (via debugging and reflection), that at runtime the property DecoreView is not null and holds object. Also I checked that all navigation is performed from UI thread.
Now I don't know where to look for what is causing issue. I've downloaded plugin repo and tried to play with Demo.Droid project in order to somehow reproduce issue. But sample project is seriously different from our solution - starting at that MainActivity inherits from Xamarin Forms base class:
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity
and that App class has NavigationPage as MainPage:
MainPage = new NavigationPage(new MainPage())
We cannot use same aspects because our app is Xamarin Native application.
I've searched any issues with this plugin related to our situation, bot with no luck. Also I think that making separate project which reproduces issue will be very complicated, because many aspects can make influence on issue: NuGet packages and their versions, our code, Native-Forms integration, MVVMCross, and so on.
So please, can anyone give some directions where to look or what to try? Or how to debug this issue to find a root cause? Any ideas are greatly appreciated, because I'm kind of stuck.
Thanks
@streamstr sorry for the radio silence, you're in a situation I am wholly unprepared for in my experience.
Have you seen anyone else get any headway with a Xamarin Native app, using Rg popups, but without MVVMCross? just trying to cross out any differences between iOS and Android.
with the app, when it says it has popped/pushed, does it have any X/Y positions? I wonder if you are able to force a layout somehow?
What I would suggest doing, is removing the NuGet from your project, download the repo, and then add it as a local reference to all your projects. From there, you can directly debug it through breakpoints and see what exactly the issue may be.
Good luck with this, sorry for the late reply, I got a bit distracted last couple of week. I hope you are able to find something.
I'm not sure if this is related to your issue @streamstr, but we have found that in a Xamarin.Forms project. When we add a native view to the stack, and try to open an RGPopup, the popup gets displayed behind the Activity that's displayed.
This seems to be an issue with how RGPopup determines the parent of the popup page to be displayed on Android.
any idea for fix?
Seems like incorrect init package. Need to init package in mainActivity