2010-05-25 34 views
13

mag ich mehrere Zeilen in einer UIPickerView wählen, so hatte ich die Idee, meine Daten in einer Tabelle zu zeigen, und diese Tabelle als Subview Picker hinzufügen. Ich habe das versucht, aber es ist mir nicht gelungen.Mehrere Zeilenauswahl in UIPickerView

Irgendwelche Vorschläge, wie man das macht?

Antwort

12

die „akzeptiert“ UI für Mehrfachauswahl auf dem iPhone ist ein UITableView mit Häkchen zu verwenden (das heißt nicht verwenden UIPickerView für Mehrfachauswahl).

Jedoch, wenn Sie müssen, gibt es Anweisungen, wie man es hier http://www.iphonedevsdk.com/forum/iphone-sdk-development/14634-uipickerview-multiple-selection.html vortäuscht, indem man einen leeren Pflücker bildet und eine Tabellenansicht darüber legt.

+0

Danke dost, es hilft mir wirklich. Mein Problem ist gelöst. Vielen Dank. – Jack

+0

in diesem Fall sollten Sie diese Antwort akzeptieren [das Häkchen klicken] (und vielleicht auch über eine anderen Ihre Fragen zurückgehen und das gleiche tun!) – Andiih

7

ein schnellen Hack implementiert, um das UIPickerView Mehrfachauswahl-Verhalten (wie in Mobile Safari) zu erhalten, ohne Zugabe von anderen Ansichten vor dem picker, wenn jemand interessiert: https://github.com/alexleutgoeb/ALPickerView

Verbesserungen sehr geschätzt werden!

14

Sie können es ohne UITableView tun, nur UITapGestureRecognizer mit :)

Fügen Sie außerdem NSMutableArray *selectedItems irgendwo in Ihrer .h-Datei.

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

    if (cell == nil) { 
     cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil]; 
     [cell setBackgroundColor:[UIColor clearColor]]; 
     [cell setBounds: CGRectMake(0, 0, cell.frame.size.width -20 , 44)]; 
     UITapGestureRecognizer *singleTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(toggleSelection:)]; 
     singleTapGestureRecognizer.numberOfTapsRequired = 1; 
     [cell addGestureRecognizer:singleTapGestureRecognizer]; 
    } 

    if ([selectedItems indexOfObject:[NSNumber numberWithInt:row]] != NSNotFound) { 
     [cell setAccessoryType:UITableViewCellAccessoryCheckmark]; 
    } else { 
     [cell setAccessoryType:UITableViewCellAccessoryNone]; 
    } 
    cell.textLabel.text = [datasource objectAtIndex:row]; 
    cell.tag = row; 

    return cell; 
} 

- (void)toggleSelection:(UITapGestureRecognizer *)recognizer { 
    NSNumber *row = [NSNumber numberWithInt:recognizer.view.tag]; 
    NSUInteger index = [selectedItems indexOfObject:row]; 
    if (index != NSNotFound) { 
     [selectedItems removeObjectAtIndex:index]; 
     [(UITableViewCell *)(recognizer.view) setAccessoryType:UITableViewCellAccessoryNone]; 
    } else { 
     [selectedItems addObject:row]; 
     [(UITableViewCell *)(recognizer.view) setAccessoryType:UITableViewCellAccessoryCheckmark]; 
    } 
} 
+0

In diesem Beispiel mögen Sie nie den recognizer.view.tag gesetzt. Vielleicht muss es überarbeitet werden –

+0

Sie haben Recht. Es ist jetzt behoben. – suda

+2

Ich habe drei Picker und ich brauche diese Art von Mehrfachauswahl nur für einen Kommissionierer .. Was soll ich für andere Kommissionierer zurückkehren? – Mano

1
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer 
{ 
     return true; 
} 

Und Sie müssen diese Methode außer Kraft zu setzen, andere sonst bilden ios9, tippen Geste recognization würde nicht funktionieren.

+0

bitte das Code-Format (4 Felder), bevor Sie den Code Beispiel, um Ihre Antwort klarer –

2

Der folgende Code funktioniert für iOS 10. Ich hatte nicht die Möglichkeit, es auf älteren Versionen zu testen, aber ich denke, es sollte funktionieren. Die Idee ähnelt der von @ suda, aber sie fügt einen einzelnen Tap Recognizer direkt der Picker-Ansicht hinzu, anstatt den Tap Recognizer zu jeder Zeile hinzuzufügen, da dies unter iOS7 + nicht funktioniert.

Der Kürze halber, ich habe nicht enthalten die vollständige Umsetzung der UIPickerViewDataSource und UIPickerViewDelegate Protokolle, nur die relevanten Teile der Mehrfachauswahl zu implementieren.

// 1. Conform to UIGestureRecognizerDelegate protocol 
@interface MyViewController() <UIPickerViewDataSource, UIPickerViewDelegate, UIGestureRecognizerDelegate> 

@property (nonatomic, strong) NSMutableArray *selectedArray; // To store which rows are selected 
@property (nonatomic, strong) NSArray *dataArray;   // Picker data 
@property (weak, nonatomic) IBOutlet UIPickerView *pickerView; 

@end 

@implementation MyViewController 

- (void)viewDidLoad 
{  
    [super viewDidLoad]; 

    self.selectedArray = [NSMutableArray array]; 
    self.dataArray = @[@"Option 1", @"Option 2", @"Option 3", @"Option 4"]; 

    // 2. Add tap recognizer to your picker view 
    UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(pickerTapped:)]; 
    tapRecognizer.delegate = self; 
    [self.pickerView addGestureRecognizer:tapRecognizer]; 
} 

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer 
{ 
    return true; 
} 

- (void)pickerTapped:(UITapGestureRecognizer *)tapRecognizer 
{ 
    // 3. Find out wich row was tapped (idea based on https://stackoverflow.com/a/25719326) 
    if (tapRecognizer.state == UIGestureRecognizerStateEnded) { 
     CGFloat rowHeight = [self.pickerView rowSizeForComponent:0].height; 
     CGRect selectedRowFrame = CGRectInset(self.pickerView.bounds, 0.0, (CGRectGetHeight(self.pickerView.frame) - rowHeight)/2.0); 
     BOOL userTappedOnSelectedRow = (CGRectContainsPoint(selectedRowFrame, [tapRecognizer locationInView:self.pickerView])); 
     if (userTappedOnSelectedRow) { 
      NSInteger selectedRow = [self.pickerView selectedRowInComponent:0]; 
      NSUInteger index = [self.selectedArray indexOfObject:[NSNumber numberWithInteger:selectedRow]]; 

      if (index != NSNotFound) { 
       NSLog(@"Row %ld OFF", (long)selectedRow); 
       [self.selectedArray removeObjectAtIndex:index]; 
      } else { 
       NSLog(@"Row %ld ON", (long)selectedRow); 
       [self.selectedArray addObject:[NSNumber numberWithInteger:selectedRow]]; 
      } 
      // I don't know why calling reloadAllComponents sometimes scrolls to the first row 
      //[self.pickerView reloadAllComponents]; 
      // This workaround seems to work correctly: 
      self.pickerView.dataSource = self;    
      NSLog(@"Rows reloaded"); 
     } 
    } 
} 

- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view 
{  
    // 4. Customize your Picker row as needed. 
    // This is a very simple view just to make the point 

    UILabel *pickerLabel = (UILabel *)view; 

    if (pickerLabel == nil) { 
     pickerLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0, 0.0, 400, 32)]; 
    } 

    BOOL isSelected = [self.selectedArray indexOfObject:[NSNumber numberWithInteger:row]] != NSNotFound; 
    NSString *text = [self.dataArray objectAtIndex:row]; 
    text = [text stringByAppendingString:isSelected ? @"☒ " : @"☐ "]; 
    [pickerLabel setText:text]; 

    return pickerLabel; 
} 


// Do not forget to add the remaining methods to conform the UIPickerViewDataSource and UIPickerViewDelegate protocols! 

@end 
+0

OMG! Vielen Dank, Mann @ Paglian! Du hast meinen Tag gerettet! Ich wurde darüber nachgedacht, wie die Schriftrollen zu deaktivieren, während reloadAllComponent 5 Stunden telefonieren! Und du rette mich mit nur 1 Codezeile !!!!!! – KTang