web-dev-qa-db-fra.com

UIScrollView - montrant la barre de défilement

Peut-être un simple!

Est-ce que quelqu'un sait comment afficher en permanence la barre de défilement d'un UIScrollView?

Il s’affiche lorsque l’utilisateur défile pour qu’il puisse voir dans quelle position de la vue de défilement il se trouve. 

MAIS je voudrais le montrer constamment parce qu'il n'est pas immédiatement évident pour l'utilisateur que le défilement est disponible

Tout conseil serait hautement apprécié.

54
Tom G

Non, vous ne pouvez pas toujours les afficher, mais vous pouvez les faire clignoter temporairement.

[myScrollView flashScrollIndicators];

Ce sont des indicateurs de défilement, pas des barres de défilement. Vous ne pouvez pas les utiliser pour faire défiler.

82
Mongus Pong

ma solution pour afficher les indicateurs de défilement tout le temps

#define noDisableVerticalScrollTag 836913
#define noDisableHorizontalScrollTag 836914

@implementation UIImageView (ForScrollView)

- (void) setAlpha:(float)alpha {

if (self.superview.tag == noDisableVerticalScrollTag) {
    if (alpha == 0 && self.autoresizingMask == UIViewAutoresizingFlexibleLeftMargin) {
        if (self.frame.size.width < 10 && self.frame.size.height > self.frame.size.width) {
            UIScrollView *sc = (UIScrollView*)self.superview;
            if (sc.frame.size.height < sc.contentSize.height) {
                return;
            }
        }
    }
}

if (self.superview.tag == noDisableHorizontalScrollTag) {
    if (alpha == 0 && self.autoresizingMask == UIViewAutoresizingFlexibleTopMargin) {
        if (self.frame.size.height < 10 && self.frame.size.height < self.frame.size.width) {
            UIScrollView *sc = (UIScrollView*)self.superview;
            if (sc.frame.size.width < sc.contentSize.width) {
                return;
            }
        }
    }
}

[super setAlpha:alpha];
}
@end

UPDATE: cette solution pose des problèmes sur 64 bits. Pour plus de détails, regardez ici

6
SAKrisT

Pour autant que je sache, ce n'est pas possible. Le seul appel d'API qui contrôle l'affichage de l'indicateur de défilement est showsVerticalScrollIndicator et qui peut uniquement désactiver l'affichage de l'indicateur.

Vous pouvez flashScrollIndicators lorsque la vue apparaît pour que l'utilisateur sache où ils se trouvent dans la vue de défilement.

4
Ben S

Celui-ci a fonctionné pour moi:

#define noDisableVerticalScrollTag 836913
#define noDisableHorizontalScrollTag 836914

@implementation UIImageView (ForScrollView) 

- (void) setAlpha:(float)alpha {

    if (self.superview.tag == noDisableVerticalScrollTag) {
        if (alpha == 0 && self.autoresizingMask == UIViewAutoresizingFlexibleLeftMargin) {
            if (self.frame.size.width < 10 && self.frame.size.height > self.frame.size.width) {
                UIScrollView *sc = (UIScrollView*)self.superview;
                if (sc.frame.size.height < sc.contentSize.height) {
                    return;
                }
            }
        }
    }

    if (self.superview.tag == noDisableHorizontalScrollTag) {
        if (alpha == 0 && self.autoresizingMask == UIViewAutoresizingFlexibleTopMargin) {
            if (self.frame.size.height < 10 && self.frame.size.height < self.frame.size.width) {
                UIScrollView *sc = (UIScrollView*)self.superview;
                if (sc.frame.size.width < sc.contentSize.width) {
                    return;
                }
            }
        }
    }

    [super setAlpha:alpha];
}
@end

J'ai eu cet extrait d'ici: http://www.developers-life.com/scrollview-with-scrolls-indicators-which-are-shown-all-the-time.html

3
sciasxp

Je veux offrir ma solution. Je n'aime pas la variante la plus populaire avec category (le fait de surcharger les méthodes de la catégorie peut être la raison de l'indétermination de la méthode à appeler à l'exécution, car il existe deux méthodes avec le même sélecteur) . Et aussi je n'ai pas besoin d'utiliser des tags.

Ajoutez cette méthode à votre contrôleur de vue, où vous avez une vue de défilement (la propriété self.categoriesTableView est une vue sous forme de tableau où je veux afficher les barres de défilement)

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    // Do swizzling to turn scroll indicator always on
    // Search correct subview with vertical scroll indicator image across tableView subviews
    for (UIView * view in self.categoriesTableView.subviews) {
        if ([view isKindOfClass:[UIImageView class]]) {
            if (view.alpha == 0 && view.autoresizingMask == UIViewAutoresizingFlexibleLeftMargin) {
                if (view.frame.size.width < 10 && view.frame.size.height > view.frame.size.width) {
                    if (self.categoriesTableView.frame.size.height < self.categoriesTableView.contentSize.height) {
                        // Swizzle class for found imageView, that should be scroll indicator
                        object_setClass(view, [AlwaysOpaqueImageView class]);
                        break;
                    }
                }
            }
        }
    }
    // Search correct subview with horizontal scroll indicator image across tableView subviews
    for (UIView * view in self.categoriesTableView.subviews) {
        if ([view isKindOfClass:[UIImageView class]]) {
            if (view.alpha == 0 && view.autoresizingMask == UIViewAutoresizingFlexibleTopMargin) {
                if (view.frame.size.height < 10 && view.frame.size.height < view.frame.size.width) {
                    if (self.categoriesTableView.frame.size.width < self.categoriesTableView.contentSize.width) {
                        // Swizzle class for found imageView, that should be scroll indicator
                        object_setClass(view, [AlwaysOpaqueImageView class]);
                        break;
                    }
                }
            }
        }
    }
    // Ask to flash indicator to turn it on
   [self.categoriesTableView flashScrollIndicators];
}

Ajouter une nouvelle classe

@interface AlwaysOpaqueImageView : UIImageView
@end

@implementation AlwaysOpaqueImageView

- (void)setAlpha:(CGFloat)alpha {
    [super setAlpha:1.0];
}

@end

L'indicateur de défilement (indicateur de défilement vertical dans le premier cycle for et horizontal dans le deuxième cycle for) sera toujours affiché à l'écran. Si vous n'avez besoin que d'un seul indicateur, ne laissez que ce cycle for dans le code et supprimez-en un autre.

1
Accid Bright

Barre de défilement qui fonctionne comme l’iOS intégré, mais vous pouvez jouer avec la couleur et la largeur.

-(void)persistantScrollBar
{
    [persistantScrollBar removeFromSuperview];
    [self.collectionView setNeedsLayout];
    [self.collectionView layoutIfNeeded];

    if (self.collectionView.contentSize.height > self.collectionView.frame.size.height + 10)
    {
        persistantScrollBar = [[UIView alloc] initWithFrame:(CGRectMake(self.view.frame.size.width - 10, self.collectionView.frame.Origin.y, 5, (self.collectionView.frame.size.height /self.collectionView.contentSize.height) * self.collectionView.frame.size.height))];
        persistantScrollBar.backgroundColor = [UIColor colorWithRed:207/255.f green:207/255.f blue:207/255.f alpha:0.5f];
        persistantScrollBar.layer.cornerRadius = persistantScrollBar.frame.size.width/2;
        persistantScrollBar.layer.zPosition = 0;
        [self.view addSubview:persistantScrollBar];
    }
}

-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    CGRect rect = persistantScrollBar.frame;
    rect.Origin.y =  scrollView.frame.Origin.y + (scrollView.contentOffset.y *(self.collectionView.frame.size.height/self.collectionView.contentSize.height));
    rect.size.height = (self.collectionView.frame.size.height /self.collectionView.contentSize.height) * self.collectionView.frame.size.height;
    if ( scrollView.contentOffset.y <= 0 )
    {
        rect.Origin.y = scrollView.frame.Origin.y;
        rect.size.height = rect.size.height + (scrollView.contentOffset.y);
    }
    else if (scrollView.contentOffset.y + scrollView.frame.size.height >= scrollView.contentSize.height)
    {
        rect.size.height = rect.size.height - ((scrollView.contentOffset.y + scrollView.frame.size.height) - scrollView.contentSize.height);
        rect.Origin.y =  (self.collectionView.frame.Origin.y + self.collectionView.frame.size.height - 5) - rect.size.height;
    }

    persistantScrollBar.frame = rect;
}
0

iOS ne propose pas l'API. Mais si vous le souhaitez vraiment, vous pouvez ajouter votre indicateur personnalisé pour faire défiler la vue et le structurer vous-même, comme le fait la démo:

- (void) layoutSubviews 
 {
 [super layoutSubviews]; 

 if (self.showsVerticalScrollIndicatorAlways) {
 scroll_indicator_position (self, k_scroll_indicator_vertical); 
 } 

 if (self.showsHorizontalScrollIndicatorAlways) {
 scroll_indicator_position (self, k_scroll_indicator_horizontal); 
 } 
} 

Le lien est https://github.com/flexih/MazeScrollView

0
flexih

Swift 3

Vous pouvez accéder à la barre de défilement à l'aide de scrollView.subviews et modifier l'alpha comme indiqué ici. Ça marche pour moi.

extension UIScrollView {
    override open func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        for x in self.subviews {
            x.alpha = 1.0
        }
    }
}

extension MyScrollViewDelegate : UIScrollViewDelegate {
    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        for x in scrollView.subviews {
            x.alpha = 1.0
        }
    }
}
0
Alfred

Pour les vues Web, où la première sous-vue est une vue de défilement, dans la dernière version du SDK, si une page HTML est plus longue que le cadre, aucune barre de défilement n'est affichée et si le contenu HTML s'aligne sur le cadre ou si vous disposez d'un espace. au bas du cadre, on dirait qu'il n'y a pas besoin de défilement et rien en dessous de la ligne. Dans ce cas, je pense que vous devriez absolument faire clignoter les barres de défilement dans la fenêtre du délégué. 

- (void)webViewDidFinishLoad:(UIWebView *)webView; 

méthode pour alerter l'utilisateur qu'il y a plus de choses "en dehors de la boîte". 

NSArray *subViews = [[NSArray alloc] initWithArray:[webView subviews]] ;
UIScrollView *webScroller = (UIScrollView *)[subViews objectAtIndex:0] ;    

Avec HTML, le contenu horizontal est automatiquement encapsulé. Vérifiez donc la hauteur de l'installateur Web.

        if (webScroller.contentSize.height > webView.frame.size.height) {
            [webScroller flashScrollIndicators];
        }

Le flash est tellement court et survient pendant le chargement des vues, qu'il peut être négligé. Pour contourner ce problème, vous pouvez également secouer, faire rebondir, faire défiler ou redimensionner un peu le contenu via le commitAnimations générique d'UIView.

0
PapaSmurf