2012-05-30 7 views
21

Ich habe mir diese Frage schon oft angesehen, aber ich bin mir immer noch nicht sicher, ob das möglich ist oder nicht. Im Wesentlichen möchte ich eine UIPickerView erstellen, die in dem Sinne kontinuierlich ist, dass Sie sie für immer drehen können und Sie werden nie das Ende davon erreichen (da auf den letzten Wert der erste Wert folgt).Wie macht man einen kreisförmigen UIPickerView (iPhone/iPad)?

Ich habe rund um Online einen Blick hatte und es scheint eine Vielzahl von Hacks, um die gewünschte Wirkung zu erzielen. Doch viele dieser Lösungen scheinen die Anzahl der Zeilen in der UIPickerView zu erhöhen, um die Benutzer dazu verleiten, die UIPickerView denken kontinuierlich ist (aber in Wirklichkeit, wenn sie Scrollen gehalten würden sie erreichen schließlich das Ende).

Was ich bin, ist eine Möglichkeit, ein UIPickerView zu erstellen, das wirklich unendlich in dem Sinne ist, dass Sie nie das Ende erreichen werden, wenn Sie für Tage, Wochen, Monate oder Jahre scrollen. Es macht mir nichts aus, wenn die Lösung ein Hack ist, da ich verstehe, dass Apple noch keine Möglichkeit bietet, den Effekt zu erzielen.

Bitte kann mir jemand raten auf eine Art und Weise, dies zu tun (oder mich zumindest in die richtige Richtung)?

Antwort

4

Ich glaube wirklich, dass die einzige hacken Sie mit nativer UIPickerView ist hier beschrieben können:

How do you make an UIPickerView component wrap around?

Der andere Weg machen wirklich geschlungenen Picker, es selbst zu implementieren ist.

Ich sah Pflücker, die mit cocos2d umgesetzt wurden, dh OpenGL-basierte. Ich denke, Sie können versuchen, es mit UIKit zu tun, wenn Sie wirklich brauchen.

oder vergiss es einfach und Kommissionierer mit NSIntegerMax Reihen mit wiederholbaren Inhalt machen. Ich denke, dass niemand es bis zum Ende drehen wird.

+0

Putting NSIntegerMax wird in der Regel das Programm abstürzen. Ich glaube, Olie's Antwort ist eine bessere und vernünftige Antwort im Falle von Benutzerfreundlichkeit und Gedächtnis. –

0

Hm .. Ich habe mich umgesehen, und es gibt ein paar Links zu einigen Möglichkeiten, das herausragendste ist dieses: The Abusive Pickerview, die Grundidee ist, dass Sie die Pickerview mit 3 Sätze Ihrer Daten bevölkern und Start und die Mitte gesetzt. Immer wenn der Benutzer zur Mitte des oberen oder unteren Satzes scrollt, setzen Sie den Zeilenwert zurück auf die Mitte des mittleren Satzes! Es scheint aufrichtiger zu sein, als eine wirklich lange Liste zu erstellen, die die Illusion der Unendlichkeit schafft. Diese Lösung kann am effektivsten und einfachsten sein, um das unendliche Pickerview-Problem zu lösen! Hoffe das hat geholfen!

+0

Im Allgemeinen sollten Sie nicht kopieren und Ihre Antworten von anderen Pfosten einfügen http://stackoverflow.com/questions/10815435/how-to-make-a-circular-uipickerview-iphone-ipad – pasawaya

+0

Hm .. Ich tat nicht tatsächlich diesen Beitrag anzeigen ... – wayway

2

Es ist möglich. Hier ist, wie Sie es tun können. Stellen Sie zuerst einen Timer ein. Nehmen wir an, int maxNumber ist eine Instanzvariable, die auf einen beliebigen Wert gesetzt ist.

In der Timer-Fire-Methode überprüfen Sie, ob eine der "Kanten" -Ansicht Ihres uipickerview angezeigt wird.

- (void)timerFireMethod:(NSTimer*)theTimer{ 
int rowSelected = [self.infinitePickerView selectedRowInComponent:0];  
for (int i=0; i<= 20; i++) { 
    UIView * viewBelow = [self.infinitePickerView viewForRow:i forComponent:0]; 
    UIView * viewAbove = [self.infinitePickerView viewForRow:maxNumber*10-20+i forComponent:0]; 
    if(viewBelow!=nil || viewAbove!=nil){ 
     int middlePosition = maxNumber * 5 + (rowSelected % maxNumber); 
     [self.infinitePickerView selectRow:middlePosition inComponent:0 animated:NO]; 
     break; 
    } 
} 
} 

Hinweis funktioniert dies, weil [self.infinitePickerView viewForRow:i forComponent:0]; eine UIView gibt nur wenn es sichtbar ist.

Natürlich muss Ihr UIPickerViewDelegate sein verwenden so etwas wie

- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{ 
    return maxNumber * 10; //returning a large number 
} 

//You cannot use this method 
/* 
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component{} 
You have to use the method below in lieu of it 
*/ 

- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view{ 

UILabel * label; 

if (!view) { 
    label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.infinitePickerView.bounds.size.width, 30)]; 
}else { 
    label = (UILabel *) view;  
} 
[label setText:[NSString stringWithFormat:@" %d", row % maxNumber]]; 
return label; 
} 

Hope this funktioniert !! :) Viel Glück!

+0

sieht aus wie ein netter Hack. @ The Crazy Chimp lassen Sie uns wissen, ob es funktioniert. –

3

Finden Sie die benutzerdefinierte UIPickerView Klasse, die sehr gut funktioniert und ist sehr einfach here

0

Es scheint mir, zu implementieren, dass Lösungen, die große Datenmengen erfordern, in die picker verschwenderisch sind gestopft werden. Die folgende Lösung verwendet Smart anstelle von Speicher.

Die einzigen Zeilen, die ausgefüllt werden müssen, sind die in der Ansicht sichtbaren Zeilen und die Zeile unmittelbar vor der ersten und die Zeile unmittelbar nach der letzten Zeile. Wenn der Benutzer eine Komponente scrollt, wird für jede durchsuchende Zeile pickerView: titleForRow: forComponent: aufgerufen.

Also die Lösung besteht darin, die Daten in PickerView: titleForRow: forComponent zu aktualisieren und dann die entsprechende Methode aufzurufen, um die Daten neu zu laden, so dass sie vorhanden sind, wenn der PickerView einen weiteren Tick scrollt.

2

Es gibt keine native-Picker, die Wraps Sie können gefälschte dies durch etwas in dieser Richtung (nicht ab iOS7.1 sowieso.):

NSArray *picks = @[ @"zero", @"one", @"two", @"three" ]; // 4 entries 

// ... 

- (NSInteger)pickerView:(UIPickerView *)pickerView 
numberOfRowsInComponent:(NSInteger)component 
{ 
    return (3 * [picks count]); // we're very tricky, displaying only 
           // ...the SECOND set of entries, to 
           // ... give the impression of wrap-around 
} 

// ... 

- (NSString *)pickerView:(UIPickerView *)pickerView 
      titleForRow:(NSInteger)row 
      forComponent:(NSInteger)component 
{ 
    // All "3" sets of entries have the same values; 
    // this is what gives the appearance of wrap-around. 
    int titleRow = row % [picks count]; 
    return [picks objectAtIndex: titleRow]; 
} 

// ... 

- (void)pickerView:(UIPickerView *)pickerView 
     didSelectRow:(NSInteger)row 
     inComponent:(NSInteger)component 
{ 
    // If the wheel turns to outside our 2nd-set range, 
    // ...set it to the matching item in the 2nd set. 
    // In this way, we always display what looks like a wrap-around. 
    int count = [picks count]; 
    if ((row < count) 
    || (row > (count * 2)) 
    { 
     [pickerView selectRow: (row % count) inComponent: component animated: NO]; 
    } 
} 

Sie müssen zwicken und passen Sie Ihre passen Bedürfnisse, natürlich, aber das ist der grundlegende Kern davon.

Viel Glück!

0

Ich weiß, es ist eine alte Frage, aber ich habe es gerade gefunden, während ich es in meinem eigenen Projekt implementiere.

Verwenden Sie Morions Methode für eine große Anzahl von Elementen mit sich wiederholendem Inhalt. Setzen Sie die Zeile dann jedes Mal zurück, wenn das Bild nicht mehr gescrollt wird. Der einzige Weg, wie jemand herausfindet, dass Sie betrogen haben, ist, wenn er ununterbrochen ohne Unterbrechung bis zum Ende scrollt und niemals die didSelectRow-Funktion aufruft. Es würde etwas Hingabe erfordern!

Unabhängig davon, wie Sie es tun, scheint es mir, dass es ein bisschen hacky fühlen, geht, muss & dies der einfachste Hack ...

0

ich ein zyklisches Tableview auf UIScrollView Basis gemacht haben. Und basierend auf diesem TableView implementiere ich UIPickerView neu. Das könnte dich interessieren. Und diese Picker-Ansicht verfügt über alle Funktionen, die UIPickerView, bietet aber auch viele neue Funktionen und benutzerdefinierte diese Picker-Ansicht ist viel einfacher.

https://github.com/danleechina/DLPickerView

Und dass dieses DLPickerView zyklisch scroll bewusst sein, wirklich Scrollen zyklisch. All die Magie geschah wegen einer anderen Klasse DLTableView.

0

verwendet I picker Selection eine kreisförmige eines zu erstellen:

import UIKit 
    class ViewController:   
UIViewController,UIPickerViewDelegate,UIPickerViewDataSource 
{ 
@IBOutlet weak var picker: UIPickerView! 
@IBOutlet weak var myLabel: UILabel! 

let numbers = [0,1,2,3,4,5,6,7,8,9] 

override func viewDidLoad() 
{ 
    super.viewDidLoad() 
    // A.Select Second Row 
    picker.selectRow(1, inComponent: 0, animated: false) 
} 
func numberOfComponents(in pickerView: UIPickerView) -> Int 
{ 
    return 1 
} 
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int 
{ 
    //B. Add 2 rows to your array count 
    return numbers.count + 2 
} 
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? 
{ 
    var rowTitle = "" 
    switch row 
    { 
    case 0: 
     // C. Set first row title to last component of the array. 
     // This row is not visible to the user as it is hidden by the   

     //selection in ViewDidLoad 
     rowTitle = "\(numbers.last!)" 
    case numbers.count + 1: 
     //D. Set last row title to first array component 
     rowTitle = "\(numbers.first!)" 
    default: 
     // E. Remember [row - 1] to avoid errors 
     rowTitle = "\(numbers[row - 1])" 
    } 
    return rowTitle 
} 
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) 
{ 
    var theText = "" 
    switch row 
    { 
    case 0: 
     //F. Select Row at array count to load the last row 
     pickerView.selectRow(numbers.count , inComponent: 0, animated: false) 
     theText = = "\(numbers.last!)" 
    case numbers.count + 1: 
    //G. This Selection will set the picker to initial state 
     pickerView.selectRow(1, inComponent: 0, animated: false) 
     theText = "\(numbers.first!)" 
    default: 
     theText = "\(numbers[row - 1])" 
    } 
    myLabel.text = theText 

} 

    } 
0

Eine sehr einfache Lösung, die u denken, es ist kein Ende des Aufnehmers Ansicht durch Scale-up des Arrays machen und Modul das entsprach machen Pick Element aus dem Array

override func viewDidLoad(){ 
    super.viewDidLoad() 
    self.yourArray.selectRow((yourArray.count*100)/2, inComponent: 0, animated: false) 
} 

func pickerView(_ pickerView: UIPickerView, numberOfRowaInComponent component: Int) -> Int{ 
    return yourArray.count*100 
} 

func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int)->String{ 
    return yourArray[row % yourArray.count] 
} 
Verwandte Themen