具有水平分页的 UIScrollView 不居中子视图

Posted

技术标签:

【中文标题】具有水平分页的 UIScrollView 不居中子视图【英文标题】:UIScrollView with horizontal paging` does not center subview 【发布时间】:2016-07-08 06:34:47 【问题描述】:

我正在尝试使用启用分页的 UIScrollView。我将各种 UIView 作为子视图添加到 UISCrollView。我希望这些子视图小于滚动视图的大小,所以我相应地修改了我的约束。现在,当我实际向左/向右滑动它们时,它们恰好不在中心。我期待它以当前页面为中心显示从侧面窥视的上一个/下一个视图。

这就是它的样子

下面是我的代码滚动视图实现

    //
    //  ViewController.m
    //  Paging
    //

#import "ViewController.h"

@interface ViewController ()
@property (nonatomic, strong) UIScrollView *pagingScrollView;
@end

@implementation ViewController
- (UIScrollView *)pagingScrollView 
    if (!_pagingScrollView) 
        _pagingScrollView = [[UIScrollView alloc] initWithFrame:CGRectZero];
        _pagingScrollView.translatesAutoresizingMaskIntoConstraints = NO;
        _pagingScrollView.backgroundColor = [UIColor orangeColor];
        _pagingScrollView.showsHorizontalScrollIndicator = NO;
        _pagingScrollView.showsVerticalScrollIndicator = NO;
        _pagingScrollView.contentInset = UIEdgeInsetsZero;
        _pagingScrollView.pagingEnabled = YES;
        _pagingScrollView.clipsToBounds = NO;
        _pagingScrollView.bounces = NO;
    
    return _pagingScrollView;

- (void)viewDidLoad 
    [super viewDidLoad];
    [self scrollViewSetUp];

    NSDictionary *views = NSDictionaryOfVariableBindings(_pagingScrollView);

    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_pagingScrollView]|"
                                                                      options:0
                                                                      metrics:nil
                                                                        views:views]];

    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_pagingScrollView]|"
                                                                      options:0
                                                                      metrics:nil
                                                                        views:views]];


- (void)scrollViewSetUp 

    [self.view addSubview:self.pagingScrollView];

    UIView *lastView = nil;
    NSInteger arrayCount = 5;

    for(NSInteger index = 0; index < arrayCount; index++)
    
        UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
        view.translatesAutoresizingMaskIntoConstraints = NO;
        view.backgroundColor = [UIColor yellowColor];

        [self.pagingScrollView addSubview:view];

        [self.pagingScrollView addConstraint:[NSLayoutConstraint constraintWithItem:view
                                                                        attribute:NSLayoutAttributeTop
                                                                        relatedBy:NSLayoutRelationEqual
                                                                           toItem:self.pagingScrollView
                                                                        attribute:NSLayoutAttributeTop
                                                                       multiplier:1
                                                                         constant:40]];

        [self.pagingScrollView addConstraint:[NSLayoutConstraint constraintWithItem:view
                                                                        attribute:NSLayoutAttributeHeight
                                                                        relatedBy:NSLayoutRelationEqual
                                                                           toItem:self.pagingScrollView
                                                                        attribute:NSLayoutAttributeHeight
                                                                       multiplier:0.80
                                                                         constant:0]];

        [self.pagingScrollView addConstraint:[NSLayoutConstraint constraintWithItem:view
                                                                        attribute:NSLayoutAttributeWidth
                                                                        relatedBy:NSLayoutRelationEqual
                                                                           toItem:self.pagingScrollView
                                                                        attribute:NSLayoutAttributeWidth
                                                                       multiplier:0.80
                                                                         constant:0]];

        if (lastView == nil && index == 0)
            [self.pagingScrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-20-[view(==_pagingScrollView)]"
                                                                                        options:0
                                                                                        metrics:nil
                                                                                          views:@@"view":view, @"_pagingScrollView":_pagingScrollView]];
         else 
            [self.pagingScrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[lastView]-20-[view]"
                                                                                        options:0
                                                                                        metrics:nil
                                                                                          views:@@"lastView":lastView, @"view":view, @"_pagingScrollView":_pagingScrollView]];
        

        if(index == arrayCount-1) 
            [self.pagingScrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[view]-20-|"
                                                                                        options:0
                                                                                        metrics:nil
                                                                                          views:@@"view":view]];
        

        lastView = view;
    

@end

高度赞赏任何指针/cmets/反馈。谢谢。

【问题讨论】:

你试过这个库吗? github.com/nicklockwood/SwipeView 【参考方案1】:

这是你想要的吗?

//
//  ViewController.h
//  Test
//
//  Created by Lee on 7/8/16.
//  Copyright © 2016 Lee. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController

@property (nonatomic, strong) UIScrollView *pagingScrollView;

@end



//
//  ViewController.m
//  Test
//
//  Created by Lee on 7/8/16.
//  Copyright © 2016 Lee. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()<UIScrollViewDelegate>
@property (nonatomic,strong)NSMutableArray *subviewsCenterArray;

@end

@implementation ViewController

- (UIScrollView *)pagingScrollView 
    if (!_pagingScrollView) 
        _pagingScrollView = [[UIScrollView alloc] initWithFrame:CGRectZero];
        _pagingScrollView.translatesAutoresizingMaskIntoConstraints = NO;
        _pagingScrollView.backgroundColor = [UIColor orangeColor];
        _pagingScrollView.showsHorizontalScrollIndicator = NO;
        _pagingScrollView.showsVerticalScrollIndicator = NO;
        _pagingScrollView.contentInset = UIEdgeInsetsZero;
        _pagingScrollView.pagingEnabled = NO;
        _pagingScrollView.clipsToBounds = NO;
        _pagingScrollView.bounces = NO;
        _pagingScrollView.delegate = self;
    
    return _pagingScrollView;

- (void)viewDidLoad 
    [super viewDidLoad];
    [self scrollViewSetUp];

    NSDictionary *views = NSDictionaryOfVariableBindings(_pagingScrollView);

    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_pagingScrollView]|"
                                                                      options:0
                                                                      metrics:nil
                                                                        views:views]];

    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_pagingScrollView]|"
                                                                      options:0
                                                                      metrics:nil
                                                                        views:views]];


- (void)scrollViewSetUp 

    [self.view addSubview:self.pagingScrollView];

    UIView *lastView = nil;
    NSInteger arrayCount = 5;
    _subviewsCenterArray = [NSMutableArray array];
    for(NSInteger index = 0; index < arrayCount; index++)
    
        UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
        view.translatesAutoresizingMaskIntoConstraints = NO;
        view.backgroundColor = [UIColor colorWithRed:arc4random()%255/255.0 green:arc4random()%255/255.0 blue:arc4random()%255/255.0 alpha:1];
        view.tag = 9999;
        view.layer.cornerRadius = 6;
        [self.pagingScrollView addSubview:view];

        [self.pagingScrollView addConstraint:[NSLayoutConstraint constraintWithItem:view
                                                                          attribute:NSLayoutAttributeTop
                                                                          relatedBy:NSLayoutRelationEqual
                                                                             toItem:self.pagingScrollView
                                                                          attribute:NSLayoutAttributeTop
                                                                         multiplier:1
                                                                           constant:40]];

        [self.pagingScrollView addConstraint:[NSLayoutConstraint constraintWithItem:view
                                                                          attribute:NSLayoutAttributeHeight
                                                                          relatedBy:NSLayoutRelationEqual
                                                                             toItem:self.pagingScrollView
                                                                          attribute:NSLayoutAttributeHeight
                                                                         multiplier:0.80
                                                                           constant:0]];

        [self.pagingScrollView addConstraint:[NSLayoutConstraint constraintWithItem:view
                                                                          attribute:NSLayoutAttributeWidth
                                                                          relatedBy:NSLayoutRelationEqual
                                                                             toItem:self.pagingScrollView
                                                                          attribute:NSLayoutAttributeWidth
                                                                         multiplier:0.80
                                                                           constant:0]];

        if (lastView == nil && index == 0)
            [self.pagingScrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-20-[view(==_pagingScrollView)]"
                                                                                          options:0
                                                                                          metrics:nil
                                                                                            views:@@"view":view, @"_pagingScrollView":_pagingScrollView]];
         else 
            [self.pagingScrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[lastView]-20-[view]"
                                                                                          options:0
                                                                                          metrics:nil
                                                                                            views:@@"lastView":lastView, @"view":view, @"_pagingScrollView":_pagingScrollView]];
        

        if(index == arrayCount-1) 
            [self.pagingScrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[view]-20-|"
                                                                                          options:0
                                                                                          metrics:nil
                                                                                            views:@@"view":view]];
        

        [self.view layoutIfNeeded];




        lastView = view;
    


- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate

    [self changeTheCardStatus:scrollView];



- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView 
    [self changeTheCardStatus:scrollView];




-(void)changeTheCardStatus:(UIScrollView *)scrollView

    for (UIView *view in scrollView.subviews) 
        if (view.tag == 9999) 
            [_subviewsCenterArray addObject:@(view.center.x)];
        

    



    CGFloat currentCenterOffsetX = scrollView.contentOffset.x + CGRectGetWidth(self.view.frame)/2.0;

    NSMutableArray *absoluteValueArray = [NSMutableArray array];
    NSMutableDictionary *absoluteValueDictionary = [NSMutableDictionary dictionary];
    for (int i  = 0; i < _subviewsCenterArray.count; i ++) 
        float subviewsCenterPointX = [_subviewsCenterArray[i] floatValue];
        double  absolute = fabs(subviewsCenterPointX - currentCenterOffsetX);
        [absoluteValueArray addObject:@(absolute)];
        [absoluteValueDictionary setValue:@(subviewsCenterPointX) forKey:[NSString stringWithFormat:@"%f",absolute]];
    


    [absoluteValueArray sortUsingComparator:^NSComparisonResult(id  _Nonnull obj1, id  _Nonnull obj2) 

        double a = [obj1 doubleValue];
        double b = [obj2 doubleValue];
        if (a>b) 
            return NSOrderedDescending;
        
        else if (a<b)
            return NSOrderedAscending;
        
        else
            return NSOrderedSame;
        

    ];


    double shortValue = [absoluteValueArray.firstObject doubleValue];
    double centerX = [[absoluteValueDictionary objectForKey:[NSString stringWithFormat:@"%f",shortValue]] doubleValue];
    [UIView animateWithDuration:0.25 animations:^
        scrollView.contentOffset = CGPointMake(centerX - CGRectGetWidth(self.view.frame)/2.0, 0);

    ];





- (void)didReceiveMemoryWarning 
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.


@end

【讨论】:

【参考方案2】:

当然不是。 pagingScrollView 的子视图没有合适的宽度!这些子视图也没有正确的水平边距。

    首先,您应该更正设置宽度代码,将乘数更改为 1,将常数更改为 -40。像这样:

    [self.pagingScrollView addConstraint:[NSLayoutConstraint constraintWithItem:view
                                                                    attribute:NSLayoutAttributeWidth
                                                                    relatedBy:NSLayoutRelationEqual
                                                                       toItem:self.pagingScrollView
                                                                    attribute:NSLayoutAttributeWidth
                                                                   multiplier:1
                                                                     constant:-40]];
    

    然后修改子视图边距,将-20改为-40,像这样

    [self.pagingScrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[lastView]-40-[view]"
                                                                                    options:0
                                                                                    metrics:nil
                                                                                      views:@@"lastView":lastView, @"view":view, @"_pagingScrollView":_pagingScrollView]];
    

【讨论】:

我需要这些子视图的尺寸小于超级视图(在本例中为滚动视图),这就是乘数为 0.80 的原因

以上是关于具有水平分页的 UIScrollView 不居中子视图的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式在 UIScrollview 水平分页中的 UITableView

UIScrollView 内的 UITableViewController 与水平分页

swift 4中的页面控制是不是可以有一个无限的水平分页uiscrollview?

缩小 UIScrollView 以专注于某个页面

带有 TabView、SwiftUI 的水平分页滚动视图

具有水平分页和垂直滚动的 UICollectionView