Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scrollview's content too tall after keyboard disappears #76

Open
danray0424 opened this issue Dec 13, 2013 · 20 comments
Open

Scrollview's content too tall after keyboard disappears #76

danray0424 opened this issue Dec 13, 2013 · 20 comments

Comments

@danray0424
Copy link

I added a UIScrollView to my view, and put all my content inside it. This is on the DetailController of a UISplitView, as generated from the Xcode template. We're inside a UINavigationController in the detail pane.

TPKeyboardAvoiding scrolls things up out of the way when the keyboard appears. Brilliant. When the keyboard disappears, the content comes down, but after returning to position the content in the scrollview is offset northward by the height of the navigationBar, and is touch-enabled, so it can be manually scrolled up and down by that amount.

@arietis
Copy link

arietis commented Dec 18, 2013

I can confirm this issue exists.

@nathankot
Copy link

I'm getting this too...

@intrepidmatt
Copy link

I got this too, it appears the trouble is with this method for calculating the underlying content size inside the scrollview:

-(CGSize)TPKeyboardAvoiding_calculatedContentSizeFromSubviewFrames {
    CGRect rect = CGRectZero;
    for ( UIView *view in self.subviews ) {
        rect = CGRectUnion(rect, view.frame);
    }
    rect.size.height += kCalculatedContentPadding;
    return rect.size;
}

The scrollview inserts two subviews for the scroll indicators that throw off the calculation. I couldn't figure out a way to exclude the scroll indicator views from that for loop. I did find that if I turned off the scroll indicators completely, the issue goes away.

@danray0424
Copy link
Author

Beautiful, that fixes it.

For others' reference, if you're using IB to make the connection between your viewController's ".view" property and your TPKeyboardAvoidingScrollView, you have to explicitly create a property called "view" of type TPKeyboardAvoidingScrollView, or else you don't have the method showsVerticalScrollIndicator on that property. TPKASV gets that method by virtue of subclassing UIScrollView.

@michaeltyson
Copy link
Owner

I can't reproduce this problem myself, but if the solution @intrepidmatt describes addresses the problem, I'd like to find a better way to avoid including the scroll indicator views in the calculation. @intrepidmatt, have you tried identifying those by class name, or perhaps tag? (if you put an NSLog on the view within that loop, it might help to show their properties, to give us something to use to identify them)

@intrepidmatt
Copy link

Results of the log:

view: <UIImageView: 0x99939c0; frame = (316 561; 3 7); alpha = 0; opaque = NO; autoresize = LM; userInteractionEnabled = NO; layer = <CALayer: 0x9993590>> 
tag: 0

@mbcoder17
Copy link

I am having this issue as well. Is there a fix for it?

@michaeltyson
Copy link
Owner

Hmm, that's not particularly helpful, is it? Is there a way to reproduce this problem reliably, ideally using the provided sample app?

@mbcoder17
Copy link

Sorry, allow me to explain what is causing the problem for me: Originally I had a UIView with all of my elements in it, then I found this amazing class that would fix my textfield problems, so in my storyboard I changed the class of my View to TPKeyboardAvoidingScrollView. The textfields move into position correctly, but when I dismiss the keyboard, the scroll view is offset and there is extra space on the top/bottom to scroll...

@michaeltyson
Copy link
Owner

Oh, apologies @mbcoder17 - by 'not particularly helpful' I was responding to @intrepidmatt's finding that the UIScrollView's scroll indicators apparently can't be uniquely identified =) Your message was fine! Alas, until we can either figure out how to exclude those indicators, I don't know how we can address the issue, but if I can reproduce it here somehow, that'd be helpful.

Cheers for the extra info all the same though!

@intrepidmatt
Copy link

In the sample app, change the deployment target to 7.0 and run in the iOS 7 3.5 inch simulator. Delete all the fields in FirstView.xib except for "Iggle" and "Splat". You'll see the scroll indicator UIImageViews if you break on line 208 of UIScrollView+TPKeyboardAvoidingAdditions.m.

Repro steps:

  1. Run in iOS 7 3.5 inch simulator
  2. Click on "Splat"
  3. Click on empty space to dismiss the keyboard.
  4. "Iggle" is now hidden

If you disable the horizontal and vertical scroll indicators on the scroll view in FirstView.xib and try the steps again, it works properly (iggle correctly scrolls back into view when the keyboard is dismissed).

@mbcoder17
Copy link

How can I implement the fix mentioned a few posts up? I don't have any scroll indicator settings in IB as I started with a UIView not a scroll view.....

On Jan 7, 2014, at 8:45 PM, Michael Tyson [email protected] wrote:

Oh, apologies @mbcoder17 - by 'not particularly helpful' I was responding to @intrepidmatt's finding that the UIScrollView's scroll indicators apparently can't be uniquely identified =) Your message was fine! Alas, until we can either figure out how to exclude those indicators, I don't know how we can address the issue, but if I can reproduce it here somehow, that'd be helpful.

Cheers for the extra info all the same though!


Reply to this email directly or view it on GitHub.

@intrepidmatt
Copy link

I was able to do so in interface builder with your sample project and no modifications:

screen shot 2014-01-07 at 9 32 07 pm

@michaeltyson
Copy link
Owner

Ah lovely, thank you @intrepidmatt ! I'll take a look.

@danray0424
Copy link
Author

I solved this by putting the .view @Property into my .h (you already have one by virtue of subclassing UIViewController, but you can override it in the header file), and explicitly making it a TPKeyboardAvoidingScrollView. Then inside -viewDidLoad I could turn off the .showsHorizontalScrollIndicator and .showsVerticalScrollIndicator.

"Solved" is a strong word--the problem is gone in my implementation, but obviously a way for TPKA to notice scroll indicators and ignore them is the real solution.

@mbcoder17
Copy link

@danray0424 that didn't fix it for me. All it did was hide the scroll bars, but there is still a taller content to scroll through...

@jonathandemoor
Copy link

👍

@mbcoder17
Copy link

Any fix yet?

@osklar0328
Copy link

If I understand this issue correct then I get this problem when I'm toggling between regular textfields and textfields with input view's such as a picker or a custom accessory view. Should it be any difference when I user pickers instead of textfields when I use TPKeyboardAvoiding?

@brianpseudo
Copy link
Contributor

I think I worked out this issue.

The problem, as @intrepidmatt stated, is that TPKeyboardAvoiding_calculatedContentSizeFromSubviewFrames is including the scroll indicators in the calculation. The scroll indicators are UIImageViews, added by the UIScrollView as subviews.

While there isn't a way to determine if the UIImageView you're looking at is a scroll indicator, they are removed when you turn off the scroll indicators.

So the fix is to simply remember if the scroll indicators are turned on before calculating the content size, then turning them off, performing the calculation, and restoring the indicators' visibilities. I'll send a push request to @michaeltyson in a moment, but here's the code in the meantime:

-(CGSize)TPKeyboardAvoiding_calculatedContentSizeFromSubviewFrames {

    BOOL wasShowingVerticalScrollIndicator = self.showsVerticalScrollIndicator;
    BOOL wasShowingHorizontalScrollIndicator = self.showsHorizontalScrollIndicator;

    self.showsVerticalScrollIndicator = NO;
    self.showsHorizontalScrollIndicator = NO;

    CGRect rect = CGRectZero;
    for ( UIView *view in self.subviews ) {
        rect = CGRectUnion(rect, view.frame);
    }
    rect.size.height += kCalculatedContentPadding;

    self.showsVerticalScrollIndicator = wasShowingVerticalScrollIndicator;
    self.showsHorizontalScrollIndicator = wasShowingHorizontalScrollIndicator;

    return rect.size;
}

brianpseudo added a commit to pseudostudios/TPKeyboardAvoiding that referenced this issue Jan 29, 2014
…izeFromSubviewFrames, the scroll indicators were included in the subview frame calculations. Now we save the visibility of the scroll indicators, then turn them off while we calculate the new contentSize, then restore the scroll indicator visibility state.
michaeltyson added a commit that referenced this issue Jan 30, 2014
Fixed issue #76.  In TPKeyboardAvoiding_calculatedContentSizeFromSubview...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants