programmatically stop uipickerview animation on iphone
Asked Answered
D

8

7

I have a UIActionSheet containing a picker and a UIToolbar. On the UIToolBar there is a save button. However, some of my users reported pressing the save button before the UIPickerView stops spinning thus only retrieving the initial value (before spinning).

Is there a way to get the currently selected item of the UIPickerView once the user taps save or get feedback of the active selected item while it's spinning?

Thanks

Duplicator answered 30/1, 2011 at 2:42 Comment(4)
what do you mean under spinning? The only spinning element in iPhone UI that I know is UIActivityIndicatorViewCaruso
I haven't tried but what happen if you do this while spinning? [picker selectRow:[picker selectedRowInComponent:i] inComponent:i animated:YES]; for each component i you have?Theorize
@Caruso on iPhone, you can swipe down on the uipickerview to make it spin (slot machine style)Duplicator
@nacho4d... I answered the same thing... you should have answered instead of commenting... that would have save time for others too..Reposeful
T
5

Even if they dismiss the picker while it's still spinning, the picker will still call the delegate with the final selected row once it stops, even if it isn't visible. Assuming you haven't deallocated it yet, you can set the delegate receiver to check if the picker is visible, and if it isn't, save the selected value.

I do this assuming it's clear the user isn't scrolling to a random value - usually when they scroll and dismiss without waiting for it to settle, it means they scrolled to either the very top or very bottom of the list. I'd say you can safely use the result of the delegate in these two cases.

Telegenic answered 16/6, 2011 at 22:52 Comment(2)
You are the closest answer so far! It would seem like it's a valid solution. However, my picker is in a UIActionSheet, so it will be released after hitting a button on the toolbar on the UIActionSheet which is very likely to happen while spinning because there aren't that many rows. Any suggestions for how to work around this or have it stop programatically? Vote up nonethelessDuplicator
Thank you so much Shaun, kicking myself a little for not thinking of this in the first place but totally helped me!! Again, thanks!Staysail
T
2

Have you ever thought about using the titleForRow method to figure this out. As the pickerview is scrolling, your titleForRow method is being called to populate the rows above or below the currently viewed row(depending on which way the picker is spinning). When the picker stops, the didSelectRow method is called and the row returned is 2 rows from the last row populated in the titleForRow method.

I would think that you could choose to stop the picker at some point (timers to detect point that are used to tell code in titleForRow to capture component and row from the call) in the scrolling and then do a selectRow to set the value to what you want it to be after it stops spinning (and didSelectRow is called).

Tivoli answered 13/3, 2011 at 7:31 Comment(0)
M
1

I don't think this is a problem you're going to be able to solve with UIPickerView by itself.

There is no way to now which row is selected without the animation stopping (and thus the picker view selecting the row it stopped on). The only way would be to tell the picker which row to stop on, by using the selectRow:inComponent:animated: but how will you know which row that is? You don't know because the picker is spinning...

I think this is just a limitation of the UIPickerView and Apple would likely describe it as expected behaviour.

Metage answered 31/1, 2011 at 11:3 Comment(1)
You can get current row by using selectedRowInComponent method of pickerView, even pickerView is spinning.Jokester
R
1

I had the same problem... I fixed it by simply adding the following code line on the method that closes or selects the picker value.

[_picker selectRow:[_picker selectedRowInComponent:0] inComponent:0 animated:YES];
Reposeful answered 24/6, 2012 at 21:47 Comment(0)
B
1

Just found solution, which works for my case. I don't need that last update event, generated when picker stops spinning after user dismissed it. So this method stops scrolling and don't causes new update selection event. Seems you'll going to check if selections are ok in picker after this (I don't care, I reselect values when I show picker).

- (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];    
}
Banderillero answered 25/10, 2012 at 17:19 Comment(0)
I
0

On "save" button click, You can retrieve the selected object from your component by

[component1Array objectAtIndex:[myPicker selectedRowInComponent:1]];

where,

  • "component1Array" is an NSArray or NSMutableArray, object which used to display the objects (raw contents) in your component.
  • "myPicker" is an UIPickerView object which displays the picker.
  • "[myPicker selectedRowInComponent:1]" will return the currently selected raw no from the myPicker in component '1'.

And "[myPicker selectedRowInComponent:2]" will return the currently selected raw no from the myPicker in component '2'. You can retrieve the selected object from your component2 by

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

Hope it works for you.

Instantly answered 31/1, 2011 at 10:19 Comment(1)
The problem is that when the save button is clicked, if the picker view is still spinning, then it's selected row hasn't been set yet. This will still always return the previously selected row, not whichever row the selection highlight appears to be on, thus not fixing the problem. The problem is how does one forcibly tell the picker view to select the row it appears to be on during a spin. I don't think you can.Metage
P
0

This might be a "hack," but it works. My case is slightly different. I'm using one UIPicker, but can change what object it is manipulation.

My issue was that you could select one object, spin the picker, and while it is finishing its spin, select a different object. What ended up happening was the new object was getting the final value of that spin, rather than it being ignored.

What I did what when setting up the UIPicker I'd give it a unique tag based on the object that it was supposed to update.

- (void)updatePickerView:(UIPickerView*)pickerView
{
    ...
    pickerView.tag = [self.myObject.position integerValue];
    [pickerView selectRow:i inComponent:0 animated:NO];
}

Then when it finishes its spin, I check to make sure that tag lines up still.

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

I'm not sure how it is functioning on Apple's side, but this was enough to make it work for me.

As a side note, and I'm not sure if this matters, but my UIPicker is in a UITableViewCell but since it is a reusable cell and because I was having the issues that I was, I assume the UIPicker is the same when it is moved from one position to another (as there is only one on screen at a time).

Page answered 15/6, 2015 at 22:33 Comment(0)
B
-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
}
Biondo answered 25/10, 2019 at 9:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.