在Xamarin表单中滚动编辑器进入视图

使用Xamarin Forms,请考虑下面的Xaml。

<StackLayout VerticalOptions="FillAndExpand"> <Image x:Name="cameraImage" Source="camera.png" /> <Label Text="Describe the image" /> <Editor /> <Button Text="Save" /> </StackLayout> 

这呈现一个图像,一个编辑器和一个保存button。 图像的图像比例为4×3,覆盖了可用屏幕高度的三分之一左右。 编辑器呈现在下面。

问题在于键盘覆盖了iOS中的编辑器。 一个标准的iOS问题通常。

问题是:什么是Xamarinforms的方式来处理这个?

谢谢

// Johan

要使用Xamarin.Forms获得编辑器和条目的自动滚动,通常只需将视图(在本例中为StackLayout)打包到ScrollView中:

 <ScrollView> <StackLayout VerticalOptions="FillAndExpand"> <Image x:Name="cameraImage" Source="camera.png" /> <Label Text="Describe the image" /> <Editor /> <Button Text="Save" /> </StackLayout> </ScrollView> 

这是应该如何工作,但截至今天(2014年6月)有一个错误,防止这个与编辑器(它适用于条目)完全工作。 这个问题是已知的,正在努力。

[更新2014-11-20]这个问题已经解决,将在XF 1.3的下一版本中提供

在编写一个基本上包含可滚动消息列表,文本条目和发送button的小型聊天应用程序时,我偶然发现了这个问题:

以前发布的解决scheme的问题是,你需要嵌套两个滚动视图,这是Xamarin.Forms文档不build议。 为了防止键盘隐藏条目,我发现了下面这个黑客:

我在主栈布局的最后添加了一个placeholder 。 根据条目是否被聚焦(即键盘是否可见),占位符的高度设置为0或键盘高度。

  // HACK: make entry visible when keyboard open var placeholder = new BoxView { HeightRequest = 0, }; entry.Focused += (sender, e) => placeholder.HeightRequest = 210; entry.Unfocused += (sender, e) => placeholder.HeightRequest = 0; Content = new StackLayout { VerticalOptions = LayoutOptions.Fill, Padding = 5, Children = { whoTable, messageScrollView, new StackLayout { Orientation = StackOrientation.Horizontal, VerticalOptions = LayoutOptions.End, HeightRequest = 70, Children = { entry, sendButton, }, }, placeholder, }, }; 

当然,这并不完美。 特别是硬编码键盘的高度应该更加优雅。 也许你应该只在iOS上应用它,而不是在Android上。

有时你不能把你的主视图放在滚动视图中,在这种情况下,你可以通过处理iOS项目的键盘事件并将它们传递给Forms级别来实现这一点。 Android照顾自己。

 using System; using Foundation; using UIKit; using RaiseKeyboard.iOS; [assembly: Xamarin.Forms.Dependency (typeof (KeyboardHelper))] namespace RaiseKeyboard.iOS { // Raises keyboard changed events containing the keyboard height and // whether the keyboard is becoming visible or not public class KeyboardHelper : IKeyboardHelper { public KeyboardHelper() { NSNotificationCenter.DefaultCenter.AddObserver(UIKeyboard.WillHideNotification, OnKeyboardNotification); NSNotificationCenter.DefaultCenter.AddObserver(UIKeyboard.WillShowNotification, OnKeyboardNotification); } public event EventHandler<KeyboardHelperEventArgs> KeyboardChanged; private void OnKeyboardNotification (NSNotification notification) { var visible = notification.Name == UIKeyboard.WillShowNotification; var keyboardFrame = visible ? UIKeyboard.FrameEndFromNotification(notification) : UIKeyboard.FrameBeginFromNotification(notification); if (KeyboardChanged != null) { KeyboardChanged (this, new KeyboardHelperEventArgs (visible, (float)keyboardFrame.Height)); } } } } 

然后在表单级别:

 using System; using Xamarin.Forms; namespace RaiseKeyboard { // Provides static access to keyboard events public static class KeyboardHelper { private static IKeyboardHelper keyboardHelper = null; public static void Init() { if (keyboardHelper == null) { keyboardHelper = DependencyService.Get<IKeyboardHelper>(); } } public static event EventHandler<KeyboardHelperEventArgs> KeyboardChanged { add { Init(); keyboardHelper.KeyboardChanged += value; } remove { Init (); keyboardHelper.KeyboardChanged -= value; } } } public interface IKeyboardHelper { event EventHandler<KeyboardHelperEventArgs> KeyboardChanged; } public class KeyboardHelperEventArgs : EventArgs { public readonly bool Visible; public readonly float Height; public KeyboardHelperEventArgs(bool visible, float height) { Visible = visible; Height = height; } } } 

如果您正在Stacklayout中工作,并希望提高键盘上的视图,则可以在堆栈底部放置一个高度为0的间隔器。 然后在键盘更改事件发生时将其设置为键盘的高度。

 spacer.HeightRequest = e.Visible ? e.Height : 0; 

如果你正在使用一个Listview,你可以通过将你的视图的重叠量翻译来处理这个问题。

 bottomOffset = mainStack.Bounds.Bottom - textStack.Bounds.Bottom; textStack.TranslationY -= e.Visible ? e.Height - bottomOffset : bottomOffset - e.Height; 

列表视图必须以不同的方式进行处理,因为高度是由表单自动调整的,并使用分隔符结果进行更正。

在这里示例: https : //github.com/naturalistic/raisekeyboard

扩展@Falko的答案,你可以检查iOS的平台,因为Android本来就是这样处理的。

我也通过这个答案添加到页面快速和脏的方向。

 static bool IsPortrait(Page p) { return p.Width < p.Height; } 

无论如何,我明白Xamarin很快就会join一些解决scheme。 虽然现在

 protected async void Message_Focused(object sender, EventArgs args) { if (Device.OS == TargetPlatform.iOS) { //TLR: still need a way to determine the iOS keyboard's height first //until then, this is a functional hack if (IsPortrait(this)) { KeyboardSpacer.HeightRequest = 165; } else { KeyboardSpacer.HeightRequest = 114; } } } protected async void Message_Unfocused(object sender, EventArgs args) { if (Device.OS == TargetPlatform.iOS) { KeyboardSpacer.HeightRequest = 0; } } 

注意, raisekeyboard只是在应用程序中的一个条目实现,如果你添加一个新的条目, KeyboardHelper.KeyboardChanged将要拍摄,当焦点在任何条目。

 KeyboardHelper.KeyboardChanged += (sender, e) =>{ bottomOffset = this.ParentView.Bounds.Bottom - _editor.Bounds.Bottom; if (KeyboardStatus) _editor.TranslationY = e.Visible ? -(e.Height - bottomOffset) : 0; else _editor.TranslationY = 0; }; 

如上所述使用ScrollView可以修复iOS中的问题,并在Android中进行部分修复。 为了完全解决Android中的问题,我发现了另外一个简单又好看的补充。

只有在Android中,我使用android特定的TextEdit控件replaceXamarin表单编辑器。 所以在我的页面构造函数中,我有以下代码只是为了android。

 #if __ANDROID__ // I have editor defined in xaml named ReportTextEditor in stacklayout named MainStackLayout Editor sharedEditor = this.ReportTextEditor; MainStackLayout.Children.Remove(sharedEditor); //removing the ReportTextEditor which was defined in xaml EditText editText = new EditText(Forms.Context); //created android specific editor editText.InputType = InputTypes.ClassText | InputTypes.TextFlagAutoCorrect | InputTypes.TextFlagCapSentences | InputTypes.TextFlagMultiLine; //keyboard options, optional MainStackLayout.Children.Add(editText); //Added android specific edit text to my stack layout #endif 

您还需要根据需要添加特定于android的命名空间。

 #if __ANDROID__ using Xamarin.Forms.Platform.Android; using Android.Widget; using Button = Xamarin.Forms.Button; using Android.Text; #endif