My app is Xamarin.Android – android:targetSdkVersion="31
I have quite a few modal Dialogs in my app, which are all based on AppCompatDialogFragment. Some are more complicated than others and so have their own classes, but they now all appear to have a problem in displaying correctly on Android 12 devices only. On any devices lower than Android 12, they display normally as they have done, since Android 10, when I first converted to AndroidX.
The simplest one of these dialogs is a class called BasicDialogFragment. An instance of it takes 2 strings, a title and a message. The layout is a NestedScrollView containing a ConstraintLayout which has a single Textview for the message, which can be of any length.
The problem is the OK button doesn’t always appear, especially on longer multi-paragraph messages which obviously can scroll. If the message is short enough that scrolling is not required, then the OK button displays normally. On dialogs with longer messages, the button might appear the first time the Dialog is called, the next time it might only be partially visible (but still tappable) and another time it is not visible. Even when not visible the dialog can still be dismissed by tapping in the area where the button should be. Quite often if you rotate the device the button will appear in Landscape and when you rotate back to Portrait the button will appear where previously it didn’t, but there is no consistent pattern to it.
There doesn’t appear to be anything wrong with the NestedScrollView because the text does scroll as you would expect, even with the new spring animation which Android 12 introduced.
I’ve rechecked, the old Android 11 version of the app and it also has the same problem on the Android 12 devices.
I have 3 Pixel devices - 3a (Android12), 4a (still Android11 – so doesn’t have the problem) and a Pixel 6.
All my other devices are Samsung (phones and tablets - Android 7 through Android 11) but none of them has Android 12 yet, so none of them exhibits the problem.
I’m using a MaterialAlertDialogBuilder in the OnCreateDialog of the BasicDialogFragment as below.
public override Dialog OnCreateDialog(Bundle savedInstanceState)
{
LayoutInflater inflater = LayoutInflater.From(Activity);
View view = inflater.Inflate(Resource.Layout.generic_dialog, null);
TextView textViewExplanation = view.FindViewById<TextView>(Resource.Id.textView_explanation);
textViewExplanation.Text = Arguments.GetString("Message");
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(Activity);
builder.SetTitle(Arguments.GetString("Title"));
builder.SetPositiveButton(Android.Resource.String.Ok, (sender, args) => { Dismiss(); });
builder.SetView(view);
return builder.Create();
}
The following is xml of generic_dialog.xml
<androidx.core.widget.NestedScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:scrollbars="vertical"
android:paddingTop="16dp"
android:paddingBottom="8dp"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/textView_explanation"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:singleLine="false"
android:textAppearance="@android:style/TextAppearance.Material"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="@string/subscription_explanation_text" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
I first tried to reproduce the problem, by building a simple app based on the Blank app template. Unfortunately, I couldn’t reproduce it with that. So, my next try was to swap to Android Studio and use one of their templates, called Navigation Drawer Activity, which is a single activity, multi fragment app using the NavigationComponent with a navigation graph, which more closely resembles my app, as I also use the NavComponent. However, I couldn’t reproduce the problem when adding my code to it, the dialogs displayed without any problem.
The next step was to convert their app to a Xamarin.Android app. I’ve now done that, and it works just the same as the Android Studio app. The only change I made, other than I borrowed most of their xml, was to replace the fragment tag they had in content_main.xml with an androidx.fragment.app.FragmentContainerView, as that is a recommendation Android made some time ago, but obviously, they haven’t got around to updating their own template. I also ignored the ViewModel and Binding stuff as they don’t really have any relevance with the problem of the OK button not displaying. Again, no luck as this version also works perfectly.
I also removed their FloatingActionButton in app_bar_main.xml and introduced a BottomNavigationView into content_main. My app has no use for a FloatingActionButton but does require a BottomNavigationBar on one of my top-level fragments. In this example, It is only shown on the SlideShowFragment as that mimics my apps behaviour. The two menu items of the BottomNavigationBar have no code attached, so they don’t do anything.
I’m attaching my Xamarin.Android example to this post. If anyone would like the Android Studio version, I can also upload that if required.
The attached app has been built with VS 2022 17.1.0 Prev 1.1 but has also been tested with VS 2022 17.0.4.
I’ve deliberately tried to use an example that displays generic text, so I chose the subscription info as the text, so I didn’t need to expose product or company info in the example of a not as yet released app. Please feel free to modify it with your text. The subscription info is normally displayed as a BottomSheetDialogFragment on my SubscriptionFragment, so I had to add a couple of paras just to make it scrollable to be able to use my BasicDialogFragment on the Pixel 6.
The one thing that I notice that is different between my own app and this example app is if I deliberately display the subscription info on the start destination fragment (not normally available from there) then I can see that the origin x,y of the dialog is lower in my app than it is in the example app on the Pixel 6. This is most obvious when you make both apps go into the background, where you can see them side by side. Unfortunately, I’m not aware of how you can take a screenshot of both apps at the same time. Why the starting point is lower on my app I’ve no idea.
I’ve been chasing this problem now for about 2 weeks and not getting anywhere with it, so I’m hoping someone here will have some brilliant solution.
A couple of warnings, if you haven’t used the navigation component before. Having a nav_graph.xml in a Xamarin.Android app gives the Xamarin.Android designer fits, in that it usually always opens any xml layout file with an error. You soon learn to ignore the error as it has no effect on the building or running of the app. If it does happen to any of you, you can eliminate the error by temporally excluding the nav_graph from the project and then the designer should open any layout file without error. You’ve just got to remember to re-include it again before your build.
The OK button problem has been reported on https://github.com/xamarin/xamarin-android/issues. Issue #6554, however, there appears to be a hold up over there as all reported problems since #6546 are still listed as “needs-triage”, hence my post here.
I look forward to any of your comments and suggestions and thanks for taking the time to have a look at my problem.
Link to zip file: https://drive.google.com/file/d/1cuByKpW38npMrLTiMT9Qk5MDeKIF0drt/view?usp=sharing