4

I've successfully implemented AdjustResize in several acitivies but one activitie in particular still refuses to do anything but pan when the keyboard is shown.

Any ideas what I'm doing wrong?

I'm using the xamarin attribute like this:

[Activity (
    LaunchMode=Android.Content.PM.LaunchMode.SingleTask, 
    Label = "Active Jobs", 
    MainLauncher = false, 
    Icon = "@drawable/icon", 
    WindowSoftInputMode = SoftInput.AdjustResize,
    ScreenOrientation = Android.Content.PM.ScreenOrientation.Portrait)]     

EDIT: The underlying axml layout for this activity

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:minWidth="25px"
        android:minHeight="25px"
        android:background="#FFFFFF"
        android:gravity="center|top"
        android:paddingTop="20dp"
        android:paddingLeft="20dp"
        android:paddingRight="20dp"
        android:paddingBottom="40dp">
        <TextView
            android:text="No active works on this device."
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:padding="0dp"
            android:gravity="center"
            android:layout_centerHorizontal="true"
            android:layout_alignParentTop="true"
            android:visibility="gone"
            android:textColor="#006985"
            android:textSize="30dp" />
        <ListView
            android:minWidth="25px"
            android:minHeight="25px"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:gravity="center"
            android:textColor="#006985"
            android:textSize="30dp"
            android:divider="@null"
            android:dividerHeight="-0.6dp"
            android:layout_gravity="top" />
    </LinearLayout>
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center|center"
        android:paddingLeft="40dp"
        android:paddingRight="40dp"
        android:paddingTop="40dp"
        android:paddingBottom="60dp"
        android:layout_alignParentBottom="true"
        android:visibility="gone"
        android:background="#006985"
        android:orientation="vertical">
        <EditText
            android:inputType="textNoSuggestions"
            android:layout_width="fill_parent"
            android:layout_height="80dp"
            android:background="#FFFFFF"
            android:textColor="#006985"
            android:textSize="30dp"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:hint="Find..." />
        <Button
            android:text="Add New Task"
            android:layout_width="fill_parent"
            android:layout_height="100dp"
            android:background="@drawable/buttonHollowWhite"
            android:layout_centerHorizontal="true"
            android:textColor="#FFFFFF"
            android:textSize="30dp"
            android:layout_marginTop="40dp"
            android:layout_gravity="center" />
    </LinearLayout>
</RelativeLayout>
Le-roy Staines
  • 2,037
  • 2
  • 22
  • 40

2 Answers2

5

Refer to this BUG in Android

I have converted a work-around to work for Xamarin.Android, based on this StackOverflow answer.

To implement the fix simply add the following code within your activity's OnCreate method.

AndroidBug5497WorkaroundForXamarinAndroid.assistActivity (this);

And the full class is:

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 (https://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 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;
            if (heightDifference > (usableHeightSansKeyboard/4)) {
                // keyboard probably just became visible
                frameLayoutParams.Height = usableHeightSansKeyboard - heightDifference;
            } else {
                // keyboard probably just became hidden
                frameLayoutParams.Height = usableHeightSansKeyboard;
            }
            mChildOfContent.RequestLayout();
            usableHeightPrevious = usableHeightNow;
        }
    }

    private int computeUsableHeight() {
        Rect r = new Rect ();
        mChildOfContent.GetWindowVisibleDisplayFrame(r);
        return (r.Bottom - r.Top);
    }

}
Community
  • 1
  • 1
Le-roy Staines
  • 2,037
  • 2
  • 22
  • 40
  • this works mostly, but 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 have such an issue? It seems to only happen in Xamarin.Forms. – Blueberry Mar 21 '16 at 23:18
  • Hey; never used Xamarin.Forms! We built our app previous to that part of Xamarin. Seems to work OK for us. – Le-roy Staines Mar 23 '16 at 03:26
0

If someone like me still annoyed buy the problem with the Back button navigation, My workaround fixed the issue for now. but I still testing. if nothing else works, have a try.

The main change was the event, that in case WindowFucusChange works smoothly with the back button. The downside is that the event is called once when the editor is focused/unfocused. That is the reason for the await Task with the while loop for the screen size. Maybe unnecessary!

vto.GlobalFocusChange += Vto_WindowFocusChange;

 private AndroidBug5497Workaround(Activity activity)
        {

        var content = (FrameLayout)activity.FindViewById(Android.Resource.Id.Content);
        mChildOfContent = content.GetChildAt(0);
        var vto = mChildOfContent.ViewTreeObserver;
        vto.GlobalFocusChange += Vto_WindowFocusChange;
        frameLayoutParams = (FrameLayout.LayoutParams)mChildOfContent.LayoutParameters;
    }

    private async void Vto_WindowFocusChange(object sender, ViewTreeObserver.GlobalFocusChangeEventArgs e)
    {
        if (e.NewFocus != null && e.OldFocus != null)
        {
                var usableHeightNow = await computeUsableHeight(mChildOfContent.RootView.Height);
                int usableHeightSansKeyboard = mChildOfContent.RootView.Height;
                int heightDifference = usableHeightSansKeyboard - usableHeightNow;
                frameLayoutParams.Height = usableHeightSansKeyboard - heightDifference;
                mChildOfContent.RequestLayout();
                usableHeightPrevious = usableHeightNow;
        }
        else
        {
                frameLayoutParams.Height = mChildOfContent.RootView.Height;
                mChildOfContent.RequestLayout();
                usableHeightPrevious = mChildOfContent.RootView.Height;
        }
    }
    private async Task<int> computeUsableHeight(int previous)
    {
        Rect r = new Rect();
        var w = previous;
        await Task.Run(async() => {

            mChildOfContent.GetWindowVisibleDisplayFrame(r);

            while (r.Bottom == previous)
            {
                await Task.Delay(150);

                if (Build.VERSION.SdkInt < BuildVersionCodes.Lollipop)
                {
                    return (r.Bottom - r.Top);
                }

                mChildOfContent.GetWindowVisibleDisplayFrame(r);

                System.Diagnostics.Debug.WriteLine("Current screen size... " + r.Bottom);
            }
            return r.Bottom;
        });
        return r.Bottom;
    }
Jaymin
  • 2,879
  • 3
  • 19
  • 35