Android keyboard and the ContentPage view collapsing/expanding issue w/ Material Design

MichaelDimoudisMichaelDimoudis AUUniversity ✭✭

Hi, after I upgraded to 1.5.1 and getting material design in place, my app is working and looking great in Android. HOWEVER the view when focussing or unfoccusing the keyboard does not work as expected.

I have a Grid with icons at the bottom of my ContentPage. So when the keyboard expands the Grid should be sitting on top of the keyboard and the Editor shrinking in height to accomodate. As mentioned this worked before the Material Design update.

I am using the IosKeyboardFixPageRenderer from http://stackoverflow.com/questions/31172518/how-do-i-keep-the-keyboard-from-covering-my-ui-instead-of-resizing-it/31172519 for iOS and it works great.

How do I fix this on Android with Material Design?

Thank you

Posts

  • TheRealJasonSmithTheRealJasonSmith USXamarin Team Xamurai

    After calling base.OnCreate in your FormsAppCompatActivity subclass, call this:

    Window.SetSoftInputMode (SoftInput.AdjustResize);

    It will restore the old behavior if you depended on it.

  • MichaelDimoudisMichaelDimoudis AUUniversity ✭✭

    Thanks, but it only work on 4.x Android, not 5+ :(

  • TheRealJasonSmithTheRealJasonSmith USXamarin Team Xamurai

    oh right I forgot this is disabled by the fullscreen flag... hmmmmmmmmmmmmm we might need to add a config option to FormsAppCompatActivity.

  • MichaelDimoudisMichaelDimoudis AUUniversity ✭✭

    If you can that will be great. My app is quite unusable in 5+ with material design as key buttons are hidden. There's also some full screen quirks, modal not going up the full way, etc. I can give you access to a private GitHub repo so you can download and run the code if you want, you'll see exactly what the issues are. Send me a private message with your GitHub username :)

  • MichaelDimoudisMichaelDimoudis AUUniversity ✭✭

    An update on this, since my app was unusable in Android 5+ I did some more digging and finally found a solution that seems to be working in the meantime. I blogged about it here: link

    Below is the code in MainActivity.cs
    // Fix the keyboard so it doesn't overlap the grid icons above keyboard etc if ((int)Build.VERSION.SdkInt >= Build.VERSION_CODES.L) { // Bug in Android 5+, this is an adequate workaround AndroidBug5497WorkaroundForXamarinAndroid.assistActivity (this, WindowManager); } else { // Only works in Android 4.x Window.SetSoftInputMode (SoftInput.AdjustResize); }

    And the AndroidBug5497WorkaroundForXamarinAndroid class implementation with thanks from these StackOverflow posts link and link

    `using System;
    using Android.App;
    using Android.Widget;
    using Android.Views;
    using Android.Graphics;
    using Android.OS;
    using Android.Util;

    namespace MyNamespace.Droid
    {
    public class AndroidBug5497WorkaroundForXamarinAndroid
    {
    private readonly View mChildOfContent;
    private int usableHeightPrevious;
    private FrameLayout.LayoutParams frameLayoutParams;

        public static void assistActivity (Activity activity, IWindowManager windowManager) {
            new AndroidBug5497WorkaroundForXamarinAndroid(activity, windowManager);
        }
    
        private AndroidBug5497WorkaroundForXamarinAndroid(Activity activity, IWindowManager windowManager) {
    
            var softButtonsHeight = getSoftbuttonsbarHeight (windowManager);
    
            var content = (FrameLayout) activity.FindViewById(Android.Resource.Id.Content);
            mChildOfContent = content.GetChildAt(0);
            var vto = mChildOfContent.ViewTreeObserver;
            vto.GlobalLayout += (sender, e) => possiblyResizeChildOfContent (softButtonsHeight);
            frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.LayoutParameters;
        }
    
        private void possiblyResizeChildOfContent(int softButtonsHeight) {
            var usableHeightNow = computeUsableHeight();
            if (usableHeightNow != usableHeightPrevious) {
                var usableHeightSansKeyboard = mChildOfContent.RootView.Height - softButtonsHeight;
                var heightDifference = usableHeightSansKeyboard - usableHeightNow;
                if (heightDifference > (usableHeightSansKeyboard / 4)) {
                    // keyboard probably just became visible
                    frameLayoutParams.Height = usableHeightSansKeyboard - heightDifference + (softButtonsHeight / 2);
                } else {
                    // keyboard probably just became hidden
                    frameLayoutParams.Height = usableHeightSansKeyboard;
                }
                mChildOfContent.RequestLayout();
                usableHeightPrevious = usableHeightNow;
            }
        }
    
        private int computeUsableHeight() {
            var r = new Rect ();
            mChildOfContent.GetWindowVisibleDisplayFrame(r);
            return (r.Bottom - r.Top);
        }
    
        private int getSoftbuttonsbarHeight(IWindowManager windowManager) {
            if ((int)Build.VERSION.SdkInt >= Build.VERSION_CODES.L) {
                var metrics = new DisplayMetrics();
                windowManager.DefaultDisplay.GetMetrics(metrics);
                int usableHeight = metrics.HeightPixels;
                windowManager.DefaultDisplay.GetRealMetrics(metrics);
                int realHeight = metrics.HeightPixels;
                if (realHeight > usableHeight)
                    return realHeight - usableHeight;
                else
                    return 0;
            }
            return 0;
        }
    }
    

    }`

  • RezaMousaviRezaMousavi GBMember
    edited March 2016

    This very nearly works - only issue I have is that sometimes Xamarin.Forms does not seem to redraw the bottom part of the screen when you press the back button. The part under the keyboard shows up as blank.

    Did you see the same behavior? Any ideas?

  • SavikPavelSavikPavel BYMember

    @RezaMousavi, I have the same issue here. Strange part here for me is that if you add a breakpoint at the first line in possiblyResizeChildOfContent method the issue is fixed, layout is fully redrawn. It's really looks like a bug

  • DiegoVarelaDiegoVarela COMember ✭✭

    After Xamarin Forms version 2.3.3.168 update, and with the new ones versions, the AndroidBug5497WorkaroundForXamarinAndroid solution no longer works, even it is causing an extra scroll out of screen bounderies, leaving a white space between the bottom of the view and the soft-keyboard without any scrolling option to get the view right.

    Could you please help us with any solution for this?

  • MichaelDimoudisMichaelDimoudis AUUniversity ✭✭

    Hi @DiegoVarela my app heavily relies on AndroidBug5497WorkaroundForXamarinAndroid, I haven't released an update to my app with Xamarin Forms 2.3.3, but I just quickly updated it to Xamarin Forms 2.3.3.180 and in the VS Android emulator, everything with the soft keyboard kept working as expected. I did make some minor tweaks to AndroidBug5497WorkaroundForXamarinAndroid though, not sure if that's what kept it working... can share my tweaks if you still have issues.

  • DiegoVarelaDiegoVarela COMember ✭✭

    Hi @MichaelDimoudis, maybe your tweaks prevent the wrong behavior that I am getting. Could you please share it?
    Thanks

  • MichaelDimoudisMichaelDimoudis AUUniversity ✭✭

    Sorry for delay @DiegoVarela, here is my file.

    `using System;
    using Android.App;
    using Android.Widget;
    using Android.Views;
    using Android.Graphics;
    using Android.OS;
    using Android.Util;

    namespace ContinuousFeedback.Droid
    {
    ///


    /// Android bug5497 workaround for xamarin android.
    /// Answer from https://stackoverflow.com/questions/26835061/android-windowsoftinputmode-adjustresize-still-panning
    ///
    /// 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 class AndroidBug5497WorkaroundForXamarinAndroid
    {
    private readonly View mChildOfContent;
    private int usableHeightPrevious;
    private FrameLayout.LayoutParams frameLayoutParams;

        public static void assistActivity (Activity activity, IWindowManager windowManager) {
            new AndroidBug5497WorkaroundForXamarinAndroid(activity, windowManager);
        }
    
        private AndroidBug5497WorkaroundForXamarinAndroid(Activity activity, IWindowManager windowManager) {
    
            var softButtonsHeight = getSoftbuttonsbarHeight (windowManager);
    
            var content = (FrameLayout) activity.FindViewById(Android.Resource.Id.Content);
            mChildOfContent = content.GetChildAt(0);
            var vto = mChildOfContent.ViewTreeObserver;
            vto.GlobalLayout += (sender, e) => possiblyResizeChildOfContent (softButtonsHeight);
            frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.LayoutParameters;
        }
    
        private void possiblyResizeChildOfContent(int softButtonsHeight) {
            var usableHeightNow = computeUsableHeight();
            if (usableHeightNow != usableHeightPrevious) {
                var usableHeightSansKeyboard = mChildOfContent.RootView.Height - softButtonsHeight;
                var extraDifference = usableHeightSansKeyboard - usableHeightPrevious; // This might be an issue on some devices with no soft buttons
                var heightDifference = usableHeightSansKeyboard - usableHeightNow;
                if (heightDifference > (usableHeightSansKeyboard / 4)) {
                    // keyboard probably just became visible
                    if (softButtonsHeight == 0) {
                        // If there is no softbutton height, there might be a gap, so add some calculated extra difference
                        frameLayoutParams.Height = usableHeightSansKeyboard - heightDifference + extraDifference;
                    } else
                        frameLayoutParams.Height = usableHeightSansKeyboard - heightDifference + (softButtonsHeight / 2);
                } else {
                    // keyboard probably just became hidden
                    frameLayoutParams.Height = usableHeightSansKeyboard;
                }
                mChildOfContent.RequestLayout();
                usableHeightPrevious = usableHeightNow;
            }
        }
    
        private int computeUsableHeight() {
            var r = new Rect ();
            mChildOfContent.GetWindowVisibleDisplayFrame(r);
            return (r.Bottom - r.Top);
        }
    
        private int getSoftbuttonsbarHeight(IWindowManager windowManager) {
            if (Build.VERSION.SdkInt >= BuildVersionCodes.Lollipop) {
                var metrics = new DisplayMetrics();
                windowManager.DefaultDisplay.GetMetrics(metrics);
                int usableHeight = metrics.HeightPixels;
                windowManager.DefaultDisplay.GetRealMetrics(metrics);
                int realHeight = metrics.HeightPixels;
                if (realHeight > usableHeight)
                    return realHeight - usableHeight;
                else
                    return 0;
            }
            return 0;
        }
    }
    

    }`

  • MichaelDimoudisMichaelDimoudis AUUniversity ✭✭
    edited January 2017

    Also this is what I have in my MainActivity.cs inside OnCreate()

    Window.SetSoftInputMode (SoftInput.AdjustResize); if (Build.VERSION.SdkInt >= BuildVersionCodes.Lollipop) { AndroidBug5497WorkaroundForXamarinAndroid.assistActivity (this, WindowManager); }

  • ConnorSchmidtConnorSchmidt USMember
    edited January 2017

    I have had this same issue and through exploring other posts, I discovered this thread: https://forums.xamarin.com/discussion/62668/appcompat-does-not-resize-screen-with-keyboard

    As someone mentioned earlier, the problem originates from Xamarin's switch to FormsAppCompatActivity from FormsApplicationActivity in MainActivity.cs. A solution was posted in that thread that simplifies the workaround posted by MichaelDimoudis. However, the solution is still broken when using the back arrow. Just kidding. When I implemented the solution from the other thread, I guess the effects of the solution in this thread still stuck around. Therefore, while the other thread has good information, it didn't really solve this problem - as far as I can tell.

    As a functional alternative, you could manually downgrade your app to use FormsApplicationActivity instead of FormsAppCompatActivity. Doing so would make the keyboard interact with the pages correctly. To do that (which I haven't) you would have to adjust some files such as MainActivity.cs, App.cs, and styles.xml.

  • At the same time that I asked in this thread, I also file a bug to Xamarin in:
    https://bugzilla.xamarin.com/show_bug.cgi?id=51285 when today this marked solved using Platform Specifics features in this way in PCL project:

    using Xamarin.Forms.PlatformConfiguration.AndroidSpecific;

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

    All the documentation and sample code is in:
    https://developer.xamarin.com/guides/xamarin-forms/user-interface/platform-specifics/consuming.

    I would try this in my project to fix it.

    Thanks a lot @MichaelDimoudis and @ConnorSchmidt for your feedback and help.

Sign In or Register to comment.