UIPickerView с многострочным UILabel

В настоящее время я работаю над программой, которая динамически заполняет представление выбора из моей настройки Core Data. У меня все работает с данными, но проблема, с которой я сталкиваюсь сейчас, - это форматирование моих этикеток.

Средство выбора представлено собственной панелью инструментов на листе действий с кнопкой в ​​правой части панели инструментов. В исходном состоянии видны 2 циферблата. когда кнопка нажата, она меняется на 3 циферблата.

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

    CGSize limitSize = CGSizeMake(100.0f, 45.0f);
    CGSize textSize;
    CGRect labelRect;
    NSString *title = @"";


    switch (numberOfComponents){
        case 2:
        {
            ...gets strings from fetched data (varying length from 4 to 20+)
                    title = someString
        }
        case 3:
        {
            ...same as above but for the second set of data.
                    title = someString
        }           
    }


    textSize = [title sizeWithFont:[UIFont systemFontOfSize:14] constrainedToSize:limitSize lineBreakMode:UILineBreakModeWordWrap];
    labelRect = CGRectMake(0, 0, textSize.width, textSize.height);
    NSLog(@"length:%i title:%@",[title length],title);
    NSLog(@"h:%f w:%f",textSize.height,textSize.width);
    if (pickerLabel == nil)
    {
        pickerLabel = [[[UILabel alloc] initWithFrame:labelRect] autorelease];
        [pickerLabel setFont:[UIFont systemFontOfSize:14]];
        [pickerLabel setBackgroundColor:[UIColor clearColor]];
        [pickerLabel setLineBreakMode:UILineBreakModeWordWrap];
        [pickerLabel setTextAlignment:UITextAlignmentCenter];
        [pickerLabel setNumberOfLines:2];
    }

    [pickerLabel setText:title];    

    return pickerLabel;
}

я вручную установил высоту строки на 32.0f. Я получаю очень странные результаты: некоторые метки во втором компоненте работают отлично. но другие вообще не переносятся, а некоторые просто отображаются как пустое место.

т.е. брюссельская капуста прекрасно обертывается (правый компонент). но молоко и сливки не отображаются (видно только молоко) овощи не отображаются вообще. Где я ошибаюсь в своем коде?


person koushi    schedule 08.12.2009    source источник
comment
Спасибо, это действительно помогло мне.   -  person Christopher Perry    schedule 19.05.2011


Ответы (3)


Мне удалось заставить его вести себя хорошо. Я изменил последнюю часть, удалив


textSize = [title sizeWithFont:[UIFont systemFontOfSize:14] constrainedToSize:limitSize lineBreakMode:UILineBreakModeWordWrap];

и я устанавливаю рамку вручную


labelRect = CGRectMake(0,0,100.0,36.0);

не уверен, почему это сработало, а динамический размер - нет.

person koushi    schedule 09.12.2009

Вот версия для быстрого.

 func pickerView(pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusingView view: UIView!) -> UIView {
    var label : UILabel
    if view == nil {
        label = UILabel(frame: CGRect(x: 0, y: 0, width: 0, height: UIFont.systemFontOfSize(UIFont.systemFontSize()).lineHeight * 2 * UIScreen.mainScreen().scale))
        label.textAlignment = NSTextAlignment.Center
        label.numberOfLines = 2
        label.lineBreakMode = NSLineBreakMode.ByWordWrapping
        label.autoresizingMask = UIViewAutoresizing.FlexibleWidth
    } else {
        label = view as UILabel
    }
    label.text = line1 + "\n" + line2

    return label;
}

func pickerView(pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat {
    return UIFont.systemFontOfSize(UIFont.systemFontSize()).lineHeight * 2 * UIScreen.mainScreen().scale
}
person Jochen Bedersdorfer    schedule 03.10.2014

Я исправил ваш код, чтобы ширина метки соответствовала ширине средства выбора. Я использовал подход коуши. Теперь это работает очень хорошо. См. мой код, добавленный здесь.

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

//assegna i nomi alle caselle del picker e assegna anche la dimensione del font e del rettangolo che contiene le scritte

UILabel *pickerLabel = (UILabel *)view;
CGRect labelRect;

NSString *title=@"";
switch (numberOfComponents){
case 2:
{
    ...gets strings from fetched data (varying length from 4 to 20+)
                title = someString
}
case 3:
{
    ...same as above but for the second set of data.
                title = someString
}           
 }

CGFloat labelWidth=pickerView.frame.size.width-50;
labelRect = CGRectMake( 0,0,labelWidth,45.0);

if (pickerLabel == nil)
{
    pickerLabel = [[UILabel alloc] initWithFrame:labelRect];
    [pickerLabel setFont:[UIFont systemFontOfSize:16]];
    [pickerLabel setBackgroundColor:[UIColor clearColor]];
    [pickerLabel setNumberOfLines:2];
}

[pickerLabel setText:title];    
return pickerLabel;

  }

О вашем исходном коде: я думаю, что иметь сборщик с элементами разного прямоугольного размера не очень хорошо для внешнего вида (взаимодействия с пользователем). Я подозреваю, что размер прямоугольника с разными метками создает проблему в вашем коде. Если текст, который вы хотите отобразить, может быть больше, чем определенный прямоугольник, я думаю, что вам следует использовать другой подход к структуре приложения.

ПРИМЕЧАНИЕ: в моем приложении я использую свойство тега выбора, чтобы определить, какой выборщик был выбран, потому что у меня есть более одного средства выбора в моем представлении. По этой причине я заменил оператор «переключатель» в вашем коде следующим кодом:

  if (pickerView.tag==1)
    title= globalSubcategoryArray[row];
  else
    title= globalAreasName[row];

и, очевидно, я также добавил:

 -(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
if (pickerView.tag==1)
    return globalSubcategoryArray.count;
else    
    return globalAreasName.count;
 }

 -(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return  1;
 }



 -(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
if (pickerView.tag==1){
    self.subcategoryTextview.text = globalSubcategoryArray[row];
    globalSelectedSubcategoryIndex=row;
    [self.subcategoryTextview resignFirstResponder];

}else{
    self.areaTextview.text= globalAreasName[row];
    globalSelectedAreaIndex=row;
    [self.areaTextview resignFirstResponder];
}

 }
person Gaucho    schedule 24.05.2015