public static void TPKeyboardAvoiding_findTextFieldAfterTextFieldbeneathViewminYfoundView(this UIScrollView scrollView, UIView firstResponder, UIView beneathView, float minY, UIView foundView) { // Search recursively for text field or text view below firstResponder nfloat priorFieldOffset = scrollView.ConvertRectFromView(firstResponder.Frame, firstResponder.Superview).GetMinY(); foreach (UIView childView in beneathView.Subviews) { if (childView.Hidden) { continue; } if ((childView is UITextView || childView is UITextField) && childView.UserInteractionEnabled) { CGRect frame = scrollView.ConvertRectFromView(childView.Frame, beneathView); if (childView != firstResponder && frame.GetMinY() >= priorFieldOffset && frame.GetMinY() < minY && !(FEqual((float)frame.Y, (float)firstResponder.Frame.Y)) && frame.X < firstResponder.Frame.X) { minY = (float)frame.GetMinY(); foundView = childView; } } else { scrollView.TPKeyboardAvoiding_findTextFieldAfterTextFieldbeneathViewminYfoundView(firstResponder, childView, minY, foundView); } } }
public static void TPKeyboardAvoiding_keyboardWillHide(this UIScrollView scrollView, NSNotification notification) { CGRect keyboardRect = scrollView.ConvertRectFromView((notification.UserInfo.ObjectForKey(UIKeyboard.FrameEndUserInfoKey) as NSValue).CGRectValue, null); if (keyboardRect == CGRect.Empty) { return; } //TPKeyboardAvoidingState state = KeyboardAvoidingState(); if (State == null) { State = new TPKeyboardAvoidingState(); } if (!State.keyboardVisible) { return; } State.keyboardRect = new CGRect(0, 0, 0, 0); State.keyboardVisible = false; // Restore dimensions to prior size //TODO : add animations UIView.BeginAnimations(null); UIView.SetAnimationCurve(UIViewAnimationCurve.EaseIn); UIView.SetAnimationDuration(1.0); if (scrollView is TPKeyboardAvoidingScrollView) { scrollView.ContentSize = State.priorContentSize; } scrollView.ContentInset = State.priorInset; scrollView.ScrollIndicatorInsets = State.priorScrollIndicatorInsets; scrollView.PagingEnabled = State.priorPagingEnabled; scrollView.LayoutIfNeeded(); UIView.CommitAnimations(); }
/*static TPKeyboardAvoidingState KeyboardAvoidingState() * { * TPKeyboardAvoidingState state = State; * if(state == null) * state = new TPKeyboardAvoidingState(); * * return state; * }*/ public static void TPKeyboardAvoiding_keyboardWillShow(this UIScrollView scrollView, NSNotification notification) { CGRect keyboardRect = scrollView.ConvertRectFromView((notification.UserInfo.ObjectForKey(UIKeyboard.FrameEndUserInfoKey) as NSValue).CGRectValue, null); if (keyboardRect == CGRect.Empty) { return; } //TPKeyboardAvoidingState state = KeyboardAvoidingState(); if (State == null) { State = new TPKeyboardAvoidingState(); } UIView firstResponder = scrollView.TPKeyboardAvoiding_findFirstResponderBeneathView(scrollView); if (firstResponder == null) { return; } State.keyboardRect = keyboardRect; if (!State.keyboardVisible) { State.priorInset = scrollView.ContentInset; State.priorScrollIndicatorInsets = scrollView.ScrollIndicatorInsets; State.priorPagingEnabled = scrollView.PagingEnabled; } State.keyboardVisible = true; scrollView.PagingEnabled = false; if (scrollView is TPKeyboardAvoidingScrollView) { State.priorContentSize = scrollView.ContentSize; if (CGSize.Equals(scrollView.ContentSize, new CGSize(0, 0))) { // Set the content size, if it's not set. Do not set content size explicitly if auto-layout // is being used to manage subviews scrollView.ContentSize = scrollView.TPKeyboardAvoiding_calculatedContentSizeFromSubviewFrames(); } } // Shrink view's inset by the keyboard's height, and scroll to show the text field/view being edited //TODO : need fix UIView.BeginAnimations(null); NSNumber number = notification.UserInfo.ValueForKey(UIKeyboard.AnimationCurveUserInfoKey) as NSNumber; UIView.SetAnimationCurve((UIViewAnimationCurve)number.Int32Value); number = notification.UserInfo.ValueForKey(UIKeyboard.AnimationDurationUserInfoKey) as NSNumber; UIView.SetAnimationDuration(number.FloatValue); // UIView.SetAnimationCurve (UIViewAnimationCurve.EaseIn); // UIView.SetAnimationDuration (1.0); scrollView.ContentInset = scrollView.TPKeyboardAvoiding_contentInsetForKeyboard(); nfloat viewableHeight = scrollView.Bounds.Size.Height - scrollView.ContentInset.Top - scrollView.ContentInset.Bottom; scrollView.SetContentOffset(new CGPoint(scrollView.ContentOffset.X, (nfloat)scrollView.TPKeyboardAvoiding_idealOffsetForViewwithViewingAreaHeight(firstResponder, viewableHeight)), false); scrollView.ScrollIndicatorInsets = scrollView.ContentInset; scrollView.LayoutIfNeeded(); UIView.CommitAnimations(); }
/// <summary> /// Make a view visible into a scroll view /// </summary> /// <param name="scrollView">The scroll view to scroll to get the item visible.</param> /// <param name="view">View to make visible.</param> /// <param name="mode">Specifies a mode to use to place the view into the view port.</param> /// <param name="padding"> /// Add an extra margin to the view from the edge of the view port when mode is /// <seealso cref="BringIntoViewMode.TopLeftOfViewPort"/> or <seealso cref="BringIntoViewMode.BottomRightOfViewPort"/>. /// </param> /// <param name="animationMode">Specifies animation mode to use to animate the scrolling (or not).</param> public static void BringIntoView( this UIScrollView scrollView, UIView view, BringIntoViewMode mode = BringIntoViewMode.ClosestEdge, int padding = 0, ScrollingMode animationMode = ScrollingMode.Forced) { var boundsOfViewInScrollViewCoordinatesSystem = scrollView.ConvertRectFromView(view.Bounds, view); var bounds = scrollView.Bounds; var inset = scrollView.ContentInset; var viewPort = new CGRect ( bounds.X + inset.Left, bounds.Y + inset.Top, bounds.Width - inset.Left - inset.Right, bounds.Height - inset.Top - inset.Bottom ); nfloat x, y; switch (mode) { case BringIntoViewMode.ClosestEdge: scrollView.ScrollRectToVisible(boundsOfViewInScrollViewCoordinatesSystem, animationMode != ScrollingMode.NotAnimated); return; case BringIntoViewMode.TopLeftOfViewPort: x = boundsOfViewInScrollViewCoordinatesSystem.Left - padding; y = boundsOfViewInScrollViewCoordinatesSystem.Top - padding; break; case BringIntoViewMode.CenterOfViewPort: x = boundsOfViewInScrollViewCoordinatesSystem.Left - (viewPort.Width / 2) + (boundsOfViewInScrollViewCoordinatesSystem.Width / 2); y = boundsOfViewInScrollViewCoordinatesSystem.Top - (viewPort.Height / 2) + (boundsOfViewInScrollViewCoordinatesSystem.Height / 2); break; case BringIntoViewMode.BottomRightOfViewPort: x = boundsOfViewInScrollViewCoordinatesSystem.Right - viewPort.Width + padding; y = boundsOfViewInScrollViewCoordinatesSystem.Bottom - viewPort.Height + padding; break; default: throw new NotSupportedException("Unknown scroll into view behavior"); } var maxX = scrollView.ContentSize.Width - viewPort.Width; var maxY = scrollView.ContentSize.Height - viewPort.Height; x = (nfloat)Math.Max(0, (nfloat)Math.Min(maxX, x)); y = (nfloat)Math.Max(0, (nfloat)Math.Min(maxY, y)); switch (animationMode) { case ScrollingMode.NotAnimated: scrollView.SetContentOffset(new CGPoint(x, y), false); break; case ScrollingMode.Animated: scrollView.SetContentOffset(new CGPoint(x, y), true); break; case ScrollingMode.Forced: scrollView.ContentOffset = new CGPoint(x, y); break; default: throw new NotSupportedException("Unknown animation mode"); } }