高度和contentOffset&QUOT的UIScrollView的动画;跳转"从底部内容 [英] UIScrollView animation of height and contentOffset "jumps" content from bottom

查看:191
本文介绍了高度和contentOffset&QUOT的UIScrollView的动画;跳转"从底部内容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

试图做类似Messages.app的行为的东西,我有一个的UIScrollView 和它下面的文本字段,并试图让键盘出现时的动画它一切都在使用移动领域的一个约束移动了键盘上方(和的UIScrollView 的身高变化,以及由于自动版式),还设置 contentOffset 滚动至底部在同一时间。

在code完成想要的最终结果,但动画权期间,当键盘动画开始滚动视图变为空白,然后将内容向上滚动从底部,而不是从它的时候,位置滚动动画开始了。

动画是这样的:

   - (无效)updateKeyboardConstraint:(CGFloat的)高度animationDuration:(NSTimeInterval)持续时间{
    self.keyboardHeight.constant = -height;
    [self.view setNeedsUpdateConstraints]    [UIView的animateWithDuration:工期延误:0选项:UIViewAnimationOptionBeginFromCurrentState动画:^ {
        [self.view layoutIfNeeded]
        self.collectionView.contentOffset =
            CGPointMake(0,self.collectionView.contentSize.height - self.collectionView.bounds.size.height);
    }完成:无];
}

问题的视频,请这里

谢谢!


解决方案

这可能是UIKit中的错误。它发生时,有 的UIScrollView contentOffset 的同时变更C>。这将会是有趣的测试,如果这种行为也恰好没有自动布局。

我发现两种方法可以解决这个问题。

使用contentInset(消息接近)

消息键盘下方可见 -

由于它可以在消息应用程序中可以看出,的UIScrollView 的身高并不时显示一个键盘改变。你可以用同样的方式。 UICollectionView 和包含视图的UITextField 的UIButton (我称之为 messageComposeView )。然后 UICollectionView 之间添加约束和底部布局指南。请将底部布局指南 messageComposeView 之间的约束和。然后使用 contentInset 来保持视力 UICollectionView 的最后一个元素在键盘上方。我做到了以下方式:

   - (无效)updateKeyboardConstraint:(CGFloat的)高度animationDuration:(NSTimeInterval)持续时间{
    self.bottomSpaceConstraint.constant =高度;    [UIView的animateWithDuration:工期延误:0选项:UIViewAnimationOptionBeginFromCurrentState动画:^ {
        CGPoint bottomOffset = CGPointMake(0,self.collectionView.contentSize.height - (self.collectionView.bounds.size.height - 高));
        [self.collectionView setContentOffset:bottomOffset动画:YES];        [self.collectionView setContentInset:UIEdgeInsetsMake(0,0,高度,0)];        [self.view layoutIfNeeded]
    }完成:无];
}

下面 self.bottomSpaceConstraint 是和底部布局指南< messageComposeView 之间的约束/ code>。 这里展示它是如何工作的视频。
更新1: 这里是我的项目在GitHub上来源。这个项目是一个有点简化。我应该考虑到在通知通过考虑选项 - (无效)keyboardWillShow:(NSNotification *)notif

在一个队列表演更改

不是一个确切的解决方案,但滚动工作正常,如果你将其移动到结束块:


 }完成:^(BOOL完){
    [self.collectionView setContentOffset:CGPointMake(0,self.collectionView.contentSize.height - self.collectionView.bounds.size.height)动画:是];
}];


这需要0.25秒的键盘来显示,所以动画的开始之间的差别可能是显着的。动画也可以以相反的顺序进行。

更新2:我也注意到,OP的code正常工作与这一变化:

  CGPoint bottomOffset = CGPointMake(0,self.collectionView.contentSize.height  - (self.collectionView.bounds.size.height  - 高));

但只有当的高度比一些固定值以下(<α contentSize href=\"https://github.com/fastred/ContentOffsetJump/blob/op_version/Playground-contentOffsetJump/ViewController.m#L52-L53\">in我周围的 800 情况下,但我的布局可能会有所不同)。

在最后,我认为,该方法我美元点$ psented使用contentInset(消息接近)比调整 UICollectionView 。当使用 contentInset 我们也得到了键盘下方的元素的可见性。这当然符合了iOS 7的风格更​​好。

Trying to do something similar to the Messages.app's behavior, I have a UIScrollView and beneath it a text field, and trying to animate it so that when the keyboard appears everything is moved up above the keyboard using a constraint that moves the field up (and the UIScrollView's height changes as well due to autolayout) and also setting the contentOffset to scroll to the bottom at the same time.

The code accomplishes the wanted end-result, but during the animation right when the keyboard animation begins the scroll view becomes blank and then the content scrolls up from the bottom, instead of scrolling from the position it was in when the animation started.

The animation is this:

- (void)updateKeyboardConstraint:(CGFloat)height animationDuration:(NSTimeInterval)duration {
    self.keyboardHeight.constant = -height;
    [self.view setNeedsUpdateConstraints];

    [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
        [self.view layoutIfNeeded];
        self.collectionView.contentOffset = 
            CGPointMake(0, self.collectionView.contentSize.height - self.collectionView.bounds.size.height);
    } completion:nil];
}

A video of the problem is available here.

Thanks!

解决方案

It might be a bug in UIKit. It happens when there's a simultaneous change of size and contentOffset of UIScrollView. It'd be interesting to test if this behavior also happens without Auto Layout.

I've found two workarounds to this problem.

Using contentInset (the Messages approach)

As it can be seen in the Messages app, UIScrollView's height doesn't change when a keyboard is shown - messages are visible under the keyboard. You can do it the same way. Remove constraint between UICollectionView and the view that contains UITextField and UIButton (I'll call it messageComposeView). Then add constraint between UICollectionView and Bottom Layout Guide. Keep the constraint between messageComposeView and the Bottom Layout Guide. Then use contentInset to keep the last element of the UICollectionView visually above the keyboard. I did it the following way:

- (void)updateKeyboardConstraint:(CGFloat)height animationDuration:(NSTimeInterval)duration {
    self.bottomSpaceConstraint.constant = height;

    [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
        CGPoint bottomOffset = CGPointMake(0, self.collectionView.contentSize.height - (self.collectionView.bounds.size.height - height));
        [self.collectionView setContentOffset:bottomOffset animated:YES];

        [self.collectionView setContentInset:UIEdgeInsetsMake(0, 0, height, 0)];

        [self.view layoutIfNeeded];
    } completion:nil];
}

Here self.bottomSpaceConstraint is a constraint between messageComposeView and Bottom Layout Guide. Here's the video showing how it works. UPDATE 1: Here's my project's source on GitHub. This project is a little simplified. I should've taken into consideration options passed in the notification in - (void)keyboardWillShow:(NSNotification *)notif.

Performing changes in a queue

Not an exact solution, but scrolling works fine if you move it to the completion block:

} completion:^(BOOL finished) {
    [self.collectionView setContentOffset:CGPointMake(0, self.collectionView.contentSize.height - self.collectionView.bounds.size.height) animated:YES];
}];

It takes 0.25s for the keyboard to show, so the difference between the beginnings of the animations might be noticeable. Animations can also be done in the reversed order.

UPDATE 2: I've also noticed that OP's code works fine with this change:

CGPoint bottomOffset = CGPointMake(0, self.collectionView.contentSize.height - (self.collectionView.bounds.size.height - height));

but only when contentSize's height is less than some fixed value (in my case around 800, but my layout may be a little different).

In the end I think that the approach I presented in Using contentInset (the Messages approach) is better than resizing UICollectionView. When using contentInset we also get the visibility of the elements under the keyboard. It certainly fits the iOS 7 style better.

这篇关于高度和contentOffset&QUOT的UIScrollView的动画;跳转&QUOT;从底部内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆