locked
AppCompat does not resize screen with keyboard. RRS feed

  • Question

  • User129559 posted

    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.

    Monday, March 14, 2016 4:00 PM

Answers

  • User53115 posted

    They actually added a PlatformSpecific for this.

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

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Tuesday, February 20, 2018 2:20 PM

All replies

  • User187715 posted

    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

    Tuesday, March 15, 2016 2:37 PM
  • User129559 posted

    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.

    Tuesday, March 15, 2016 2:45 PM
  • User129559 posted

    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.

    Friday, March 18, 2016 2:50 PM
  • User129559 posted

    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)));
    }
    
    Friday, March 18, 2016 9:55 PM
  • User187715 posted

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

    Monday, March 21, 2016 7:39 AM
  • User187715 posted

    @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.

    Monday, April 4, 2016 2:12 PM
  • User187715 posted

    @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.

    Monday, April 4, 2016 2:13 PM
  • User129559 posted

    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.

    Monday, April 4, 2016 2:13 PM
  • User187715 posted

    @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)));
                }
    
    Friday, August 26, 2016 9:59 AM
  • User53115 posted

    @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.

    Friday, August 26, 2016 1:55 PM
  • User181025 posted

    @JoeManke @AdamMeaney @HRO_Jordy I'm linking two PRs that should help you address your issues:

    https://github.com/xamarin/Xamarin.Forms/pull/422 https://github.com/xamarin/Xamarin.Forms/pull/552

    Thursday, December 8, 2016 1:58 AM
  • User187715 posted

    @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.

    Tuesday, December 13, 2016 10:32 AM
  • User181025 posted

    @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.

    Tuesday, December 13, 2016 2:57 PM
  • User187715 posted

    @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().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:

    Tuesday, December 13, 2016 4:05 PM
  • User251799 posted

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

    Tuesday, January 3, 2017 3:04 PM
  • User170624 posted

    ~~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)

    Friday, January 13, 2017 10:02 PM
  • User259582 posted

    I faced this issue today. I created a project in Android Studio, set to AdjustResize and worked fine. Then I created a new project in Xamarin.Forms, just added this code:

    Window.SetSoftInputMode(SoftInput.AdjustResize); Window.DecorView.SystemUiVisibility = 0;

    And the XAML <?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="TracRite.Optimum.Mobile.Invent.UI.Views.TestPage"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="60*" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <StackLayout Grid.Row="0" Orientation="Vertical" BackgroundColor="Lime" Margin="0,0,0,0"> <Button x:Name="btnScan" Text="Scan" TextColor="White" BackgroundColor="Black" /> <Button x:Name="btnProgress" Text="Test progress" /> <Entry Text="Test" HorizontalOptions="Start" WidthRequest="60"></Entry> </StackLayout> <StackLayout Grid.Row="1" BackgroundColor="White"> <ListView x:Name="listItems"> <ListView.ItemTemplate> <DataTemplate> <ViewCell> <ViewCell.View> <StackLayout> <Label Text="{Binding Name}"/> </StackLayout> </ViewCell.View> </ViewCell> </DataTemplate> </ListView.ItemTemplate> </ListView> </StackLayout> <StackLayout Grid.Row="2" BackgroundColor="Red"> <Label Text="Testando"/> </StackLayout> </Grid> </ContentPage>

    This worked fine. But when I changed the same thing on my existing app, the AdjustResize did not work. I created a new Page and pasted the same code above and still not working. So, I added the following code:

    public class AndroidBug5497WorkaroundForXamarinAndroid
    {
    
        // For more information, see https://code.google.com/p/android/issues/detail?id=5497
        // To use this class, simply invoke assistActivity() on an Activity that already has its content view set.
    
        // CREDIT TO Joseph Johnson (http://stackoverflow.com/users/341631/joseph-johnson) for publishing the original Android solution on stackoverflow.com
    
        public static void assistActivity(Activity activity)
        {
            new AndroidBug5497WorkaroundForXamarinAndroid(activity);
        }
    
        private Android.Views.View mChildOfContent;
        private int usableHeightPrevious;
        private FrameLayout.LayoutParams frameLayoutParams;
    
        private AndroidBug5497WorkaroundForXamarinAndroid(Activity activity)
        {
            FrameLayout content = (FrameLayout)activity.FindViewById(Android.Resource.Id.Content);
            mChildOfContent = content.GetChildAt(0);
            ViewTreeObserver vto = mChildOfContent.ViewTreeObserver;
            vto.GlobalLayout += (object sender, EventArgs e) => {
                possiblyResizeChildOfContent();
            };
            frameLayoutParams = (FrameLayout.LayoutParams)mChildOfContent.LayoutParameters;
        }
    
        private void possiblyResizeChildOfContent()
        {
            int usableHeightNow = computeUsableHeight();
            if (usableHeightNow != usableHeightPrevious)
            {
                int usableHeightSansKeyboard = mChildOfContent.RootView.Height;
                int heightDifference = usableHeightSansKeyboard - usableHeightNow;
    
                frameLayoutParams.Height = usableHeightSansKeyboard - heightDifference;
    
                mChildOfContent.RequestLayout();
                usableHeightPrevious = usableHeightNow;
            }
        }
    
        private int computeUsableHeight()
        {
            Rect r = new Rect();
            mChildOfContent.GetWindowVisibleDisplayFrame(r);
            if (Build.VERSION.SdkInt < BuildVersionCodes.Lollipop)
            {
                return (r.Bottom - r.Top);
            }
            return r.Bottom;
        }
    }
    

    And added to OnCreate on MainActivity.cs AndroidBug5497WorkaroundForXamarinAndroid.assistActivity(this);

    Now it's working. But I agree with other fellows... still waiting for a fix to this issue... =)

    Monday, January 16, 2017 8:17 PM
  • User216022 posted

    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!

    Tuesday, March 28, 2017 12:28 PM
  • User21936 posted

    Related bug report: https://bugzilla.xamarin.com/show_bug.cgi?id=39765

    Wednesday, July 26, 2017 8:33 PM
  • User303876 posted

    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);
        }
    }
    
    Tuesday, February 20, 2018 8:18 AM
  • User53115 posted

    They actually added a PlatformSpecific for this.

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

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Tuesday, February 20, 2018 2:20 PM
  • User368965 posted

    @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?

    Friday, July 13, 2018 10:18 AM
  • User53115 posted

    @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.

    Friday, July 13, 2018 4:59 PM
  • User209529 posted

    @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!

    Monday, July 23, 2018 10:34 AM