2015-07-01 8 views

cevap

17

Bunu düzeltmenin yolu, klavyenin gösterilmesini dinleyen ve oradayken dolgu ekleyen bir özel oluşturucu ile gerçekleştirilir. senin PCL projede

, KeyboardResizingAwareContentPage.cs: iOS projesinde

using Xamarin.Forms; 

public class KeyboardResizingAwareContentPage : ContentPage { 
    public bool CancelsTouchesInView = true; 
} 

, IosKeyboardFixPageRenderer.cs:

using Foundation; 
using MyProject.iOS.Renderers; 
using UIKit; 
using Xamarin.Forms; 
using Xamarin.Forms.Platform.iOS; 

[assembly: ExportRenderer(typeof(KeyboardResizingAwareContentPage), typeof(IosKeyboardFixPageRenderer))] 

namespace MyProject.iOS.Renderers { 
    public class IosKeyboardFixPageRenderer : PageRenderer { 
     NSObject observerHideKeyboard; 
     NSObject observerShowKeyboard; 

     public override void ViewDidLoad() 
     { 
      base.ViewDidLoad(); 

      var cp = Element as KeyboardResizingAwareContentPage; 
      if (cp != null && !cp.CancelsTouchesInView) { 
       foreach (var g in View.GestureRecognizers) { 
        g.CancelsTouchesInView = false; 
       } 
      } 
     } 

     public override void ViewWillAppear(bool animated) 
     { 
      base.ViewWillAppear(animated); 

      observerHideKeyboard = NSNotificationCenter.DefaultCenter.AddObserver(UIKeyboard.WillHideNotification, OnKeyboardNotification); 
      observerShowKeyboard = NSNotificationCenter.DefaultCenter.AddObserver(UIKeyboard.WillShowNotification, OnKeyboardNotification); 
     } 

     public override void ViewWillDisappear(bool animated) 
     { 
      base.ViewWillDisappear(animated); 

      NSNotificationCenter.DefaultCenter.RemoveObserver(observerHideKeyboard); 
      NSNotificationCenter.DefaultCenter.RemoveObserver(observerShowKeyboard); 
     } 

     void OnKeyboardNotification(NSNotification notification) 
     { 
      if (!IsViewLoaded) return; 

      var frameBegin = UIKeyboard.FrameBeginFromNotification(notification); 
      var frameEnd = UIKeyboard.FrameEndFromNotification(notification); 

      var page = Element as ContentPage; 
      if (page != null && !(page.Content is ScrollView)) { 
       var padding = page.Padding; 
       page.Padding = new Thickness(padding.Left, padding.Top, padding.Right, padding.Bottom + frameBegin.Top - frameEnd.Top); 
      } 
     } 
    } 
} 
+0

Sonuç iyi, ancak klavyeyi gizlemek için nasıl yapabilirim? Çünkü klavyenin dışına dokunursam kapanmıyorsa ... –

+0

@ Fran_gg7 ResignFirstResponder() öğesini kullanın. Yani "Klavyeyi etkinleştiren Denetiminiz" ResignFirstResponder(); – Sturla

+0

Xamarin Formlar, sayfada “ResignFirstResponder” öğesini otomatik olarak çağıran bir jest tanıyıcıya sahip olmalıdır. Bazen bu davranışı istemezsiniz, 'CancelsTouchesInView' boolean'ın amacı; Xamarin Forms'ın varsayılan davranışını iptal etmek için false değerine ayarlayın. –

2

Bu Xamarin Forum question bunu tartışır. Ayrıca

size sadece ana aktivitede bu ayarlayabilirsiniz Xamarin/Formlar kullanan Android bunu istiyorum:

[Activity(WindowSoftInputMode = Android.Views.SoftInput.AdjustResize)] 
public class MainActivity 
    ... 
3

Ben KeyboardOverlap plugin Anthony çözümünde daha iyi çalıştığını gördük.

  1. özel oluşturucusunu
public class KeyboardResizingAwareContentPage : ContentPage 
{ 
} 
oluştur
  1. iOS'ta özel renderer uygulayın:

    Bu onu nasıl kullanılacağı.

[Preserve (AllMembers = true)] 
public class KeyboardOverlapRenderer : PageRenderer 
{ 
    NSObject _keyboardShowObserver; 
    NSObject _keyboardHideObserver; 
    private bool _pageWasShiftedUp; 
    private double _activeViewBottom; 
    private bool _isKeyboardShown; 

    public static void Init() 
    { 
     var now = DateTime.Now; 
     Debug.WriteLine ("Keyboard Overlap plugin initialized {0}", now); 
    } 

    public override void ViewWillAppear (bool animated) 
    { 
     base.ViewWillAppear (animated); 

     var page = Element as ContentPage; 

     if (page != null) { 
      var contentScrollView = page.Content as ScrollView; 

      if (contentScrollView != null) 
       return; 

      RegisterForKeyboardNotifications(); 
     } 
    } 

    public override void ViewWillDisappear (bool animated) 
    { 
     base.ViewWillDisappear (animated); 

     UnregisterForKeyboardNotifications(); 
    } 

    void RegisterForKeyboardNotifications() 
    { 
     if (_keyboardShowObserver == null) 
      _keyboardShowObserver = NSNotificationCenter.DefaultCenter.AddObserver (UIKeyboard.WillShowNotification, OnKeyboardShow); 
     if (_keyboardHideObserver == null) 
      _keyboardHideObserver = NSNotificationCenter.DefaultCenter.AddObserver (UIKeyboard.WillHideNotification, OnKeyboardHide); 
    } 

    void UnregisterForKeyboardNotifications() 
    { 
     _isKeyboardShown = false; 
     if (_keyboardShowObserver != null) { 
      NSNotificationCenter.DefaultCenter.RemoveObserver (_keyboardShowObserver); 
      _keyboardShowObserver.Dispose(); 
      _keyboardShowObserver = null; 
     } 

     if (_keyboardHideObserver != null) { 
      NSNotificationCenter.DefaultCenter.RemoveObserver (_keyboardHideObserver); 
      _keyboardHideObserver.Dispose(); 
      _keyboardHideObserver = null; 
     } 
    } 

    protected virtual void OnKeyboardShow (NSNotification notification) 
    { 
     if (!IsViewLoaded || _isKeyboardShown) 
      return; 

     _isKeyboardShown = true; 
     var activeView = View.FindFirstResponder(); 

     if (activeView == null) 
      return; 

     var keyboardFrame = UIKeyboard.FrameEndFromNotification (notification); 
     var isOverlapping = activeView.IsKeyboardOverlapping (View, keyboardFrame); 

     if (!isOverlapping) 
      return; 

     if (isOverlapping) { 
      _activeViewBottom = activeView.GetViewRelativeBottom (View); 
      ShiftPageUp (keyboardFrame.Height, _activeViewBottom); 
     } 
    } 

    private void OnKeyboardHide (NSNotification notification) 
    { 
     if (!IsViewLoaded) 
      return; 

     _isKeyboardShown = false; 
     var keyboardFrame = UIKeyboard.FrameEndFromNotification (notification); 

     if (_pageWasShiftedUp) { 
      ShiftPageDown (keyboardFrame.Height, _activeViewBottom); 
     } 
    } 

    private void ShiftPageUp (nfloat keyboardHeight, double activeViewBottom) 
    { 
     var pageFrame = Element.Bounds; 

     var newY = pageFrame.Y + CalculateShiftByAmount (pageFrame.Height, keyboardHeight, activeViewBottom); 

     Element.LayoutTo (new Rectangle (pageFrame.X, newY, 
      pageFrame.Width, pageFrame.Height)); 

     _pageWasShiftedUp = true; 
    } 

    private void ShiftPageDown (nfloat keyboardHeight, double activeViewBottom) 
    { 
     var pageFrame = Element.Bounds; 

     var newY = pageFrame.Y - CalculateShiftByAmount (pageFrame.Height, keyboardHeight, activeViewBottom); 

     Element.LayoutTo (new Rectangle (pageFrame.X, newY, 
      pageFrame.Width, pageFrame.Height)); 

     _pageWasShiftedUp = false; 
    } 

    private double CalculateShiftByAmount (double pageHeight, nfloat keyboardHeight, double activeViewBottom) 
    { 
     return (pageHeight - activeViewBottom) - keyboardHeight; 
    } 
} 

Ve eksik uzantıları::

public static class ViewExtensions 
{ 
    /// <summary> 
    /// Find the first responder in the <paramref name="view"/>'s subview hierarchy 
    /// </summary> 
    /// <param name="view"> 
    /// A <see cref="UIView"/> 
    /// </param> 
    /// <returns> 
    /// A <see cref="UIView"/> that is the first responder or null if there is no first responder 
    /// </returns> 
    public static UIView FindFirstResponder (this UIView view) 
    { 
     if (view.IsFirstResponder) { 
      return view; 
     } 
     foreach (UIView subView in view.Subviews) { 
      var firstResponder = subView.FindFirstResponder(); 
      if (firstResponder != null) 
       return firstResponder; 
     } 
     return null; 
    } 

    /// <summary> 
    /// Returns the new view Bottom (Y + Height) coordinates relative to the rootView 
    /// </summary> 
    /// <returns>The view relative bottom.</returns> 
    /// <param name="view">View.</param> 
    /// <param name="rootView">Root view.</param> 
    public static double GetViewRelativeBottom (this UIView view, UIView rootView) 
    { 
     var viewRelativeCoordinates = rootView.ConvertPointFromView (view.Frame.Location, view); 
     var activeViewRoundedY = Math.Round (viewRelativeCoordinates.Y, 2); 

     return activeViewRoundedY + view.Frame.Height; 
    } 

    /// <summary> 
    /// Determines if the UIView is overlapped by the keyboard 
    /// </summary> 
    /// <returns><c>true</c> if is keyboard overlapping the specified activeView rootView keyboardFrame; otherwise, <c>false</c>.</returns> 
    /// <param name="activeView">Active view.</param> 
    /// <param name="rootView">Root view.</param> 
    /// <param name="keyboardFrame">Keyboard frame.</param> 
    public static bool IsKeyboardOverlapping (this UIView activeView, UIView rootView, CGRect keyboardFrame) 
    { 
     var activeViewBottom = activeView.GetViewRelativeBottom (rootView); 
     var pageHeight = rootView.Frame.Height; 
     var keyboardHeight = keyboardFrame.Height; 

     var isOverlapping = activeViewBottom >= (pageHeight - keyboardHeight); 

     return isOverlapping; 
    } 
} 
  1. Kullanım özel sayfa oluşturucu
public partial class LoginPage : KeyboardResizingAwareContentPage 
{ 
    public LoginPage() 
    { 
     // your content 
     // note: you have to use base.Navigation.PushAsync(), base.DisplayAlert(), ... 
    } 
} 
Burada önemli paulpatarinski kod parçasıdır
<?xml version="1.0" encoding="utf-8" ?> 
<renderer:KeyboardResizingAwareContentPage xmlns="http://xamarin.com/schemas/2014/forms" 
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
    x:Class="App.Pages.LoginPage" 
    xmlns:renderer="clr-namespace:App.CustomRenderers;assembly=App"> 
    <!-- your content --> 
</renderer:KeyboardResizingAwareContentPage> 

Bunun için tüm kredi Paul! Bunun için teşekkürler!

+0

Bu çözümün yanı sıra (üretim günlüklerinden): System.ObjectDisposedException: Atılan bir nesneye erişilemiyor.Nesne adı: 'IosKeyboardFixPageRenderer'. –

+0

_isKeyboardShown = false; UnregisterForKeyboardNotifications yönteminin sonunda taşınmalıdır –

İlgili konular