預(yù)覽
前言
好奇心日報的有的文章頁面是這樣展示的滤蝠,點擊其中一個就可以進(jìn)入單個的文章詳情頁面李根,于是想了一下該怎么實現(xiàn)。
思路
一開始想的是用一個ScrollView去實現(xiàn)几睛,后來發(fā)現(xiàn)一個ScrollView實現(xiàn)的話最后一頁會有問題,也沒有想到解決方案粤攒,于是就用兩個ScrollView來實現(xiàn)
第一張圖藍(lán)色標(biāo)記的是底下的小的ScrollView,它的作用是實現(xiàn)翻頁效果所森,第二張圖藍(lán)色標(biāo)記的是上層的大的ScrollView,用來展示內(nèi)容夯接,用小的UIScrollView來帶動大的ScrollView滑動焕济,大的ScrollView不參與用戶滑動事件
實現(xiàn)
假設(shè)展示4頁內(nèi)容
一些宏定義
#define kScreenWidth ([UIScreen mainScreen].bounds.size.width)
#define kScreenHeight ([UIScreen mainScreen].bounds.size.height)
#define kContentWidth 250
#define kContentHeight 400
#define kPadding 20
SmallScrollView
需要注意的是,小的ScrollView最后一頁的寬度需要計算一下
self.smallScrollView = ({
UIScrollView *scroll = [[UIScrollView alloc] init];
scroll.delegate = self;
scroll.showsHorizontalScrollIndicator = NO;
scroll.pagingEnabled = YES;
[self addSubview:scroll];
[scroll makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self).offset(UIEdgeInsetsMake(0, kPadding / 2, 0, kScreenWidth - kPadding - kContentWidth - kPadding / 2));
}];
UIView *content = [[UIView alloc] init];
[scroll addSubview:content];
[content makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(scroll);
make.height.equalTo(scroll);
}];
UIView *lastView;
for (NSInteger i=0; i<4; i++) {
UIView *view = [[UIView alloc] init];
[content addSubview:view];
if (i == 0) {
[view makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(kPadding / 2);
make.top.bottom.equalTo(content);
make.width.equalTo(kContentWidth);
make.height.equalTo(kContentHeight);
}];
} else if (i == 3) {
[view makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(lastView.right).offset(kPadding);
make.top.bottom.equalTo(content);
make.width.equalTo(kContentWidth - (kScreenWidth - kPadding * 2 - kContentWidth));
make.height.equalTo(kContentHeight);
}];
} else {
[view makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(lastView.right).offset(kPadding);
make.top.bottom.equalTo(content);
make.width.equalTo(kContentWidth);
make.height.equalTo(kContentHeight);
}];
}
lastView = view;
}
[content makeConstraints:^(MASConstraintMaker *make) {
make.right.equalTo(lastView.right).offset(kPadding / 2);
}];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(smallScrollTap:)];
[scroll addGestureRecognizer:tap];
scroll;
});
BigScrollView
self.bigScrollView = ({
UIScrollView *scroll = [[UIScrollView alloc] init];
scroll.clipsToBounds = NO;
scroll.showsHorizontalScrollIndicator = NO;
[self addSubview:scroll];
[scroll makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self).offset(UIEdgeInsetsMake(0, kPadding / 2, 0, kPadding / 2));
}];
UIView *content = [[UIView alloc] init];
[scroll addSubview:content];
[content makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(scroll);
make.height.equalTo(scroll);
}];
UIView *lastView;
for (NSInteger i=0; i<4; i++) {
UIView *view = [[UIView alloc] init];
view.backgroundColor = [self randomColor];
[content addSubview:view];
if (i == 0) {
[view makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(kPadding / 2);
make.top.equalTo(content);
make.width.equalTo(kContentWidth);
make.height.equalTo(kContentHeight);
}];
} else {
[view makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(lastView.right).offset(kPadding);
make.top.equalTo(content);
make.width.equalTo(kContentWidth);
make.height.equalTo(kContentHeight);
}];
}
lastView = view;
// UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
// [btn setBackgroundColor:[UIColor lightGrayColor]];
// [btn setTitle:@"Button" forState:UIControlStateNormal];
// [btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];
// [view addSubview:btn];
// [btn makeConstraints:^(MASConstraintMaker *make) {
// make.centerX.equalTo(view);
// make.width.equalTo(100);
// make.height.equalTo(50);
// make.bottom.equalTo(-50);
// }];
}
[content makeConstraints:^(MASConstraintMaker *make) {
make.right.equalTo(lastView.right).offset(kPadding / 2);
}];
scroll;
});
其它
前面說到大的ScrollView不參與用戶事件盔几,那該怎樣做到呢晴弃?
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
return self.smallScrollView;
}
就是這么簡單。。上鞠。所有事件都讓底下的小的ScrollView去處理际邻,實現(xiàn)ScrollView的代理方法,進(jìn)而帶動大的ScrollView滑動
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (scrollView == self.smallScrollView) {
[self.bigScrollView setContentOffset:scrollView.contentOffset animated:NO];
}
}
關(guān)于滑動的就處理完了
點擊事件
下面就是處理用戶點擊單個頁面了,給小的ScrollView添加單擊手勢芍阎,然后將點轉(zhuǎn)化到大的ScrollView即完成了單擊手勢的檢測世曾,假如頁面上有button,判斷點是否在button內(nèi)進(jìn)而處理
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(smallScrollTap:)];
[scroll addGestureRecognizer:tap];
- (void)smallScrollTap:(UITapGestureRecognizer *)sender{
[self.bigSubViews removeAllObjects];
[self listSubviewsOfView:self.bigScrollView];
CGPoint bigPoint = [sender locationInView:self.bigScrollView];
for (UIView *view in self.bigSubViews.reverseObjectEnumerator) {
if ([view isKindOfClass:[UIButton class]]) {
CGPoint buttonPoint = [view convertPoint:bigPoint fromView:self.bigScrollView];
if (CGRectContainsPoint(view.bounds, buttonPoint)) {
[(UIButton *)view sendActionsForControlEvents:UIControlEventTouchUpInside];
}
}
}
}
- (void)listSubviewsOfView:(UIView *)view {
NSArray *subviews = [view subviews];
if ([subviews count] == 0) return;
for (UIView *subview in subviews) {
[self.bigSubViews addObject:subview];
[self listSubviewsOfView:subview];
}
}
不足
我也不清楚別人是怎么實現(xiàn)這種ScrollView效果的谴咸,這個方法我也不清楚是不是最好的轮听,只是我能想到的方法,當(dāng)然有些許不足岭佳,比如都交給小的ScrollView處理血巍,展示的內(nèi)容如果有button,button在normall,highlighted,selected狀態(tài)設(shè)置了不同的樣式珊随,該實現(xiàn)是沒有辦法展示的述寡,因為我只是發(fā)送了一個事件過去。所以如果你有更好的方法玫恳,不妨發(fā)表一下辨赐!