前言
在开发中,遇到了计算View显示的百分比来表明是否曝光
主要的场景就是在滑动列表中View展示的百分比。
RXViewVisiableCell
@implementation RXViewVisiableCell
- (void)refreshViewWithIndex:(NSInteger)index {
if (self.label == nil) {
// cell height = 200
self.label = [[UILabel alloc] initWithFrame:CGRectMake(0, 100, [UIScreen mainScreen].bounds.size.width, 100)];
self.label.textColor = [UIColor whiteColor];
self.label.backgroundColor = [UIColor redColor];
[self.contentView addSubview:self.label];
}
NSLog(@"refreshViewWithIndex self.hidden:%zd", (long)self.hidden);
self.label.text = [NSString stringWithFormat:@"%zd", (long)index];
if (index == 4) {
[self startTimer];
} else {
[self endTimer];
}
}
- (void)startTimer {
if (self.timer == nil) {
__weak typeof(self) weakSelf = self;
self.timer = [NSTimer rxv_scheduleTimerWithTimeInterval:1.0 repeats:YES usingBlock:^(NSTimer * _Nonnull timer) {
CGFloat percent = [weakSelf.label rxv_viewVisiable];
NSLog(@"visiableCell index:%@ percent:%.3f self:%p self.label:%p self.hidden:%zd", weakSelf.label.text, percent, weakSelf, weakSelf.label, (long)weakSelf.hidden);
if (weakSelf.hidden) {
NSLog(@"timer find cell hidden, need to endTimer");
[weakSelf endTimer];
}
}];
}
}
- (void)endTimer {
[self.timer invalidate];
self.timer = nil;
}
@end
UIView+RXVerify.h
- (CGFloat)rxv_viewVisiable {
// 未添加到superview
if (self.superview == nil) {
return 0;
}
// view 隐藏
if (self.hidden) {
return 0;
}
UIView *rootView = self;
while (rootView != nil) {
UIView *superView = rootView.superview;
if (superView.hidden) {
return 0;
}
if (superView == nil) {
break;
}
rootView = superView;
}
UIWindow *window = [UIApplication sharedApplication].keyWindow;
UIScrollView *scrollView = nil;
UIView *pView = self;
while (pView != nil) {
if ([pView isKindOfClass:[UIScrollView class]]) {
scrollView = (UIScrollView *)pView;
break;
}
pView = pView.superview;
}
UIView *visiableView = scrollView ? scrollView : window;
CGRect rect = [visiableView convertRect:self.frame fromView:self.superview];
if (CGRectIsEmpty(rect) || CGRectIsNull(rect) || CGSizeEqualToSize(rect.size, CGSizeZero)) {
return 0;
}
// 获取 该view与visiableView 交叉的 Rect
CGRect screenRect = visiableView.bounds;
CGRect intersectionRect = CGRectIntersection(rect, screenRect);
if (CGRectIsEmpty(intersectionRect) || CGRectIsNull(intersectionRect)) {
return 0;
}
// 展示面积与实际面积的百分比
CGFloat dividend = intersectionRect.size.width * intersectionRect.size.height;
CGFloat divisor = (self.frame.size.width * self.frame.size.height);
CGFloat showPercent = dividend / divisor;
return showPercent;
}
@end
重点
superView.hidden
如果其中之一的superview hidden了,那么就是0- UIView *visiableView = scrollView ? scrollView : window; 如果在其中之一的superview找到scrollView,那么以这个scrollView为基础进行判断 (这里有一个潜在的假设是此scrollView处在屏幕中)