具有水平分页的 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 与水平分页