在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