Как изменить высоту UIPickerView

Можно ли изменить высоту UIPickerView? Некоторые приложения, кажется, имеют более короткие PickerViews, но установка меньшего фрейма, кажется, не работает, и фрейм заблокирован в Интерфейсном Разработчике.

28 ответов

Решение

Кажется очевидным, что Apple не особо приглашает к гадости с высотой по умолчанию UIPickerView, но я обнаружил, что вы можете добиться изменения высоты просмотра, взяв полный контроль и передавая желаемый размер кадра во время создания, например:

smallerPicker = [[UIPickerView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 120.0)];

Вы обнаружите, что на разной высоте и ширине, есть визуальные глюки. Очевидно, что эти глюки нужно было бы как-то обойти, или выбрать другой размер, который их не демонстрирует.

Ни один из вышеперечисленных подходов не работает в iOS 4.0

Высота pickerView больше не может быть изменена. Существует сообщение, которое выводится на консоль, если вы пытаетесь изменить кадр средства выбора в 4.0:

-[UIPickerView setFrame:]: invalid height value 66.0 pinned to 162.0 

В итоге я сделал нечто радикальное, чтобы получить эффект меньшего средства выбора, которое работает как в OS 3.xx, так и в OS 4.0. Я оставил средство выбора того размера, который, по мнению SDK, должно быть, и вместо этого сделал прозрачное окно на моем фоновом изображении, через которое средство выбора становится видимым. Затем просто поместите средство выбора позади (Z Order wise) моего фона UIImageView, чтобы была видна только часть средства выбора, что определяется прозрачным окном на моем фоне.

Есть только три допустимых высоты для UIPickerView (162.0, 180.0 and 216.0),

Вы можете использовать CGAffineTransformMakeTranslation а также CGAffineTransformMakeScale функции, чтобы правильно подобрать подборщик для вашего удобства.

Пример:

CGAffineTransform t0 = CGAffineTransformMakeTranslation (0, pickerview.bounds.size.height/2);
CGAffineTransform s0 = CGAffineTransformMakeScale       (1.0, 0.5);
CGAffineTransform t1 = CGAffineTransformMakeTranslation (0, -pickerview.bounds.size.height/2);
pickerview.transform = CGAffineTransformConcat          (t0, CGAffineTransformConcat(s0, t1));

Приведенный выше код изменяет высоту окна выбора на половину и перемещает его в точное положение (Left-x1, Top-y1).

Пытаться:

pickerview.transform = CGAffineTransformMakeScale(.5, 0.5);

В iOS 4.2 и 4.3 работает следующее:

UIDatePicker *datePicker = [[UIDatePicker alloc] init];
datePicker.frame = CGRectMake(0, 0, 320, 180);
[self addSubview:datePicker];

Следующее не работает:

UIDatePicker *datePicker = [[UIDatePicker alloc] initWithFrame:CGRectMake(0, 0, 320, 180)];
[self addSubview:datePicker];

У меня есть приложение, которое находится в магазине приложений с 3-строчной системой выбора даты. Я думал, что изменение высоты, возможно, было предотвращено, потому что вы видите текст под рамкой выбора даты, но это происходит и с обычным выбором даты 216 высоты.

Какая ошибка? Твоя догадка так же хороша как и моя.

Также есть 3 действительных высоты для UIDatePicker (а также UIPickerView) 162,0, 180,0 и 216,0. Если вы установите UIPickerView Высота до всего остального вы увидите в консоли при отладке на устройстве iOS.

2011-09-14 10:06:56.180 DebugHarness[1717:707] -[UIPickerView setFrame:]: invalid height value 300.0 pinned to 216.0

Начиная с iOS 9, вы можете свободно менять UIPickerViewширина и высота. Нет необходимости использовать вышеупомянутые хаки преобразования.

Я обнаружил, что вы можете редактировать размер UIPickerView - только не с помощью конструктора интерфейса. откройте файл.xib с помощью текстового редактора и установите размер представления выбора на все, что вы хотите. Конструктор интерфейса не сбрасывает размер и, похоже, работает. Я уверен, что яблоко заблокировало размер по причине, поэтому вам придется экспериментировать с разными размерами, чтобы увидеть, что работает.

Преимущества:

  1. Делает набор кадра UIPickerView вести себя как следует
  2. Нет кода трансформации в вашем UIViewController
  3. Работает в viewWillLayoutSubviews изменить масштаб / положение UIPickerView
  4. Работает на iPad без UIPopover
  5. Суперкласс всегда получает действительную высоту
  6. Работает с iOS 5

Недостатки:

  1. Требует от вас подкласса UIPickerView
  2. Требует использования pickerView viewForRow отменить преобразование для подвидов
  3. UIAnimations может не работать

Решение:

Подкласс UIPickerView и перезаписать два метода, используя следующий код. Он сочетает в себе подклассы, фиксированную высоту и подход преобразования.

#define FIXED_PICKER_HEIGHT 216.0f
- (void) setFrame:(CGRect)frame
{
    CGFloat targetHeight = frame.size.height;
    CGFloat scaleFactor = targetHeight / FIXED_PICKER_HEIGHT;
    frame.size.height = FIXED_PICKER_HEIGHT;//fake normal conditions for super
    self.transform = CGAffineTransformIdentity;//fake normal conditions for super
    [super setFrame:frame];
    frame.size.height = targetHeight;
    CGFloat dX=self.bounds.size.width/2, dY=self.bounds.size.height/2;
    self.transform = CGAffineTransformTranslate(CGAffineTransformScale(CGAffineTransformMakeTranslation(-dX, -dY), 1, scaleFactor), dX, dY);
}

- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
{
    //Your code goes here

    CGFloat inverseScaleFactor = FIXED_PICKER_HEIGHT/self.frame.size.height;
    CGAffineTransform scale = CGAffineTransformMakeScale(1, inverseScaleFactor);
    view.transform = scale;
    return view;
}

Простой способ изменить видимую высоту представления средства выбора - встроить средство выбора в UIView, отрегулировать высоту родительского представления в соответствии с высотой, которую вы хотите видеть из средства выбора, а затем включить "Подвиды клипа" в Интерфейсном Разработчике в родительском UIView. или установить view.clipsToBounds = true в коде.

Клип подпредставлений в IB

Это сильно изменилось в iOS 9 (в iOS 8 это очень похоже на то, что мы видим здесь). Если вы можете позволить себе только iOS 9, измените размер UIPickerView как считаете нужным, установив его рамку. Хорошо!

Вот это из iOS 9 Примечания к выпуску

Размеры UIPickerView и UIDatePicker теперь можно изменять и адаптировать. Ранее эти представления применяли размер по умолчанию, даже если вы пытались изменить их размер. Эти представления также теперь по умолчанию имеют ширину 320 точек на всех устройствах, а не ширину устройства на iPhone.

Интерфейсы, которые полагаются на старое применение размера по умолчанию, скорее всего, будут выглядеть неправильно при компиляции для iOS 9. Любые возникшие проблемы могут быть решены путем полного ограничения или изменения размера представления выбора до желаемого размера вместо использования неявного поведения.

Я не смог последовать ни одному из вышеперечисленных советов.

Я посмотрел несколько учебных пособий и нашел это наиболее полезным:

Я добавил следующий код, чтобы установить новую высоту внутри метода viewDidLoad, который работал в моем приложении.

UIPickerView *picker = [[UIPickerView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 120.0)]; 
[self.view addSubview:picker];
picker.delegate = self;
picker.dataSource = self;

Надеюсь, это было полезно!

Создайте представление в IB или коде. Добавьте свой подборщик как подпредставление этого представления. Измените размер представления. Это проще всего сделать в IB. Создайте ограничения от представления к его суперпредставлению и от средства выбора до этого нового представления.

Так как сборщик изгибается вокруг него, он выливается сверху и снизу от вида. Вы можете видеть в IB, когда вы добавляете верхние и нижние ограничения из средства выбора к представлению, оно показывает стандартное пространство, примерно 16 точек выше и ниже контейнера суперпредставления. Установите вид, чтобы обрезать его, если вы не хотите этого поведения (ужасное предупреждение).

Вот как это выглядит на 96 баллов на iPhone 5. Сборщик с побочным эффектом составляет около 130 баллов. Довольно тощий!

Я использую это в своем проекте, чтобы предотвратить распространение сборщика на ненужную высоту. Эта техника урезает его и вызывает более плотный разлив. На самом деле это выглядит более компактно.

Вот изображение вида, показывающего побочный эффект.

Вот ограничения IB, которые я добавил.

Как уже упоминалось выше UIPickerView теперь можно изменить размер. Я просто хочу добавить, что если вы хотите изменить высоту pickerView в ячейке tableView, у меня не получится установить постоянную высоту привязки высоты. Однако, используя lessThanOrEqualToConstant похоже на работу.

 class PickerViewCell: UITableViewCell {

    let pickerView = UIPickerView()

    func setup() {

        // call this from however you initialize your cell

        self.contentView.addSubview(self.pickerView)
        self.pickerView.translatesAutoresizingMaskIntoConstraints = false

        let constraints: [NSLayoutConstraint] = [
            // pin the pickerView to the contentView's layoutMarginsGuide

            self.pickerView.leadingAnchor.constraint(equalTo: self.contentView.layoutMarginsGuide.leadingAnchor),
            self.pickerView.topAnchor.constraint(equalTo: self.contentView.layoutMarginsGuide.topAnchor),
            self.pickerView.trailingAnchor.constraint(equalTo: self.contentView.layoutMarginsGuide.trailingAnchor),
            self.pickerView.bottomAnchor.constraint(equalTo: self.contentView.layoutMarginsGuide.bottomAnchor),

            // set the height using lessThanOrEqualToConstant
            self.pickerView.heightAnchor.constraint(lessThanOrEqualToConstant: 100)
        ]

        NSLayoutConstraint.activate(constraints)
     }

 }

Я работаю с ios 7, Xcode 5. Мне удалось косвенно отрегулировать высоту выбора даты, заключив его в представление. Высота просмотра контейнеров может быть скорректирована.

Хорошо, после долгой борьбы с дурацким средством выбора в iOS 4 я решил изменить свой элемент управления на простую таблицу: вот код:

ComboBoxView.m = which is actually looks more like pickerview.

//
//  ComboBoxView.m
//  iTrophy
//
//  Created by Gal Blank on 8/18/10.
//

#import "ComboBoxView.h"
#import "AwardsStruct.h"


@implementation ComboBoxView

@synthesize displayedObjects;

#pragma mark -
#pragma mark Initialization

/*
- (id)initWithStyle:(UITableViewStyle)style {
    // Override initWithStyle: if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
    if ((self = [super initWithStyle:style])) {
    }
    return self;
}
*/


#pragma mark -
#pragma mark View lifecycle

/*
- (void)viewDidLoad {
    [super viewDidLoad];

    // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
    // self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
*/

/*
- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
}
*/
/*
- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
}
*/
/*
- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
}
*/
/*
- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];
}
*/
/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/


#pragma mark -
#pragma mark Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    // Return the number of sections.
    return 1;
}


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    // Return the number of rows in the section.
    self.tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
    return [[self displayedObjects] count];
}


// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {


    NSString *MyIdentifier = [NSString stringWithFormat:@"MyIdentifier %i", indexPath.row];

    UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:MyIdentifier];

    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:MyIdentifier] autorelease];
        //cell.contentView.frame = CGRectMake(0, 0, 230.0,16);
        UILabel *label = [[[UILabel alloc] initWithFrame:CGRectMake(0, 5, 230.0,19)] autorelease];
        VivatAwardsStruct *vType = [displayedObjects objectAtIndex:indexPath.row];
        NSString *section = [vType awardType]; 
        label.tag = 1;
        label.font = [UIFont systemFontOfSize:17.0];
        label.text = section;
        label.textAlignment = UITextAlignmentCenter;
        label.baselineAdjustment = UIBaselineAdjustmentAlignCenters;
        label.adjustsFontSizeToFitWidth=YES;
        label.textColor = [UIColor blackColor];
        //label.autoresizingMask = UIViewAutoresizingFlexibleHeight;
        [cell.contentView addSubview:label]; 
        //UIImage *image = nil;
        label.backgroundColor = [UIColor whiteColor];
        //image = [awards awardImage];
        //image = [image imageScaledToSize:CGSizeMake(32.0, 32.0)];

        //[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
        //UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
        //cell.accessoryView = imageView;
        //[imageView release];
    }

    return cell;
}


/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
    // Return NO if you do not want the specified item to be editable.
    return YES;
}
*/


/*
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {

    if (editingStyle == UITableViewCellEditingStyleDelete) {
        // Delete the row from the data source
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES];
    }   
    else if (editingStyle == UITableViewCellEditingStyleInsert) {
        // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
    }   
}
*/


/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
}
*/


/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
    // Return NO if you do not want the item to be re-orderable.
    return YES;
}
*/


#pragma mark -
#pragma mark Table view delegate

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    // Navigation logic may go here. Create and push another view controller.
    /*
     <#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:@"<#Nib name#>" bundle:nil];
     // ...
     // Pass the selected object to the new view controller.
     [self.navigationController pushViewController:detailViewController animated:YES];
     [detailViewController release];
     */
}


#pragma mark -
#pragma mark Memory management

- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Relinquish ownership any cached data, images, etc that aren't in use.
}

- (void)viewDidUnload {
    // Relinquish ownership of anything that can be recreated in viewDidLoad or on demand.
    // For example: self.myOutlet = nil;
}


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


@end

Вот файл.h для этого:

//
//  ComboBoxView.h
//  iTrophy
//
//  Created by Gal Blank on 8/18/10.
//

#import <UIKit/UIKit.h>


@interface ComboBoxView : UITableViewController {
    NSMutableArray *displayedObjects;
}

@property (nonatomic, retain) NSMutableArray *displayedObjects;


@end

now, in the ViewController where I had Apple UIPickerView I replaced with my own ComboBox view and made it size what ever I wish.

ComboBoxView *mypickerholder = [[ComboBoxView alloc] init]; 
[mypickerholder.view setFrame:CGRectMake(50, 220, 230, 80)];
[mypickerholder setDisplayedObjects:awardTypesArray];

вот и все, теперь осталось только создать переменную-член в представлении комбинированного списка, которая будет содержать текущий выбор строки, и мы готовы идти дальше.

Наслаждайтесь всеми.

Обычно вы не можете сделать это в xib или установить фрейм программно, но если вы откроете его родительский xib в качестве источника и измените высоту оттуда, то это сработает. Щелкните правой кнопкой мыши на xib, внутри которого содержится представление выбора, выберите Поиск выбора, и вы сможете найти высоту, ширину и т. Д. в этом теге измените высоту и сохраните файл.

<pickerView contentMode="scaleToFill" id="pai-pm-hjZ">
                                    <rect key="frame" x="0.0" y="41" width="320" height="100"/>
                                    <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
                                    <connections>
                                        <outlet property="dataSource" destination="-1" id="Mo2-zp-Sl4"/>
                                        <outlet property="delegate" destination="-1" id="nfW-lU-tsU"/>
                                    </connections>
                                </pickerView>

Даже при том, что это не изменение размера, другой трюк может помочь в ситуации, когда UIPicker расположен в нижней части экрана.

Можно попытаться переместить его немного вниз, но центральный ряд должен оставаться видимым. Это поможет выявить некоторое пространство над подборщиком, так как нижние ряды будут за кадром.

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

Мой трюк: используйте слой маски datepicker, чтобы сделать datePicker какой-то частью видимой. как вы видите, как изменить рамку DatePick.

- (void)timeSelect:(UIButton *)timeButton {
UIDatePicker *timePicker = [[UIDatePicker alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, 550)];
timePicker.backgroundColor = [UIColor whiteColor];
timePicker.layer.mask = [self maskLayerWithDatePicker:timePicker];
timePicker.layer.masksToBounds = YES;
timePicker.datePickerMode = UIDatePickerModeTime;
[self.view addSubview:timePicker];
}

- (CALayer *)maskLayerWithDatePicker:(UIDatePicker *)datePicker {
CAShapeLayer *shapeLayer = [[CAShapeLayer alloc] init];
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, datePicker.width*0.8, datePicker.height*0.8) cornerRadius:10];
shapeLayer.path = path.CGPath;
return shapeLayer;
}

Swift: вам нужно добавить подпредставление с клипом к границам

    var DateView = UIView(frame: CGRectMake(0, 0, view.frame.width, 100))
    DateView.layer.borderWidth=1
    DateView.clipsToBounds = true

    var myDatepicker = UIDatePicker(frame:CGRectMake(0,-20,view.frame.width,162));
    DateView.addSubview(myDatepicker);
    self.view.addSubview(DateView)

Это должно добавить ограниченный выбор даты 100 высот в верхней части контроллера представления.

Посмотрите мой ответ на этот вопрос: Размеры UIPicker в ландшафтном режиме

Вставить в виде стека. Представление стека - это компонент, недавно добавленный Apple в их iOS SDK, чтобы отразить реализации на основе сетки в библиотеках внешнего интерфейса java-скриптов, таких как начальная загрузка.

Насколько я знаю, невозможно сжать UIPickerView. Я также фактически не видел более короткий, используемый где-нибудь. Я предполагаю, что это была пользовательская реализация, если им удавалось уменьшить ее.

Я использую слой маски, чтобы изменить его размер дисплея

// swift 3.x
let layer = CALayer()
layer.frame = CGRect(x: 0,y:0, width: displayWidth, height: displayHeight)
layer.backgroundColor = UIColor.red.cgColor
pickerView.layer.mask = layer

Если вы хотите создать свой сборщик в IB, вы можете изменить его размер до меньшего размера. Убедитесь, что он по-прежнему правильно рисует, поскольку наступает момент, когда он выглядит отвратительно.

После долгого дня, почесав голову, я нашел то, что мне подходит. Приведенные ниже коды воссоздают UIDatePicker каждый раз, когда пользователь меняет ориентацию телефона. Это удалит все глюки, которые есть у UIDatePicker после изменения ориентации.

Поскольку мы воссоздаем UIDatePicker, нам нужна переменная экземпляра, в которой будет сохранено выбранное значение даты. Коды ниже тестируются на iOS 4.0.

    @interface AdvanceDateViewController : UIViewController<UIPickerViewDelegate> {
        UIDatePicker *datePicker;
        NSDate *date;
    }


    @property (nonatomic, retain) UIDatePicker *datePicker;
    @property (nonatomic, retain) NSDate *date;

    -(void)resizeViewWithOrientation:(UIInterfaceOrientation) orientation;

    @end

    @implementation AdvanceDateViewController
    @synthesize datePicker, date;

    - (void)viewDidLoad {
      [super viewDidLoad];
          [self resizeViewWithOrientation:self.interfaceOrientation];
    }


    -(void)viewWillAppear:(BOOL)animated{
         [super viewWillAppear:animated];
         [self resizeViewWithOrientation:self.interfaceOrientation];
     }

     - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
         return YES;
     }

     -(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
      [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
      [self resizeViewWithOrientation:toInterfaceOrientation];
      }

     -(void)resizeViewWithOrientation:(UIInterfaceOrientation) orientation{
          [self.datePicker removeFromSuperview];
          [self.datePicker removeTarget:self action:@selector(refreshPickupDate) forControlEvents:UIControlEventValueChanged];
          self.datePicker = nil;

          //(Re)initialize the datepicker, thanks to Apple's buggy UIDatePicker implementation
          UIDatePicker *dummyDatePicker = [[UIDatePicker alloc] init];
          self.datePicker = dummyDatePicker;
          [dummyDatePicker release];

          [self.datePicker setDate:self.date animated:YES];
          [self.datePicker addTarget:self action:@selector(refreshPickupDate) forControlEvents:UIControlEventValueChanged];

          if(UIInterfaceOrientationIsLandscape(orientation)){
                 self.datePicker.frame = CGRectMake(0, 118, 480, 162);    
           } else {
                 self.datePicker.frame = CGRectMake(0, 200, 320, 216);
           }

           [self.view addSubview:self.datePicker];
           [self.view setNeedsDisplay];
      }

      @end

Для iOS 5:

если вы быстро посмотрите на ссылку на протокол UIPickerView

ты найдешь

– pickerView:rowHeightForComponent:
– pickerView:widthForComponent:

Я думаю, это первое, что вы ищете

stockPicker = [[UIPickerView alloc] init];
stockPicker.frame = CGRectMake(70.0,155, 180,100);

Если вы хотите установить размер UiPickerView. Над кодом наверняка сработает.

В iOS 5.0 я получил следующее для работы:

UIDatePicker *picker = [[UIDatePicker alloc] init];
picker.frame = CGRectMake(0.0, 0.0, 320.0, 160.0);

Это создало средство выбора даты, аналогичное тому, которое Apple использует в приложении "Календарь" при создании нового события в альбомном режиме. (3 строки выше, чем 5.) Это не сработало, когда я установил рамку внутри initWithFrame: метод, но пока работает при настройке его с помощью отдельного метода.

Другие вопросы по тегам