2014-09-26 16 views
10

Obecnie rozwijam aplikację za pomocą Swift, gdzie używam UIPickerView, patrz poniżej dla obrazu. Obecnie UIPickerView zatrzymuje się, gdy użytkownik przewinął do ostatnich danych, ale chcę, aby nigdy się nie zatrzymywał. Chcę, aby można było zacząć od pierwszych danych, po prostu przewijaj dalej, gdy jesteś na dole. Lub przewiń w górę, gdy jesteś na górze. Chcę, żeby było jak Odliczanie Apple, gdzie możesz przeciągać w górę lub w dół, kiedy tylko chcesz.UIPickerView - Loop danych

Jak ma to być:

enter image description here

Jak to jest obecnie:

enter image description here

Odpowiedz

9

Nie będzie cztery kroki tutaj - będziemy skonfigurować pewne stałe trzymać dane widoku kompletacji i bit konfiguracji, a następnie dodamy metody UIPickerViewDataSource i UIPickerViewDelegate, a my skończymy z inicjalizacją viewDidLoad.

Pierwsza konfiguracja:

private let pickerViewData = Array(0...59)  // contents will be 0, 1, 2, 3...59, change to whatever you want 
private let pickerViewRows = 10_000   // any big number 
private let pickerViewMiddle = ((pickerViewRows/pickerViewData.count)/2) * pickerViewData.count 

Uwaga stała pickerViewMiddle - to obliczone, aby to bardzo łatwo dostać naszą aktualną wartość offsetu z rzędu. Na źródła danych - naprawdę wystarczy podać tytuł dla każdego wiersza, ale dodamy metody pomocnika do konwertowania numer wiersza do wartości z tablicy:

extension ViewController : UIPickerViewDataSource { 
    func valueForRow(row: Int) -> Int { 
     // the rows repeat every `pickerViewData.count` items 
     return pickerViewData[row % pickerViewData.count] 
    } 

    func rowForValue(value: Int) -> Int? { 
     if let valueIndex = find(pickerViewData, value) { 
      return pickerViewMiddle + value 
     } 
     return nil 
    } 

    func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! { 
     return "\(valueForRow(row))" 
    } 
} 

I wreszcie” ll skonfigurować delegat:

extension ViewController : UIPickerViewDelegate { 
    func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int { 
     return 1 
    } 

    func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { 
     return pickerViewRows 
    } 

    // whenever the picker view comes to rest, we'll jump back to 
    // the row with the current value that is closest to the middle 
    func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { 
     let newRow = pickerViewMiddle + (row % pickerViewData.count) 
     pickerView.selectRow(newRow, inComponent: 0, animated: false) 
     println("Resetting row to \(newRow)") 
    } 

} 

aby zainicjować w swojej viewDidLoad ustawić źródło delegata i danych, a następnie przejść do odpowiedniego wiersza w środku swojej kompletacji:

self.picker.delegate = self 
self.picker.dataSource = self 
let initialValue = 0 
if let row = rowForValue(initialValue) { 
    self.picker.selectRow(row, inComponent: 0, animated: false) 
} 
// or if you just want to start in the middle: 
// self.picker.selectRow(pickerViewMiddle, inComponent: 0, animated: false) 
+0

Dzięki! Działa doskonale! – ThomasGulli

+1

Jak wspomniano w [tej odpowiedzi] (http://stackoverflow.com/a/367436/172218) ustawienie liczby wierszy w selektorze na "dowolną dużą liczbę" powoduje wkręcenie VoiceOver, podając "[element] z [duża liczba ] ", co stanowi problem z dostępnością. Jakikolwiek sposób obejścia tego? –

+0

Cześć, Nate! Gdzie deklarujesz swoją konfigurację? Ogłosiłem to na mojej lekcji, ale daj mi błąd, ponieważ instancja nie może być użyta w mojej klasie. –

2

To już odpowiedział tutaj: How do you make an UIPickerView component wrap around?

Podstawową ideą jest po prostu utworzenie widoku wyboru z dużą liczbą powtarzających się rzędów, które prawdopodobnie nigdy nie dotrą do końca. W powyższej odpowiedzi jest problem z tym, w jaki sposób tworzona jest liczba rzędów, więc zredagowałem ten fragment i podałem poniżej pozostałą odpowiedź. To objective-c więc trzeba go przekonwertować do szybkich do swoich celów ...

@implementation ViewController 
NSInteger numberItems; 
NSInteger currentValue; 

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    self.pickerView.delegate = self; 
    numberItems = 60; 
    currentValue = 0; 
    [self.pickerView selectRow:(currentValue + (numberItems * 50)) inComponent:0 animated:NO]; 
    [self.view addSubview:self.pickerView]; 
} 

- (void)didReceiveMemoryWarning { 
    [super didReceiveMemoryWarning]; 
} 

- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { 
    //return NSIntegerMax; -- this does not work on 64-bit CPUs, pick an arbitrary value that the user will realistically never scroll to like this... 
    return numberItems * 100; 
} 

- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component { 
    return [NSString stringWithFormat:@"%ld", row % numberItems]; 
} 

- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { 
    NSInteger rowValueSelected = row % numberItems; 
    NSLog(@"row value selected: %ld", (long)rowValueSelected); 
} 

@end