Commit 68290a71 cgx

首页轮播图

1 个父辈 4d307e26
...@@ -7,8 +7,9 @@ ...@@ -7,8 +7,9 @@
#import "AISleepCoachController.h" #import "AISleepCoachController.h"
#import <WebKit/WebKit.h> #import <WebKit/WebKit.h>
#import <JavaScriptCore/JavaScriptCore.h>
@interface AISleepCoachController () <WKNavigationDelegate> @interface AISleepCoachController () <WKNavigationDelegate, WKScriptMessageHandler, WKUIDelegate>
@property (strong, nonatomic) WKWebView *aiWebView; @property (strong, nonatomic) WKWebView *aiWebView;
@property (nonatomic, strong) UIProgressView *progressView; @property (nonatomic, strong) UIProgressView *progressView;
@end @end
...@@ -54,15 +55,65 @@ ...@@ -54,15 +55,65 @@
DSLog(@"百度主页加载失败:%@", error.userInfo); 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 { - (WKWebView *)aiWebView {
if (!_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.backgroundColor = DSWhite;
_aiWebView.UIDelegate = self;
[_aiWebView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil]; [_aiWebView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];
_aiWebView.navigationDelegate = self; _aiWebView.navigationDelegate = self;
_aiWebView.scrollView.showsVerticalScrollIndicator = NO; _aiWebView.scrollView.showsVerticalScrollIndicator = NO;
_aiWebView.scrollView.showsHorizontalScrollIndicator = NO; _aiWebView.scrollView.showsHorizontalScrollIndicator = NO;
// iOS 11:
_aiWebView.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
// 测试地址:https://www.cbti.cn/sleep/ai/sleep_aicocah // 测试地址:https://www.cbti.cn/sleep/ai/sleep_aicocah
NSURL *url = [NSURL URLWithString:@"https://cbti.mynatapp.cc/sleep/ai/sleep_aicocah"]; NSURL *url = [NSURL URLWithString:@"https://cbti.mynatapp.cc/sleep/ai/sleep_aicocah"];
...@@ -77,7 +128,7 @@ ...@@ -77,7 +128,7 @@
_progressView = [[UIProgressView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, 0)]; _progressView = [[UIProgressView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, 0)];
_progressView.tintColor = HighlightColor; _progressView.tintColor = HighlightColor;
// 通过放大Y轴来改变高度 // 通过放大Y轴来改变高度
_progressView.transform = CGAffineTransformMakeScale(1.0f, 5.0f);; _progressView.transform = CGAffineTransformMakeScale(1.0f, 3.0f);;
} }
return _progressView; return _progressView;
} }
......
<?xml version="1.0" encoding="UTF-8"?> <?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"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict/>
<key>com.apple.developer.associated-domains</key>
<array>
<string>applinks:https://help.wechat.com/sdksample/</string>
</array>
</dict>
</plist> </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 @@ ...@@ -7,9 +7,10 @@
#import "HomeViewController.h" #import "HomeViewController.h"
#import "DSGifHeader.h" #import "DSGifHeader.h"
#import "HomeTableView.h"
@interface HomeViewController () @interface HomeViewController ()
@property (nonatomic, strong) HomeTableView *homeTV;
@end @end
@implementation HomeViewController @implementation HomeViewController
...@@ -17,6 +18,9 @@ ...@@ -17,6 +18,9 @@
- (void)viewDidLoad { - (void)viewDidLoad {
[super viewDidLoad]; [super viewDidLoad];
self.view = self.homeTV;
// 导航栏背景色 // 导航栏背景色
// self.navigationController.navigationBar.dk_barTintColorPicker = DKColorPickerWithKey(NaviBG); // self.navigationController.navigationBar.dk_barTintColorPicker = DKColorPickerWithKey(NaviBG);
...@@ -33,13 +37,13 @@ ...@@ -33,13 +37,13 @@
// self.navigationController.navigationBar.shadowImage = [UIImage new]; // self.navigationController.navigationBar.shadowImage = [UIImage new];
// view背景色 // view背景色
self.view.dk_backgroundColorPicker = DKColorPickerWithKey(VCViewBG); // self.view.dk_backgroundColorPicker = DKColorPickerWithKey(VCViewBG);
self.tableView.mj_header = [DSGifHeader headerWithRefreshingBlock:^{ // self.tableView.mj_header = [DSGifHeader headerWithRefreshingBlock:^{
dispatch_after(2.0, dispatch_get_main_queue(), ^{ // dispatch_after(2.0, dispatch_get_main_queue(), ^{
[self.tableView.mj_header endRefreshing]; // [self.tableView.mj_header endRefreshing];
}); // });
}]; // }];
// 设置导航栏返回按钮文字 // 设置导航栏返回按钮文字
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc]
...@@ -65,14 +69,21 @@ ...@@ -65,14 +69,21 @@
} }
} }
#pragma mark - Table view data source //#pragma mark - Table view data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { //- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 1; // 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 { - (HomeTableView *)homeTV {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"homeCell" forIndexPath:indexPath]; if (!_homeTV) {
return cell; _homeTV = [[HomeTableView alloc] initDemo];
}
return _homeTV;
} }
@end @end
...@@ -20,9 +20,11 @@ ...@@ -20,9 +20,11 @@
self.window = [UIWindow.alloc initWithFrame:UIScreen.mainScreen.bounds]; self.window = [UIWindow.alloc initWithFrame:UIScreen.mainScreen.bounds];
self.window.backgroundColor = DSWhite; self.window.backgroundColor = DSWhite;
[self.window makeKeyAndVisible]; [self.window makeKeyAndVisible];
UIStoryboard * mainStoryBoard =[UIStoryboard storyboardWithName:@"Main" bundle:nil];
UINavigationController *navi = [[UINavigationController alloc] initWithRootViewController:[[PrivacyViewController alloc] init]]; self.window.rootViewController = [mainStoryBoard instantiateViewControllerWithIdentifier:@"mainSB"];
self.window.rootViewController = navi;
// UINavigationController *navi = [[UINavigationController alloc] initWithRootViewController:[[PrivacyViewController alloc] init]];
// self.window.rootViewController = navi;
[self initWeChat]; [self initWeChat];
......
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
#import "AdaptationUtil.h" #import "AdaptationUtil.h"
#import "MacroFuncUtil.h" #import "MacroFuncUtil.h"
#import "DSDataSource.h"
#import <DKNightVersion/DKNightVersion.h> #import <DKNightVersion/DKNightVersion.h>
#import <Masonry/Masonry.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
//
// 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!