0
点赞
收藏
分享

微信扫一扫

iOS小技能:下拉刷新控件的适配

boomwu 2022-11-01 阅读 93

前言

  1. 下拉顶部背景色设置: 往tableView的父控件添加拉伸背景视图
  2. present 半屏适配

iOS13 modalPresentationStyle属性默认不是全屏样式​​UIModalPresentationFullScreen​​,而是半屏样式,需要根据需求手动设置。 present 半屏,会导致列表下拉刷新失效。

I 下拉刷新适配

1.1 下拉顶部背景色设置

iOS小技能:下拉刷新控件的适配_#import

  1. 设置下拉样式

#import <MJRefresh/MJRefresh.h>
@interface ERPMJRefreshNormalHeader4StyleWhite : MJRefreshNormalHeader

+ (instancetype)headerWithRefreshingTarget:(id)target refreshingAction:(SEL)action
{
MJRefreshHeader *cmp = [[self alloc] init];

[cmp setRefreshingTarget:target refreshingAction:action];
[self setupStyleWhite:cmp];
return cmp;
}

+(void)setupStyleWhite:(MJRefreshNormalHeader*)mj_header{


mj_header.stateLabel.textColor = UIColor.whiteColor;
mj_header.lastUpdatedTimeLabel.textColor=mj_header.stateLabel.textColor;
mj_header.loadingView.activityIndicatorViewStyle =UIActivityIndicatorViewStyleWhite;

}

  1. 下拉顶部背景色设置:往tableView的父控件添加拉伸背景视图

ERPMJRefreshNormalHeader4StyleWhite *mj_header =[ERPMJRefreshNormalHeader4StyleWhite headerWithRefreshingTarget:self refreshingAction:@selector(headerRereshing)];

UIImage *bgImg = [UIImage getMaingradientColorImage];

UIColor *tmpColor = [UIColor colorWithPatternImage:bgImg];

mj_header.backgroundColor =tmpColor;

[self setupStretchViewColor:mj_header.backgroundColor tableView:_vcView.tableView];

_vcView.tableView.mj_header = mj_header;

_vcView.tableView.bounces = YES;

- (void)setupStretchViewColor:(UIColor*) stretchViewColor tableView:(UIView*)tableView{


[tableView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:nil];


self.stretchView.backgroundColor =stretchViewColor;
//往tableView的父控件添加拉伸背景视图
[tableView.superview addSubview:self.stretchView];


}

#pragma mark - 拉顶部背景色
-(void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id>*)change context:(void*)context{
if([keyPath isEqualToString:@"contentOffset"]){
NSValue *value = change[NSKeyValueChangeNewKey];
CGFloat chaneoffsetY = value.UIOffsetValue.vertical;
UIView *mj_header= self.vcView.tableView.mj_header;

self.stretchView.frame = CGRectMake(0,0,mj_header.width,-chaneoffsetY-mj_header.height);
}
}

/**
拉伸背景

@return view
*/
-(UIView *)stretchView{

if (!_stretchView) {

UIView *tmp =[[UIView alloc] init];
_stretchView =tmp;
// _stretchView.backgroundColor = self.backgroundColor;
}
return _stretchView;
}

1.2 present 半屏适配

  1. 手动设置全屏样式

xxNavigationViewController *nav = [[xxNavigationViewController alloc] initWithRootViewController:loginViewController];
nav.modalPresentationStyle = UIModalPresentationFullScreen;
[self presentViewController:nav animated:YES completion:nil];
//推荐使用UIModalPresentationOverFullScreen

  1. 灵活控制模态展示的视图样式

​​iOS13适配【灵活控制模态展示的视图样式】(全屏/下滑返回)文中提供完整demo源码​​

  1. 全局hook presentViewController方法

//
// UIViewController+ERPPresent13.h

#import <UIKit/UIKit.h>
#import <objc/runtime.h>

NS_ASSUME_NONNULL_BEGIN

@interface UIViewController (ERPPresent13)

/**
Whether or not to set ModelPresentationStyle automatically for instance, Default is [Class K_automaticallySetModalPresentationStyle].
@return BOOL
*/
@property (nonatomic, assign) BOOL K_automaticallySetModalPresentationStyle;

/**
Whether or not to set ModelPresentationStyle automatically, Default is YES, but UIImagePickerController/UIAlertController is NO.
@return BOOL
*/
+ (BOOL)K_automaticallySetModalPresentationStyle;

@end

NS_ASSUME_NONNULL_END

//
// UIViewController+ERPPresent13.m

#import "UIViewController+ERPPresent13.h"

static const char *K_automaticallySetModalPresentationStyleKey;

@implementation UIViewController (ERPPresent13)
+ (void)load {
Method originAddObserverMethod = class_getInstanceMethod(self, @selector(presentViewController:animated:completion:));
Method swizzledAddObserverMethod = class_getInstanceMethod(self, @selector(K_presentViewController:animated:completion:));
method_exchangeImplementations(originAddObserverMethod, swizzledAddObserverMethod);
}

- (void)setK_automaticallySetModalPresentationStyle:(BOOL)K_automaticallySetModalPresentationStyle {
objc_setAssociatedObject(self, K_automaticallySetModalPresentationStyleKey, @(K_automaticallySetModalPresentationStyle), OBJC_ASSOCIATION_ASSIGN);
}

- (BOOL)K_automaticallySetModalPresentationStyle {
id obj = objc_getAssociatedObject(self, K_automaticallySetModalPresentationStyleKey);
if (obj) {
return [obj boolValue];
}
return [self.class K_automaticallySetModalPresentationStyle];
}

+ (BOOL)K_automaticallySetModalPresentationStyle {
if ([self isKindOfClass:[UIImagePickerController class]] || [self isKindOfClass:[UIAlertController class]]) {
return NO;
}
return YES;
}

- (void)K_presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion {
if (@available(iOS 13.0, *)) {
if (viewControllerToPresent.K_automaticallySetModalPresentationStyle) {
viewControllerToPresent.modalPresentationStyle = UIModalPresentationFullScreen;
}
[self K_presentViewController:viewControllerToPresent animated:flag completion:completion];
} else {
// Fallback on earlier versions
[self K_presentViewController:viewControllerToPresent animated:flag completion:completion];
}
}

@end

II 上拉加载适配

2.1 安全距离适配

问题:没有上拉的时候加载更多控件的文案也显示出来了

iOS小技能:下拉刷新控件的适配_控件_02

修复方式1:修改视图距离底部的高度

[self.vcView mas_makeConstraints:^(MASConstraintMaker *make) {

make.left.equalTo(weakSelf.view).offset(0);
make.right.equalTo(weakSelf.view).offset(- 0);
make.top.equalTo(weakSelf.view).offset(0);
if(isHasSafeAreaInsets()){// 避免没有上拉的时候加载更多控件的文案也显示出来了
UIWindow *mainWindow = [[[UIApplication sharedApplication] delegate] window];
CGFloat bottom = mainWindow.safeAreaInsets.bottom;
make.bottom.equalTo(weakSelf.view).offset(bottom);

}else{
make.bottom.equalTo(weakSelf.view);
}


}];

修复方式2:修改上拉加载控件距离底部的高度 【推荐】

/** 忽略多少scrollView的contentInset的bottom */
//@property (assign, nonatomic) CGFloat ignoredScrollViewContentInsetBottom;

UIWindow *mainWindow = [[[UIApplication sharedApplication] delegate] window];
CGFloat bottom = mainWindow.safeAreaInsets.bottom;//34
_tableView.mj_footer.ignoredScrollViewContentInsetBottom = isIphoneX ? bottom : 0;

iOS小技能:下拉刷新控件的适配_控件_03

判断安全区域距离

static inline BOOL isIPhoneXSeries() {
if (@available(iOS 11.0, *)) {
UIWindow *mainWindow = [[[UIApplication sharedApplication] delegate] window];
if (mainWindow.safeAreaInsets.bottom > 0.0) {
return YES;
}
}
return NO;
}

2.2 分页并发适配

方式1. 升级MJRefresh到3.7.5版本 ​​Fix/duplicated async method -> Installing MJRefresh 3.7.5 (was 3.3.1)​

- (void)executeRefreshingCallback
{
if (self.refreshingBlock) {
self.refreshingBlock();
}
if ([self.refreshingTarget respondsToSelector:self.refreshingAction]) {
MJRefreshMsgSend(MJRefreshMsgTarget(self.refreshingTarget), self.refreshingAction, self);
}
if (self.beginRefreshingCompletionBlock) {
self.beginRefreshingCompletionBlock();
}
}

方式2. 使用自动刷新控件​​MJRefreshNormalHeader->MJRefreshAutoNormalFooter​

iOS小技能:下拉刷新控件的适配_#import_04

see also

公号:iOS逆向

举报

相关推荐

0 条评论