aufty
aufty

Reputation: 417

Why is ScrollToRect not working for a TextField inside a Tableview, inside a ScrollView?

I know this is kind of obnoxious and technically not recommended, but I have a UITableViewCell inside a UITableView (of course) inside a ScrollView, inside another view.

Here's the hierarchy

View
=> ScrollView
    => TableView (also a scrollview)
        => Cell
            => TextField

Currently, I have a bit of code in the controller for the top view that scrolls the screen when a TextField is activated inside the ScrollView. That looks like this:

/// <summary>
/// Event fired when keyboard is popping up
/// Prevents keyboard from hiding selected text fields
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
private void ShowCallback(object sender, UIKeyboardEventArgs args)
{
    var currentStep = steps[currentIndex];

    // Get the size of the keyboard
    CGRect keyboardBounds = args.FrameEnd;
    nfloat bottomGap = View.Frame.Bottom - currentView.Frame.Bottom;
    // Create an inset and assign it to the tableview
    UIEdgeInsets originalInsets = currentStep.ScrollView.ContentInset;
    UIEdgeInsets contentInsets = new UIEdgeInsets(originalInsets.Top, 0.0f, keyboardBounds.Size.Height - bottomGap, 0.0f);
    currentStep.ScrollView.DelaysContentTouches = false;
    currentStep.ScrollView.ContentInset = contentInsets;
    currentStep.ScrollView.ScrollIndicatorInsets = contentInsets;
    UITextField tf = currentStep.GetActiveTextfield(currentView);
    if (tf != null)
    {
        currentStep.ScrollView.ScrollRectToVisible(tf, true);
    }


}

This works great for TextFields inside the ScrollView, but doesn't work for TextFields inside the TableView. "tf" is not null, so it's definitely getting the value, but the ScrollView doesn't budge and I'm still having the hidden textfield problem.

I've spent so much time fixing issues with the keyboard hiding my content. I wish there was a built-in, easy solution from Apple.

Upvotes: 0

Views: 503

Answers (2)

aufty
aufty

Reputation: 417

Converting Rect of a Subview's Subview

Carter's answer got me started, but what I needed to do was get the coordinates of the TextField as it related to the top level ScrollView using ConvertRectFromView:

CGRect frame = currentStep.ScrollView.ConvertRectFromView(tf.Frame, tf.Superview);

currentStep.ScrollView.ScrollRectToVisible(frame, true);

This gave the me the position of the TextField inside the scrollview, instead of the coordinates inside the Cell. Scrolling works as expected after this addition.

Supporting Information

Apple documentation: https://developer.apple.com/reference/uikit/uiview/1622498-convertrect?language=objc

A link that helped me understand how to use the method: http://www.infragistics.com/community/blogs/torrey-betts/archive/2013/05/06/quick-tip-convert-coordinate-system-of-a-uiview.aspx

Objective C usage:

- (CGRect)convertRect:(CGRect)rect 
         fromView:(UIView *)view;

Upvotes: 0

Carter
Carter

Reputation: 3093

Built-in, easy solution from Apple :)

There's actually a function to scroll the cell you want to be visible! In Swift, it looks like:

self.tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Top, animated: true)

So with this solution, just get the cell of the UITextField and ask your table view to scroll to that cell.


Alternative Answer

Problem

The UITextField's frame is relative to its super view, the cell. In this case, the text field probably has a frame like CGRect(x:0, y:0, width: cell.frame.size.width, height:cell.frame.size.height), so when you call ScrollRectToVisible, the scrollView won't move.

Solution

To solve this, call ScrollRectToVisible on the cell's frame instead, for example:

UITextField tf = currentStep.GetActiveTextfield(currentView);
UIView v = tf.superView;
if (v != null) {
    currentStep.ScrollView.ScrollRectToVisible(v, true);
}

I'm not used to xamarin, so please correct any formatting or errors you see!

Upvotes: 1

Related Questions