Можно ли добавить фиксированный контент в UIScrollView?

Я хочу создать подкласс UITableView или UIScrollView который будет иметь некоторое затенение сверху, когда смещение содержимого> 0 означает, что контент прокручивается. (См. Изображение прилагается) enter image description here

То, как я реализую это сейчас, - это использовать UIViewController который является делегатом tableView. У меня просто есть GradientView поверх tableView, и я перехватываю scrollViewDidScroll: для анимации видимости этого верхнего градиента.

Моя проблема с этой реализацией заключается в том, что она не "чиста". Я хочу, чтобы мои UIViewControllers позаботились о логике, а не UIViewControllers применения градиентов и т.д. Хотел бы я просто удалить подкласс UITableView, который сделает это для меня.

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

Другой вопрос: какой метод /UIScrollView я должен переопределить для перехвата события прокрутки. Очевидно, я не хочу, чтобы tableView был делегатом сам по себе...

Есть идеи?

Благодарю!

Ответ 1

Хорошо, поэтому я нашел решение на Apple WWDC 2011 Session 104 video - Advanced Scroll View Techniques.

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

Я попробовал это, и это на самом деле довольно легко и работает как ожидалось.

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

-(void) layoutSubviews
{
    [super layoutSubviews];
    [self positionTopShadow];
}

-(void) positionTopShadow
{
    CGFloat yOffset = self.contentOffset.y;
    // I'm doing some limiting so that the maximum height of the shadow view will be 40 pixels
    yOffset = MIN(yOffset, 40);
    yOffset = MAX(0, yOffset);

    CGRect frame = self.topShadowView.frame;
    // The origin should be exactly like the content offset so it would look like
    // the shadow is at the top of the table (when it actually just part of the content) 
    frame.origin = CGPointMake(0, self.contentOffset.y);
    frame.size.height = yOffset;
    frame.size.width = self.frame.size.width;
    self.topShadowView.frame = frame;

    if (self.topShadowView.superview == nil)
    {
        [self addSubview:self.topShadowView];
    }
    [self bringSubviewToFront:self.topShadowView];
}

Ответ 2

Мне удалось найти гораздо более простой способ сделать это, чем это сделал Авраам.

Я использую тот факт, что UIScrollView вызывает scrollViewDidScroll: когда-либо пиксель изменений прокрутки для установки объекта в месте смещения. Ниже мой полный код, чтобы сохранить серый стол в верхней части scrollview при перемещении:

- (void)viewDidLoad {
    UIScrollView* scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(5.0, 50.0, self.bounds.size.width - 15.0, self.bounds.size.height - 60.0)];
    [scrollView setBackgroundColor:[UIColor colorWithRed:251.0/255.0 green:251.0/255.0 blue:251.0/255.0 alpha:1.0]];
    [scrollView setContentSize:CGSizeMake(scrollView.frame.size.width + 500, 1000.0)];
    [scrollView setDelegate:self];
    [self addSubview:scrollView];

    UIView* header = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, scrollView.contentSize.width, 40.0)];
    [header setTag:100];
    [header setBackgroundColor:[UIColor darkGrayColor]];
    [scrollView addSubview:header];
}

-(void)scrollViewDidScroll:(UIScrollView *)scrollView {
    UIView* header = [self viewWithTag:100];
    [header setFrame:CGRectMake(0.0, scrollView.contentOffset.y, header.bounds.size.width, header.bounds.size.height)];
}

Ответ 3

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

Ответ 4

#define kImageOriginHight 300

- (void)scrollViewDidScroll:(UIScrollView *)scrollView1{
CGFloat yOffset  = scrollView1.contentOffset.y;

// NSLog(@" y offset := %f", yOffset);

//zoom images and hide upper view while scrooling to down position
if (yOffset < 0) {//-kImageOriginHight


    CGRect f = imgV.frame;
    f.origin.y = yOffset;
    f.size.height =  -yOffset + kImageOriginHight;
    imgV.frame = f;

    //viewTableUpperView.alpha = 1.5 - (yOffset/-kImageOriginHight);
    //viewTableUpperView.userInteractionEnabled = NO;

    if(yOffset+0.5 == -kImageOriginHight){
        [UIView animateWithDuration:0.1 animations:^{
            //viewTableUpperView.alpha = 1.0;
        }];
        //viewTableUpperView.userInteractionEnabled = YES;
    }
}

}