Прокрутка, масштабирование UIScrollView и поворот ориентации интерфейса. Как использовать авторазмер и многое другое - PullRequest
4 голосов
/ 07 октября 2011

Это должно быть довольно распространенным делом, но я не смог заставить его работать точно.

У меня прямоугольный контент. Обычно он умещается в 320x361: портретный режим минус строка состояния минус ad минус панель вкладок.

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

Что мне нужно сделать в Интерфейсном Разработчике и коде, чтобы сделать это? Как мне установить авторейзинг для разных видов? Как мне установить contentSize и contentInsets?

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

То, как я это делаю сейчас, верно на 80%. То есть из 10 вещей, которые он должен делать, он делает 8 из них. Две вещи, которые он делает неправильно:

  1. При увеличении в портретном режиме вы можете прокрутить границы содержимого и увидеть черный фон. Это не так уж много, чтобы жаловаться. По крайней мере, вы можете увидеть весь контент. В альбомном режиме, увеличенном или уменьшенном, черный фон за краем виден нормально, поскольку контент не имеет достаточной ширины, чтобы заполнить экран при уровне масштабирования 1: 1 (минимум).

  2. Я все еще получаю контент, застрявший на краю, когда он запускается на тестовом устройстве под управлением iOS 3.0, но он работает на моем, работающем под управлением 4.x. - На самом деле это было с предыдущим решением. Мой тестер не пробовал последнее решение.

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

Просмотр иерархии:

  • вид
    • Scrollview
      • scrollableArea
        • содержание
    • Объявление

Представление имеет размер 320x411 и имеет все параметры автоматического изменения размера, поэтому соответствует форме экрана

scrollView имеет значение 480 x 361, начинается с начала координат -80,0, блокируется только сверху и отключает растяжение

scrollableArea - 480 x 361 и фиксируется слева и сверху. Поскольку scrollView отключает растяжение, маски авторазмера для его подпредставлений не имеют значения, но я все равно говорю вам.

содержимое имеет размер 320x361, начинается с начала 80,0 и фиксируется наверху

Я устанавливаю scrollView.contentSize на 480x361.

shouldAutorotateToInterfaceOrientation поддерживает все ориентации, кроме портрета вверх ногами.

В didRotateFromInterfaceOrientation я устанавливаю нижнюю вставку содержимого 160, если ориентация горизонтальная, и сбрасываю на 0, если нет. Я устанавливаю левый и правый индикатор вставки по 80 каждый, если ориентация портретная, сбрасываю, если нет.

scrollView.minimumZoomScale = 1.0

scrollView.maximumZoomScale = 2.0

viewForZoomingInScrollView возвращает прокручиваемую область

Ответы [ 4 ]

4 голосов
/ 13 октября 2011
// in IB it would be all options activated
scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
scrollView.contentSize = content.frame.size; // or bounds, try both

что вы имеете в виду под scrollableArea?

ваш minZoomScale установлен на 1.0, что хорошо для портретного режима, но не для ландшафтного. Поскольку в альбомной ориентации ваш рост меньше, чем в портретной, вам нужно иметь значение меньше 1.0. Для меня я использую эту реализацию и вызываю ее каждый раз, кадр scrollView менялся:

- (void)setMaxMinZoomScalesForCurrentBounds {
    CGSize boundsSize = self.bounds.size; // self is a UIScrollView here
    CGSize contentSize = content.bounds.size;

    CGFloat xScale = boundsSize.width / contentSize.width;
    CGFloat yScale = boundsSize.height / contentSize.height;
    CGFloat minScale = MIN(xScale, yScale);

    if (self.zoomScale < minScale) {
        [self setZoomScale:minScale animated:NO];
    }
    if (minScale<self.maximumZoomScale) self.minimumZoomScale = minScale;
    //[self setZoomScale:minScale animated:YES];
}

- (void)setFrame:(CGRect)rect { // again, this class is a UIScrollView
    [super setFrame:rect];
    [self setMaxMinZoomScalesForCurrentBounds];
}
0 голосов
/ 19 октября 2011

Если вы хотите поместить контент (экземпляр UIView, давайте назовем его theViewInstance) в UIScrollView, а затем прокрутить / увеличить theViewInstance, способ сделать это:

  • theViewInstance следует добавить в качестве подпредставления UIScrollView
  • , установить делегата для UIScrollView instance и реализовать селектор для возвратапредставление, которое следует использовать для масштабирования / прокрутки:

    -(UIView*)viewForZoomingInScrollView:(UIScrollView *)scrollView {  
          return theViewInstance;  
    } 
    
  • Установите для contentSize UIScrollView фрейм theViewInstance по умолчанию:

    scrollView.contentSize=theViewInstance.frame.size;
    

    ( Кроме того, в UIScrollView можно установить допустимые уровни масштабирования: )

    scrollView.minimumZoomScale=1.0;
    scrollView.maximumZoomScale=3.0;
    

Это способ увеличения изображения в UIImage: aUIImageView добавляется в UIScrollView, а в реализации UIScrollViewDelegate возвращается UIImageView (как описано, например, здесь ).

Для поддержки вращения это делается в UIViewController, UIView которого содержитUIScrollView, о котором мы только что говорили.

0 голосов
/ 17 октября 2011

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

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

Я оставил немного белой области для баров / пользовательских панелей.

- (void)viewDidLoad
{  
    [super viewDidLoad];

    //first inits and allocs
    scrollView2 = [[UIScrollView alloc] initWithFrame:self.view.frame];
    imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"someImageName"]];
    [scrollView2 addSubview:imageView];
    [self drawContent]; //refreshing the content
    [self.view addSubview:scrollView2];
}

-(void)drawContent
{
    //this refreshes the screen to the right sizes and zoomscales.
    [scrollView2 setBackgroundColor:[UIColor blackColor]];
    [scrollView2 setCanCancelContentTouches:NO];
    scrollView2.clipsToBounds = YES;
    [scrollView2 setDelegate:self];
    scrollView2.indicatorStyle = UIScrollViewIndicatorStyleWhite;

    [scrollView2 setContentSize:CGSizeMake(imageView.frame.size.width, imageView.frame.size.height)];
    [scrollView2 setScrollEnabled:YES];

    float minZoomScale;
    float zoomHeight = imageView.frame.size.height / scrollView2.frame.size.height;
    float zoomWidth = imageView.frame.size.width / scrollView2.frame.size.width;

    if(zoomWidth > zoomHeight)
    {
        minZoomScale = 1.0 / zoomWidth;
    }
    else
    {
        minZoomScale = 1.0 / zoomHeight;
    }

    [scrollView2 setMinimumZoomScale:minZoomScale];
    [scrollView2 setMaximumZoomScale:7.5];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations

    if (interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown) {

        // Portrait 
        //the 88pxls is the white area that is left for the navbar etc.

        self.scrollView2.frame = CGRectMake(0, 88, [UIScreen mainScreen].bounds.size.width, self.view.frame.size.height - 88);
        [self drawContent];
    }
    else {

        // Landscape
        //the 88pxls is the white area that is left for the navbar etc.

        self.scrollView2.frame = CGRectMake(0, 88, [UIScreen mainScreen].bounds.size.height, self.view.frame.size.width);
        [self drawContent];
    }
    return YES;
}

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
    return self.imageView;
}

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

0 голосов
/ 07 октября 2011

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

Насколько я знаю (и работал с UIScrollView), контент внутри UIScrollViewавтоматически не изменяет размер вместе с UIScrollView.

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

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

Для правильного автоматического изменения размера вы должны изменить contentSize для scrollView (чтобы он знал размер вашей вселенной), а также изменить размер UIView.Я думаю, именно поэтому вы смогли прокрутить и получить этот черный контент.Может быть, вы только что обновили contentSize, но теперь просматриваете содержимое на самом деле.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...