Reputation: 3070
I have a Xamarin.Forms project on Android and I want to use "AdjustResize" as the default method for dealing with the soft keyboard. I do this by setting it in OnCreate
like this:
[Activity(Label = "TestWhite.Droid", Icon = "@drawable/icon", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : FormsAppCompatActivity
{
protected override void OnCreate(Bundle bundle)
{
FormsAppCompatActivity.ToolbarResource = Resource.Layout.toolbar;
FormsAppCompatActivity.TabLayoutResource = Resource.Layout.tabs;
base.OnCreate(bundle);
global::Xamarin.Forms.Forms.Init(this, bundle);
Window.SetSoftInputMode(SoftInput.AdjustResize);
LoadApplication(new App());
}
}
Since I have updated to AppCompat
, AdjustResize
does not work with API 22, while it still works with API 19.
The problem can be tested very easily with an application containing just one page containing an a scroll view and an editor at the bottom of the page:
public MainPage()
{
InitializePage();
}
void InitializePage()
{
var editor = new Editor
{
VerticalOptions = LayoutOptions.FillAndExpand,
HorizontalOptions = LayoutOptions.FillAndExpand,
HeightRequest = 200,
};
var tallLayout = new StackLayout
{
HorizontalOptions = LayoutOptions.FillAndExpand,
Orientation = StackOrientation.Horizontal,
HeightRequest = 450,
BackgroundColor = Color.Lime,
};
var layout = new StackLayout
{
Orientation = StackOrientation.Vertical,
VerticalOptions = LayoutOptions.FillAndExpand,
HorizontalOptions = LayoutOptions.FillAndExpand,
Children = { tallLayout, editor },
};
var scrollView = new ScrollView
{
VerticalOptions = LayoutOptions.FillAndExpand,
HorizontalOptions = LayoutOptions.FillAndExpand,
};
scrollView.Content = layout;
Content = scrollView;
}
With API 19 when the user clicks on the Editor
, the view gets pushed up so that the user can see what he's writing. With API 22, instead, the keyboard just appears on the view, hiding the Editor
. Any ideas about the reason behind this behaviour?
Upvotes: 1
Views: 1633
Reputation: 3266
In the OnCreate method of your MainActivity you should set your input mode to AdjustResize. Then, to deal with the android bug reported here, you can use the utility class below (originally converted from java code by @user1658602). Happy Coding!
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
Xamarin.Forms.Forms.Init(this, bundle);
Window.SetSoftInputMode(SoftInput.AdjustResize);
AndroidBug5497WorkaroundForXamarinAndroid.assistActivity(this);
ToolbarResource = Resource.Layout.toolbar;
TabLayoutResource = Resource.Layout.tabs;
LoadApplication(new App());
}
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;
}
}
Upvotes: 4