2010-05-25 7 views
13

Я хочу выбрать несколько строк в UIPickerView, поэтому у меня возникла идея показать мои данные в таблице и добавить эту таблицу в качестве подзаголовка для сборщика. Я пробовал это, но не смог.Выбор нескольких строк в UIPickerView

Любые предложения, как это сделать?

ответ

12

«принятый» пользовательский интерфейс для множественного выбора на iPhone - использовать UITableView с галочками (т. Е. Не использовать UIPickerView для множественного выбора).

Однако, если вам нужно, есть инструкции о том, как подделать его здесь http://www.iphonedevsdk.com/forum/iphone-sdk-development/14634-uipickerview-multiple-selection.html, сделав пустой сборщик и положив на него верх таблицы.

+0

Thanx dost, это действительно помогает мне. Моя проблема решена. Большое спасибо. – Jack

+0

в этом случае вы должны принять этот ответ [щелкнуть отметку галочки] (и, возможно, вернуться к некоторым другим вопросам и сделать то же самое!) – Andiih

7

Реализован быстрый хак, чтобы получить множественный выбор-поведение UIPickerView (например, в Mobile Safari) без добавления других взглядов перед pickerview, если кто интересуется: https://github.com/alexleutgoeb/ALPickerView

Улучшения высоко ценятся!

14

Вы можете сделать это без UITableView, используя только UITapGestureRecognizer :)

Кроме того, добавьте NSMutableArray *selectedItems где-то в файле .h.

- (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

В этом примере вы никогда не устанавливаете распознаватель.view.tag. Возможно, его нужно пересмотреть. –

+0

Вы правы. Теперь это исправлено. – suda

+2

У меня есть три сборщика, и мне нужен такой выбор для всего одного сборщика. Чему я должен вернуться для других сборщиков? – Mano

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

И вы должны переопределить этот метод, другие еще образуют ios9, водопроводная жест recognization не будет работать.

+0

, пожалуйста, используйте код (4 пробела) перед вашим примером кода, чтобы сделать свой ответ clearer –

2

Следующий код работает для iOS 10. У меня не было возможности проверить его на более старых версиях, но я думаю, что он должен работать. Идея похожа на @ suda's, но добавляет один распознаватель кран непосредственно в представление выбора, вместо добавления распознавателя кран в каждую строку, так как это не работает на iOS7 +.

Для краткости я не включил полную реализацию протоколов UIPickerViewDataSource и UIPickerViewDelegate, только соответствующие части для реализации множественного выбора.

// 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! большое спасибо человеку @Paglian! Ты спас мой день! Я думал о том, как отключить свитки при вызове reloadAllComponent в течение 5 часов! И вы спасете меня только с одной строкой кода !!!!!! – KTang