Центральное содержание UIScrollView, когда меньший

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

136
задан Pang 28 March 2018 в 00:36
поделиться

10 ответов

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

1
ответ дан 23 November 2019 в 23:37
поделиться

Я сделал это так, чтобы добавить дополнительное представление в иерархию:

UIScrollView -> UIView -> UIImageView

Дайте вашему UIView такое же соотношение сторон, что и у вашего UIScrollView и поместите в него свой UIImageView .

1
ответ дан 23 November 2019 в 23:37
поделиться

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

Вот код:

- (void) scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale {

CGSize screenSize = [[self view] bounds].size;

if (myScrollView.zoomScale <= initialZoom +0.01) //This resolves a problem with the code not working correctly when zooming all the way out.
{
    imageView.frame = [[self view] bounds];
    [myScrollView setZoomScale:myScrollView.zoomScale +0.01];
}

if (myScrollView.zoomScale > initialZoom)
{
    if (CGImageGetWidth(temporaryImage.CGImage) > CGImageGetHeight(temporaryImage.CGImage)) //If the image is wider than tall, do the following...
    {
        if (screenSize.height >= CGImageGetHeight(temporaryImage.CGImage) * [myScrollView zoomScale]) //If the height of the screen is greater than the zoomed height of the image do the following...
        {
            imageView.frame = CGRectMake(0, 0, 320*(myScrollView.zoomScale), 368);
        }
        if (screenSize.height < CGImageGetHeight(temporaryImage.CGImage) * [myScrollView zoomScale]) //If the height of the screen is less than the zoomed height of the image do the following...
        {
            imageView.frame = CGRectMake(0, 0, 320*(myScrollView.zoomScale), CGImageGetHeight(temporaryImage.CGImage) * [myScrollView zoomScale]);
        }
    }
    if (CGImageGetWidth(temporaryImage.CGImage) < CGImageGetHeight(temporaryImage.CGImage)) //If the image is taller than wide, do the following...
    {
        CGFloat portraitHeight;
        if (CGImageGetHeight(temporaryImage.CGImage) * [myScrollView zoomScale] < 368)
        { portraitHeight = 368;}
        else {portraitHeight = CGImageGetHeight(temporaryImage.CGImage) * [myScrollView zoomScale];}

        if (screenSize.width >= CGImageGetWidth(temporaryImage.CGImage) * [myScrollView zoomScale]) //If the width of the screen is greater than the zoomed width of the image do the following...
        {
            imageView.frame = CGRectMake(0, 0, 320, portraitHeight);
        }
        if (screenSize.width < CGImageGetWidth (temporaryImage.CGImage) * [myScrollView zoomScale]) //If the width of the screen is less than the zoomed width of the image do the following...
        {
            imageView.frame = CGRectMake(0, 0, CGImageGetWidth(temporaryImage.CGImage) * [myScrollView zoomScale], portraitHeight);
        }
    }
    [myScrollView setZoomScale:myScrollView.zoomScale -0.01];
}
0
ответ дан 23 November 2019 в 23:37
поделиться

One elegant way to center the content of UISCrollView is this.

Add one observer to the contentSize of your UIScrollView, so this method will be called everytime the content change...

[myScrollView addObserver:delegate 
               forKeyPath:@"contentSize"
                  options:(NSKeyValueObservingOptionNew) 
                  context:NULL];

Now on your observer method:

- (void)observeValueForKeyPath:(NSString *)keyPath   ofObject:(id)object   change:(NSDictionary *)change   context:(void *)context { 

    // Correct Object Class.
    UIScrollView *pointer = object;

    // Calculate Center.
    CGFloat topCorrect = ([pointer bounds].size.height - [pointer viewWithTag:100].bounds.size.height * [pointer zoomScale])  / 2.0 ;
            topCorrect = ( topCorrect < 0.0 ? 0.0 : topCorrect );

    topCorrect = topCorrect - (  pointer.frame.origin.y - imageGallery.frame.origin.y );

    // Apply Correct Center.
    pointer.center = CGPointMake(pointer.center.x,
                                 pointer.center.y + topCorrect ); }
  • You should change the [pointer viewWithTag:100]. Replace by your представление содержимого UIView .

    • Также измените imageGallery , указывающий на размер вашего окна.

Это исправит центр содержимого каждый раз, когда его размер изменится.

ПРИМЕЧАНИЕ: Этот контент работает не очень хорошо, только если используются стандартные функции масштабирования UIScrollView .

1
ответ дан 23 November 2019 в 23:37
поделиться

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

 myScrollView.bouncesZoom = YES; 

чтобы исправить проблему с видом не по центру, когда на minZoomScale.

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGSize screenSize = [[self view] bounds].size;//[[UIScreen mainScreen] bounds].size;//
CGSize photoSize = [yourImage size];
CGFloat topInset = (screenSize.height - photoSize.height * [myScrollView zoomScale]) / 2.0;
CGFloat sideInset = (screenSize.width - photoSize.width * [myScrollView zoomScale]) / 2.0;

if (topInset < 0.0)
{ topInset = 0.0; }
if (sideInset < 0.0)
{ sideInset = 0.0; } 
[myScrollView setContentInset:UIEdgeInsetsMake(topInset, sideInset, -topInset, -sideInset)];
ApplicationDelegate *appDelegate = (ApplicationDelegate *)[[UIApplication sharedApplication] delegate];

CGFloat scrollViewHeight; //Used later to calculate the height of the scrollView
if (appDelegate.navigationController.navigationBar.hidden == YES) //If the NavBar is Hidden, set scrollViewHeight to 480
{ scrollViewHeight = 480; }
if (appDelegate.navigationController.navigationBar.hidden == NO) //If the NavBar not Hidden, set scrollViewHeight to 360
{ scrollViewHeight = 368; }

imageView.frame = CGRectMake(0, 0, CGImageGetWidth(yourImage)* [myScrollView zoomScale], CGImageGetHeight(yourImage)* [myScrollView zoomScale]);

[imageView setContentMode:UIViewContentModeCenter];
}

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

- (void) scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale {
myScrollView.frame = CGRectMake(0, 0, 320, 420);
 //put the correct parameters for your scroll view width and height above
}
0
ответ дан 23 November 2019 в 23:37
поделиться

Хорошо, это решение работает для меня. У меня есть подкласс UIScrollView со ссылкой на UIImageView, который он отображает. Каждый раз, когда UIScrollView увеличивает масштаб, свойство contentSize изменяется. Именно в сеттере я соответствующим образом масштабирую UIImageView, а также регулирую его центральное положение.

-(void) setContentSize:(CGSize) size{
CGSize lSelfSize = self.frame.size;
CGPoint mid;
if(self.zoomScale >= self.minimumZoomScale){
    CGSize lImageSize = cachedImageView.initialSize;
    float newHeight = lImageSize.height * self.zoomScale;

    if (newHeight < lSelfSize.height ) {
        newHeight = lSelfSize.height;
    }
    size.height = newHeight;

    float newWidth = lImageSize.width * self.zoomScale;
    if (newWidth < lSelfSize.width ) {
        newWidth = lSelfSize.width;
    }
    size.width = newWidth;
    mid = CGPointMake(size.width/2, size.height/2);

}
else {
    mid = CGPointMake(lSelfSize.width/2, lSelfSize.height/2);
}

cachedImageView.center = mid;
[super  setContentSize:size];
[self printLocations];
NSLog(@"zoom %f setting size %f x %f",self.zoomScale,size.width,size.height);
}

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

-(void) resetSize{
    if (!scrollView){//scroll view is view containing imageview
        return;
    }

    CGSize lSize = scrollView.frame.size;

    CGSize lSelfSize = self.image.size; 
    float lWidth = lSize.width/lSelfSize.width;
    float lHeight = lSize.height/lSelfSize.height;

    // choose minimum scale so image width fits screen
    float factor  = (lWidth<lHeight)?lWidth:lHeight;

    initialSize.height = lSelfSize.height  * factor;
    initialSize.width = lSelfSize.width  * factor;

    [scrollView setContentSize:lSize];
    [scrollView setContentOffset:CGPointZero];
    scrollView.userInteractionEnabled = YES;
}

С помощью этих двух методов я могу получить представление, которое ведет себя так же, как приложение "Фотографии".

2
ответ дан 23 November 2019 в 23:37
поделиться

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

Я в основном прошел через то, что есть у всех: поискал в StackOverflow, форумах разработчиков Apple, просмотрел код для three20, ScrollingMadness, ScrollTestSuite и т.д. / или вставки из ViewController и т. д., но ничего не работало отлично (как и все остальные).

Выспавшись на нем, я попробовал несколько альтернативных ракурсов:

  1. Создание подкласса для UIImageView, чтобы он динамически изменял свой размер - это совсем не сработало.
  2. Создание подкласса UIScrollView для динамического изменения собственного contentOffset - это тот вариант, который мне кажется победителем.

С помощью этого подкласса метода UIScrollView я переопределяю мутатор contentOffset, поэтому он не устанавливает {0,0}, когда изображение масштабируется меньше, чем область просмотра - вместо этого он устанавливает смещение таким образом, чтобы изображение оставалось центрированным в область просмотра. Пока вроде всегда работает. Я проверил это с широкими, высокими, крошечными и большими изображениями, и у меня нет проблемы «работает, но ущипнуть при минимальном увеличении не удается».

Я загрузил на github пример проекта, который использует это решение, вы можете найти его здесь: http://github.com/nyoron/NYOBetterZoom

25
ответ дан 23 November 2019 в 23:37
поделиться

У меня очень простое решение! Все, что вам нужно, это обновить центр вашего подпредставления (изображения) при масштабировании ScrollViewDelegate. Если увеличенное изображение меньше, чем scrollview, отрегулируйте subview. Center else center равно (0,0).

- (void)scrollViewDidZoom:(UIScrollView *)scrollView 
{
    UIView *subView = [scrollView.subviews objectAtIndex:0];

    CGFloat offsetX = MAX((scrollView.bounds.size.width - scrollView.contentSize.width) * 0.5, 0.0);
    CGFloat offsetY = MAX((scrollView.bounds.size.height - scrollView.contentSize.height) * 0.5, 0.0);

    subView.center = CGPointMake(scrollView.contentSize.width * 0.5 + offsetX, 
                                 scrollView.contentSize.height * 0.5 + offsetY);
}
228
ответ дан 23 November 2019 в 23:37
поделиться

Apple выпустила видеозаписи сессии WWDC 2010 для всех участников программы для разработчиков iphone. Одна из обсуждаемых тем - как они создали приложение "Фото"!!! Они создали очень похожее приложение шаг за шагом и предоставили весь код бесплатно.

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

http://connect.apple.com/cgi-bin/WebObjects/MemberSite.woa/wa/getSoftware?code=y&source=x&bundleID=20645

И, вот ссылка на страницу iTunes WWDC:

http://insideapple.apple.com/redir/cbx-cgi.do?v=2&la=en&lc=&a=kGSol9sgPHP%2BtlWtLp%2BEP%2FnxnZarjWJglPBZRHd3oDbACudP51JNGS8KlsFgxZto9X%2BTsnqSbeUSWX0doe%2Fzv%2FN5XV55%2FomsyfRgFBysOnIVggO%2Fn2p%2BiweDK%2F%2FmsIXj

7
ответ дан 23 November 2019 в 23:37
поделиться

Этот код должен работать на большинстве версий iOS (и был протестирован для работы на 3.1 и более поздних версиях).

Он основан на коде Apple WWDC для фотоскладчика.

Добавьте приведенный ниже код в свой подкласс UIScrollView и замените tileContainerView представлением, содержащим ваше изображение или фрагменты:

- (void)layoutSubviews {
    [super layoutSubviews];

    // center the image as it becomes smaller than the size of the screen
    CGSize boundsSize = self.bounds.size;
    CGRect frameToCenter = tileContainerView.frame;

    // center horizontally
    if (frameToCenter.size.width < boundsSize.width)
        frameToCenter.origin.x = (boundsSize.width - frameToCenter.size.width) / 2;
    else
        frameToCenter.origin.x = 0;

    // center vertically
    if (frameToCenter.size.height < boundsSize.height)
        frameToCenter.origin.y = (boundsSize.height - frameToCenter.size.height) / 2;
    else
        frameToCenter.origin.y = 0;

    tileContainerView.frame = frameToCenter;
}
23
ответ дан 23 November 2019 в 23:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: