Commit 68290a71 cgx

首页轮播图

1 个父辈 4d307e26
......@@ -8,6 +8,14 @@
/* Begin PBXBuildFile section */
39CC172FB610DA5F29120B56 /* Pods_DreamSleep.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2D11699D88A7A7BDB6168B71 /* Pods_DreamSleep.framework */; settings = {ATTRIBUTES = (Required, ); }; };
D01814D127FFCBAF00583D4E /* CWCarousel.m in Sources */ = {isa = PBXBuildFile; fileRef = D01814CB27FFCBAF00583D4E /* CWCarousel.m */; };
D01814D227FFCBAF00583D4E /* CWFlowLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = D01814CD27FFCBAF00583D4E /* CWFlowLayout.m */; };
D01814D527FFCCFA00583D4E /* HomeTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = D01814D427FFCCFA00583D4E /* HomeTableView.m */; };
D01814DC27FFD92200583D4E /* DSDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = D01814DB27FFD92200583D4E /* DSDataSource.m */; };
D01814DF27FFDB6A00583D4E /* HomeTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = D01814DE27FFDB6A00583D4E /* HomeTableViewCell.m */; };
D01814E227FFDBB800583D4E /* HomeHeaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = D01814E127FFDBB800583D4E /* HomeHeaderView.m */; };
D01814E5280016EA00583D4E /* CarouselModel.m in Sources */ = {isa = PBXBuildFile; fileRef = D01814E4280016EA00583D4E /* CarouselModel.m */; };
D01814E8280020F900583D4E /* CWPageControl.m in Sources */ = {isa = PBXBuildFile; fileRef = D01814E6280020F800583D4E /* CWPageControl.m */; };
D027EE2627FB3DC0004BBA61 /* NetLoadingStateView.m in Sources */ = {isa = PBXBuildFile; fileRef = D027EE2527FB3DC0004BBA61 /* NetLoadingStateView.m */; };
D027EE2927FB51D0004BBA61 /* DSGifHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = D027EE2827FB51D0004BBA61 /* DSGifHeader.m */; };
D027EE3027FB52DA004BBA61 /* UIImage+Extras.m in Sources */ = {isa = PBXBuildFile; fileRef = D027EE2F27FB52DA004BBA61 /* UIImage+Extras.m */; };
......@@ -47,6 +55,24 @@
2D11699D88A7A7BDB6168B71 /* Pods_DreamSleep.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_DreamSleep.framework; sourceTree = BUILT_PRODUCTS_DIR; };
72E2054B343085AE9898C560 /* Pods-DreamSleep.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DreamSleep.debug.xcconfig"; path = "Target Support Files/Pods-DreamSleep/Pods-DreamSleep.debug.xcconfig"; sourceTree = "<group>"; };
9B4D4A8254C6E2872914AB4D /* Pods-DreamSleep.beta.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DreamSleep.beta.xcconfig"; path = "Target Support Files/Pods-DreamSleep/Pods-DreamSleep.beta.xcconfig"; sourceTree = "<group>"; };
D01814CB27FFCBAF00583D4E /* CWCarousel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CWCarousel.m; sourceTree = "<group>"; };
D01814CC27FFCBAF00583D4E /* CWCarouselHeader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CWCarouselHeader.h; sourceTree = "<group>"; };
D01814CD27FFCBAF00583D4E /* CWFlowLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CWFlowLayout.m; sourceTree = "<group>"; };
D01814CE27FFCBAF00583D4E /* CWCarouselProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CWCarouselProtocol.h; sourceTree = "<group>"; };
D01814CF27FFCBAF00583D4E /* CWCarousel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CWCarousel.h; sourceTree = "<group>"; };
D01814D027FFCBAF00583D4E /* CWFlowLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CWFlowLayout.h; sourceTree = "<group>"; };
D01814D327FFCCFA00583D4E /* HomeTableView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HomeTableView.h; sourceTree = "<group>"; };
D01814D427FFCCFA00583D4E /* HomeTableView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HomeTableView.m; sourceTree = "<group>"; };
D01814DA27FFD92200583D4E /* DSDataSource.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DSDataSource.h; sourceTree = "<group>"; };
D01814DB27FFD92200583D4E /* DSDataSource.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DSDataSource.m; sourceTree = "<group>"; };
D01814DD27FFDB6A00583D4E /* HomeTableViewCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HomeTableViewCell.h; sourceTree = "<group>"; };
D01814DE27FFDB6A00583D4E /* HomeTableViewCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HomeTableViewCell.m; sourceTree = "<group>"; };
D01814E027FFDBB800583D4E /* HomeHeaderView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HomeHeaderView.h; sourceTree = "<group>"; };
D01814E127FFDBB800583D4E /* HomeHeaderView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HomeHeaderView.m; sourceTree = "<group>"; };
D01814E3280016EA00583D4E /* CarouselModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CarouselModel.h; sourceTree = "<group>"; };
D01814E4280016EA00583D4E /* CarouselModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CarouselModel.m; sourceTree = "<group>"; };
D01814E6280020F800583D4E /* CWPageControl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CWPageControl.m; sourceTree = "<group>"; };
D01814E7280020F900583D4E /* CWPageControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CWPageControl.h; sourceTree = "<group>"; };
D027EE2427FB3DC0004BBA61 /* NetLoadingStateView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NetLoadingStateView.h; sourceTree = "<group>"; };
D027EE2527FB3DC0004BBA61 /* NetLoadingStateView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NetLoadingStateView.m; sourceTree = "<group>"; };
D027EE2727FB51D0004BBA61 /* DSGifHeader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DSGifHeader.h; sourceTree = "<group>"; };
......@@ -136,6 +162,30 @@
name = Frameworks;
sourceTree = "<group>";
};
D01814CA27FFCBAF00583D4E /* CWCarousel */ = {
isa = PBXGroup;
children = (
D01814CF27FFCBAF00583D4E /* CWCarousel.h */,
D01814CB27FFCBAF00583D4E /* CWCarousel.m */,
D01814D027FFCBAF00583D4E /* CWFlowLayout.h */,
D01814CD27FFCBAF00583D4E /* CWFlowLayout.m */,
D01814E7280020F900583D4E /* CWPageControl.h */,
D01814E6280020F800583D4E /* CWPageControl.m */,
D01814CC27FFCBAF00583D4E /* CWCarouselHeader.h */,
D01814CE27FFCBAF00583D4E /* CWCarouselProtocol.h */,
);
path = CWCarousel;
sourceTree = "<group>";
};
D01814D927FFD91100583D4E /* DataSource */ = {
isa = PBXGroup;
children = (
D01814DA27FFD92200583D4E /* DSDataSource.h */,
D01814DB27FFD92200583D4E /* DSDataSource.m */,
);
path = DataSource;
sourceTree = "<group>";
};
D027EE2327FB3C99004BBA61 /* Network */ = {
isa = PBXGroup;
children = (
......@@ -204,6 +254,14 @@
D04B3DB227F6F6070022F8DF /* Home.storyboard */,
D04B3DC127F6F9390022F8DF /* HomeViewController.h */,
D04B3DC227F6F9390022F8DF /* HomeViewController.m */,
D01814E3280016EA00583D4E /* CarouselModel.h */,
D01814E4280016EA00583D4E /* CarouselModel.m */,
D01814E027FFDBB800583D4E /* HomeHeaderView.h */,
D01814E127FFDBB800583D4E /* HomeHeaderView.m */,
D01814D327FFCCFA00583D4E /* HomeTableView.h */,
D01814D427FFCCFA00583D4E /* HomeTableView.m */,
D01814DD27FFDB6A00583D4E /* HomeTableViewCell.h */,
D01814DE27FFDB6A00583D4E /* HomeTableViewCell.m */,
);
path = Home;
sourceTree = "<group>";
......@@ -311,6 +369,8 @@
D0E9408127FE961300D57495 /* Vendors */ = {
isa = PBXGroup;
children = (
D01814CA27FFCBAF00583D4E /* CWCarousel */,
D01814D927FFD91100583D4E /* DataSource */,
D0E9408227FE96A900D57495 /* WechatOpenSDK_1.9.2_NoPay */,
);
path = Vendors;
......@@ -460,24 +520,32 @@
buildActionMask = 2147483647;
files = (
D04B3D9A27F6D4D90022F8DF /* LeadingController.m in Sources */,
D01814E5280016EA00583D4E /* CarouselModel.m in Sources */,
D0B5ECAC27F2D9DE003EDFE3 /* ViewController.m in Sources */,
D0B5ECD827F2F1B0003EDFE3 /* ServerAPIUtil.m in Sources */,
D0B5ECA627F2D9DE003EDFE3 /* AppDelegate.m in Sources */,
D04B3DC027F6F82D0022F8DF /* ProfileController.m in Sources */,
D0C50B3027FD1BEB00DC68F0 /* PrivacyView.m in Sources */,
D0B5ECD527F2F0B2003EDFE3 /* AdaptationUtil.m in Sources */,
D01814D127FFCBAF00583D4E /* CWCarousel.m in Sources */,
D0B5ECB727F2D9E0003EDFE3 /* main.m in Sources */,
D0C50B3F27FD381000DC68F0 /* UIView+Extras.m in Sources */,
D04B3DBB27F6F7940022F8DF /* AISleepCoachController.m in Sources */,
D027EE2627FB3DC0004BBA61 /* NetLoadingStateView.m in Sources */,
D0C50B4627FD66FB00DC68F0 /* DSConstUtil.m in Sources */,
D01814D227FFCBAF00583D4E /* CWFlowLayout.m in Sources */,
D01814DF27FFDB6A00583D4E /* HomeTableViewCell.m in Sources */,
D01814D527FFCCFA00583D4E /* HomeTableView.m in Sources */,
D076C14327F49DC000340B46 /* TmpViewController.m in Sources */,
D04B3DAC27F6EEB50022F8DF /* DSTabBarController.m in Sources */,
D0C50B4F27FD832300DC68F0 /* LeadView.m in Sources */,
D0C50B4227FD39C800DC68F0 /* UIViewController+FullScreenModal.m in Sources */,
D027EE2927FB51D0004BBA61 /* DSGifHeader.m in Sources */,
D01814DC27FFD92200583D4E /* DSDataSource.m in Sources */,
D0B5ECC827F2E97A003EDFE3 /* MacroFuncUtil.m in Sources */,
D01814E227FFDBB800583D4E /* HomeHeaderView.m in Sources */,
D0C50B3C27FD2EFD00DC68F0 /* PrivacyViewController.m in Sources */,
D01814E8280020F900583D4E /* CWPageControl.m in Sources */,
D027EE3027FB52DA004BBA61 /* UIImage+Extras.m in Sources */,
D04B3DC327F6F9390022F8DF /* HomeViewController.m in Sources */,
);
......@@ -624,10 +692,10 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = DreamSleep/DreamSleep.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 4NDZ6UX8PW;
DEVELOPMENT_TEAM = SPH85C3TWU;
GCC_PREFIX_HEADER = "${SRCROOT}/DreamSleep/Utils/PrefixHeader.pch";
GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)";
GENERATE_INFOPLIST_FILE = YES;
......@@ -654,9 +722,9 @@
"-all_load",
"-l\"c++\"",
);
PRODUCT_BUNDLE_IDENTIFIER = com.aolei.sleep;
PRODUCT_BUNDLE_IDENTIFIER = com.aolei.sleep.DreamSleep;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = xiaomengSleep_debug_profile;
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_EMIT_LOC_STRINGS = YES;
TARGETED_DEVICE_FAMILY = 1;
};
......@@ -772,10 +840,10 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = DreamSleep/DreamSleep.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 4NDZ6UX8PW;
DEVELOPMENT_TEAM = "";
GCC_PREFIX_HEADER = "${SRCROOT}/DreamSleep/Utils/PrefixHeader.pch";
GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)";
GENERATE_INFOPLIST_FILE = YES;
......@@ -804,7 +872,7 @@
);
PRODUCT_BUNDLE_IDENTIFIER = com.aolei.sleep;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = xiaomengSleep_debug_profile;
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_EMIT_LOC_STRINGS = YES;
TARGETED_DEVICE_FAMILY = 1;
};
......
......@@ -7,8 +7,9 @@
#import "AISleepCoachController.h"
#import <WebKit/WebKit.h>
#import <JavaScriptCore/JavaScriptCore.h>
@interface AISleepCoachController () <WKNavigationDelegate>
@interface AISleepCoachController () <WKNavigationDelegate, WKScriptMessageHandler, WKUIDelegate>
@property (strong, nonatomic) WKWebView *aiWebView;
@property (nonatomic, strong) UIProgressView *progressView;
@end
......@@ -54,15 +55,65 @@
DSLog(@"百度主页加载失败:%@", error.userInfo);
}
//iOS端 wkwebview代理方法
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
if ([navigationAction.request.URL.absoluteString isEqualToString:@"xc://scan"]) {
//调用原生扫描二维码
decisionHandler(WKNavigationActionPolicyCancel);
return;
}
decisionHandler(WKNavigationActionPolicyAllow);
}
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
if ([message.name isEqualToString:@"click"]) {
// NSDictionary *jsData = message.body;
// NSLog(@"%@", message.name);
//读取js function的字符串
// NSString *jsFunctionString = jsData[@"result"];
// //拼接调用该方法的js字符串(convertDictionaryToJson:方法将NSDictionary转成JSON格式的字符串)
// NSString *jsonString = [NSDictionary convertDictionaryToJson:@{@"test":@"123", @"data":@"666"}];
// NSString *jsCallBack = [NSString stringWithFormat:@"(%@)(%@);", jsFunctionString, jsonString];
// //执行回调
// [self.weWebView evaluateJavaScript:jsCallBack completionHandler:^(id _Nullable result, NSError * _Nullable error) {
// if (error) {
// NSLog(@"err is %@", error.domain);
// }
// }];
}
}
- (WKWebView *)aiWebView {
if (!_aiWebView) {
_aiWebView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, kScreenHeight - kTabBarHeight)];
// _aiWebView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, kScreenHeight - kTabBarHeight)];
// _aiWebView.backgroundColor = DSWhite;
// 进行配置控制器
WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
// 实例化对象
configuration.userContentController = [WKUserContentController new];
// 调用JS方法
[configuration.userContentController addScriptMessageHandler:self name:@"click"];
// 进行偏好设置
WKPreferences *preferences = [WKPreferences new];
preferences.javaScriptCanOpenWindowsAutomatically = YES;
configuration.preferences = preferences;
// 初始化WKWebView
_aiWebView = [[WKWebView alloc]initWithFrame:CGRectMake(0, 0, kScreenWidth, kScreenHeight - kTabBarHeight) configuration:configuration];
_aiWebView.backgroundColor = DSWhite;
_aiWebView.UIDelegate = self;
[_aiWebView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];
_aiWebView.navigationDelegate = self;
_aiWebView.scrollView.showsVerticalScrollIndicator = NO;
_aiWebView.scrollView.showsHorizontalScrollIndicator = NO;
// iOS 11:
_aiWebView.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
// 测试地址:https://www.cbti.cn/sleep/ai/sleep_aicocah
NSURL *url = [NSURL URLWithString:@"https://cbti.mynatapp.cc/sleep/ai/sleep_aicocah"];
......@@ -77,7 +128,7 @@
_progressView = [[UIProgressView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, 0)];
_progressView.tintColor = HighlightColor;
// 通过放大Y轴来改变高度
_progressView.transform = CGAffineTransformMakeScale(1.0f, 5.0f);;
_progressView.transform = CGAffineTransformMakeScale(1.0f, 3.0f);;
}
return _progressView;
}
......
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.developer.associated-domains</key>
<array>
<string>applinks:https://help.wechat.com/sdksample/</string>
</array>
</dict>
<dict/>
</plist>
//
// CarouselModel.h
// DreamSleep
//
// Created by peter on 2022/4/8.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface CarouselModel : NSObject
+ (NSArray *)getCarouselImages;
@end
NS_ASSUME_NONNULL_END
//
// CarouselModel.m
// DreamSleep
//
// Created by peter on 2022/4/8.
//
#import "CarouselModel.h"
@implementation CarouselModel
+ (NSArray *)getCarouselImages {
return @[@"banner1", @"banner2", @"banner3", @"banner4"];;
}
@end
//
// HomeHeaderView.h
// DreamSleep
//
// Created by peter on 2022/4/8.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface HomeHeaderView : UIView
@end
NS_ASSUME_NONNULL_END
//
// HomeHeaderView.m
// DreamSleep
//
// Created by peter on 2022/4/8.
//
#import "HomeHeaderView.h"
#import "CWCarousel.h"
#import "CWPageControl.h"
#import "CarouselModel.h"
@interface HomeHeaderView () <CWCarouselDatasource, CWCarouselDelegate>
// 轮播图
@property (nonatomic, strong) CWCarousel *barnnerView;
@property (nonatomic, strong) NSArray *imgs;
@end
@implementation HomeHeaderView
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
self.imgs = [CarouselModel getCarouselImages];
[self addSubview:self.barnnerView];
dispatch_after(1, dispatch_get_main_queue(), ^{
[self.barnnerView freshCarousel];
});
}
return self;
}
- (void)layoutSubviews {
[self.barnnerView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self).offset(15);
make.width.mas_equalTo(self);
make.height.mas_equalTo(2*(kScreenWidth - 48)/5);
}];
}
- (CWCarousel *)barnnerView {
if (!_barnnerView) {
// 自定义布局
CWFlowLayout *flowLayout = [[CWFlowLayout alloc] initWithStyle:CWCarouselStyle_H_2];
flowLayout.itemWidth = kScreenWidth - 48;
flowLayout.itemSpace_H = 12;
// 自定义pagecontrol
CGFloat width = [CWPageControl widthFromNumber:self.imgs.count];
CWPageControl *pageC = [[CWPageControl alloc] initWithFrame:CGRectMake(0, 0, width, 20)];
pageC.translatesAutoresizingMaskIntoConstraints = NO;
[[pageC.widthAnchor constraintEqualToConstant:width] setActive:YES];
_barnnerView = [[CWCarousel alloc] initWithFrame:CGRectZero
delegate:self
datasource:self
flowLayout:flowLayout];
_barnnerView.translatesAutoresizingMaskIntoConstraints = NO;
_barnnerView.isAuto = YES;
_barnnerView.endless = YES;
_barnnerView.autoTimInterval = 3;
_barnnerView.backgroundColor = self.backgroundColor;
_barnnerView.customPageControl = pageC;
[_barnnerView registerViewClass:[UICollectionViewCell class] identifier:@"barnnerCellID"];
}
return _barnnerView;
}
#pragma mark - CWCarouselDatasource
- (NSInteger)numbersForCarousel {
return self.imgs.count;
}
#define TmpTag 666
- (UICollectionViewCell *)viewForCarousel:(CWCarousel *)carousel indexPath:(NSIndexPath *)indexPath index:(NSInteger)index{
UICollectionViewCell *cell = [carousel.carouselView dequeueReusableCellWithReuseIdentifier:@"barnnerCellID" forIndexPath:indexPath];
UIImageView *imgView = [cell.contentView viewWithTag:TmpTag];
if(!imgView) {
imgView = [[UIImageView alloc] initWithFrame:cell.contentView.bounds];
imgView.tag = TmpTag;
imgView.contentMode = UIViewContentModeScaleAspectFit;
[cell.contentView addSubview:imgView];
}
[imgView setImage:[UIImage imageNamed:self.imgs[index]]];
// 通过alpha来控制夜间模式
// imgView.alpha = .5;
return cell;
}
#pragma mark - CWCarouselDelegate
- (void)CWCarousel:(CWCarousel *)carousel didSelectedAtIndex:(NSInteger)index {
DSLog(@"did selected at index %ld", index);
// 判断是否登录
}
@end
//
// HomeTableView.h
// DreamSleep
//
// Created by peter on 2022/4/8.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface HomeTableView : UITableView
- (instancetype)initDemo;
@end
NS_ASSUME_NONNULL_END
//
// HomeTableView.m
// DreamSleep
//
// Created by peter on 2022/4/8.
//
#import "HomeTableView.h"
#import "DSGifHeader.h"
#import "HomeTableViewCell.h"
#import "HomeHeaderView.h"
@interface HomeTableView ()
@property (nonatomic, strong) HomeHeaderView *headerView;
@property (nonatomic, strong) DSDataSource *homeDataSource;
@end
@implementation HomeTableView
- (instancetype)initDemo {
if (self = [super initWithFrame:CGRectMake(0, 0, kScreenWidth, kScreenHeight) style:UITableViewStylePlain]) {
self.dk_backgroundColorPicker = DKColorPickerWithKey(VCViewBG);
self.mj_header = [DSGifHeader headerWithRefreshingBlock:^{
dispatch_after(2.0, dispatch_get_main_queue(), ^{
[self.mj_header endRefreshing];
});
}];
[self.homeDataSource addDataArray:@[]];
// [self debugViewShowBorder];
}
return self;
}
- (void)layoutSubviews {
[self.headerView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self);
make.width.mas_equalTo(self);
make.height.mas_equalTo(@300);
}];
}
- (DSDataSource *)homeDataSource {
if (!_homeDataSource) {
CellConfigureBlock cellBlock = ^(id cell, id model, NSIndexPath * indexPath) {
// [cell configureCell:model];
};
NSString * const homeCellIdentifier = @"HomeCellIdentifier";
_homeDataSource = [[DSDataSource alloc] initWithIdentifier:homeCellIdentifier datas:@[] isSection:NO configureBlock:cellBlock];
self.dataSource = _homeDataSource;
[self registerClass:[HomeTableViewCell class] forCellReuseIdentifier:homeCellIdentifier];
self.tableHeaderView = self.headerView;
}
return _homeDataSource;
}
- (HomeHeaderView *)headerView {
if (!_headerView) {
_headerView = [[HomeHeaderView alloc] init];
}
return _headerView;
}
@end
//
// HomeTableViewCell.h
// DreamSleep
//
// Created by peter on 2022/4/8.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface HomeTableViewCell : UITableViewCell
@end
NS_ASSUME_NONNULL_END
//
// HomeTableViewCell.m
// DreamSleep
//
// Created by peter on 2022/4/8.
//
#import "HomeTableViewCell.h"
@implementation HomeTableViewCell
- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
@end
......@@ -7,9 +7,10 @@
#import "HomeViewController.h"
#import "DSGifHeader.h"
#import "HomeTableView.h"
@interface HomeViewController ()
@property (nonatomic, strong) HomeTableView *homeTV;
@end
@implementation HomeViewController
......@@ -17,6 +18,9 @@
- (void)viewDidLoad {
[super viewDidLoad];
self.view = self.homeTV;
// 导航栏背景色
// self.navigationController.navigationBar.dk_barTintColorPicker = DKColorPickerWithKey(NaviBG);
......@@ -33,13 +37,13 @@
// self.navigationController.navigationBar.shadowImage = [UIImage new];
// view背景色
self.view.dk_backgroundColorPicker = DKColorPickerWithKey(VCViewBG);
// self.view.dk_backgroundColorPicker = DKColorPickerWithKey(VCViewBG);
self.tableView.mj_header = [DSGifHeader headerWithRefreshingBlock:^{
dispatch_after(2.0, dispatch_get_main_queue(), ^{
[self.tableView.mj_header endRefreshing];
});
}];
// self.tableView.mj_header = [DSGifHeader headerWithRefreshingBlock:^{
// dispatch_after(2.0, dispatch_get_main_queue(), ^{
// [self.tableView.mj_header endRefreshing];
// });
// }];
// 设置导航栏返回按钮文字
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc]
......@@ -65,14 +69,21 @@
}
}
#pragma mark - Table view data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 1;
}
//#pragma mark - Table view data source
//- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// return 1;
//}
//
//- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"homeCell" forIndexPath:indexPath];
// return cell;
//}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"homeCell" forIndexPath:indexPath];
return cell;
- (HomeTableView *)homeTV {
if (!_homeTV) {
_homeTV = [[HomeTableView alloc] initDemo];
}
return _homeTV;
}
@end
......@@ -20,9 +20,11 @@
self.window = [UIWindow.alloc initWithFrame:UIScreen.mainScreen.bounds];
self.window.backgroundColor = DSWhite;
[self.window makeKeyAndVisible];
UIStoryboard * mainStoryBoard =[UIStoryboard storyboardWithName:@"Main" bundle:nil];
self.window.rootViewController = [mainStoryBoard instantiateViewControllerWithIdentifier:@"mainSB"];
UINavigationController *navi = [[UINavigationController alloc] initWithRootViewController:[[PrivacyViewController alloc] init]];
self.window.rootViewController = navi;
// UINavigationController *navi = [[UINavigationController alloc] initWithRootViewController:[[PrivacyViewController alloc] init]];
// self.window.rootViewController = navi;
[self initWeChat];
......
......@@ -13,6 +13,8 @@
#import "AdaptationUtil.h"
#import "MacroFuncUtil.h"
#import "DSDataSource.h"
#import <DKNightVersion/DKNightVersion.h>
#import <Masonry/Masonry.h>
......
//
// CWCarousel.h
// CWCarousel
//
// Created by WangChen on 2018/4/3.
// Copyright © 2018年 ChenWang. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "CWCarouselProtocol.h"
#import "CWFlowLayout.h"
@class CWCarouselCollectionView;
@interface CWCarousel : UIView
#pragma mark - < 相关属性 >
/**
控件版本号
*/
@property (nonatomic, readonly, copy) NSString * _Nullable version;
/**
相关代理
*/
@property (nonatomic, assign) id <CWCarouselDelegate> _Nullable delegate;
/**
相关数据源
*/
@property (nonatomic, assign) id <CWCarouselDatasource> _Nullable datasource;
/**
布局自定义layout
*/
@property (nonatomic, strong, readonly) CWFlowLayout * _Nonnull flowLayout;
/**
样式风格
*/
@property (nonatomic, assign, readonly) CWCarouselStyle style;
/**
style = CWCarouselStyle_H_3时的扩展高度 (1.1.0版本后该属性废弃,请不要使用了)
*/
@property (nonatomic, assign, readonly) CGFloat addHeight;
/**
实际的示轮播图内容的视图(其实就是基于collectionView实现的)
*/
@property (nonatomic, strong, readonly) CWCarouselCollectionView * _Nonnull carouselView;
/**
是否自动轮播, 默认为NO
*/
@property (nonatomic, assign) BOOL isAuto;
/**
自动轮播时间间隔, 默认 3s
*/
@property (nonatomic, assign) NSTimeInterval autoTimInterval;
/**
默认的pageControl, 当设置了customPageControl时, 该属性为nil
*/
@property (nonatomic, strong) UIPageControl * _Nullable pageControl;
/**
自定义的pageControl
*/
@property (nonatomic, strong) UIView<CWCarouselPageControlProtocol> * _Nullable customPageControl;
/**
是否开始无限轮播
YES: 可以无限衔接
NO: 滑动到第一张或者最后一张就不能滑动了
*/
@property (nonatomic, assign) BOOL endless;
#pragma mark - < 相关方法 >
/**
创建实例构造方法
@param frame 尺寸大小
@param delegate 代理
@param datasource 数据源
@param flowLayout 自定义flowlayout
@return 实例对象
*/
- (instancetype _Nullable )initWithFrame:(CGRect)frame
delegate:(id<CWCarouselDelegate> _Nullable)delegate
datasource:(id<CWCarouselDatasource> _Nullable)datasource
flowLayout:(nonnull CWFlowLayout *)flowLayout;
/**
注册自定视图
@param viewClass 自定义视图类名
@param identifier 重用唯一标识符
*/
- (void)registerViewClass:(Class _Nullable )viewClass identifier:(NSString *_Nullable)identifier;
/**
注册自定义视图
@param nibName 自定义视图xib相关文件名
@param identifier 重用唯一标识符
*/
- (void)registerNibView:(NSString *_Nullable)nibName identifier:(NSString *_Nullable)identifier;
/**
刷新轮播图
*/
- (void)freshCarousel;
/**
暂停轮播图后,可以调用改方法继续播放
*/
- (void)resumePlay;
/**
轮播图暂停自动播放
*/
- (void)pause;
/**
如果开启自动轮播,销毁前需要调用该方法,释放定时器.否则可能内存泄漏
注: 1.1.9版本之后无需再手动调用该方法, 控件内部会自动释放.
*/
- (void)releaseTimer;
/**
轮播图所处控制器WillAppear方法里调用
*/
- (void)controllerWillAppear;
/**
轮播图所处控制器WillDisAppear方法里调用
*/
- (void)controllerWillDisAppear;
/// 滚动到指定下标
/// @param index 指定下标
/// @param animation 是否开启滚动动画
- (void)scrollTo:(NSInteger)index animation:(BOOL)animation;
@end
@interface CWCarouselCollectionView: UICollectionView<UIGestureRecognizerDelegate>
@end
//
// CWCarousel.m
// CWCarousel
//
// Created by WangChen on 2018/4/3.
// Copyright © 2018年 ChenWang. All rights reserved.
//
#import "CWCarousel.h"
@interface CWCarouselCollectionView()
@property (nonatomic, copy) void (^ _Nullable tapCallback) (void);
@end
@implementation CWCarouselCollectionView
- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout {
if(self = [super initWithFrame:frame collectionViewLayout:layout]) {
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction:)];
[self addGestureRecognizer:tap];
tap.delegate = self;
}
return self;
}
- (void)tapAction:(UITapGestureRecognizer *)tap {
if (!self.tapCallback) {
return;
}
self.tapCallback();
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if ([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]] == NO) {
return YES;
}
if ([[touch view] isKindOfClass:[UICollectionView class]]) {
return YES;
}
return NO;
}
- (void)dealloc {
NSLog(@"[CWCarouselCollectionView dealloc]");
}
@end
@interface CWTempleteCell: UICollectionViewCell
@end
@implementation CWTempleteCell
@end
@interface MyProxy : NSProxy
@property (nonatomic, weak) id _Nullable target;
- (instancetype)init:(id)target;
@end
@implementation MyProxy
- (instancetype)init:(id)target {
self.target = target;
return self;
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
return [self.target methodSignatureForSelector:sel];
}
- (void)forwardInvocation:(NSInvocation *)invocation {
[invocation invokeWithTarget:self.target];
}
@end
@interface CWCarousel ()<UICollectionViewDelegate, UICollectionViewDataSource> {
}
/// collectionView
@property (nonatomic, strong) CWCarouselCollectionView *carouselView;
/// 轮播总数
@property (nonatomic, assign) NSInteger numbers;
/// 当前居中的业务逻辑下标
@property (nonatomic, assign) NSInteger currentIndex;
/// 当前居中的实际下标
@property (nonatomic, assign) NSInteger infactIndex;
/// (已经废弃)
@property (nonatomic, assign) CGFloat addHeight;
/**
自动播放是否暂停
*/
@property (nonatomic, assign) BOOL isPause;
/**
当前展示在中间的cell下标
*/
@property (nonatomic, strong) NSIndexPath *currentIndexPath;
@property (nonatomic, strong) MyProxy *timerProxy;
@property (nonatomic, strong) NSTimer *timer;
@end
@implementation CWCarousel
@synthesize carouselView = _carouselView;
- (instancetype)initWithFrame:(CGRect)frame delegate:(id<CWCarouselDelegate>)delegate datasource:(id<CWCarouselDatasource>)datasource flowLayout:(CWFlowLayout *)flowLayout {
CGFloat addHeight = 0;
frame.size.height += addHeight;
self.addHeight = addHeight;
if(self = [super initWithFrame:frame]) {
_flowLayout = flowLayout;
self.delegate = delegate;
self.datasource = datasource;
self.isAuto = NO;
self.autoTimInterval = 3;
self.endless = YES;
[self configureView];
[self addNotify];
}
NSAssert(self != nil, @"CWCarousel 初始化失败!");
return self;
}
- (void)appBecomeInactive:(NSNotification *)notification {
[self adjustErrorCell:YES];
}
- (void)appBecomeActive:(NSNotification *)notification {
[self adjustErrorCell:YES];
}
- (void)controllerWillAppear {
if(self.isAuto) {
[self resumePlay];
}
[self addNotify];
[self adjustErrorCell:YES];
}
- (void)controllerWillDisAppear {
if(self.isAuto) {
[self pause];
}
[self removeNotify];
[self adjustErrorCell:YES];
}
- (void)addNotify {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appBecomeInactive:) name:UIApplicationWillResignActiveNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil];
}
- (void)removeNotify {
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillResignActiveNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil];
}
- (void)dealloc {
NSLog(@"[CWCarousel dealloc]");
[self removeNotify];
[self releaseTimer];
}
- (void)willMoveToSuperview:(UIView *)newSuperview {
[super willMoveToSuperview:newSuperview];
if (nil == self.customPageControl && nil == self.pageControl.superview) {
[self configurePageControl];
}
}
- (void)willMoveToWindow:(UIWindow *)newWindow {
[super willMoveToWindow:newWindow];
if (nil == self.customPageControl && nil == self.pageControl.superview) {
[self configurePageControl];
}
}
- (void)registerViewClass:(Class)viewClass identifier:(NSString *)identifier {
[self.carouselView registerClass:viewClass forCellWithReuseIdentifier:identifier];
}
- (void)registerNibView:(NSString *)nibName identifier:(NSString *)identifier {
[self.carouselView registerNib:[UINib nibWithNibName:nibName bundle:[NSBundle mainBundle]]
forCellWithReuseIdentifier:identifier];
}
- (void)freshCarousel {
if([self numbers] < 0) {
return;
}
[self.carouselView reloadData];
[self layoutIfNeeded];
if (self.endless)
[self.carouselView scrollToItemAtIndexPath:[self originIndexPath] atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:NO];
else {
if(self.flowLayout.style == CWCarouselStyle_Normal) {
[self.carouselView scrollToItemAtIndexPath:self.currentIndexPath = [NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:NO];
}
else {
[self.carouselView scrollToItemAtIndexPath:self.currentIndexPath = [NSIndexPath indexPathForRow:1 inSection:0] atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:NO];
}
}
self.carouselView.userInteractionEnabled = YES;
if (self.isAuto) {
[self play];
}
}
#pragma mark - < Scroll Delegate >
/// 开始拖拽
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
// 防止拖动加速度太大,一次跳过多张图片,这里设置一下
if (@available(iOS 14.0, *)) {
scrollView.pagingEnabled = NO;
} else {
scrollView.pagingEnabled = YES;
}
if (self.isAuto) {
[self stop];
}
if (self.delegate && [self.delegate respondsToSelector:@selector(CWCarousel:didStartScrollAtIndex:indexPathRow:)]) {
[self.delegate CWCarousel:self didStartScrollAtIndex:[self caculateIndex:self.currentIndexPath.row] indexPathRow:self.currentIndexPath.row];
}
}
/// 将要结束拖拽
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {
NSInteger num = [self numbers];
if (num <= 0) {
return;
}
if (self.endless == NO)
{
// 非无限轮播
NSInteger maxIndex = num - 1;
NSInteger minIndex = 0;
if(self.flowLayout.style != CWCarouselStyle_Normal)
{
// 后面有一个占位cell, 所以减2, 不是减1
maxIndex = [self infactNumbers] - 2;
// 前面有一个占位cell, 所以下标是从1开始
minIndex = 1;
}
if (velocity.x == 0) {
[self velocityZero];
return;
}
if (velocity.x >= 0 && self.currentIndexPath.row == maxIndex) {
// 已经是最后一张了
return;
}
if (velocity.x <= 0 && self.currentIndexPath.row == minIndex) {
// 已经是第一张了
return;
}
}
if(velocity.x > 0) {
//左滑,下一张
self.currentIndexPath = [NSIndexPath indexPathForRow:self.currentIndexPath.row + 1 inSection:self.currentIndexPath.section];
}else if (velocity.x < 0) {
//右滑,上一张
self.currentIndexPath = [NSIndexPath indexPathForRow:self.currentIndexPath.row - 1 inSection:self.currentIndexPath.section];
}else if (velocity.x == 0) {
[self velocityZero];
}
}
/// 开始减速
- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView {
[self cusScrollViewWillBeginDecelerating:YES scroll:scrollView];
}
- (void)cusScrollViewWillBeginDecelerating:(BOOL)animation scroll:(UIScrollView *)scrollView{
if (self.currentIndexPath == nil) {
return;
}
if (self.currentIndexPath.row >= [self infactNumbers]) {
return;
}
if (self.currentIndexPath.row < 0) {
return;
}
// 中间一张轮播,居中显示
if (self.endless == NO)
{
// 非无限轮播, 非CWCarouselStyle_Normal样式下, 前后有两张占位cell, 这里需要处理一下.
if (self.currentIndexPath.row == 0 && self.style != CWCarouselStyle_Normal) {
self.currentIndexPath = [NSIndexPath indexPathForRow:1 inSection:self.currentIndexPath.section];
}else if (self.currentIndexPath.row == [self infactNumbers] - 1 && self.style != CWCarouselStyle_Normal) {
self.currentIndexPath = [NSIndexPath indexPathForRow:[self infactNumbers] - 2 inSection:self.currentIndexPath.section];
}
}
[self.carouselView scrollToItemAtIndexPath:self.currentIndexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:animation];
if (animation == NO) {
[self cusScrollAnimationEnd:scrollView];
}
}
/// 减速完成
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
// 打开交互
scrollView.pagingEnabled = NO;
if(self.isAuto) {
[self play];
}
}
/// 滚动动画完成
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView {
[self cusScrollAnimationEnd:scrollView];
}
- (void)cusScrollAnimationEnd:(UIScrollView *)scrollView {
// 滚动完成,打开交互,关掉pagingEnabled
// 为什么要关掉pagingEnabled呢,因为切换控制器的时候会有系统级bug,不信你试试.
scrollView.userInteractionEnabled = YES;
scrollView.pagingEnabled = NO;
if(self.isAuto) {
[self play];
}
if (self.endless) {
[self checkOutofBounds];
}
if (self.delegate && [self.delegate respondsToSelector:@selector(CWCarousel:didEndScrollAtIndex:indexPathRow:)]) {
[self.delegate CWCarousel:self didEndScrollAtIndex:[self caculateIndex:self.currentIndexPath.row] indexPathRow:self.currentIndexPath.row];
}
}
// 滚动中
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
}
#pragma mark - < Logic Helper >
- (NSIndexPath *)originIndexPath {
NSInteger num = [self numbers];
if (num <= 0) {
return [[NSIndexPath alloc] initWithIndex:0];
}
if (self.endless == NO) {
NSInteger row = self.flowLayout.style == CWCarouselStyle_Normal ? 0 : 1;
self.currentIndexPath = [NSIndexPath indexPathForRow:row inSection:0];
return self.currentIndexPath;
}
NSInteger centerIndex = [self infactNumbers] / num; //一共有多少组
if (centerIndex == 0) {
// 异常, 一组都没有
NSAssert(true, @"计算起始下标异常, 分组不足一组.");
return self.currentIndexPath = [NSIndexPath indexPathForRow:0 inSection:0];
}
if (centerIndex == 1) {
return self.currentIndexPath = [NSIndexPath indexPathForRow:0 inSection:0];
}
// 取中间一组展示
self.currentIndexPath = [NSIndexPath indexPathForRow:centerIndex / 2 * num inSection:0];
return self.currentIndexPath;
}
// 检测是否到了边界
- (void)checkOutofBounds {
if ([self numbers] <= 0) {return;}
BOOL scroll = NO;
NSInteger index = self.currentIndex;
// 越界检查
if(self.currentIndexPath.row == [self infactNumbers] - 1) {
index = [self caculateIndex:self.currentIndexPath.row] - 1; //最后一张
scroll = YES;
}else if(self.currentIndexPath.row == 0) {
index = [self caculateIndex:self.currentIndexPath.row]; //第一张
scroll = YES;
}
self.carouselView.userInteractionEnabled = YES;
if (scroll == NO) {
return;
}
NSIndexPath *origin = [self originIndexPath];
self.currentIndexPath = [NSIndexPath indexPathForRow:origin.row + index inSection:origin.section];
[self.carouselView scrollToItemAtIndexPath:self.currentIndexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:NO];
}
/**
实际下标转换成业务需求下标
@param factIndex 实际下标
@return 业务需求下标
*/
- (NSInteger)caculateIndex:(NSInteger)factIndex {
NSInteger num = [self numbers];
if (num <= 0) {
return 0;
}
NSInteger row = factIndex % num;
if(self.endless == NO && self.flowLayout.style != CWCarouselStyle_Normal) {
// 这种情况有占位cell
row = factIndex % [self infactNumbers] - 1;
}
return row;
}
- (void)adjustErrorCell:(BOOL)isScroll {
NSArray <NSIndexPath *> *indexPaths = [self.carouselView indexPathsForVisibleItems];
CGFloat centerX = self.carouselView.contentOffset.x + CGRectGetWidth(self.carouselView.frame) * 0.5;
__block CGFloat minSpace = MAXFLOAT;
[indexPaths enumerateObjectsUsingBlock:^(NSIndexPath * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
UICollectionViewLayoutAttributes *attri = [self.carouselView layoutAttributesForItemAtIndexPath:obj];
attri.zIndex = 0;
if(ABS(minSpace) > ABS(attri.center.x - centerX)) {
minSpace = attri.center.x - centerX;
self.currentIndexPath = attri.indexPath;
}
}];
if(isScroll) {
[self scrollViewWillBeginDecelerating:self.carouselView];
}
}
/// velocity == 0时的处理
- (void)velocityZero {
// 还有一种情况,当滑动后手指按住不放,然后松开,此时的加速度其实是为0的
[self adjustErrorCell:NO];
if (@available(iOS 14.0, *)) {
// iOS14以前,就算加速度为0,后续系统会还是会走scrollViewWillBeginDecelerating:回调
// 但是iOS14以后,加速度为0时,不会在后续执行回调.这里手动触发一下
[self scrollViewWillBeginDecelerating:self.carouselView];
}
}
- (void)play {
if(self.isPause) {
return;
}
if (NO == self.isAuto) {
return;
}
if (self.timer) {
[self resumePlay];
return;
}
self.timer = [NSTimer timerWithTimeInterval:self.autoTimInterval target:self.timerProxy selector:@selector(nextCell) userInfo:nil repeats:YES];
[self.timer setFireDate:[NSDate dateWithTimeIntervalSinceNow:self.autoTimInterval]];
[[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
}
- (void)nextCell {
if([self numbers] <= 0) {
return;
}
if (!self.isAuto) {
return;
}
NSInteger maxIndex = 1;
if(!self.endless && self.flowLayout.style != CWCarouselStyle_Normal)
{
maxIndex = 2;
}
if(self.currentIndexPath.row < [self infactNumbers] - maxIndex)
{
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:self.currentIndexPath.row + 1 inSection:self.currentIndexPath.section];
[self.carouselView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:YES];
self.currentIndexPath = indexPath;
}
else if(!self.endless)
{
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:maxIndex - 1 inSection:self.currentIndexPath.section];
[self.carouselView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:YES];
self.currentIndexPath = indexPath;
}
}
- (void)stop {
if (!self.timer) {
return;
}
[self.timer setFireDate:[NSDate distantFuture]];
}
- (void)resumePlay {
self.isPause = NO;
if (self.timer) {
[self.timer setFireDate:[NSDate dateWithTimeIntervalSinceNow:self.autoTimInterval]];
return;
}
[self play];
}
- (void)pause {
self.isPause = YES;
[self stop];
}
- (void)releaseTimer {
// [self stop];
if (!self.timer) {
return;
}
[self.timer setFireDate:[NSDate distantFuture]];
[self.timer invalidate];
self.timer = nil;
}
- (void)scrollTo:(NSInteger)index animation:(BOOL)animation {
if (index < 0 || index >= [self numbers]) {
// 防止越界
return;
}
[self stop];
if (index == self.currentIndex) {
[self play];
return;
}
self.currentIndexPath = [NSIndexPath indexPathForRow:self.currentIndexPath.row + (index - self.currentIndex) inSection:0];
[self cusScrollViewWillBeginDecelerating:animation scroll:self.carouselView];
}
- (void)configurePageControl {
UIView *control = self.customPageControl;
BOOL isDefault = NO;
if (nil == control || NO == [control isKindOfClass:[UIView class]]) {
control = self.pageControl;
isDefault = YES;
}
if (self.delegate && [self.delegate respondsToSelector:@selector(CWCarousel:addPageControl:isDefault:)]) {
[self.delegate CWCarousel:self addPageControl:control isDefault:isDefault];
return;
}
[self addSubview:control];
control.translatesAutoresizingMaskIntoConstraints = NO;
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[control(20)]-0-|"
options:kNilOptions
metrics:nil
views:@{@"control" : control}]];
[[control.centerXAnchor constraintEqualToAnchor:self.centerXAnchor] setActive:YES];
}
#pragma mark - < Configure View>
- (void)configureView {
self.backgroundColor = [UIColor blackColor];
self.carouselView.showsVerticalScrollIndicator = NO;
self.carouselView.showsHorizontalScrollIndicator = NO;
self.carouselView.decelerationRate = 0;
}
#pragma mark - < Delegate, Datasource >
- (nonnull __kindof UICollectionViewCell *)collectionView:(nonnull UICollectionView *)collectionView cellForItemAtIndexPath:(nonnull NSIndexPath *)indexPath {
__weak __typeof(&*self) weakSelf = self;
UICollectionViewCell* (^returnCell)(NSIndexPath *) = ^UICollectionViewCell* (NSIndexPath *idx) {
if (self.datasource && [self.datasource respondsToSelector:@selector(viewForCarousel:indexPath:index:)]) {
UICollectionViewCell *cell = [weakSelf.datasource viewForCarousel:weakSelf indexPath:indexPath index:[weakSelf caculateIndex:indexPath.row]];
return cell;
}
return nil;
};
if (self.endless) {
return returnCell(indexPath);
}
if (self.flowLayout.style != CWCarouselStyle_Normal
&& (indexPath.row == 0 || indexPath.row == [self infactNumbers] - 1)) {
// 非无限轮播情况下, "第一个"和"最后一个"是占位cell
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"tempCell" forIndexPath:indexPath];
cell.contentView.backgroundColor = [UIColor clearColor];
return cell;
}
return returnCell(indexPath);
}
- (NSInteger)collectionView:(nonnull UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return [self infactNumbers];
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
if(self.delegate &&
[self.delegate respondsToSelector:@selector(CWCarousel:didSelectedAtIndex:)]) {
[self.delegate CWCarousel:self didSelectedAtIndex:[self caculateIndex:indexPath.row]];
}
// 处于动画中时,点击cell,可能会出现cell不居中问题.这里处理下
// 将里中心点最近的那个cell居中
[self adjustErrorCell:YES];
}
#pragma mark - <setter>
- (void)setBackgroundColor:(UIColor *)backgroundColor {
self.carouselView.backgroundColor = backgroundColor;
[super setBackgroundColor:backgroundColor];
}
- (void)setCurrentIndexPath:(NSIndexPath *)currentIndexPath {
_currentIndexPath = currentIndexPath;
if (_currentIndexPath) {
self.currentIndex = [self caculateIndex:_currentIndexPath.row];
}
if(self.customPageControl == nil)
self.pageControl.currentPage = [self caculateIndex:currentIndexPath.row];
else
self.customPageControl.currentPage = [self caculateIndex:currentIndexPath.row];
}
- (void)setEndless:(BOOL)endless {
if(_endless != endless) {
_endless = endless;
}
}
- (void)setCustomPageControl:(UIView<CWCarouselPageControlProtocol> *)customPageControl {
if (_customPageControl == customPageControl) {
return;
}
if (_customPageControl) {
[_customPageControl removeFromSuperview];
}
_customPageControl = customPageControl;
if (customPageControl && self.pageControl) {
[self.pageControl removeFromSuperview];
self.pageControl = nil;
}
[self configurePageControl];
}
#pragma mark - < getter >
- (UICollectionView *)carouselView {
if(!_carouselView) {
self.carouselView = [[CWCarouselCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:self.flowLayout];
_carouselView.delegate = self;
_carouselView.dataSource = self;
_carouselView.translatesAutoresizingMaskIntoConstraints = NO;
[_carouselView registerClass:[CWTempleteCell class] forCellWithReuseIdentifier:@"tempCell"];
[self addSubview:_carouselView];
NSDictionary *views = @{@"view" : self.carouselView};
NSDictionary *margins = @{@"top" : @(self.addHeight * 0.5),
@"bottom" : @(self.addHeight * 0.5)
};
NSString *str = @"H:|-0-[view]-0-|";
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:str
options:kNilOptions
metrics:margins
views:views]];
str = @"V:|-top-[view]-top-|";
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:str
options:kNilOptions
metrics:margins
views:views]];
__weak __typeof(&*self) weakSelf = self;
[_carouselView setTapCallback:^{
[weakSelf adjustErrorCell:YES];
}];
}
return _carouselView;
}
- (CWCarouselStyle)style {
if(self.flowLayout) {
return self.flowLayout.style;
}
return CWCarouselStyle_Unknow;
}
/**
Description
@return 业务需求需要展示轮播图个数
*/
- (NSInteger)numbers {
if(self.datasource &&
[self.datasource respondsToSelector:@selector(numbersForCarousel)]) {
NSInteger num = [self.datasource numbersForCarousel];
if (self.pageControl) {
self.pageControl.numberOfPages = num;
}
if (self.customPageControl) {
self.customPageControl.pageNumbers = num;
}
return num;
}
return 0;
}
/**
轮播图实际加载视图个数
@return 轮播图实际加载视图个数
*/
- (NSInteger)infactNumbers {
NSInteger num = [self numbers];
if ( num <= 0) {
return 0;
}
[self.carouselView setScrollEnabled:YES];
if (self.endless) {
// 无限轮播
if (num == 1) {
// 只有一张, 不让滚动
[self.carouselView setScrollEnabled:NO];
return num;
}
// 不止一张, 默认加载300个 (cell有复用机制, 不用担心)
return 300;
}
// 非无限轮播, 除了第一种样式, 其他的样式要加2个占位空cell
if(self.flowLayout.style == CWCarouselStyle_Normal) {
return num;
}
if (num == 1) {
[self.carouselView setScrollEnabled:NO];
}
// 前后2个占位cell,所以+2
return num + 2;
}
- (UIPageControl *)pageControl {
if(!_pageControl) {
self.pageControl = [[UIPageControl alloc] initWithFrame:CGRectZero];
_pageControl.pageIndicatorTintColor = [UIColor blackColor];
_pageControl.currentPageIndicatorTintColor = [UIColor whiteColor];
_pageControl.userInteractionEnabled = NO;
}
return _pageControl;
}
- (MyProxy *)timerProxy {
if (!_timerProxy) {
self.timerProxy = [[MyProxy alloc] init:self];
}
return _timerProxy;
}
- (NSString *)version {
return @"1.1.9";
}
@end
//
// CWCarouselHeader.h
// CWCarousel
//
// Created by WangChen on 2018/4/3.
// Copyright © 2018年 ChenWang. All rights reserved.
//
#ifndef CWCarouselHeader_h
#define CWCarouselHeader_h
#import "CWCarousel.h"
#import "CWCarouselProtocol.h"
#endif /* CWCarouselHeader_h */
//
// CWCarouselProtocol.h
// CWCarousel
//
// Created by WangChen on 2018/4/3.
// Copyright © 2018年 ChenWang. All rights reserved.
//
#ifndef CWCarouselProtocol_h
#define CWCarouselProtocol_h
@class CWCarousel;
@protocol CWCarouselDelegate<NSObject>
/**
轮播图点击代理
@param carousel 轮播图实例对象
@param index 被点击的下标
*/
- (void)CWCarousel:(CWCarousel *)carousel didSelectedAtIndex:(NSInteger)index;
@optional
/**
将要开始滑动时,会触发该代理
@param carousel 轮播图控件
@param index 开始滑动时,处于中心点图片的下标
@param indexPathRow 开始滑动时,处于中心点图片的在控件内部的实际下标
*/
- (void)CWCarousel:(CWCarousel *)carousel didStartScrollAtIndex:(NSInteger)index indexPathRow:(NSInteger)indexPathRow;
/**
滑动结束后,会触发该代理
@param carousel 轮播图控件
@param index 结束滑动时,处于中心点图片的下标
@param indexPathRow 结束滑动时,处于中心点图片在控件内部的实际下标
*/
- (void)CWCarousel:(CWCarousel *)carousel didEndScrollAtIndex:(NSInteger)index indexPathRow:(NSInteger)indexPathRow;
/// 开始布局pageControl时会触发该回调
/// @param carousel 轮播组件对象
/// @param pageControl pageControl对象
/// @param isDefault YES: 组件内部默认的UIPageControl, NO: 自定义的customPageControl
///
/// 可以在这个回调中自定义pageControl的布局, 如果没有实现该回调, 将默认在底部居中.
///
/// 注意:
/// 1. 先设置customPageControl, 后将CWCarousel添加到父视图中, 此回调只会被调用一次.
/// 2. 先将CWCarousel添加到父视图中, 后设置customPageControl, 此回调会被调用两次, 第一次isDefault = YES, 第二次isDefault = NO. 因为将CWCarousel添加到父视图时检测到没有customPageControl, 组件内部并不清楚外部调用者是否会设置customPageControl, 会先创建并添加默认的pageControl.
/// 3. 当自定义的customPageControl宽度布局不是自己撑开的时候, 请在该回调中自己布局. 否则采用默认的布局将不可见.
- (void)CWCarousel:(CWCarousel *)carousel addPageControl:(UIView *)pageControl isDefault:(BOOL)isDefault;
@end
@protocol CWCarouselDatasource<NSObject>
/**
轮播图数量
@return 轮播图展示个数
*/
- (NSInteger)numbersForCarousel;
/**
自定义每个轮播图视图
@param carousel 轮播图控件
@param indexPath 轮播图cell实际下标
@param index 业务逻辑需要的下标
@return 自定义视图
*/
- (UICollectionViewCell *)viewForCarousel:(CWCarousel *)carousel indexPath:(NSIndexPath *)indexPath index:(NSInteger)index;
@end
@protocol CWCarouselPageControlProtocol<NSObject>
@required
/**
总页数
*/
@property (nonatomic, assign, readonly) NSInteger pageNumbers;
/**
当前页
*/
@property (nonatomic, assign, readonly) NSInteger currentPage;
- (void)setCurrentPage:(NSInteger)currentPage;
- (void)setPageNumbers:(NSInteger)pageNumbers;
@end
#endif /* CWCarouselProtocol_h */
//
// CWFlowLayout.h
// CWCarousel
//
// Created by WangChen on 2018/4/3.
// Copyright © 2018年 ChenWang. All rights reserved.
//
#import <UIKit/UIKit.h>
typedef NS_ENUM(NSUInteger, CWCarouselStyle) {
CWCarouselStyle_Unknow = 0, ///<未知样式
CWCarouselStyle_Normal, ///<普通样式,一张图占用整个屏幕宽度
CWCarouselStyle_H_1, ///<自定义样式一, 中间一张居中,前后2张图有部分内容在屏幕内可以预览到
CWCarouselStyle_H_2, ///<自定义样式二, 中间一张居中,前后2张图有部分内容在屏幕内可以预览到,并且中间一张图正常大小,前后2张图会缩放
CWCarouselStyle_H_3, ///<自定义样式三, 中间一张居中,前后2张图有部分内容在屏幕内可以预览到,中间一张有放大效果,前后2张正常大小
};
@interface CWFlowLayout : UICollectionViewFlowLayout
/**
影响轮播图风格
*/
@property (nonatomic, assign) CWCarouselStyle style;
/**
* 横向滚动时,每张轮播图之间的间距
* CWCarouselStyle_H_3 样式时请设置负值
*/
@property (nonatomic, assign) CGFloat itemSpace_H;
/**
* 横向滚动时,每张轮播图的宽度
* style = CWCarouselStyle_Normal 时设置无效
*/
@property (nonatomic, assign) CGFloat itemWidth;
/**
* style = CWCarouselStyle_H_2, CWCarouselStyle_H_3 有效
* 前后2张图的缩小比例 (0.0 ~ 1.0)
* 默认: 0.8
*/
@property (nonatomic, assign) CGFloat minScale;
/**
* (注: 1.1.7 版本后该属性已经废弃, 设置该属性将不生效. 请使用 minScale代替.)
* style = CWCarouselStyle_H_3 有效
* 中间一张图放大比例
* 默认: 1.2
* 1.1.0版本后,无论设置多少,中间一张的cell的比例始终是原始size, 这个比例是相对两边cell的size的相对比例
也就是说,该值越大,那么两边的cell就会相对越小.反之越大.
*/
@property (nonatomic, assign) CGFloat maxScale;
/**
纵向滚动时,每张轮播图之间的间距(暂未实现)
*/
@property (nonatomic, assign) CGFloat itemSpace_V;
/**
构造方法
@param style 轮播图风格
@return 实例对象
*/
- (instancetype)initWithStyle:(CWCarouselStyle)style;
@end
//
// CWFlowLayout.m
// CWCarousel
//
// Created by WangChen on 2018/4/3.
// Copyright © 2018年 ChenWang. All rights reserved.
//
#import "CWFlowLayout.h"
@interface CWFlowLayout () {
}
/**
默认轮播图宽度
*/
@property (nonatomic, assign) CGFloat defaultItemWidth;
@property (nonatomic, assign) CGFloat factItemSpace;
@end
@implementation CWFlowLayout
- (instancetype)initWithStyle:(CWCarouselStyle)style {
if(self = [super init]) {
self.style = style;
[self initial];
}
return self;
}
- (void)dealloc {
NSLog(@"%s", __func__);
}
- (void)initial {
self.itemSpace_H = 0;
self.itemSpace_V = 0;
self.minScale = 0.8;
self.maxScale = 1.2;
}
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
if (self.style == CWCarouselStyle_Unknow) {
return NO;
}
if (self.style == CWCarouselStyle_Normal) {
return NO;
}
if (self.style == CWCarouselStyle_H_1) {
return NO;
}
return YES;
}
- (void)prepareLayout {
[super prepareLayout];
switch (self.style) {
case CWCarouselStyle_Normal: {
CGFloat width = CGRectGetWidth(self.collectionView.frame);
CGFloat height = CGRectGetHeight(self.collectionView.frame);
self.itemWidth = width;
self.itemSize = CGSizeMake(width, height);
self.minimumLineSpacing = self.itemSpace_H;
self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
}
break;
case CWCarouselStyle_H_1: {
CGFloat width = self.itemWidth <= 0 ? self.defaultItemWidth : self.itemWidth;
self.itemWidth = width;
CGFloat height = CGRectGetHeight(self.collectionView.frame);
self.itemSize = CGSizeMake(width, height);
self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
self.minimumLineSpacing = self.itemSpace_H;
break;
}
case CWCarouselStyle_H_2: {
CGFloat width = self.itemWidth <= 0 ? self.defaultItemWidth : self.itemWidth;
self.itemWidth = width;
CGFloat height = CGRectGetHeight(self.collectionView.frame);
self.itemSize = CGSizeMake(width, height);
self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
CGFloat padding = width * (1 - self.minScale) * 0.5;
self.factItemSpace = 0;
self.minimumLineSpacing = self.itemSpace_H - padding;
}
break;
case CWCarouselStyle_H_3: {
CGFloat width = self.itemWidth <= 0 ? self.defaultItemWidth : self.itemWidth;
self.itemWidth = width;
CGFloat height = CGRectGetHeight(self.collectionView.frame);
self.itemSize = CGSizeMake(width, height);
self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
CGFloat padding = width * (1 - self.minScale) * 0.5;
self.factItemSpace = 0;
// if(width * (1 - self.minScale) * 0.5 < self.itemSpace_H) {
// self.factItemSpace = self.itemSpace_H - width * (1 - self.minScale) * 0.5;
// }
// self.minimumLineSpacing = self.factItemSpace;
self.minimumLineSpacing = self.itemSpace_H - padding;
}
break;
default:
break;
}
}
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
if (self.style == CWCarouselStyle_Unknow ||
self.style == CWCarouselStyle_Normal ||
self.style == CWCarouselStyle_H_1) {
return [super layoutAttributesForElementsInRect:rect];
}
NSArray<UICollectionViewLayoutAttributes *> *arr = [[NSArray alloc] initWithArray:[super layoutAttributesForElementsInRect:rect] copyItems:YES];
CGFloat centerX = self.collectionView.contentOffset.x + CGRectGetWidth(self.collectionView.frame) * 0.5;
__block CGFloat maxScale = 0;
__block UICollectionViewLayoutAttributes *attri = nil;
[arr enumerateObjectsUsingBlock:^(UICollectionViewLayoutAttributes * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
CGFloat space = ABS(obj.center.x - centerX);
space = MIN(space, self.itemWidth + self.factItemSpace);
obj.zIndex = 0;
if(space >= 0) {
CGFloat scale = 1;
if (self.style == CWCarouselStyle_H_2 ||
self.style == CWCarouselStyle_H_3) {
/**
公式: scale = k * space + a
其中: k = (minScale - 1) / (itemWidth + factItemSpace)
其中: a = 1
综上所述:
scale = (minScale - 1) / (itemWitdh + factItemSpace) * space + 1
*/
scale = (self.minScale - 1) / (self.itemWidth + self.factItemSpace) * space + 1;
}else {
// scale = -((self.maxScale - 1) / width) * space + self.maxScale;
}
obj.transform = CGAffineTransformMakeScale(scale, scale);
if(maxScale < scale) {
maxScale = scale;
attri = obj;
}
}
}];
if (attri) {
attri.zIndex = 1;
}
return arr;
}
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity {
return proposedContentOffset;
}
#pragma mark - Property
- (CGFloat)defaultItemWidth {
switch (self.style) {
case CWCarouselStyle_Unknow:
case CWCarouselStyle_Normal:
return self.collectionView.frame.size.width;
break;
case CWCarouselStyle_H_1:
case CWCarouselStyle_H_2:
case CWCarouselStyle_H_3:
return self.collectionView.frame.size.width * 0.75;
break;
default:
break;
}
}
- (void)setMaxScale:(CGFloat)maxScale {
_maxScale = maxScale;
if(maxScale < 1) {
_maxScale = 1;
}
}
- (void)setMinScale:(CGFloat)minScale {
_minScale = minScale;
if(minScale < 0) {
_minScale = 0.1;
}
if (minScale >= 1) {
_minScale = 1;
}
}
@end
//
// CWPageControl.h
// CWCarousel
//
// Created by chenwang on 2018/7/16.
// Copyright © 2018年 ChenWang. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "CWCarouselProtocol.h"
@interface CWPageControl : UIView <CWCarouselPageControlProtocol>
+ (CGFloat)widthFromNumber:(NSInteger)num;
@end
//
// CWPageControl.m
// CWCarousel
//
// Created by chenwang on 2018/7/16.
// Copyright © 2018年 ChenWang. All rights reserved.
//
#define PageControlWidth 10
#define PageControlHeight 4
#define PageControlSpace 4
#define PageControlRadius 2
#import "CWPageControl.h"
@interface CWPageControl ()
@property (nonatomic, assign) NSInteger myPageNumbers;
@property (nonatomic, assign) NSInteger myCurrentPage;
@property (nonatomic, strong) NSArray<UIView *> *indicatorArr;
@property (nonatomic, strong) UIView *currentIndicator;
@end
@implementation CWPageControl
@synthesize currentPage;
@synthesize pageNumbers;
#pragma mark - INITIAL
- (instancetype)initWithFrame:(CGRect)frame {
if(self = [super initWithFrame:frame]) {
[self configureView];
}
return self;
}
#pragma mark - PROPERTY
- (void)setCurrentPage:(NSInteger)currentPage {
if (currentPage >= self.indicatorArr.count) {
return;
}
self.myCurrentPage = currentPage;
UIView *indicator = self.indicatorArr[currentPage];
[UIView animateWithDuration:0.25 animations:^{
self.currentIndicator.frame = indicator.frame;
}];
}
- (void)setPageNumbers:(NSInteger)pageNumbers {
if (self.pageNumbers == pageNumbers) {
return;
}
self.myPageNumbers = pageNumbers;
[self createIndicator];
}
- (NSInteger)currentPage {
return self.currentPage;
}
- (NSInteger)pageNumbers {
return self.myPageNumbers;
}
#pragma mark - LOGIC HELPER
- (void)configureView {
}
+ (CGFloat)widthFromNumber:(NSInteger)num {
return PageControlWidth * num + PageControlSpace * (num - 1);
}
- (void)createIndicator {
[self.indicatorArr makeObjectsPerformSelector:@selector(removeFromSuperview)];
CGFloat width = PageControlWidth;
CGFloat height = PageControlHeight;
CGFloat space = PageControlSpace;
CGFloat containerWidth = (width + space) * self.pageNumbers - space;
UIView *container = [[UIView alloc] initWithFrame:CGRectMake((CGRectGetWidth(self.frame) - containerWidth) * 0.5, 0, containerWidth, CGRectGetHeight(self.frame))];
[self addSubview:container];
NSMutableArray *arr = [NSMutableArray arrayWithCapacity:self.pageNumbers];
for(int i = 0; i < self.pageNumbers; i ++) {
CGFloat y = (CGRectGetHeight(self.frame) - height) * 0.5;
CGFloat x = (width + space) * i;
UIView *indictor = [[UIView alloc] initWithFrame:CGRectMake(x, y, width, height)];
indictor.layer.masksToBounds = YES;
indictor.layer.cornerRadius = PageControlRadius;
[container addSubview:indictor];
indictor.backgroundColor = ColorFromHex(0xB8BEDB);
[arr addObject:indictor];
if(i == 0 && self.currentIndicator == nil) {
UIView *indictor = [[UIView alloc] initWithFrame:CGRectMake(x, y, width, height)];
[container addSubview:indictor];
self.currentIndicator = indictor;
self.currentIndicator.layer.masksToBounds = YES;
self.currentIndicator.layer.cornerRadius = PageControlRadius;
self.currentIndicator.backgroundColor = BrandColor;
self.currentIndicator.layer.zPosition = 999;
}
}
self.indicatorArr = [NSArray arrayWithArray:arr];
}
@end
//
// DSDataSource.h
// DreamSleep
//
// Created by peter on 2022/4/8.
//
#import <Foundation/Foundation.h>
typedef void (^CellConfigureBlock)(id cell, id model, NSIndexPath * indexPath);
NS_ASSUME_NONNULL_BEGIN
/**
自定义数据源,用于瘦身控制器
UITableViewDataSource、UICollectionViewDataSource
*/
@interface DSDataSource : NSObject <UITableViewDataSource>
// sb
@property (nonatomic, strong) IBInspectable NSString *cellIdentifier;
// 数据
@property (nonatomic, strong) NSMutableArray *dataArray;
// cell block
@property (nonatomic, copy) CellConfigureBlock cellConfigureBlock;
- (id)initWithIdentifier:(NSString *)identifier datas:(NSArray *)datas isSection:(BOOL)isSection configureBlock:(CellConfigureBlock)cellBlock;
- (void)addDataArray:(NSArray *)datas;
- (id)modelAtIndexPath:(NSIndexPath *)indexPath;
@end
NS_ASSUME_NONNULL_END
//
// DSDataSource.m
// DreamSleep
//
// Created by peter on 2022/4/8.
//
#import "DSDataSource.h"
@interface DSDataSource ()
/** 是否是section */
@property NSInteger isSection;
@end
@implementation DSDataSource
- (id)initWithIdentifier:(NSString *)identifier datas:(NSArray *)datas isSection:(BOOL)isSection configureBlock:(CellConfigureBlock)cellBlock {
if (self = [super init]) {
_cellIdentifier = identifier;
_dataArray = [NSMutableArray arrayWithArray:datas];
_isSection = isSection;
_cellConfigureBlock = [cellBlock copy];
}
return self;
}
- (void)addDataArray:(NSArray *)datas {
if(!datas) { return; }
if (self.dataArray.count > 0) { [self.dataArray removeAllObjects]; }
[self.dataArray addObjectsFromArray:datas];
}
- (id)modelAtIndexPath:(NSIndexPath *)indexPath {
// 需要判断是否是row还是section
if (self.isSection) {
return self.dataArray.count > indexPath.section ? self.dataArray[indexPath.section] : nil;
} else {
return self.dataArray.count > indexPath.row ? self.dataArray[indexPath.row] : nil;
}
}
#pragma mark - UITableViewDataSource
- (nonnull UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath {
UITableViewCell *cell = self.cellIdentifier ? [tableView dequeueReusableCellWithIdentifier:self.cellIdentifier forIndexPath:indexPath] :
[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
id model = [self modelAtIndexPath:indexPath];
if (self.cellConfigureBlock) {
self.cellConfigureBlock(cell, model, indexPath);
}
return cell;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
if (self.isSection) {
return !self.dataArray ? 1 : self.dataArray.count;
} else {
return 1;
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (self.isSection) {
return 1;
} else {
return !self.dataArray ? 1 : self.dataArray.count;
}
}
@end
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!