AppCompat does not resize screen with keyboard.

AdamMeaneyAdamMeaney USMember ✭✭✭✭✭

Given a simple ContentPage with an Editor at the bottom and a list as the first item (Stack with list and Editor), I cannot get the page to be the correct size.

I can put the stack into a scrollview or not, with the Android option AdjustResize set or not, and anyway I do it, the screen pushes the Toolbar or Tabs off the top, unable to be seen.

This does not happen when using FormsApplicationActivity, just the FormsAppCompatActivity.

Any ideas on how to get a user interface that is similar to how traditional chat applications look? Sample project included.

Best Answer

Answers

  • HRO_JordyHRO_Jordy NLMember ✭✭

    I think there is a bug in the FormsAppCompatActivity. I've got a similar issue:

    A ContentPage with a StackLayout that contains first an Entry and second a Listview with 26 item. Using the default MainApplication : FormsApplicationActivity the app behaves as expected: when the focus is on the Entry, the Keyboard pops up and the screen is panned. When using MainApplication : FormsAppCompatActivity and the Theme = "@style/Theme.AppCompat.Light.NoActionBar" I can no longer reach the last few items in the listview, because the Keyboard covers the listview and the screen is not panned.

    This happens on a Nexus S KitKat, Nexus 7 Lollipop and Nexus 7 Marshmallow.

    Comparison video

  • AdamMeaneyAdamMeaney USMember ✭✭✭✭✭

    Glad to see I am not the only one. If no one responds with some kind of fix, I may try a bug report and see what happens.

  • AdamMeaneyAdamMeaney USMember ✭✭✭✭✭

    As a note, when I spoke with Xamarin support, they gave me some ideas that at least stop it from pushing it all offscreen for now while they investigate and try to resolve this.

    Quote from support guy:

    I’ve been working on this issue and I’ve managed to partly figure out what the cause is. When using FormsAppCompatActivity, the WindowSoftInputMode attribute is being ignored because after base.OnCreate() is called, it gets reset to AdjustPan no matter what. So to get around this, you’ll have to call:

    Window.SetSoftInputMode(SoftInput.AdjustResize);

    But just reversing the change doesn’t get fix the issue. For some reason you also have to set:

    Window.DecorView.SystemUiVisibility = 0;

    That was actually something Jason on the Forms team suggested when I spoke with him about the issue. Initially it didn’t help because it was before I realized base.OnCreate was resetting the attribute. Combining the two seems to fix the issue, though it does causes the status bar to be translucent compared to the toolbar’s color.

  • AdamMeaneyAdamMeaney USMember ✭✭✭✭✭

    Along with the support guy code, added these bits of code to color the status bar as the weird translucent bug was bothering me.

    var statusBarHeightInfo = typeof(FormsAppCompatActivity).GetField("statusBarHeight", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
    statusBarHeightInfo.SetValue(this, 0);
    
    if (Build.VERSION.SdkInt >= BuildVersionCodes.Kitkat)
    {
        Window.SetStatusBarColor(new Android.Graphics.Color(ContextCompat.GetColor(this, Resource.Color.statusBarColor)));
    }
    
  • HRO_JordyHRO_Jordy NLMember ✭✭

    Hm, strange. In my case it looks like the AdjustPan doesn't work in the described example.

  • HRO_JordyHRO_Jordy NLMember ✭✭

    @AdamMeaney said:
    Along with the support guy code, added these bits of code to color the status bar as the weird translucent bug was bothering me.

    var statusBarHeightInfo = typeof(FormsAppCompatActivity).GetField("statusBarHeight", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
    statusBarHeightInfo.SetValue(this, 0);
    
    if (Build.VERSION.SdkInt >= BuildVersionCodes.Kitkat)
    {
        Window.SetStatusBarColor(new Android.Graphics.Color(ContextCompat.GetColor(this, Resource.Color.statusBarColor)));
    }
    

    SetStatusBarColor isn't available for Kitkat, it's supported since Lollipop.

  • HRO_JordyHRO_Jordy NLMember ✭✭

    @HRO_Jordy said:
    Hm, strange. In my case it looks like the AdjustPan doesn't work in the described example.

    I was wrong, It was also the AdjustResize what I needed.

  • AdamMeaneyAdamMeaney USMember ✭✭✭✭✭

    I noticed that eventually. Sorry I didn't come back to correct that code.

    Thanks for helping to keep it working right for anyone else who comes here.

  • HRO_JordyHRO_Jordy NLMember ✭✭

    @AdamMeaney said:
    Along with the support guy code, added these bits of code to color the status bar as the weird translucent bug was bothering me.

    var statusBarHeightInfo = typeof(FormsAppCompatActivity).GetField("statusBarHeight", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
    statusBarHeightInfo.SetValue(this, 0);
    
    if (Build.VERSION.SdkInt >= BuildVersionCodes.Kitkat)
    {
        Window.SetStatusBarColor(new Android.Graphics.Color(ContextCompat.GetColor(this, Resource.Color.statusBarColor)));
    }
    

    It seems that they've changed the field name in a newer version of AppCompat to _statusBarHeight

    // soft input mode resets to AdjustPan after base.OnCreate, change it to the desired mode
                Window.SetSoftInputMode(Android.Views.SoftInput.AdjustResize);
                // but it's not enough, set the following property to really fix the issue
                Window.DecorView.SystemUiVisibility = 0;
                if (Build.VERSION.SdkInt >= BuildVersionCodes.Lollipop)
                {
                   // unfortunately this creates a transparent statusbar, so 're-color' the status bar again
                   var statusBarHeightInfo = typeof(FormsAppCompatActivity).GetField("_statusBarHeight", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
                   if (statusBarHeightInfo != null)
                   {
                      statusBarHeightInfo.SetValue(this, 0);
                   }
                   Window.SetStatusBarColor(new Android.Graphics.Color(Android.Support.V4.Content.ContextCompat.GetColor(this, Resource.Color.primaryDark)));
                }
    
  • JoeMankeJoeManke USMember ✭✭✭✭✭

    @HRO_Jordy Yes, from what I can tell that was done in Xamarin.Forms 2.2.0. We had corrected it in our own code but once again didn't update this thread.

  • HRO_JordyHRO_Jordy NLMember ✭✭

    @AdamMeaney @JoeManke

    I can confirm this is still an issue in Xamarin Forms 2.3.3.175. This Forms version actually fixes the statusbar issue in this workaround, but it also activates the bug again and this workaround doesn't work.

    @AdrianKnight it's this bugreport: https://bugzilla.xamarin.com/show_bug.cgi?id=39916, and while it indicates this bug is SOLVED FIXED, it seems this is not the case.

  • AdrianKnightAdrianKnight USMember ✭✭✭✭

    @HRO_Jordy I do not believe the default behavior is going to be AdjustResize on AppCompat unfortunately, This is to prevent breaking changes. I have an issue with the XF team when it comes to such changes. I do believe breaking changes are OK so long as they are communicated properly. They seem to avoid such changes to their best ability, hence the platform specific option to control resize mode.

    The PRs I added above should make the experience better. They are still open unfortunately.

  • HRO_JordyHRO_Jordy NLMember ✭✭
    edited December 2016

    @AdrianKnight I can live with the fact that AdjustResize is not default behavior for AppCompat. But I still think what is considered a fix, is actually the same workaround as described in this discussion but typed differently:

    using Xamarin.Forms.PlatformConfiguration;
    using Xamarin.Forms.PlatformConfiguration.AndroidSpecific;
    
    Xamarin.Forms.Application.Current.On<Android>().UseWindowSoftInputModeAdjust(WindowSoftInputModeAdjust.Resize);
    

    Also this 'fix' again breaks the statusbar, so it really is almost same workaround as described earlier in this discussion.

    (@AdamMeaney @JoeManke we're still investigating this, but a combination of the above code and the earlier mentioned workaround seems to make it work like normal again in Forms 2.3.3.175)

    The original problem: keyboard covers listviewitems, because android doesn't AdjustResize, because AppCompat defaults it to AdjustPan (I believe). So what I would like to do (in the Droid project) is to set the WindowsSoftInputMode in the Activity Attribute:

    [Activity(Label = "AppName", Icon = "@drawable/icon", MainLauncher = false, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation, WindowSoftInputMode = Android.Views.SoftInput.AdjustResize | Android.Views.SoftInput.AdjustPan)]
    public class MainActivity : XLabs.Forms.XFormsAppCompatDroid
    

    but again AppCompat does not respect the WindowsSoftInputMode attribute (I think this is the bug), but defaults it to the AppCompat default.

    I agree with you that breaking changes are OK, when communicated properly :smile:

  • PhilippSumiPhilippSumi USMember ✭✭✭

    Bump. Anybody from Xamarin willing to comment on this? This seems common enough to affect a lot of scenarios...

  • ConnorSchmidtConnorSchmidt USMember ✭✭
    edited January 2017

    I used a solution from above and it works... to a point. Nevermind. After cleaning and rebuilding my project, the problem (described below) re-appeared.

    I am using the AndroidBug5497WorkaroundForXamarinAndroid fix in my proejct. If I push a new page using Navigation.PushAsync and use the resulting software Back arrow (top left) to go back to the previous Page while the keyboard is up, the keyboard goes away but the screen remains sized like it has the keyboard up. It also happens when using Navigation.PopAsync (as described here: https://forums.xamarin.com/discussion/54773/android-keyboard-and-the-contentpage-view-collapsing-expanding-issue-w-material-design)

  • czPePczPeP CZMember

    Just discovered this as well. After changing the app to use FormsAppCompatActivity the
    WindowSoftInputMode = Android.Views.SoftInput.AdjustResize
    attribute stopped working.
    Currently I am using this "fix" (didn't realize at first it had to be added manually):
    Current.On<Android>().UseWindowSoftInputModeAdjust(WindowSoftInputModeAdjust.Resize);
    Although this is enough on my KitKat device it still does not fix newer Android versions.
    So I also used "AndroidBug5497WorkaroundForXamarinAndroid" helper class (which initially didn't work without the first part).
    Now it all works as expected (AFAIK).

    But it's far from nice and smooth and needs fixing!

  • JGoldbergerJGoldberger USMember, Forum Administrator, Xamarin Team, University Xamurai
    edited July 2017
  • Hildebrand4Hildebrand4 DEMember ✭✭
    edited February 2018

    So, as of 2018 this bug still seems to be around, and none of the workarounds mentioned here or elsewhere seem to be working correctly anymore.
    For anyone also still having this issue, the only thing that worked for me was setting the SoftInputMode each time in the FocusChange event of my Entry and Editor renderers.

    private void OnFocusChange(object sender, FocusChangeEventArgs args)
    {
        if (true == args.HasFocus)
        {
            MainActivity.Instance.Window.SetSoftInputMode(SoftInput.AdjustResize);
        }
    }
    
  • BhautikBhautik Member ✭✭✭

    @JoeManke said:
    They actually added a PlatformSpecific for this.

    Application.Current.On<Xamarin.Forms.PlatformConfiguration.Android>().UseWindowSoftInputModeAdjust(WindowSoftInputModeAdjust.Resize);

    It is working fine for Android only.What about iOS?

  • JoeMankeJoeManke USMember ✭✭✭✭✭

    @Bhautik This thread is entirely about an Android-specific issue. You may want to make a new thread for your iOS issues. Describe what you want to do thoroughly and include some screenshots/a repro project.

  • j.kj.k BYMember ✭✭

    @Hildebrand4 said:
    So, as of 2018 this bug still seems to be around, and none of the workarounds mentioned here or elsewhere seem to be working correctly anymore.
    For anyone also still having this issue, the only thing that worked for me was setting the SoftInputMode each time in the FocusChange event of my Entry and Editor renderers.

    private void OnFocusChange(object sender, FocusChangeEventArgs args)
    {
        if (true == args.HasFocus)
        {
            MainActivity.Instance.Window.SetSoftInputMode(SoftInput.AdjustResize);
        }
    }
    

    This is the only thing worked for me. Thanks a lot!

Sign In or Register to comment.