UIPickerView 高度约束动画跳跃

Posted

技术标签:

【中文标题】UIPickerView 高度约束动画跳跃【英文标题】:UIPickerView height constraint animation jumps 【发布时间】:2016-10-13 12:02:17 【问题描述】:

我正在为 UIPickerView 的高度约束设置动画。 视图跳到一个小的高度仍然显示 1 行,然后动画直到高度 0。

UIView.animate(withDuration: 0.5, animations: 
        self.timePickerHeightConstraint.constant =    self.pickerIsClosed ? 216 : 0
        self.view.layoutIfNeeded()
    )  compilation in
        self.pickerIsClosed = !self.pickerIsClosed
    

有什么建议吗? 谢谢

【问题讨论】:

【参考方案1】:

试试这样的,

func showPickerView(_ animated: Bool) 
    weak var weakSelf = self
    UIView.animate(withDuration: (animated ? kPickerView_AppearanceAnimationDuration : 0.0), delay: (animated ? kPickerView_AppearanceAnimationDelay : 0.0), options: (animations as! UIViewAnimationOptionCurveEaseInOut), () -> Void in
        weakSelf!.pickerViewContainerView.transform = CGAffineTransform(translationX: 0, y: 0)
    , completion: (finished: Bool) -> Void in
        weakSelf!.view.layoutIfNeeded()
    )


func hidePickerView(_ animated: Bool) 
    weak var weakSelf = self
    UIView.animate(withDuration: (animated ? kPickerView_DisappearanceAnimationDuration : 0.0), delay: (animated ? kPickerView_DisappearanceAnimationDelay : 0.0), options: (animations as! UIViewAnimationOptionCurveEaseInOut), () -> Void in
        weakSelf!.pickerViewContainerView.transform = CGAffineTransform(translationX: 0, y: kPickerView_Height)
    , completion: (finished: Bool) -> Void in

它对我有用。

【讨论】:

【参考方案2】:

您应该在动画块之外更改约束常量值,

self.timePickerHeightConstraint.constant =    self.pickerIsClosed ? 216 : 0

UIView.animate(withDuration: 0.5, animations: 
    self.view.layoutIfNeeded()
)  compilation in
    self.pickerIsClosed = !self.pickerIsClosed

另外请确保您没有设置顶部和底部约束,因为这将不允许自动布局将高度设置为 0 点。

【讨论】:

谢谢,但同样的问题。 您为 PickerView 设置了哪些约束? 尾随、前导、高度、顶部、底部 在这种情况下,将高度更改为 0 将不起作用,因为自动布局引擎需要打破约束。尝试设置垂直和水平中心约束并设置宽度和高度约束,只需制作高度约束的出口并更新。根据需要进行更改。【参考方案3】:

我遇到了同样的问题。似乎 UIPickerView 的高度动画效果不佳,或者至少按照我希望的方式进行动画处理。

我发现的解决方法是将 UIPickerView 包装在 UIView 中,将 UIView 的 clipsToBounds 设置为 true,然后在 UIView 包装器的高度约束上执行动画,而不是直接使用 UIPickerView。需要注意的一点是,要使其正常工作,UIPicker 视图的高度必须独立于包装器视图的高度进行约束,否则它的反应方式与没有包装器时相同。

 // create and add UIPicker to view
    UIPickerView *picker = [[UIPickerView alloc] init];
    picker.translatesAutoresizingMaskIntoConstraints = NO;
    picker.delegate = self;
    picker.dataSource = self;
    picker.alpha = 0.0;
    _myUiPicker = picker; // weak reference property

    // make wrapper view
    UIView *wrapper = [UIView new];
    wrapper.translatesAutoresizingMaskIntoConstraints = NO;
    wrapper.clipsToBounds = YES;
    [wrapper addSubview:picker];
    [self.view addSubview:wrapper];

    // Picker constraints
    [picker.leadingAnchor constraintEqualToAnchor:wrapper.leadingAnchor].active = YES;
    [picker.trailingAnchor constraintEqualToAnchor:wrapper.trailingAnchor].active = YES;

    // ***** Note this height is not determined by wrapper view ***
    [picker.heightAnchor constraintEqualToConstant:130.0].active = YES;
    // ****
    [picker.topAnchor constraintEqualToAnchor:wrapper.topAnchor].active = YES;

    // wrapper constraints
    [wrapper.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor].active = YES;
    [wrapper.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor].active = YES;
    // **** this is the constraint you will animate ***
    NSLayoutConstraint *heightConstraint = [wrapper.heightAnchor constraintEqualToConstant:0.0];
    heightConstraint.active = YES;
    // ****
    NSLayoutConstraint *topConstraint = [wrapper.topAnchor constraintEqualToAnchor:self.view.topAnchor constant:8.0];
    topConstraint.active = YES;
    [self.view layoutIfNeeded]; // initial layout

    // animate picker height and reminderBtn position
    [UIView animateWithDuration:JAPPickerAnimationTime animations:^
        heightConstraint.constant = 130.0; // from 0 to 130
        picker.alpha = 1.0; // make is show
        [self.view layoutIfNeeded];
    ];

【讨论】:

听起来是个不错的解决方案——你能展示一些代码吗?我不明白你的最后一句话(即独立约束需要)。您能否详细说明一下您是如何做到的? @iKK 我添加了一个代码示例。我所说的独立高度的意思是,设置 UIPickerView 高度的约束与充当包装器的 UIView 的高度无关或绑定。【参考方案4】:

选择器组件行的高度是多少。签到

func pickerView(pickerView: UIPickerView, rowHeightForComponent 组件: Int)

当 self.pickerIsClosed == true 时返回 0。

【讨论】:

还会在动画块完成时重新加载选取器视图。

以上是关于UIPickerView 高度约束动画跳跃的主要内容,如果未能解决你的问题,请参考以下文章

高度约束动画“跳跃”

约束动画之前的跳跃图像

自定尺寸单元格高度变化导致跳跃动画

动画 UIView 大小跳跃

相互切换2个UIPickerview的组件

触摸 UITextField 时设置 UIPickerView 的默认值