16 votes

Est-il possible d'ajouter un contenu fixe à un UIScrollView ?

Je veux créer une sous-classe de UITableView o UIScrollView qui aura un ombrage en haut lorsque le décalage du contenu est > 0 pour indiquer que le contenu est défilable. (Voir image jointe) enter image description here

La façon dont je l'implémente actuellement est d'utiliser la fonction UIViewController qui est le délégué de la tableView . J'ai simplement un GradientView sur le dessus de la tableView et j'intercepte scrollViewDidScroll: pour animer la visibilité de ce gradient supérieur.

Mon problème avec cette mise en œuvre est qu'elle n'est pas "propre". Je veux que mon UIViewControllers pour s'occuper de la logique, et non pour s'occuper de l'application des dégradés et autres. J'aimerais pouvoir créer une sous-classe de UITableView qui fera ça pour moi.

Le problème pour moi est que je n'arrive pas à comprendre comment le tableView pourrait ajouter à lui-même un contenu fixe par-dessus le contenu défilant.

Une autre question est de savoir quelle(s) méthode(s) de UIScrollView que je dois surcharger pour intercepter l'événement de défilement. Évidemment, je ne veux pas que le tableView soit le délégué de lui-même...

Des idées ?

Gracias.

29voto

Avraham Shukron Points 2556

Ok, j'ai trouvé la solution dans la vidéo de la session 104 de la WWDC 2011 d'Apple - Advanced Scroll View Techniques.

Dans cette vidéo, il y a toute une section sur les "vues stationnaires" à l'intérieur d'une vue défilante. Selon Apple, la solution consiste à remplacer layoutSubviews et à y placer tout le code nécessaire pour positionner ce que vous voulez, où vous voulez.

J'ai essayé et c'est en fait assez facile et ça fonctionne comme prévu.

Ainsi, par exemple, si je souhaite qu'un en-tête ombragé apparaisse en haut du tableau lorsque le contenu défile, voici le code que je dois écrire :

-(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's 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];
}

4voto

John Riselvato Points 5217

J'ai réussi à trouver une façon beaucoup plus simple de faire ça que ce qu'Abraham a fait.

J'utilise le fait que l'UIScrollView appelle scrollViewDidScroll : à chaque pixel de changement de défilement pour placer l'objet à l'emplacement du décalage. Voici mon code complet pour garder une barre grise en haut du scrollview lorsque vous vous déplacez :

- (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)];
}

0voto

Prathiba Points 267

Vous pourriez essayer d'utiliser la méthode viewForHeaderInSection de tableView pour la vue ombrée (et aussi heightForHeaderInSection)... Faites de la partie ombragée un en-tête, de façon à ce qu'il y ait un contenu fixe au-dessus du contenu défilant.

0voto

arvind Points 368
#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;
    }
}

}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X