以编程方式停止iPhone上UIPickerView的动画

7

我有一个包含选择器和工具栏的UIActionSheet。在UIToolBar上有一个保存按钮。然而,我的一些用户报告说在UIPickerView停止旋转之前按下保存按钮,因此只能检索初始值(旋转之前)。

是否有办法在用户点击保存时获取UIPickerView当前选定的项目或在其旋转时获取活动选定项目的反馈?

谢谢


你所说的“spinning”是什么意思?我所知道的iPhone UI中唯一的旋转元素是UIActivityIndicatorView。 - Max
我没有尝试过,但如果您在旋转时对每个组件i执行以下操作会发生什么? [picker selectRow:[picker selectedRowInComponent:i] inComponent:i animated:YES]; - nacho4d
@Max 在 iPhone 上,你可以向下滑动 uipickerview 使其旋转(类似于老虎机)。 - zsniperx
@nacho4d... 我回答了同样的问题... 你应该回答而不是评论... 这也会节省其他人的时间.. - yunas
8个回答

5
即使在选择器仍在旋转时被关闭,一旦它停止,选择器仍将调用代理以获取最终选择的行,即使它不可见。假设您尚未取消分配它,可以将代理接收器设置为检查选择器是否可见,如果不可见,则保存所选值。
我这样做是因为我认为用户没有滚动到随机值 - 通常当他们滚动并在等待它稳定之前关闭时,这意味着他们滚动到列表的顶部或底部。我认为在这两种情况下可以安全地使用代理的结果。

你是目前最接近答案的人!看起来这是一个有效的解决方案。然而,我的选择器在UIActionSheet中,因此在旋转时很可能会在UIActionSheet上的工具栏按钮被按下后释放,因为行数不多。有什么建议可以解决这个问题或者让它在程序上停止?尽管如此,请投赞成票。 - zsniperx
非常感谢你,肖恩。有点后悔一开始没想到这个,但是你真的帮了我很多!再次感谢! - crojassoto

2
你是否曾考虑过使用titleForRow方法来解决这个问题。当pickerview滚动时,你的titleForRow方法被调用以填充当前查看行以上或以下的行(取决于选择器旋转的方向)。当选择器停止时,didSelectRow方法被调用,并且返回的行是在titleForRow方法中填充的最后一行的后面两行。

我认为你可以选择在滚动到某个点时停止选择器(使用计时器检测点,用于告诉titleForRow中的代码捕获组件和行),然后执行selectRow将值设置为你希望它在停止旋转后的值(并且会调用didSelectRow)。


1

刚刚找到了解决方案,适用于我的情况。当用户取消选择器后,我不需要最后一个更新事件,因为它会在选择器停止旋转时生成。因此,这种方法停止滚动并且不会引起新的更新选择事件。看起来你将在此之后检查选择器中的选择是否正确(我不在意,在显示选择器时我会重新选择值)。

- (void)_resetPickerViewDelegates {
    id delegate = [_pickerView.delegate retain];
    id dataSource = [_pickerView.dataSource retain];

    _pickerView.delegate = nil;
    _pickerView.dataSource = nil;
    [_pickerView reloadAllComponents];
    _pickerView.delegate = delegate;
    _pickerView.dataSource = dataSource;

    [delegate release];
    [dataSource release];    
}

1

我曾经遇到过同样的问题... 我通过在关闭或选择选取器值的方法中简单地添加以下代码行来解决它。

[_picker selectRow:[_picker selectedRowInComponent:0] inComponent:0 animated:YES];

1

我认为这不是你能够仅通过UIPickerView解决的问题。

除非动画停止(因此选择器视图选择了它停在的行),否则无法知道选择了哪一行。唯一的方法是告诉选择器停在哪一行,使用selectRow:inComponent:animated:但是你怎么知道那是哪一行?因为选择器正在旋转,所以你不知道...

我认为这只是UIPickerView的限制,苹果可能会将其描述为预期行为。


您可以使用pickerView的selectedRowInComponent方法来获取当前行,即使pickerView正在旋转。 - HiZaib

0
在“保存”按钮点击时,您可以通过以下方式从组件中检索所选对象:
[component1Array objectAtIndex:[myPicker selectedRowInComponent:1]];

在这里,

  • "component1Array" 是一个NSArray或NSMutableArray对象,用于显示组件中的原始内容。
  • "myPicker" 是一个UIPickerView对象,用于显示选择器。
  • "[myPicker selectedRowInComponent:1]" 将返回当前从 myPicker 中的组件 '1' 选择的原始编号。

"[myPicker selectedRowInComponent:2]" 将返回当前从 myPicker 中的组件 '2' 选择的原始编号。 您可以通过以下方式检索组件2中选定的对象

 [component2Array objectAtIndex:[myPicker selectedRowInComponent:2]];

希望它对你有用。

2
问题在于当点击保存按钮时,如果选择器视图仍在旋转,则其选定的行尚未设置。这仍将始终返回先前选择的行,而不是选择突出显示的任何行,因此无法解决问题。问题在于如何强制告诉选择器视图在旋转期间选择它所在的行。我认为你不能这样做。 - Jasarien

0
这可能是一种“hack”的方法,但它确实有效。我的情况略有不同。我正在使用一个UIPicker,但可以更改它操作的对象。
我的问题是,您可以选择一个对象,旋转选择器,而当它完成旋转时,选择另一个对象。最终发生的是,新对象获得了该旋转的最终值,而不是被忽略。
我所做的是,在设置UIPicker时,根据它应该更新的对象为其分配一个唯一的tag
- (void)updatePickerView:(UIPickerView*)pickerView
{
    ...
    pickerView.tag = [self.myObject.position integerValue];
    [pickerView selectRow:i inComponent:0 animated:NO];
}

然后当它完成旋转时,我会检查标签是否仍然对齐。

    - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
    {
        if (pickerView.tag == [self.myObject.position integerValue]) {
            ...
        }
    }

我不确定苹果的这个功能是如何运作的,但这对我来说已经足够使其正常工作了。

另外一件事,我不确定这是否重要,但我的 UIPicker 在一个 UITableViewCell 中,但由于它是可重用的单元格,并且因为我遇到了问题,我假设当 UIPicker 从一个位置移动到另一个位置时是相同的(因为屏幕上一次只有一个)。


-2
var isSpinning  = false (Global)

func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
  self.isSpinning = true
}

func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
  self.isSpinning = false
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接