Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
GMBase
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
gengmeiios
GMBase
Commits
f3583eb0
Commit
f3583eb0
authored
May 12, 2020
by
luyueming
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
删除文件
parent
1826794b
Show whitespace changes
Inline
Side-by-side
Showing
91 changed files
with
0 additions
and
7347 deletions
+0
-7347
GMBaseWebViewController.h
GMBase/Classes/Common/GMBaseWebViewController.h
+0
-124
GMBaseWebViewController.m
GMBase/Classes/Common/GMBaseWebViewController.m
+0
-1568
JXCategoryBaseCell.h
...sses/JXPagerView/JXCategoryView/Base/JXCategoryBaseCell.h
+0
-20
JXCategoryBaseCell.m
...sses/JXPagerView/JXCategoryView/Base/JXCategoryBaseCell.m
+0
-35
JXCategoryBaseCellModel.h
...JXPagerView/JXCategoryView/Base/JXCategoryBaseCellModel.h
+0
-26
JXCategoryBaseCellModel.m
...JXPagerView/JXCategoryView/Base/JXCategoryBaseCellModel.m
+0
-20
JXCategoryBaseView.h
...sses/JXPagerView/JXCategoryView/Base/JXCategoryBaseView.h
+0
-190
JXCategoryBaseView.m
...sses/JXPagerView/JXCategoryView/Base/JXCategoryBaseView.m
+0
-471
JXCategoryCollectionView.h
...agerView/JXCategoryView/Common/JXCategoryCollectionView.h
+0
-15
JXCategoryCollectionView.m
...agerView/JXCategoryView/Common/JXCategoryCollectionView.m
+0
-22
JXCategoryFactory.h
...ses/JXPagerView/JXCategoryView/Common/JXCategoryFactory.h
+0
-18
JXCategoryFactory.m
...ses/JXPagerView/JXCategoryView/Common/JXCategoryFactory.m
+0
-31
JXCategoryIndicatorParamsModel.h
...ew/JXCategoryView/Common/JXCategoryIndicatorParamsModel.h
+0
-27
JXCategoryIndicatorParamsModel.m
...ew/JXCategoryView/Common/JXCategoryIndicatorParamsModel.m
+0
-13
JXCategoryIndicatorProtocol.h
...rView/JXCategoryView/Common/JXCategoryIndicatorProtocol.h
+0
-50
JXCategoryListContainerView.h
...rView/JXCategoryView/Common/JXCategoryListContainerView.h
+0
-87
JXCategoryListContainerView.m
...rView/JXCategoryView/Common/JXCategoryListContainerView.m
+0
-134
JXCategoryListVCContainerView.h
...iew/JXCategoryView/Common/JXCategoryListVCContainerView.h
+0
-39
JXCategoryListVCContainerView.m
...iew/JXCategoryView/Common/JXCategoryListVCContainerView.m
+0
-160
JXCategoryViewDefines.h
...JXPagerView/JXCategoryView/Common/JXCategoryViewDefines.h
+0
-22
UIColor+JXAdd.h
...Classes/JXPagerView/JXCategoryView/Common/UIColor+JXAdd.h
+0
-19
UIColor+JXAdd.m
...Classes/JXPagerView/JXCategoryView/Common/UIColor+JXAdd.m
+0
-35
JXCategoryDotCell.h
...lasses/JXPagerView/JXCategoryView/Dot/JXCategoryDotCell.h
+0
-13
JXCategoryDotCell.m
...lasses/JXPagerView/JXCategoryView/Dot/JXCategoryDotCell.m
+0
-78
JXCategoryDotCellModel.h
...s/JXPagerView/JXCategoryView/Dot/JXCategoryDotCellModel.h
+0
-31
JXCategoryDotCellModel.m
...s/JXPagerView/JXCategoryView/Dot/JXCategoryDotCellModel.m
+0
-13
JXCategoryDotView.h
...lasses/JXPagerView/JXCategoryView/Dot/JXCategoryDotView.h
+0
-25
JXCategoryDotView.m
...lasses/JXPagerView/JXCategoryView/Dot/JXCategoryDotView.m
+0
-50
JXCategoryImageCell.h
...es/JXPagerView/JXCategoryView/Image/JXCategoryImageCell.h
+0
-15
JXCategoryImageCell.m
...es/JXPagerView/JXCategoryView/Image/JXCategoryImageCell.m
+0
-60
JXCategoryImageCellModel.h
...PagerView/JXCategoryView/Image/JXCategoryImageCellModel.h
+0
-31
JXCategoryImageCellModel.m
...PagerView/JXCategoryView/Image/JXCategoryImageCellModel.m
+0
-13
JXCategoryImageView.h
...es/JXPagerView/JXCategoryView/Image/JXCategoryImageView.h
+0
-33
JXCategoryImageView.m
...es/JXPagerView/JXCategoryView/Image/JXCategoryImageView.m
+0
-92
JXCategoryIndicatorBackgroundView.h
...icator/IndicatorViews/JXCategoryIndicatorBackgroundView.h
+0
-23
JXCategoryIndicatorBackgroundView.m
...icator/IndicatorViews/JXCategoryIndicatorBackgroundView.m
+0
-113
JXCategoryIndicatorBallView.h
...ew/Indicator/IndicatorViews/JXCategoryIndicatorBallView.h
+0
-19
JXCategoryIndicatorBallView.m
...ew/Indicator/IndicatorViews/JXCategoryIndicatorBallView.m
+0
-179
JXCategoryIndicatorComponentView.h
...dicator/IndicatorViews/JXCategoryIndicatorComponentView.h
+0
-90
JXCategoryIndicatorComponentView.m
...dicator/IndicatorViews/JXCategoryIndicatorComponentView.m
+0
-75
JXCategoryIndicatorImageView.h
...w/Indicator/IndicatorViews/JXCategoryIndicatorImageView.h
+0
-19
JXCategoryIndicatorImageView.m
...w/Indicator/IndicatorViews/JXCategoryIndicatorImageView.m
+0
-102
JXCategoryIndicatorLineView.h
...ew/Indicator/IndicatorViews/JXCategoryIndicatorLineView.h
+0
-27
JXCategoryIndicatorLineView.m
...ew/Indicator/IndicatorViews/JXCategoryIndicatorLineView.m
+0
-195
JXCategoryIndicatorRainbowLineView.h
...cator/IndicatorViews/JXCategoryIndicatorRainbowLineView.h
+0
-22
JXCategoryIndicatorRainbowLineView.m
...cator/IndicatorViews/JXCategoryIndicatorRainbowLineView.m
+0
-38
JXCategoryIndicatorTriangleView.h
...ndicator/IndicatorViews/JXCategoryIndicatorTriangleView.h
+0
-17
JXCategoryIndicatorTriangleView.m
...ndicator/IndicatorViews/JXCategoryIndicatorTriangleView.m
+0
-96
JXCategoryViewAnimator.h
...oryView/Indicator/IndicatorViews/JXCategoryViewAnimator.h
+0
-23
JXCategoryViewAnimator.m
...oryView/Indicator/IndicatorViews/JXCategoryViewAnimator.m
+0
-71
JXCategoryIndicatorCell.h
...erView/JXCategoryView/Indicator/JXCategoryIndicatorCell.h
+0
-13
JXCategoryIndicatorCell.m
...erView/JXCategoryView/Indicator/JXCategoryIndicatorCell.m
+0
-54
JXCategoryIndicatorCellModel.h
...w/JXCategoryView/Indicator/JXCategoryIndicatorCellModel.h
+0
-28
JXCategoryIndicatorCellModel.m
...w/JXCategoryView/Indicator/JXCategoryIndicatorCellModel.m
+0
-13
JXCategoryIndicatorView.h
...erView/JXCategoryView/Indicator/JXCategoryIndicatorView.h
+0
-42
JXCategoryIndicatorView.m
...erView/JXCategoryView/Indicator/JXCategoryIndicatorView.m
+0
-215
JXCategoryView.h
GMBase/Classes/JXPagerView/JXCategoryView/JXCategoryView.h
+0
-24
JXCategoryNumberCell.h
.../JXPagerView/JXCategoryView/Number/JXCategoryNumberCell.h
+0
-13
JXCategoryNumberCell.m
.../JXPagerView/JXCategoryView/Number/JXCategoryNumberCell.m
+0
-57
JXCategoryNumberCellModel.h
...gerView/JXCategoryView/Number/JXCategoryNumberCellModel.h
+0
-20
JXCategoryNumberCellModel.m
...gerView/JXCategoryView/Number/JXCategoryNumberCellModel.m
+0
-13
JXCategoryNumberView.h
.../JXPagerView/JXCategoryView/Number/JXCategoryNumberView.h
+0
-45
JXCategoryNumberView.m
.../JXPagerView/JXCategoryView/Number/JXCategoryNumberView.m
+0
-49
JXCategoryTitleCell.h
...es/JXPagerView/JXCategoryView/Title/JXCategoryTitleCell.h
+0
-17
JXCategoryTitleCell.m
...es/JXPagerView/JXCategoryView/Title/JXCategoryTitleCell.m
+0
-101
JXCategoryTitleCellModel.h
...PagerView/JXCategoryView/Title/JXCategoryTitleCellModel.h
+0
-36
JXCategoryTitleCellModel.m
...PagerView/JXCategoryView/Title/JXCategoryTitleCellModel.m
+0
-13
JXCategoryTitleView.h
...es/JXPagerView/JXCategoryView/Title/JXCategoryTitleView.h
+0
-41
JXCategoryTitleView.m
...es/JXPagerView/JXCategoryView/Title/JXCategoryTitleView.m
+0
-135
JXCategoryTitleImageCell.h
...XCategoryView/Title/TitleImage/JXCategoryTitleImageCell.h
+0
-15
JXCategoryTitleImageCell.m
...XCategoryView/Title/TitleImage/JXCategoryTitleImageCell.m
+0
-119
JXCategoryTitleImageCellModel.h
...goryView/Title/TitleImage/JXCategoryTitleImageCellModel.h
+0
-42
JXCategoryTitleImageCellModel.m
...goryView/Title/TitleImage/JXCategoryTitleImageCellModel.m
+0
-13
JXCategoryTitleImageView.h
...XCategoryView/Title/TitleImage/JXCategoryTitleImageView.h
+0
-35
JXCategoryTitleImageView.m
...XCategoryView/Title/TitleImage/JXCategoryTitleImageView.m
+0
-120
JXPagerCollectionViewCell.h
GMBase/Classes/JXPagerView/JXPagerCollectionViewCell.h
+0
-17
JXPagerCollectionViewCell.m
GMBase/Classes/JXPagerView/JXPagerCollectionViewCell.m
+0
-23
JXPagerListContainerView.h
GMBase/Classes/JXPagerView/JXPagerListContainerView.h
+0
-55
JXPagerListContainerView.m
GMBase/Classes/JXPagerView/JXPagerListContainerView.m
+0
-147
JXPagerListRefreshView.h
GMBase/Classes/JXPagerView/JXPagerListRefreshView.h
+0
-14
JXPagerListRefreshView.m
GMBase/Classes/JXPagerView/JXPagerListRefreshView.m
+0
-85
JXPagerMainTableView.h
GMBase/Classes/JXPagerView/JXPagerMainTableView.h
+0
-19
JXPagerMainTableView.m
GMBase/Classes/JXPagerView/JXPagerMainTableView.m
+0
-25
JXPagerView.h
GMBase/Classes/JXPagerView/JXPagerView.h
+0
-174
JXPagerView.m
GMBase/Classes/JXPagerView/JXPagerView.m
+0
-293
JXPageListContainerView.h
...lasses/JXPagerView/PageListView/JXPageListContainerView.h
+0
-41
JXPageListContainerView.m
...lasses/JXPagerView/PageListView/JXPageListContainerView.m
+0
-98
JXPageListMainTableView.h
...lasses/JXPagerView/PageListView/JXPageListMainTableView.h
+0
-13
JXPageListMainTableView.m
...lasses/JXPagerView/PageListView/JXPageListMainTableView.m
+0
-20
JXPageListView.h
GMBase/Classes/JXPagerView/PageListView/JXPageListView.h
+0
-108
JXPageListView.m
GMBase/Classes/JXPagerView/PageListView/JXPageListView.m
+0
-253
No files found.
GMBase/Classes/Common/GMBaseWebViewController.h
deleted
100644 → 0
View file @
1826794b
//
// GMBaseWebViewController.h
// ZhengXing
//
// Created by wangyang on 3/5/19.
// Copyright (c) 2019 Wanmei Creative. All rights reserved.
// 后期替代WMBaseViewController&WMBrowserViewController
#define kWebPhantom @"phantom"// 常用于H5新页面
#define kWebHybrid @"hybrid" // 常用于H5老页面
#import "GMShareView.h"
#import "WMShareObject.h"
#import "GMDiaryShareView.h"
#import "GMClientH5Object.h"
#import "GMWebViewModel.h"
typedef
NS_ENUM
(
NSInteger
,
GMWebPageType
)
{
GMWebPageTypeNomal
=
0
,
GMWebPageTypeSign
=
1
,
// 签到H5页面
GMWebPageTypeTopicDetail
=
2
,
// 日记贴
GMWebPageTypeAnswer
=
3
,
// 回答
GMWebPageTypeArticle
=
4
,
// 话题
GMWebPageTypeSpecial
=
5
,
// 专栏
GMWebPageTypeUserTopic
=
6
,
// 用户贴
GMWebPageTypeQuestion
=
7
,
// 回答 7.20 灰度用
GMWebPageTypeHospitalRank
=
8
,
// 医院榜单
GMWebPageTypeDoctorRank
=
9
,
// 医生榜单
};
@import
GMKit
;
@class
GMWebViewComponent
;
@interface
GMBaseWebViewController
:
WMBaseViewController
<
GMClientH5BridgeDelegate
>
{
/**
* @brief 下面都是从js中得到的数据。其中_jsGlobalObject字典包含其它数据
*/
NSDictionary
*
_jsGlobalObject
;
// 是否显示了分享
BOOL
_isShowShare
;
// 是否收藏
BOOL
_isFavored
;
// 是否是自己发的贴
BOOL
_isPrivate
;
// 是否是签到,签到导航栏透明,返回按钮、title颜色、rightIcon单独设置
BOOL
_isSign
;
}
@property
(
nonatomic
,
strong
)
GMWebViewComponent
*
webCompent
;
/// web上数据处理
@property
(
nonatomic
,
strong
)
GMWebViewModel
*
viewModel
;
/**
* @brief 要请求的 H5 url 除了 http://backend.dev.gengmei.cc/hybrid" 这部分后的path。比如一个h5是 http://backend.dev.gengmei.cc/hybrid/topic/3332214,那么path指需要赋值@"/topic/3332214"即可.
@note 在viewDidLoad前配置好。必须以"/"开头。重写moreQueryParameters可以添加额外query
*/
@property
(
nonatomic
,
strong
)
NSString
*
path
;
/**
* @brief 对于从服务器那儿获取到的完整H5 url,使用该属性。
@note 在viewDidLoad前配置好。会覆盖path属性。重写moreQueryParameters可以添加额外query
*/
@property
(
nonatomic
,
strong
)
NSString
*
fullURL
;
/// 通过webPageType 页面不同设置不同的差异性
@property
(
nonatomic
,
assign
)
GMWebPageType
webPageType
;
#pragma mark - 分享
@property
(
nonatomic
,
strong
)
GMShareView
*
shareView
;
@property
(
nonatomic
,
strong
)
GMDiaryShareView
*
diaryShareView
;
/*** @brief 收藏url**/
@property
(
nonatomic
,
strong
)
NSString
*
favUrl
;
/*** @brief 从_jsGlobalObject中获取的分享Model */
@property
(
nonatomic
,
strong
)
WMShareObject
*
shareObject
;
/*** @brief 日记分享Model数组 */
@property
(
nonatomic
,
strong
)
NSMutableArray
*
diaryShareArr
;
/*** @brief 微信分享Model */
@property
(
nonatomic
,
strong
)
WMShareObject
*
weixinShareObject
;
/*** @brief 分享的配置 */
@property
(
nonatomic
,
strong
)
GMShareConfigObject
*
shareConfigObject
;
@property
(
nonatomic
,
strong
)
NSString
*
favorType
;
/**
设置打开的权限类型
*/
@property
(
nonatomic
,
assign
)
NSInteger
settingType
;
@property
(
nonatomic
,
assign
)
BOOL
backNeedRefresh
;
/**
* @brief 重写该方法,为fullURL在请求前添加更多参数。必须以 & 开头
* 原方法只返回了空字符串,不需要call super
*
* @return 要额外添加的参数。如:&key1=value&key2=value
*/
-
(
NSString
*
)
moreQueryParameters
;
/**
调用该方法以重新构造URL并且[_webView loadRequest:request];
*/
-
(
void
)
reloadURL
;
/**
处理请求URL
*/
-
(
void
)
handleURL
;
// 一般情况下 页面刷新时候调用
-
(
void
)
refreshWebView
;
// 本地获取通用数据
-
(
NSString
*
)
nativeCommonParam
;
@end
GMBase/Classes/Common/GMBaseWebViewController.m
deleted
100644 → 0
View file @
1826794b
//
// WMDiaryAndTopicBaseController.m
// ZhengXing
//
// Created by wangyang on 3/5/15.
// Copyright (c) 2015 Wanmei Creative. All rights reserved.
//
#import "GMBaseWebViewController.h"
#import "AppDelegate+AppInit.h"
#import "Gengmei-Swift.h"
#import "UIViewController+UrlScheme.h"
#import "WMBaseViewController+OCNavigationBar.h"
#import <mach/mach_time.h>
#import "GMCookieManager.h"
#import "GMWebViewUrlProtocol.h"
#import "GMWeixinShareView.h"
#import "WMShareObject.h"
@interface
GMBaseWebViewController
()
<
MFMessageComposeViewControllerDelegate
,
GMCommonAlertViewDelegate
,
GMPhotoPickDismissDelegate
,
WKWebViewDelegate
,
GMShareViewDelegate
,
GMDiaryShareViewDelegate
>
{
// 是否显示微信快照和朋友圈快照
BOOL
_isShowScreenshot
;
GMAddressManager
*
_manager
;
// 是否需要回调权限打开状态
BOOL
_isSettingCallback
;
// 表示要上传的照片是可以公开的还是具体保护性的
BOOL
_isPrivatePhoto
;
// 接受h5的参数,图片上传成功后,以这个参数为key,把图片Url返回给h5
NSString
*
_requestCoder
;
// 是否显示了来自h5设置的rightButton
BOOL
_isJsRightButton
;
BOOL
_isJsNearRightButton
;
// 导航栏是否透明,YES透明,NO不透明
BOOL
_isNavigationAlpha
;
// 导航栏是否隐藏
BOOL
_isNavigationHidden
;
}
@property
(
nonatomic
,
assign
)
CGFloat
animationDistance
;
@property
(
nonatomic
,
strong
)
GMPlayerView
*
playBackView
;
@property
(
nonatomic
,
assign
)
BOOL
goToAppSettingsPage
;
// 跳转到系统设置页面
@end
@implementation
GMBaseWebViewController
#pragma mark - init
-
(
void
)
initController
{
[
super
initController
];
self
.
viewModel
=
[
GMWebViewModel
new
];
self
.
goToAppSettingsPage
=
NO
;
self
.
webPageType
=
GMWebPageTypeNomal
;
// 短信链接唤起app埋点 @author 李震(WMBrowserViewController)
if
([
AppDelegate
shareInstance
].
extraParam
.
isNonEmpty
)
{
self
.
extraParam
=
[
AppDelegate
shareInstance
].
extraParam
;
[
AppDelegate
shareInstance
].
extraParam
=
@""
;
}
}
#pragma mark - view lifeCycle
-
(
void
)
viewDidLoad
{
[
super
viewDidLoad
];
[
self
initReferer
];
[
self
initRefererLink
];
[
self
initReferrerTabName
];
self
.
navigationBar
.
isShowShadow
=
NO
;
self
.
backNeedRefresh
=
NO
;
CGFloat
top
=
OCNavigationBar
.
barHeight
;
[
self
.
webCompent
mas_makeConstraints
:
^
(
MASConstraintMaker
*
make
)
{
make
.
left
.
right
.
mas_equalTo
(
0
);
make
.
top
.
mas_equalTo
(
top
);
make
.
bottom
.
mas_equalTo
(
0
);
}];
// 设置Agent,关键字是最后的那个Gengmei,这样服务端就知道是通过app内部加载网页。
NSDictionary
*
dictionary
=
USER_AGENT_DIC
;
[[
NSUserDefaults
standardUserDefaults
]
registerDefaults
:
dictionary
];
// 加载URL
[
self
reloadURL
];
// 添加通知监听
[
self
addActiveObserver
];
// 导航栏渐变
[
self
prepareNavigation
];
}
/// 通过webPageType 页面不同设置不同的差异性
/// @param webPageType webPageType
-
(
void
)
setWebPageType
:
(
GMWebPageType
)
webPageType
{
_webPageType
=
webPageType
;
switch
(
webPageType
)
{
case
GMWebPageTypeSign
:
self
.
pageName
=
@"new_sign"
;
break
;
case
GMWebPageTypeQuestion
:
{
self
.
pageName
=
@"question_answer_detail"
;
}
break
;
default
:
break
;
}
}
-
(
void
)
viewWillAppear
:
(
BOOL
)
animated
{
[
super
viewWillAppear
:
animated
];
[
self
nativeAppearToCallJS
];
}
-
(
void
)
viewWillDisappear
:
(
BOOL
)
animated
{
[
super
viewWillDisappear
:
animated
];
if
(
self
.
backNeedRefresh
)
{
[
self
refreshWebView
];
self
.
backNeedRefresh
=
NO
;
}
[
self
nativeDisAppearToCallJS
];
}
#pragma mark - Load Request
-
(
void
)
reloadURL
{
[
self
handleURL
];
[
self
webViewLoadRequest
];
}
-
(
void
)
webViewLoadRequest
{
if
(
self
.
fullURL
==
nil
||
[
self
.
fullURL
isEqualToString
:
@""
])
{
return
;
}
[
UIApplication
sharedApplication
].
networkActivityIndicatorVisible
=
YES
;
self
.
webCompent
.
fullUrl
=
self
.
fullURL
;
// self.webCompent.fullUrl = @"http://172.30.8.83:3000/phantom/question/3482021";
[
self
.
webCompent
webviewLoad
:
self
];
}
// 一般情况下 页面刷新时候调用
-
(
void
)
refreshWebView
{
//自己本地调用webview刷新时候,绑定关系还存在,不需要重新绑定GMClient和window上的方法.
[
self
.
webCompent
reload
];
}
#pragma mark - Handle URL
/**
不允许重写
*/
-
(
void
)
handleURL
{
if
(
_fullURL
.
length
==
0
)
{
// 使用path拼接,并且加上query
_fullURL
=
[
self
wrapWebUrlWithPath
];
}
else
{
// 为fullURL加上默认query
_fullURL
=
[
self
wrapWebUrlWithFullURL
];
}
if
(
!
[
_fullURL
isNonEmpty
])
return
;
// 额外的参数
_fullURL
=
[
_fullURL
stringByAppendingString
:[
self
moreQueryParameters
]];
/// 添加referrer_link
_fullURL
=
[
self
addReferrerLinkWithFullURL
];
self
.
webCompent
.
fullUrl
=
_fullURL
;
}
/**
不允许重写
*/
-
(
NSString
*
)
wrapWebUrlWithPath
{
if
(
!
[
_path
isNonEmpty
])
{
return
@""
;
}
NSString
*
path
=
self
.
path
;
NSString
*
parames
=
[
NSString
stringWithString
:
GMNetworking
.
urlCommonParameters
];
if
([
path
containsString
:
@"?"
])
{
parames
=
[
parames
stringByReplacingOccurrencesOfString
:
@"?"
withString
:
@"&"
];
}
NSString
*
wrapedUrl
=
[
NSString
stringWithFormat
:
@"%@%@%@"
,
GMServerDomains
.
apiHost
,
path
,
parames
];
// 兼容新老页面,在此认为新的没有host域名的h5页面默认携带phantom,而不进行拼接
NSArray
*
pathArray
=
[
path
componentsSeparatedByString
:
@"/"
];
if
(
!
[
pathArray
containsObject
:
kWebPhantom
]
&&
!
[
pathArray
containsObject
:
kWebHybrid
])
{
wrapedUrl
=
[
NSString
stringWithFormat
:
@"%@/%@%@%@"
,
GMServerDomains
.
apiHost
,
kWebHybrid
,
path
,
parames
];
}
return
wrapedUrl
;
}
/**
不允许重写
*/
-
(
NSString
*
)
wrapWebUrlWithFullURL
{
// 因为有的 fullURL 带了一部分 query,而将要拼接的urlCommonParameters还带了一个问号,所以要做判断
NSString
*
defaultQuery
=
GMNetworking
.
urlCommonParameters
;
if
([
_fullURL
rangeOfString
:
@"?"
].
length
>
0
)
{
defaultQuery
=
[
defaultQuery
stringByReplacingOccurrencesOfString
:
@"?"
withString
:
@"&"
];
}
NSString
*
wrapedUrl
=
[
NSString
stringWithFormat
:
@"%@%@"
,
_fullURL
,
defaultQuery
];
return
wrapedUrl
;
}
/// 添加referrer_link 不允许重写
-
(
NSString
*
)
addReferrerLinkWithFullURL
{
NSString
*
referrerLink
=
@""
;
NSDictionary
*
param
=
[
_fullURL
urlQueryToDictionary
];
if
(
!
[
param
.
allKeys
containsObject
:
@"referrer_link"
])
{
BOOL
aiConsultGray
=
GMLaunchManager
.
shareManager
.
appConfigObject
.
aiConsultGray
;
NSString
*
referrerLinkString
=
[
self
.
referrerLink
componentsJoinedByString
:
@","
];
referrerLink
=
[
NSString
stringWithFormat
:
@"&ai_consult_gray=%@&referrer_link=%@"
,(
aiConsultGray
?
@"1"
:
@"0"
),
referrerLinkString
];
}
return
[
NSString
stringWithFormat
:
@"%@%@"
,
_fullURL
,
referrerLink
];
}
-
(
NSString
*
)
moreQueryParameters
{
return
@""
;
}
-
(
void
)
setFullURL
:
(
NSString
*
)
fullURL
{
_fullURL
=
fullURL
;
debugLog
(
@"%@"
,
_fullURL
);
NSDictionary
*
params
=
[
fullURL
urlQueryToDictionary
];
if
([
params
.
allKeys
containsObject
:
@"referrer"
])
{
self
.
referer
=
params
[
@"referrer"
];
}
// cpc 相关
if
([
params
.
allKeys
containsObject
:
@"cpc_referer"
])
{
self
.
cpc_referer
=
[
params
[
@"cpc_referer"
]
integerValue
];
}
if
([
params
.
allKeys
containsObject
:
@"is_cpc"
])
{
self
.
is_cpc
=
[
params
[
@"is_cpc"
]
boolValue
];
}
// navigation_color_clear: 1透明,0不透明
if
([
params
[
@"navigation_color_clear"
]
intValue
])
{
_isNavigationAlpha
=
YES
;
// referer: push:表示来源为推送;pop_ad:表示来源开屏小广告(没有倒计时);big_ad:表示来源开屏大广告(有倒计时)
self
.
navigationBar
.
leftIcon
=
@"back_circle_white"
;
self
.
navigationBar
.
buttonMargin
=
10
;
}
// 设置导航栏是否隐藏
_isNavigationHidden
=
[
params
[
@"navigation_hidden"
]
boolValue
];
}
#pragma mark - 分享 GMShareViewDelegate
-
(
void
)
willShowShareView
:
(
GMShareView
*
)
shareView
{
shareView
.
hasFav
=
_isFavored
;
shareView
.
showDelete
=
_isPrivate
;
shareView
.
showScreenshot
=
_isShowScreenshot
;
// 连续签到,补签分享,隐藏复制链接、举报、刷新
shareView
.
showReport
=
!
[
_shareConfigObject
.
hideReport
boolValue
];
shareView
.
showCopyLink
=
!
[
_shareConfigObject
.
hideCopyLink
boolValue
];
shareView
.
showRefresh
=
!
[
_shareConfigObject
.
hideRefresh
boolValue
];
if
([
_shareConfigObject
.
hideReport
boolValue
]
&&
[
_shareConfigObject
.
hideCopyLink
boolValue
]
&&
[
_shareConfigObject
.
hideRefresh
boolValue
])
{
shareView
.
topLineView
.
hidden
=
YES
;
}
else
{
shareView
.
topLineView
.
hidden
=
NO
;
}
shareView
.
taskType
=
_shareConfigObject
.
taskType
;
shareView
.
isReportShareResult
=
_shareConfigObject
.
isReportShareResult
;
shareView
.
shareObject
=
_shareObject
;
}
-
(
NSString
*
)
shareViewNeedBusinessId
{
return
self
.
businessId
;
}
-
(
void
)
shareResponseSuccess
{
[
self
.
webCompent
.
webView
evaluateJavaScript
:
_shareConfigObject
.
shareCallback
completionHandler
:
nil
];
}
/**@brief 获取分享内容的协议方法需在子类实现,因为需要定制,删除和收藏的协议方法在子类实现即可*/
-
(
void
)
shareView
:
(
GMShareView
*
)
shareView
favriteContentWithIndexPath
:
(
NSIndexPath
*
)
indexPath
{
if
([[
GMLoginManager
shareInstance
]
showLoginViewIfNeeded
]){
return
;
}
GMHTTPMethod
method
=
_isFavored
?
GMHTTPMethodDelete
:
GMHTTPMethodPost
;
__weak
__typeof
(
self
)
weakSelf
=
self
;
[
GMNetworking
requestOCWithApi
:
self
.
favUrl
method
:
method
parameters
:
nil
completion
:^
(
GMResponseOC
*
_Nonnull
responseObject
)
{
if
(
responseObject
.
isSuccess
)
{
_isFavored
=
!
_isFavored
;
shareView
.
hasFav
=
_isFavored
;
NSString
*
action
;
if
(
_isFavored
)
{
action
=
@"do"
;
[
weakSelf
showComplete
:
@"收藏成功"
];
}
else
{
action
=
@"undo"
;
[
weakSelf
showComplete
:
@"取消收藏成功"
];
}
// 分享的埋点
NSDictionary
*
dic
=
@{
@"action"
:
action
,
@"type"
:
weakSelf
.
favorType
,
@"business_id"
:
weakSelf
.
businessId
};
[
Phobos
track
:
@"favor"
attributes
:
dic
];
[
shareView
.
shareCollectionView
reloadItemsAtIndexPaths
:@[
indexPath
]];
}
else
{
[
weakSelf
showWarning
:
responseObject
.
message
];
}
}];
}
#pragma mark - GMShareViewDelegate
-
(
void
)
copyShareUrl
{
UIPasteboard
*
pasteboard
=
[
UIPasteboard
generalPasteboard
];
if
([
_shareObject
.
url
isNonEmpty
])
{
pasteboard
.
string
=
_shareObject
.
url
;
[
self
toast
:
@"链接已复制到系统粘帖板"
];
}
}
-
(
NSMutableDictionary
*
)
fetchSharePublishContent
:
(
GMSharePlatform
)
shareType
{
//这里时间是native,所以只能弹普通的大分享
id
shareImage
=
nil
;
GMShareContentType
contentType
=
GMShareContentTypeAuto
;
WMShareBasicObject
*
object
=
[
WMShareBasicObject
new
];
NSString
*
image
=
_shareObject
.
image
;
if
(
image
.
length
!=
0
)
{
shareImage
=
[
GMShareSDK
compressWithUrl
:
image
];
}
else
{
// 使用app logo做图标
shareImage
=
[
UIImage
imageNamed
:
@"icon"
];
}
// 微信会话分享且微信小程序内容不为空的时候,认为是微信小程序分享
if
(
shareType
==
GMSharePlatformWechatSession
&&
[
_shareObject
.
wechatmini
.
path
isNonEmpty
])
{
shareType
=
GMSharePlatformWechatMiniProgram
;
}
NSString
*
channel
=
@""
;
switch
(
shareType
)
{
case
GMSharePlatformWechatSession
:
object
=
_shareObject
.
wechat
;
channel
=
@"wechat"
;
break
;
case
GMSharePlatformWechatTimeline
:
object
=
_shareObject
.
wechatline
;
channel
=
@"wechatline"
;
break
;
case
GMSharePlatformQQFriend
:
object
=
_shareObject
.
qq
;
channel
=
@"qq"
;
break
;
case
GMSharePlatformQQSpace
:
object
=
_shareObject
.
qq
;
channel
=
@"qzone"
;
break
;
case
GMSharePlatformSinaWeibo
:
object
=
_shareObject
.
weibo
;
channel
=
@"tsina"
;
break
;
case
GMSharePlatformWechatSessionSnapShot
:
object
=
_shareObject
.
wechatScreenshot
;
contentType
=
GMShareContentTypeImage
;
//这里不能压缩图片,要保证质量分享
shareImage
=
_shareObject
.
wechatScreenshot
.
content
;
break
;
case
GMSharePlatformWechatTimelineSnapShot
:
object
=
_shareObject
.
wechatlineScreenshot
;
shareImage
=
_shareObject
.
wechatlineScreenshot
.
content
;
contentType
=
GMShareContentTypeImage
;
break
;
default
:
break
;
}
if
(
_isSign
)
{
if
([
_shareObject
.
url
containsString
:
@"?"
])
{
_shareObject
.
url
=
[
NSString
stringWithFormat
:
@"%@&referrer=%@"
,
_shareObject
.
url
,
channel
];
}
else
{
_shareObject
.
url
=
[
NSString
stringWithFormat
:
@"%@?referrer=%@"
,
_shareObject
.
url
,
channel
];
}
}
NSMutableDictionary
*
shareParams
=
[
NSMutableDictionary
dictionary
];
if
(
shareType
==
GMSharePlatformWechatMiniProgram
){
[
shareParams
shareSetupMiniProgramShareParamsByUrl
:
_shareObject
.
url
userName
:
_shareObject
.
wechatmini
.
userName
path
:
_shareObject
.
wechatmini
.
path
title
:
_shareObject
.
wechatmini
.
title
description
:
_shareObject
.
wechatmini
.
desc
thumbImage
:
_shareObject
.
wechatmini
.
thumbImageUrl
hdImageData
:
_shareObject
.
wechatmini
.
hdImageUrl
];
}
else
{
[
shareParams
shareSetupShareParamsByText
:
object
.
content
images
:
shareImage
url
:
[
NSURL
URLWithString
:
_shareObject
.
url
]
title
:
object
.
title
type
:
contentType
];
}
return
shareParams
;
}
#pragma mark - GMClientH5BridgeDelegate
/**
* @brief pageData
*/
-
(
void
)
jsGlobalDataLoaded
:
(
NSString
*
)
jsonString
{
NSData
*
jsonData
=
[
jsonString
dataUsingEncoding
:
NSUTF8StringEncoding
];
_jsGlobalObject
=
[
NSJSONSerialization
JSONObjectWithData
:
jsonData
options
:
NSJSONReadingMutableContainers
error
:
nil
];
if
(
_jsGlobalObject
==
nil
)
{
return
;
}
// 从H5中取得全局变量
@try
{
// JIRA 上曾有一个关于此处的bug上报,因为无法查明原因,所以加try catch
[
self
.
webCompent
.
webView
evaluateJavaScript
:
@"window.GLOBAL.pagedata"
completionHandler
:
nil
];
// 当前版本对h5返回businessid和pageName的处理,只在commonwebview中处理,basewebview中不处理
}
@catch
(
NSException
*
exception
)
{
// [Bugly reportException:[NSException exceptionWithName:@"_jsGlobalObject获取异常" reason:exception.reason userInfo:@{@"exceptionInfo": exception.userInfo, @"url": self.fullURL}]];
}
if
(
_jsGlobalObject
[
@"page_name"
])
{
self
.
pageName
=
_jsGlobalObject
[
@"page_name"
];
}
if
([
_jsGlobalObject
[
@"business_id"
]
isNonEmpty
])
{
self
.
businessId
=
SafeString
(
_jsGlobalObject
[
@"business_id"
]);
}
if
([
_jsGlobalObject
.
allValues
containsObject
:
@"back_need_refresh"
])
{
_backNeedRefresh
=
[
_jsGlobalObject
[
@"back_need_refresh"
]
boolValue
];
}
// 是否收藏
_isFavored
=
[
_jsGlobalObject
[
@"is_favord"
]
boolValue
];
// 是否是自己的帖子
_isPrivate
=
[
_jsGlobalObject
[
@"is_private"
]
boolValue
];
//分享数据源
_shareObject
=
[[
WMShareObject
alloc
]
initWithDictionary
:
_jsGlobalObject
[
@"share_data"
]
error
:
nil
];
_shareConfigObject
=
[[
GMShareConfigObject
alloc
]
initWithDictionary
:
_jsGlobalObject
[
@"share_config"
]
error
:
nil
];
//同时不为空的时候才显示微信快照和朋友圈快照
_isShowScreenshot
=
[
_shareObject
.
wechatScreenshot
.
content
isNonEmpty
]
&&
[
_shareObject
.
wechatScreenshot
.
content
isNonEmpty
];
// 是否隐藏分享按钮
if
([
_jsGlobalObject
.
allKeys
containsObject
:
@"hide_share"
]
&&
!
[
_jsGlobalObject
[
@"hide_share"
]
boolValue
]
&&
_shareObject
)
{
_isShowShare
=
YES
;
}
else
{
_isShowShare
=
NO
;
}
_isSign
=
[
_jsGlobalObject
[
@"navigation"
][
@"nav_type"
]
isEqualToString
:
@"sign"
];
// 连续补签,分享日记
if
([
_jsGlobalObject
[
@"topic_share_data"
]
count
])
{
self
.
diaryShareArr
=
[
NSMutableArray
array
];
[
self
.
diaryShareArr
addObjectsFromArray
:[
GMDiaryShareObject
arrayOfModelsFromDictionaries
:
_jsGlobalObject
[
@"topic_share_data"
]
error
:
NULL
]];
}
// 处理导航栏数据
[
self
dealNavigationData
];
}
#pragma mark - Deal Navigation
// 导航栏隐藏显示
-
(
void
)
jsControlTitleBarVisible
:
(
NSString
*
)
jsonString
{
NSData
*
data
=
[
jsonString
dataUsingEncoding
:
NSUTF8StringEncoding
];
NSDictionary
*
showDic
=
[
NSJSONSerialization
JSONObjectWithData
:
data
options
:
NSJSONReadingMutableLeaves
error
:
nil
];
if
([
showDic
[
@"show"
]
boolValue
])
{
if
(
!
_isSign
)
{
self
.
navigationBar
.
backgroundColor
=
[
UIColor
whiteColor
];
self
.
navigationBar
.
isShowShadow
=
YES
;
}
else
{
self
.
navigationBar
.
backgroundColor
=
[
UIColor
clearColor
];
}
}
else
{
self
.
navigationBar
.
backgroundColor
=
[
UIColor
.
blackColor
colorWithAlphaComponent
:
0
.
6
];
self
.
navigationBar
.
isShowShadow
=
NO
;
}
}
// 设置导航数据
-
(
void
)
dealNavigationData
{
NSDictionary
*
navDict
=
_jsGlobalObject
[
@"navigation"
];
if
(
navDict
)
{
// 右侧图标
NSString
*
rightIcon
=
navDict
[
@"right_button"
];
if
(
rightIcon
.
isNonEmpty
)
{
self
.
navigationBar
.
rightIconURL
=
rightIcon
;
}
// 右侧文案
NSString
*
rightText
=
navDict
[
@"right_text"
];
if
(
rightText
.
isNonEmpty
)
{
self
.
navigationBar
.
rightTitle
=
rightText
;
}
self
.
navigationBar
.
rightButton
.
hidden
=
_isNavigationAlpha
;
// 签到
if
(
_isSign
)
{
[
self
.
navigationBar
.
rightButton
mas_updateConstraints
:
^
(
MASConstraintMaker
*
make
)
{
make
.
right
.
mas_equalTo
(
0
);
}];
}
// 设置导航栏是否透明
if
([
navDict
.
allKeys
containsObject
:
@"navigation_color_clear"
])
{
_isNavigationAlpha
=
[
navDict
[
@"navigation_color_clear"
]
intValue
]
?
YES
:
NO
;
}
self
.
animationDistance
=
[
navDict
[
@"header_height"
]
intValue
];
// 设置导航栏是否隐藏
_isNavigationHidden
=
[
navDict
[
@"navigation_hidden"
]
boolValue
];
// 设置侧滑手势禁用
self
.
fd_interactivePopDisabled
=
[
navDict
[
@"pop_disabled"
]
boolValue
];
}
// 设置导航栏
[
self
prepareNavigation
];
// 设置导航栏Title
[
self
setupNavigateTitle
];
}
/// 设置导航栏Title
-
(
void
)
setupNavigateTitle
{
// 设置导航栏
NSString
*
title
=
[
_jsGlobalObject
[
@"name"
]
isNonEmpty
]
?
_jsGlobalObject
[
@"name"
]
:
self
.
title
;
if
(
_isShowShare
)
{
[
self
setNavigateTitle
:
title
rightButtonOption
:
OCBarButtonImageTypeShare
];
}
else
{
[
self
setNavigateTitle
:
title
rightButtonOption
:
OCBarButtonImageTypeDefault
];
}
}
/// 设置导航栏是否隐藏
-
(
void
)
prepareNavigation
{
// navigation_color_clear: 1透明,0不透明
CGFloat
top
=
(
_isNavigationAlpha
||
_isNavigationHidden
)?
0
:
OCNavigationBar
.
barHeight
;
if
(
_isNavigationAlpha
)
{
self
.
navigationBar
.
leftIcon
=
@"back_circle_white"
;
self
.
navigationBar
.
buttonMargin
=
10
;
self
.
webCompent
.
webView
.
scrollView
.
contentInset
=
UIEdgeInsetsMake
(
0
,
0
,
0
,
0
);
self
.
webCompent
.
webView
.
scrollView
.
delegate
=
self
;
[
self
scrollViewDidScroll
:
self
.
webCompent
.
webView
.
scrollView
];
}
[
self
.
webCompent
mas_updateConstraints
:
^
(
MASConstraintMaker
*
make
)
{
make
.
top
.
mas_equalTo
(
top
);
}];
self
.
navigationBar
.
hidden
=
_isNavigationHidden
;
}
/// 前端调用客户端方法进行返回操作
-
(
void
)
jsPopViewControllerAnimated
:
(
BOOL
)
animated
{
if
([
self
.
parentViewController
isKindOfClass
:[
UINavigationController
class
]])
{
UINavigationController
*
navigation
=
(
UINavigationController
*
)
self
.
parentViewController
;
NSArray
*
controllers
=
navigation
.
viewControllers
;
if
(
self
.
presentingViewController
&&
controllers
.
count
==
1
)
{
[
self
dismissViewControllerAnimated
:
YES
completion
:
nil
];
}
else
{
[
self
.
navigationController
popViewControllerAnimated
:
YES
];
}
}
else
{
[
self
dismissViewControllerAnimated
:
YES
completion
:
nil
];
}
}
#pragma mark - Deal Gload
/**
* @brief js调用该方法以hideLoading
*/
-
(
void
)
loadDomFinished
{
[
self
hideLoading
];
// 因为此时_jsGlobalObject还不能从H5中获取,所以只先设置一个title,与数据相关的分享功能先不展示
// self.title = [self.webCompent.webView evaluateJavaScript:@"document.title" completionHandler:nil];
[
self
.
webCompent
.
webView
evaluateJavaScript
:
@"document.title"
completionHandler
:
^
(
id
resonse
,
NSError
*
_Nullable
error
)
{
NSLog
(
@"%@"
,
resonse
);
}];
}
-
(
void
)
jsShowLoading
{
[
self
showLoading
:
nil
];
}
-
(
void
)
jsHideLoading
{
[
self
hideLoading
];
}
-
(
void
)
jsLogout
{
[[
GMLoginManager
shareInstance
]
doLogoutAndShowLoginView
];
}
// 显示空白页面
-
(
void
)
jsShowNativeEmptyView
{
[
self
showEmptyView
:
GMEmptyViewTypeException
];
}
-
(
void
)
emptyViewDidClickReload
{
[
Phobos
track
:
@"on_click_button"
attributes
:@{
@"page_name"
:
SafeString
(
self
.
pageName
),
@"button_name"
:
@"click_reload"
}];
[
self
hideEmptyView
];
[
self
refreshWebView
];
}
// 网络状态 2: 其他 1:wifi 0:无网络
-
(
NSInteger
)
jsCheckNetworkState
{
NSInteger
networkState
=
0
;
if
([
AFNetworkReachabilityManager
sharedManager
].
isReachable
)
{
// 联网状态
if
([
AFNetworkReachabilityManager
sharedManager
].
reachableViaWiFi
==
NO
)
{
// 非WiFi
networkState
=
2
;
}
else
{
networkState
=
1
;
}
}
#warning h5
NSString
*
javaScriptStr
=
[
NSString
stringWithFormat
:
@"window.gm.pack.run('jsCheckNetworkStateCallback',%zd)"
,
networkState
];
[
self
.
webCompent
.
webView
evaluateJavaScript
:
javaScriptStr
completionHandler
:
nil
];
return
networkState
;
}
-
(
void
)
jsLocationShowAlertIfNotAllowed
{
[
GMLocationManager
showAlertIfNotAllowed
];
}
#pragma mark - ShareView
-
(
void
)
jsObjShowShareViewWithJSONString
:
(
NSString
*
)
JSONString
{
if
([
JSONString
isNonEmpty
])
{
_shareObject
=
[[
WMShareObject
alloc
]
initWithString
:
JSONString
error
:
nil
];
}
[
self
.
shareView
showWithShareUrl
:
_shareObject
.
url
];
[
self
addShareTopView
:
self
.
shareView
.
topView
];
}
-
(
void
)
jsObjShowDiaryShareViewWithJSONString
:
(
NSString
*
)
JSONString
{
if
([
JSONString
isNonEmpty
])
{
self
.
diaryShareArr
=
[
NSMutableArray
array
];
NSData
*
data
=
[
JSONString
dataUsingEncoding
:
NSUTF8StringEncoding
];
NSArray
*
shareArr
=
[
NSJSONSerialization
JSONObjectWithData
:
data
options
:
NSJSONReadingMutableLeaves
error
:
nil
];
[
self
.
diaryShareArr
addObjectsFromArray
:[
GMDiaryShareObject
arrayOfModelsFromDictionaries
:
shareArr
error
:
NULL
]];
}
[
self
.
diaryShareView
showWithShareArr
:
self
.
diaryShareArr
];
[
self
addShareTopView
:
self
.
diaryShareView
.
topView
];
}
-
(
void
)
addShareTopView
:
(
UIView
*
)
topView
{
// 连续签到,补签标题
[(
GMShareTopView
*
)
topView
setName
:
_shareConfigObject
.
shareTitle
title
:
_shareConfigObject
.
shareInfo
subTitle
:
_shareConfigObject
.
shareTip
];
if
([
_shareConfigObject
.
shareTitle
isNonEmpty
]
||
[
_shareConfigObject
.
shareInfo
isNonEmpty
]
||
[
_shareConfigObject
.
shareTip
isNonEmpty
])
{
_shareView
.
topView
.
hidden
=
NO
;
}
else
{
_shareView
.
topView
.
hidden
=
YES
;
}
}
-
(
void
)
jsShowWXShareViewWithJSONString
:
(
NSString
*
)
JSONString
{
if
([
JSONString
isNonEmpty
])
{
_weixinShareObject
=
[[
WMShareObject
alloc
]
initWithString
:
JSONString
error
:
nil
];
}
if
(
_weixinShareObject
!=
nil
)
{
GMWeixinShareView
*
weiXinShareView
=
[
GMWeixinShareView
shareView
];
weiXinShareView
.
weixinShareObject
=
_weixinShareObject
;
weiXinShareView
.
sourceController
=
self
;
[
self
.
view
addSubview
:
weiXinShareView
];
[
weiXinShareView
mas_makeConstraints
:
^
(
MASConstraintMaker
*
make
)
{
make
.
edges
.
equalTo
(
self
.
view
).
insets
(
UIEdgeInsetsZero
);
}];
[
weiXinShareView
layoutIfNeeded
];
[
weiXinShareView
showShareView
:
nil
];
}
}
// 根据type 展示跳转指定分享平台(V7.16.1)
-
(
void
)
jsSharewithType
:
(
NSDictionary
*
)
data
{
NSString
*
type
=
data
[
@"type"
]?:
@"Wechat"
;
self
.
shareObject
=
[[
WMShareObject
alloc
]
initWithDictionary
:
data
[
@"share_data"
]
error
:
nil
];
GMSharePlatform
shareType
=
GMSharePlatformWechatTimeline
;
if
([
type
isEqualToString
:
@"QZone"
])
{
shareType
=
GMSharePlatformQQSpace
;
}
else
if
([
type
isEqualToString
:
@"QQ"
])
{
shareType
=
GMSharePlatformQQFriend
;
}
else
if
([
type
isEqualToString
:
@"Wechat"
])
{
shareType
=
GMSharePlatformWechatSession
;
}
else
if
([
type
isEqualToString
:
@"WechatMoments"
])
{
shareType
=
GMSharePlatformWechatTimeline
;
}
else
if
([
type
isEqualToString
:
@"SinaWeibo"
])
{
shareType
=
GMSharePlatformSinaWeibo
;
}
self
.
shareView
.
shareUrl
=
self
.
shareObject
.
url
;
[
self
.
shareView
shareWithType
:
shareType
];
}
// 根据type 展示跳转指定分享平台(兼容之前的代码)
-
(
void
)
jsShare
:
(
NSString
*
)
shareDataString
withType
:
(
NSString
*
)
type
{
NSData
*
shareData
=
[
shareDataString
dataUsingEncoding
:
NSUTF8StringEncoding
];
NSDictionary
*
data
=
[
NSJSONSerialization
JSONObjectWithData
:
shareData
options
:
NSJSONReadingAllowFragments
error
:
NULL
];
if
([
type
isNonEmpty
])
{
NSMutableDictionary
*
dict
=
[
NSMutableDictionary
dictionaryWithDictionary
:
data
];
dict
[
@"type"
]
=
type
;
data
=
dict
;
}
[
self
jsSharewithType
:
data
];
}
/*** 回放 */
-
(
void
)
jsPlayVideo
:
(
NSString
*
)
JSONString
{
if
(
!
[
JSONString
isNonEmpty
])
{
[
self
toast
:
@"视频无法播放"
];
return
;
}
NSData
*
data
=
[
JSONString
dataUsingEncoding
:
NSUTF8StringEncoding
];
NSDictionary
*
jsonDict
=
[
NSJSONSerialization
JSONObjectWithData
:
data
options
:
NSJSONReadingMutableLeaves
error
:
NULL
];
NSString
*
playFrom
=
jsonDict
[
@"page_name"
];
NSString
*
topicId
=
jsonDict
[
@"topic_id"
];
NSString
*
businessId
=
jsonDict
[
@"business_id"
];
NSString
*
cardType
=
jsonDict
[
@"card_type"
];
NSInteger
index
=
[
jsonDict
[
@"index"
]
integerValue
];
CGFloat
currentTime
=
[
jsonDict
[
@"currentTime"
]
floatValue
];
NSInteger
state
=
[
jsonDict
[
@"state"
]
integerValue
];
GMVideoObject
*
video
=
[
GMVideoObject
new
];
video
.
businessId
=
SafeString
(
businessId
);
video
.
cardType
=
SafeString
(
cardType
);
video
.
pageName
=
SafeString
(
playFrom
);
_playBackView
=
[[
GMPlayerView
alloc
]
init
];
_playBackView
.
topicId
=
SafeString
(
topicId
);
_playBackView
.
from
=
SafeString
(
playFrom
);
_playBackView
.
video
=
video
;
_playBackView
.
needSkipSeconds
=
currentTime
;
_playBackView
.
index
=
index
;
_playBackView
.
playState
=
state
;
NSString
*
playUrl
=
jsonDict
[
@"url"
];
[
_playBackView
play
:
playUrl
animationRect
:
CGRectZero
];
}
/**
获取用户通讯录
@author zhaiguojun 16-09-21 in 6.3.2
@since 6.4.1
*/
-
(
void
)
jsGetAddressBook
{
dispatch_async
(
dispatch_get_main_queue
(),
^
{
_manager
=
[
GMAddressManager
new
];
[
_manager
getAddressBookAuthorization
];
});
}
/**
弹出通讯录供用户选择
@author zhaiguojun 16-09-28 in 6.4.1
*/
-
(
void
)
jsChooseOneContactPerson
:
(
NSString
*
)
key
{
_manager
=
[
GMAddressManager
new
];
__weak
__typeof
(
self
)
weakSelf
=
self
;
_manager
.
getOneContactPersonBlock
=
^
(
NSDictionary
*
result
){
NSData
*
jsParamData
=
[
NSJSONSerialization
dataWithJSONObject
:@{
key
:
result
}
options
:
0
error
:
NULL
];
NSString
*
jsParam
=
[[
NSString
alloc
]
initWithData
:
jsParamData
encoding
:
NSUTF8StringEncoding
];
NSString
*
jsString
=
[
NSString
stringWithFormat
:
@"gm.util.setContactPerson('%@')"
,
jsParam
];
[
weakSelf
.
webCompent
.
webView
evaluateJavaScript
:
jsString
completionHandler
:
nil
];
};
[
_manager
chooseContactPersonAddressBookJsonString
];
}
#pragma mark - AlertView
-
(
void
)
jsShowTaskAlert
:
(
NSString
*
)
extra
{
NSData
*
data
=
[
extra
dataUsingEncoding
:
NSUTF8StringEncoding
];
NSDictionary
*
extraDic
=
[
NSJSONSerialization
JSONObjectWithData
:
data
options
:
NSJSONReadingMutableLeaves
error
:
nil
];
if
(
extraDic
==
nil
)
{
return
;
}
[
AppDelegate
.
shareInstance
showPointAlert
:
extraDic
];
}
-
(
void
)
jsShowAlertViewWithJSONString
:
(
NSString
*
)
JSONString
{
WMAlertParameterObject
*
object
=
nil
;
if
([
JSONString
isNonEmpty
])
{
object
=
[[
WMAlertParameterObject
alloc
]
initWithString
:
JSONString
error
:
nil
];
}
__weak
typeof
(
self
)
weakSelf
=
self
;
NSString
*
title
=
object
.
title
?:
@"标题"
;
NSString
*
content
=
object
.
content
?:
@"内容"
;
NSString
*
confirmText
=
object
.
confirmText
?:
@"确定"
;
NSString
*
confirmCallback
=
object
.
confirmCallback
?:
@""
;
UIAlertController
*
alert
=
[
UIAlertController
showCustomAlertWithTitle
:
title
message
:
content
];
[
alert
addAction
:
confirmText
actionHandler
:
^
{
[
weakSelf
.
webCompent
.
webView
evaluateJavaScript
:
confirmCallback
completionHandler
:
nil
];
}];
}
-
(
void
)
jsShowConfirmViewWithJSONString
:
(
NSString
*
)
JSONString
{
WMAlertParameterObject
*
object
=
nil
;
if
([
JSONString
isNonEmpty
])
{
object
=
[[
WMAlertParameterObject
alloc
]
initWithString
:
JSONString
error
:
nil
];
}
NSString
*
title
=
object
.
title
?:
@"标题"
;
NSString
*
content
=
object
.
content
?:
@"内容"
;
NSString
*
confirmText
=
object
.
confirmText
?:
@"确定"
;
NSString
*
cancelText
=
object
.
cancelText
?:
@"取消"
;
NSString
*
confirmCallback
=
object
.
confirmCallback
?:
@""
;
NSString
*
cancelCallback
=
object
.
cancelCallback
?:
@""
;
__weak
typeof
(
self
)
weakSelf
=
self
;
UIAlertController
*
alert
=
[
UIAlertController
showCustomAlertWithTitle
:
title
message
:
content
];
[
alert
addAction
:
confirmText
actionHandler
:
^
{
[
weakSelf
.
webCompent
.
webView
evaluateJavaScript
:
confirmCallback
completionHandler
:
nil
];
}];
[
alert
addAction
:
cancelText
actionHandler
:
^
{
[
weakSelf
.
webCompent
.
webView
evaluateJavaScript
:
cancelCallback
completionHandler
:
nil
];
}];
}
-
(
void
)
jsShowToastWithJSONString
:
(
NSString
*
)
JSONString
{
WMToastParameterObject
*
object
=
nil
;
if
([
JSONString
isNonEmpty
])
{
object
=
[[
WMToastParameterObject
alloc
]
initWithString
:
JSONString
error
:
nil
];
}
[
self
toast
:
SafeValue
(
object
.
text
)];
}
#pragma mark - JumpToOtherPage
-
(
void
)
jsOpenBrowser
:
(
NSString
*
)
url
{
UIAlertController
*
alert
=
[
UIAlertController
showCustomAlertWithTitle
:
@"提示"
message
:
@"你访问的网址将以外部浏览器打开,是否继续?"
];
[
alert
addAction
:
@"否"
actionHandler
:
nil
];
[
alert
addAction
:
@"是"
actionHandler
:
^
{
NSURL
*
browserUrl
=
[
NSURL
URLWithString
:
url
];
if
(
SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO
(
@"10.0"
))
{
[[
UIApplication
sharedApplication
]
openURL
:
browserUrl
options
:@{}
completionHandler
:
NULL
];
}
else
{
[[
UIApplication
sharedApplication
]
openURL
:
browserUrl
];
}
}];
}
// 调起第三方APP 比如 爱奇艺 7.15.1
-
(
void
)
jsSkipToThirdApp
:
(
NSString
*
)
jsonString
{
NSData
*
jsonData
=
[
jsonString
dataUsingEncoding
:
NSUTF8StringEncoding
];
NSDictionary
*
dic
=
[
NSJSONSerialization
JSONObjectWithData
:
jsonData
options
:
NSJSONReadingMutableContainers
error
:
nil
];
NSURL
*
url
=
[
NSURL
URLWithString
:
dic
[
@"target_url"
]];
if
(
SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO
(
@"10.0"
))
{
[[
UIApplication
sharedApplication
]
openURL
:
url
options
:@{}
completionHandler
:
NULL
];
}
else
{
[[
UIApplication
sharedApplication
]
openURL
:
url
];
}
}
// 跳转到设置页面
-
(
void
)
jsJumpToLocationSettings
{
[
GMLocationManager
jumpToSettings
];
}
// 调用打电话
-
(
void
)
jsCallPhone
:
(
NSString
*
)
phone
{
NSString
*
phoneStr
=
[
NSString
stringWithFormat
:
@"tel:%@"
,
phone
];
[[
UIApplication
sharedApplication
]
openURL
:[
NSURL
URLWithString
:
phoneStr
]];
}
// 发短信
-
(
void
)
jsSendMessage
:
(
NSString
*
)
phone
withBody
:
(
NSString
*
)
body
{
if
([
GMMessageController
canSendText
])
{
GMMessageController
*
messageVc
=
[[
GMMessageController
alloc
]
init
];
messageVc
.
messageComposeDelegate
=
self
;
messageVc
.
recipients
=
@[
phone
];
messageVc
.
body
=
body
;
#warning ios 13
messageVc
.
modalPresentationStyle
=
UIModalPresentationFullScreen
;
[
self
presentViewController
:
messageVc
animated
:
YES
completion
:
nil
];
}
else
{
[
self
toast
:
@"当前设备不支持发短信"
];
}
}
/*!
* @author zhaiguojun, 16-07-05
*
* @brief 选择图片上传,然后把返回的URL返回给前端
*
* @param requestCode 传过来的标识
*
* @since 6.2.0
*/
-
(
void
)
openAlbum
:
(
NSString
*
)
requestCode
isPrivate
:
(
BOOL
)
isPrivate
{
_requestCoder
=
requestCode
;
_isPrivatePhoto
=
isPrivate
;
GMPhotoPickController
*
controller
=
[[
GMPhotoPickController
alloc
]
initWithMaxImageCount
:
1
maxVideoCount
:
0
maxCount
:
1
photoDisplayType
:
GMPhotosDisplayImageType
];
controller
.
dismissDelegate
=
self
;
controller
.
root
.
singleSelection
=
YES
;
#warning ios 13
controller
.
modalPresentationStyle
=
UIModalPresentationFullScreen
;
[
self
presentViewController
:
controller
animated
:
YES
completion
:
NULL
];
}
-
(
void
)
hintGotoSetting
{
UIAlertAction
*
action
=
[
UIAlertAction
actionWithTitle
:
@"我知道了"
style
:
UIAlertActionStyleCancel
handler
:
nil
];
UIAlertAction
*
gotoAction
=
[
UIAlertAction
actionWithTitle
:
@"去设置"
style
:
UIAlertActionStyleDefault
handler
:^
(
UIAlertAction
*
_Nonnull
action
)
{
[
self
goToAppSystemSettings
];
}];
UIAlertController
*
alert
=
[
UIAlertController
alertControllerWithTitle
:
@"温馨提示"
message
:
@"请您先去设置允许APP访问您的相机 设置>隐私>相机"
preferredStyle
:
UIAlertControllerStyleAlert
];
[
alert
addAction
:
action
];
[
alert
addAction
:
gotoAction
];
[
self
presentViewController
:
alert
animated
:
YES
completion
:
nil
];
}
/// 保险状态返回
/// @param dict has_bought: true(确定购买) / false(取消购买)
-
(
void
)
jsInsurancePurchase
:
(
NSDictionary
*
)
dict
{
//可以考虑废弃 在GMInsuranceWebviewController做了处理 避免其他类用到这个方法因此先保存着
dispatch_async
(
dispatch_get_main_queue
(),
^
{
[[
NSNotificationCenter
defaultCenter
]
postNotificationName
:
REFRESH_SETTLEMENT_LIST
object
:
nil
userInfo
:
dict
];
[
self
.
navigationController
popViewControllerAnimated
:
YES
];
});
}
#pragma mark - MFMessageComposeViewControllerDelegate
-
(
void
)
messageComposeViewController
:
(
MFMessageComposeViewController
*
)
controller
didFinishWithResult
:
(
MessageComposeResult
)
result
{
[
controller
dismissViewControllerAnimated
:
true
completion
:
nil
];
}
#pragma mark - local Data
-
(
void
)
jsSetLocalStorage
:
(
NSString
*
)
key
withStorage
:
(
NSString
*
)
value
{
if
(
!
[
value
isNonEmpty
])
{
value
=
@""
;
}
[
GMCache
storeObjectAtDocumentPathWithkey
:
key
object
:
value
];
}
-
(
NSString
*
)
jsGetLocalStorage
:
(
NSString
*
)
key
{
NSString
*
cacheKey
=
[
GMCache
fetchObjectAtDocumentPathWithkey
:
key
];
#warning h5
NSString
*
javaScriptStr
=
[
NSString
stringWithFormat
:
@"window.gm.pack.run('getLocalStorage',%@)"
,
cacheKey
];
[
self
.
webCompent
.
webView
evaluateJavaScript
:
javaScriptStr
completionHandler
:
nil
];
if
(
!
[
cacheKey
isNonEmpty
])
{
return
@""
;
}
return
cacheKey
;
}
-
(
void
)
jsSyncSSOInfo
:
(
NSString
*
)
jsonString
{
NSData
*
data
=
[
jsonString
dataUsingEncoding
:
NSUTF8StringEncoding
];
NSDictionary
*
info
=
[
NSJSONSerialization
JSONObjectWithData
:
data
options
:
NSJSONReadingMutableLeaves
error
:
nil
];
if
(
info
[
@"user_id"
]
!=
nil
)
{
[[
GMLoginManager
shareInstance
]
loginSuccessWithUserInfo
:
info
shouldBroadcast
:
NO
];
}
if
(
info
[
@"cookie"
]
!=
nil
&&
info
[
@"domain"
]
!=
nil
)
{
[
GMCookieManager
saveSessionId
:
info
[
@"cookie"
]
domain
:
info
[
@"domain"
]];
}
}
-
(
void
)
jsNewbieCouponGot
:
(
NSInteger
)
flag
{
[
GMCache
storeObjectAtMemoryWithkey
:
kNewUserTicketHasGot
object
:
@
(
flag
)];
}
/**
* @author wangjun, 16-07-04 14:07:51
*
* 秒杀页面添加到系统日历事件
* @param jsonString H5传来的的美购信息
*/
-
(
void
)
jsRemindEvent
:
(
NSString
*
)
jsonString
{
NSData
*
data
=
[
jsonString
dataUsingEncoding
:
NSUTF8StringEncoding
];
NSDictionary
*
json
=
[
NSJSONSerialization
JSONObjectWithData
:
data
options
:
NSJSONReadingMutableLeaves
error
:
NULL
];
NSInteger
beginTime
=
[
json
[
@"start_time"
]
longValue
];
NSInteger
endTime
=
[
json
[
@"end_time"
]
longValue
];
NSString
*
title
=
json
[
@"title"
];
NSString
*
url
=
json
[
@"url"
];
NSString
*
serviceId
=
json
[
@"service_id"
];
BOOL
notify
=
[
json
[
@"notify"
]
boolValue
];
GMCalendarEventManager
*
manager
=
[[
GMCalendarEventManager
alloc
]
init
];
__weak
typeof
(
manager
)
weakManager
=
manager
;
manager
.
authorizationAllowed
=
^
{
NSMutableDictionary
*
param
=
[
NSMutableDictionary
dictionary
];
param
[
@"service_id"
]
=
serviceId
;
//7.3.0修改,@王成亮
[
Phobos
track
:
@"activity_promotion_seckill_notice"
attributes
:
param
];
[
weakManager
addEvent
:
title
startDate
:
beginTime
endDate
:
endTime
serviceId
:
serviceId
url
:
url
];
};
if
([
manager
checkAuthorized
])
{
if
(
notify
)
{
//添加提醒
NSMutableDictionary
*
param
=
[
NSMutableDictionary
dictionary
];
param
[
@"service_id"
]
=
serviceId
;
[
Phobos
track
:
@"activity_promotion_seckill_notice"
attributes
:
param
];
[
manager
addEvent
:
title
startDate
:
beginTime
endDate
:
endTime
serviceId
:
serviceId
url
:
url
];
}
else
{
//取消提醒
[
manager
removeEvent
:
serviceId
];
}
}
}
-
(
BOOL
)
jsIsLocationEnable
{
BOOL
isLocation
=
[
GMLocationManager
hasOpenLocationService
];
NSString
*
javaScriptStr
=
[
NSString
stringWithFormat
:
@"window.gm.pack.run('isLocationEnableCallback',%d)"
,
isLocation
];
[
self
.
webCompent
.
webView
evaluateJavaScript
:
javaScriptStr
completionHandler
:
nil
];
return
isLocation
;
}
#pragma mark - 导航栏按键响应
-
(
void
)
backAction
:
(
OCNavigationBarButton
*
)
button
{
// 目前只有签到页面和获取列表支持返回拦截,后续建议逐渐删除
if
([
_jsGlobalObject
[
@"page_name"
]
isEqualToString
:
@"activity_list"
])
{
[
self
.
webCompent
.
webView
evaluateJavaScript
:
@"window.gm.pack.run('activityListBack')"
completionHandler
:
nil
];
}
[
self
nativeBackToCallJS
];
// 由前端控制当前页面的返回事件是否需要拦截
if
(
!
[
_jsGlobalObject
.
allKeys
containsObject
:
@"back_call"
]
||
!
[
_jsGlobalObject
[
@"back_call"
]
boolValue
])
{
[
super
backAction
:
button
];
}
}
-
(
void
)
rightButtonClicked
:
(
OCNavigationBarButton
*
)
button
{
[
super
rightButtonClicked
:
button
];
// 隐藏键盘,避免不必要的bug发生
[
self
.
view
endEditing
:
YES
];
if
(
_isSign
)
{
return
;
}
// 显示分享
if
(
_isShowShare
)
{
// self.shareView = nil 这句话不能删除。删除了会导致 shareView 的背景消失
self
.
shareView
=
nil
;
[
self
.
shareView
showWithShareUrl
:
self
.
shareObject
.
url
];
}
/*
统计预告分享pv uv(device)。另外数据端还可以利用这个做其它统计。in 7.0.5
*/
if
([
self
.
pageName
isNonEmpty
]
&&
_isShowShare
)
{
NSDictionary
*
dic
=
@{
@"business_id"
:
self
.
businessId
,
@"page_name"
:
self
.
pageName
,
@"referrer"
:
self
.
referer
};
[
Phobos
track
:
@"on_click_common_webview_share"
attributes
:
dic
];
}
// 没有分享,只显示了一个JS_Button
if
(
!
_isShowShare
&&
_isJsRightButton
)
{
NSString
*
jumpURL
=
_jsGlobalObject
[
@"right_button"
][
@"url"
];
NSString
*
jsFunction
=
_jsGlobalObject
[
@"right_button"
][
@"js_function"
];
if
([
jumpURL
isNonEmpty
])
{
[[
GMRouter
sharedInstance
]
pushScheme
:
jumpURL
];
}
if
([
jsFunction
isNonEmpty
])
{
[
self
.
webCompent
.
webView
evaluateJavaScript
:
jsFunction
completionHandler
:
nil
];
}
}
// 口红王子投票活动
if
([
_jsGlobalObject
[
@"navigation"
][
@"right_action"
]
isNonEmpty
])
{
NSString
*
rightAction
=
_jsGlobalObject
[
@"navigation"
][
@"right_action"
];
[
self
.
webCompent
.
webView
evaluateJavaScript
:
rightAction
completionHandler
:
nil
];
}
}
-
(
void
)
nearRightButtonClicked
:
(
OCNavigationBarButton
*
)
button
{
[
super
nearRightButtonClicked
:
button
];
if
(
_isShowShare
&&
_isJsRightButton
)
{
NSString
*
jumpURL
=
_jsGlobalObject
[
@"right_button"
][
@"url"
];
NSString
*
jsFunction
=
_jsGlobalObject
[
@"right_button"
][
@"js_function"
];
if
([
jumpURL
isNonEmpty
])
{
[[
GMRouter
sharedInstance
]
pushScheme
:
jumpURL
];
}
if
([
jsFunction
isNonEmpty
])
{
[
self
.
webCompent
.
webView
evaluateJavaScript
:
jsFunction
completionHandler
:
nil
];
}
}
}
#pragma mark - UIScrollViewDelegate
-
(
void
)
scrollViewDidScroll
:
(
UIScrollView
*
)
scrollView
{
if
(
_isNavigationAlpha
)
{
// animationDistance 为0时表示header_height值在h5端还未确认
if
(
self
.
animationDistance
>
0
)
{
[
self
animationBar
:
self
.
navigationBar
withScrollView
:
scrollView
];
}
else
{
CGFloat
headerHeight
=
[
_jsGlobalObject
[
@"header_height"
]
floatValue
];
// 如果header_height不为0,表示图片大小已经确定,
if
(
headerHeight
!=
0
)
{
self
.
animationDistance
=
headerHeight
-
OCNavigationBar
.
barHeight
;
}
}
CGFloat
alpha
=
[
self
animationBar
:
self
.
navigationBar
withScrollView
:
scrollView
];
if
(
_isSign
)
{
// 签到 rightButton不隐藏ase
CGFloat
offsetY
=
self
.
contentOffsetY
>
0
?
self
.
contentOffsetY
:
scrollView
.
contentOffset
.
y
;
self
.
navigationBar
.
rightButton
.
hidden
=
NO
;
self
.
navigationBar
.
titleLabel
.
hidden
=
NO
;
if
(
offsetY
>
[
_jsGlobalObject
[
@"header_height"
]
floatValue
]
-
OCNavigationBar
.
statusBarHeight
)
{
self
.
navigationBar
.
titleLabel
.
textColor
=
[
UIColor
colorWithWhite
:
0
alpha
:
alpha
];
self
.
navigationBar
.
rightIconURL
=
_jsGlobalObject
[
@"navigation"
][
@"right_scrolled_button"
];
self
.
navigationBar
.
leftIcon
=
@"back"
;
}
else
{
self
.
navigationBar
.
titleLabel
.
textColor
=
[
UIColor
whiteColor
];
self
.
navigationBar
.
rightIconURL
=
_jsGlobalObject
[
@"navigation"
][
@"right_button"
];
self
.
navigationBar
.
leftIcon
=
@"backWhite"
;
}
}
else
{
self
.
navigationBar
.
rightButton
.
hidden
=
!
(
alpha
==
1
);
}
}
}
-
(
void
)
showReport
{
[
self
showComplete
:
@"举报成功,所长会尽快处理哒"
];
}
/**
粘贴邀请好友口令到粘贴板
@param boardText 粘贴板文字
*/
-
(
void
)
jsClipboard
:
(
NSString
*
)
boardText
{
UIPasteboard
*
board
=
[
UIPasteboard
generalPasteboard
];
board
.
string
=
boardText
;
[
self
toast
:
@"复制成功"
];
}
#pragma mark - GMPhotoPickDismissDelegate
-
(
void
)
dismissPhotoPick
:
(
NSArray
<
GMEditPhotoInfo
*>
*
)
infos
{
if
(
infos
.
count
==
0
)
{
return
;
}
GMEditPhotoInfo
*
model
=
infos
.
firstObject
;
UIImage
*
image
=
model
.
finshedImage
;
NSString
*
remoteUrl
=
_isPrivatePhoto
?
API_UPLOAD_IMAGE_SAFE
:
API_UPLOAD_IMAGE
;
WMImageUploadOperation
*
operation
=
[[
WMImageUploadOperation
alloc
]
initWithImage
:
image
url
:
remoteUrl
withCompressionQuality
:
0
.
75
];
[
operation
setImageUploadFinishBlock
:
^
(
NSDictionary
*
JSON
)
{
NSString
*
publicUrl
=
@""
;
NSString
*
jsParam
=
@""
;
if
(
_isPrivatePhoto
)
{
publicUrl
=
JSON
[
@"data"
][
@"public_url"
];
NSString
*
privateUrl
=
JSON
[
@"data"
][
@"private_url"
];
if
([
publicUrl
isNonEmpty
]
&&
[
privateUrl
isNonEmpty
])
{
NSDictionary
*
data
=
@{
_requestCoder
:
@{
@"private_url"
:
privateUrl
,
@"public_url"
:
publicUrl
}};
NSData
*
jsParamData
=
[
NSJSONSerialization
dataWithJSONObject
:
data
options
:
0
error
:
NULL
];
jsParam
=
[[
NSString
alloc
]
initWithData
:
jsParamData
encoding
:
NSUTF8StringEncoding
];
}
}
else
{
publicUrl
=
JSON
[
@"data"
][
@"public_url"
];
NSDictionary
*
data
=
@{
_requestCoder
:
@{
@"public_url"
:
publicUrl
}};
NSData
*
jsParamData
=
[
NSJSONSerialization
dataWithJSONObject
:
data
options
:
0
error
:
NULL
];
jsParam
=
[[
NSString
alloc
]
initWithData
:
jsParamData
encoding
:
NSUTF8StringEncoding
];
}
NSString
*
jsString
=
[
NSString
stringWithFormat
:
@"gm.util.setPageData('%@')"
,
jsParam
];
[
self
.
webCompent
.
webView
evaluateJavaScript
:
jsString
completionHandler
:
nil
];
}];
[
operation
startUpload
];
}
// 签到页弹窗提示后,点击不再提醒会调用
-
(
void
)
jsSignNeverNotify
{
[
self
.
navigationController
popViewControllerAnimated
:
YES
];
}
-
(
int
)
jsIsUserLogin
{
int
isLogin
=
GMLoginManager
.
shareInstance
.
isVisitor
?
0
:
1
;
NSString
*
javaScriptStr
=
[
NSString
stringWithFormat
:
@"window.gm.pack.run('isUserLoginCallback',%d)"
,
isLogin
];
[
self
.
webCompent
.
webView
evaluateJavaScript
:
javaScriptStr
completionHandler
:
nil
];
return
isLogin
;
}
// js 获取NativeData数据
-
(
NSString
*
)
jsNativeDataLoaded
{
NSString
*
trackerJson
=
[
self
nativeCommonParam
];
if
([
trackerJson
isNonEmpty
])
{
NSString
*
jsonStr
=
[
NSString
stringWithFormat
:
@"window.gm.pack.run('setNativeDataLoaded','%@')"
,
trackerJson
];
[
self
.
webCompent
.
webView
evaluateJavaScript
:
jsonStr
completionHandler
:
nil
];
return
trackerJson
;
}
return
@""
;
}
// 本地获取通用数据
-
(
NSString
*
)
nativeCommonParam
{
NSMutableDictionary
*
param
=
[
NSMutableDictionary
dictionaryWithDictionary
:[
NSDictionary
trackerPageParam
:
self
]];
[
param
setValue
:
SafeString
(
@
(
OCNavigationBar
.
barHeight
))
forKey
:
@"title_bar_height"
];
[
param
setValue
:(
self
.
referrerLink
?
:
@[])
forKey
:
@"referrer_link"
];
// 仅当 cpc_referer 不为none时候传递此参数
if
(
self
.
cpc_referer
!=
GMCpcNone
)
{
[
param
setValue
:
SafeString
(
@
(
self
.
is_cpc
))
forKey
:
@"is_cpc"
];
[
param
setValue
:
SafeString
(
@
(
self
.
cpc_referer
))
forKey
:
@"cpc_referer"
];
}
NSData
*
referrerData
=
[
NSJSONSerialization
dataWithJSONObject
:
param
options
:
0
error
:
NULL
];
NSString
*
trackerJson
=
[[
NSString
alloc
]
initWithData
:
referrerData
encoding
:
NSUTF8StringEncoding
];
if
([
trackerJson
isNonEmpty
])
{
return
trackerJson
;
}
return
@""
;
}
-
(
NSString
*
)
jsInflateUserInfo
{
NSDictionary
*
userDic
=
@{
@"user_id"
:
@
([
GMLoginManager
shareInstance
].
user
.
userId
),
@"user_name"
:
SafeString
([
GMLoginManager
shareInstance
].
user
.
nickName
)};
NSData
*
userData
=
[
NSJSONSerialization
dataWithJSONObject
:
userDic
options
:
0
error
:
NULL
];
NSString
*
userParam
=
[[
NSString
alloc
]
initWithData
:
userData
encoding
:
NSUTF8StringEncoding
];
NSString
*
js
=
[
NSString
stringWithFormat
:
@"window.gm.pack.run('setInflateUserInfo',%@)"
,
userParam
];
[
self
.
webCompent
.
webView
evaluateJavaScript
:
js
completionHandler
:
nil
];
return
userParam
;
}
-
(
void
)
jsShowActionSheet
:
(
NSString
*
)
jsonString
{
NSArray
*
jsonArray
=
[
NSJSONSerialization
JSONObjectWithData
:[
jsonString
dataUsingEncoding
:
NSUTF8StringEncoding
]
options
:
NSJSONReadingAllowFragments
error
:
nil
];
if
(
jsonArray
.
count
<=
0
)
{
return
;
}
GMActionSheet
*
alertView
=
[[
GMActionSheet
alloc
]
init
];
// 回复弹窗内容和回调方法
for
(
NSDictionary
*
dic
in
jsonArray
)
{
GMActionSheetItemType
type
;
if
([
dic
[
@"title"
]
isEqualToString
:
@"取消"
])
{
type
=
GMActionSheetItemTypeCancel
;
[
alertView
addItemWithTitle
:
dic
[
@"title"
]
style
:
type
color
:
UIColor
.
headlineText
handle
:
nil
];
}
else
{
__weak
__typeof
(
self
)
weakSelf
=
self
;
type
=
GMActionSheetItemTypeDefault
;
[
alertView
addItemWithTitle
:
dic
[
@"title"
]
style
:
type
color
:
UIColor
.
headlineText
handle
:^
(
NSInteger
index
)
{
NSDictionary
*
className
=
jsonArray
[
index
];
NSString
*
js
=
[
NSString
stringWithFormat
:
@"window.gm.pack.run('%@')"
,
SafeString
(
className
[
@"callback"
])];
[
weakSelf
.
webCompent
.
webView
evaluateJavaScript
:
js
completionHandler
:
nil
];
}];
}
}
[
alertView
show
];
}
-
(
void
)
jsRightbuttonCallBack
:
(
NSString
*
)
json
{
NSData
*
jsonData
=
[
json
dataUsingEncoding
:
NSUTF8StringEncoding
];
NSDictionary
*
dict
=
[
NSJSONSerialization
JSONObjectWithData
:
jsonData
options
:
NSJSONReadingMutableContainers
error
:
nil
];
self
.
navigationBar
.
rightIconURL
=
dict
[
@"icon_url"
];
}
-
(
int
)
jsNavigationbarHeight
{
float
barH
=
OCNavigationBar
.
barHeight
;
NSString
*
javaScriptStr
=
[
NSString
stringWithFormat
:
@"window.gm.pack.run('navigationbarHeightCallback',%f)"
,
barH
];
[
self
.
webCompent
.
webView
evaluateJavaScript
:
javaScriptStr
completionHandler
:
nil
];
return
OCNavigationBar
.
barHeight
;
}
-
(
void
)
jsCheckAuthority
:
(
NSString
*
)
jsonString
{
[
AppDelegate
.
shareInstance
userIsAllowPush
:
^
(
BOOL
status
)
{
if
(
!
status
)
{
_isSettingCallback
=
YES
;
NSData
*
jsonData
=
[
jsonString
dataUsingEncoding
:
NSUTF8StringEncoding
];
NSDictionary
*
dict
=
[
NSJSONSerialization
JSONObjectWithData
:
jsonData
options
:
NSJSONReadingMutableContainers
error
:
nil
];
GMCommonAlertView
*
alertView
=
[[
GMCommonAlertView
alloc
]
init
];
alertView
.
titleLabel
.
text
=
dict
[
@"title"
];
alertView
.
subLabel
.
text
=
dict
[
@"tip"
];
[
alertView
.
button1
setTitle
:
dict
[
@"openName"
]
forState
:
UIControlStateNormal
];
[
alertView
.
button2
setTitle
:
dict
[
@"cancelName"
]
forState
:
UIControlStateNormal
];
alertView
.
button3
.
hidden
=
YES
;
self
.
settingType
=
[
dict
[
@"type"
]
integerValue
];
alertView
.
delegate
=
self
;
[
alertView
show
];
}
else
{
[
self
excuteSettingCallback
:
YES
];
}
}];
}
-
(
void
)
didClickCommonAlertWithButtonIndex
:
(
NSInteger
)
buttonIndex
alertView
:
(
GMCommonAlertView
*
)
alertView
{
[
alertView
dismiss
];
if
(
buttonIndex
==
1
)
{
//打开
[
self
goToAppSystemSettings
];
self
.
goToAppSettingsPage
=
YES
;
}
else
if
(
buttonIndex
==
2
)
{
[
self
excuteSettingCallback
:
NO
];
}
}
-
(
void
)
excuteSettingCallback
:
(
BOOL
)
setting
{
NSString
*
javaScriptStr
=
[
NSString
stringWithFormat
:
@"window.gm.pack.run('settingCallback',%d)"
,
setting
];
[
self
.
webCompent
.
webView
evaluateJavaScript
:
javaScriptStr
completionHandler
:
nil
];
}
#pragma mark - Native Call JS
/// Native 告知 H5页面展现
-
(
void
)
nativeAppearToCallJS
{
[
self
.
webCompent
.
webView
evaluateJavaScript
:
@"window.gm&&window.gm.pack&&window.gm.pack.run('appear')"
completionHandler
:
nil
];
}
/// Native 告知 H5页面不可见
-
(
void
)
nativeDisAppearToCallJS
{
[
self
.
webCompent
.
webView
evaluateJavaScript
:
@"window.gm&&window.gm.pack&&window.gm.pack.run('disappear')"
completionHandler
:
nil
];
}
/// Native 告知 H5返回执行
-
(
void
)
nativeBackToCallJS
{
[
self
.
webCompent
.
webView
evaluateJavaScript
:
@"window.gm.pack.run('backAction')"
completionHandler
:
nil
];
}
/// Native 告知 H5取消登录
-
(
void
)
nativeLoginCancelToCallJS
{
[
self
.
webCompent
.
webView
evaluateJavaScript
:
@"window.gm.pack.run('loginCancel')"
completionHandler
:
nil
];
}
/// Native 告知 H5进入后台
-
(
void
)
nativeEnterBackgroundToCallJS
{
[
self
.
webCompent
.
webView
evaluateJavaScript
:
@"window.gm.pack.run('enterBackground')"
completionHandler
:
nil
];
}
/// Native 告知 H5进入前台
-
(
void
)
nativeEnterForgroundToCallJS
{
[
self
.
webCompent
.
webView
evaluateJavaScript
:
@"window.gm.pack.run('enterForground')"
completionHandler
:
nil
];
}
#pragma mark - 埋点
/*** type由h5负责,所有h5埋点的方法都走这里 */
-
(
void
)
jsTrackEvent
:
(
NSString
*
)
JSONString
{
@try
{
NSData
*
data
=
[
JSONString
dataUsingEncoding
:
NSUnicodeStringEncoding
];
NSMutableDictionary
*
dict
=
[
NSJSONSerialization
JSONObjectWithData
:
data
options
:
NSJSONReadingAllowFragments
error
:
nil
];
id
pa
=
dict
[
@"params"
];
BOOL
sendNow
=
[
dict
[
@"nowSend"
]
boolValue
];
NSDictionary
*
json
;
if
(
pa
!=
nil
)
{
if
([
pa
isKindOfClass
:[
NSString
class
]])
{
NSError
*
jsonError
;
NSData
*
objectData
=
[
pa
dataUsingEncoding
:
NSUTF8StringEncoding
];
json
=
[
NSJSONSerialization
JSONObjectWithData
:
objectData
options
:
NSJSONReadingMutableContainers
error
:&
jsonError
];
[
Phobos
track
:
dict
[
@"type"
]
attributes
:
json
sendNow
:
sendNow
];
}
else
{
[
Phobos
track
:
dict
[
@"type"
]
attributes
:
dict
[
@"params"
]
sendNow
:
sendNow
];
}
}
else
{
[
Phobos
track
:
dict
[
@"type"
]
attributes
:@{}
sendNow
:
sendNow
];
}
}
@catch
(
NSException
*
exception
)
{
debugLog
(
@"exception:%@"
,
exception
);
}
}
/*** 精准曝光 */
-
(
void
)
jsHybridExposure
:
(
NSString
*
)
JSONString
{
@try
{
NSData
*
data
=
[
JSONString
dataUsingEncoding
:
NSUnicodeStringEncoding
];
NSMutableDictionary
*
dict
=
[
NSJSONSerialization
JSONObjectWithData
:
data
options
:
NSJSONReadingAllowFragments
error
:
nil
];
if
(
dict
)
{
[
Phobos
track
:
@"page_precise_exposure"
attributes
:
dict
sendNow
:
YES
currentAPI
:
GMExactExposureApi
];
}
}
@catch
(
NSException
*
exception
)
{
debugLog
(
@"exception:%@"
,
exception
);
}
}
#pragma mark - notification
-
(
void
)
addActiveObserver
{
[[
NSNotificationCenter
defaultCenter
]
addObserver
:
self
selector
:
@selector
(
didBecomeActive
)
name
:
UIApplicationDidBecomeActiveNotification
object
:
nil
];
[[
NSNotificationCenter
defaultCenter
]
addObserver
:
self
selector
:
@selector
(
willResignActive
)
name
:
UIApplicationWillResignActiveNotification
object
:
nil
];
[[
NSNotificationCenter
defaultCenter
]
addObserver
:
self
selector
:
@selector
(
loginCancelNotification
)
name
:
LOGIN_CANCEL_NOTIFICATION
object
:
nil
];
[[
NSNotificationCenter
defaultCenter
]
addObserver
:
self
selector
:
@selector
(
enterBackground
)
name
:
UIApplicationDidEnterBackgroundNotification
object
:
nil
];
[[
NSNotificationCenter
defaultCenter
]
addObserver
:
self
selector
:
@selector
(
enterForground
)
name
:
UIApplicationWillEnterForegroundNotification
object
:
nil
];
}
-
(
void
)
enterBackground
{
[
self
nativeEnterBackgroundToCallJS
];
}
-
(
void
)
enterForground
{
[
self
nativeEnterForgroundToCallJS
];
}
-
(
void
)
willResignActive
{
// 活动页面
if
([
_jsGlobalObject
[
@"page_name"
]
isEqualToString
:
@"activity_list"
])
{
[
self
nativeDisAppearToCallJS
];
}
}
-
(
void
)
didBecomeActive
{
if
([
_jsGlobalObject
[
@"page_name"
]
isEqualToString
:
@"activity_list"
])
{
[
self
nativeAppearToCallJS
];
}
// 前往设置页面后 回到当前页面需要告知前端状态,前端会直接弹出“开抢提醒”弹框
if
(
self
.
goToAppSettingsPage
)
{
[
AppDelegate
.
shareInstance
userIsAllowPush
:
^
(
BOOL
status
)
{
[
self
excuteSettingCallback
:
status
];
// 返回app的时候把数据清空了,所以延迟3秒执行
dispatch_after
(
dispatch_time
(
DISPATCH_TIME_NOW
,
(
int64_t
)(
3
*
NSEC_PER_SEC
)),
dispatch_get_main_queue
(),
^
{
// 获取通知权限浮层页授权按钮点击(需要获取授权状态)
[
Phobos
track
:
@"authority_page_click"
attributes
:@{
@"user_id"
:
@
([
GMLoginManager
shareInstance
].
user
.
userId
),
@"authority_type"
:
@
(
status
)}];
});
}];
}
// 由于秒杀专场使用了common_webivew协议,所以这段逻辑不得不放到这个controller里,并且添加相关页面的判断
// 秒杀专场的url activity/promotion/1024/seckill
// 美购专题的url special_promotion
if
([
_jsGlobalObject
[
@"is_seckill"
]
boolValue
]
&&
[
GMLocationManager
hasOpenLocationService
]
&&
[
GMLocationManager
shareInstance
].
statusWhenAppBackground
!=
[
CLLocationManager
authorizationStatus
])
{
/*
当系统地理位置权限改变后再回到app时,需要刷新webview,也就是说要重新确认 is_location_enable 参数的状态
由于先前使用的是query的方式来取得该参数,导致在webView.refresh时,该参数状态还是原来的状态,并没有改变
所以采取了下面强制webview重新loadRequest
由于是又加载了一个页面,在后退时webView是内部后退,而不是controller后退,所以又得重写 backAction 方法
如果h5方便的时候,将 is_location_enable 改为js主动获取,而不是使用query参数,这样更灵活。
*/
[
self
webViewLoadRequest
];
}
}
// 用户取消登录通知
-
(
void
)
loginCancelNotification
{
[
self
nativeLoginCancelToCallJS
];
}
#pragma mark - lazy loading
-
(
GMWebViewComponent
*
)
webCompent
{
if
(
!
_webCompent
)
{
_webCompent
=
[
GMWebViewComponent
new
];
_webCompent
.
delegate
=
self
;
_webCompent
.
clientH5Object
.
delegate
=
self
;
}
if
(
!
_webCompent
.
superview
)
{
[
self
.
view
addSubview
:
_webCompent
];
}
return
_webCompent
;
}
-
(
GMShareView
*
)
shareView
{
if
(
!
_shareView
)
{
_shareView
=
[[
GMShareView
alloc
]
init
];
_shareView
.
delegate
=
self
;
}
return
_shareView
;
}
-
(
GMDiaryShareView
*
)
diaryShareView
{
if
(
!
_diaryShareView
)
{
_diaryShareView
=
[[
GMDiaryShareView
alloc
]
init
];
_diaryShareView
.
delegate
=
self
;
}
return
_diaryShareView
;
}
-
(
void
)
dealloc
{
[[
NSNotificationCenter
defaultCenter
]
removeObserver
:
self
];
// 在某些情况下,如果controller先dealloc了,会导致webView找不到delegate而crash。例如修复jspatch与webview冲突时就会遇到。
// 复现步骤:先注释以下代码,再push到一个webController,加载时立即后退,等待,然后crash,提示 “webView:identifierForInitialRequest:fromDataSource”
_webCompent
.
delegate
=
nil
;
[
_webCompent
.
webView
stopLoading
];
}
@end
GMBase/Classes/JXPagerView/JXCategoryView/Base/JXCategoryBaseCell.h
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryBaseCell.h
// UI系列测试
//
// Created by jiaxin on 2018/3/15.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "JXCategoryBaseCellModel.h"
@interface
JXCategoryBaseCell
:
UICollectionViewCell
@property
(
nonatomic
,
strong
)
JXCategoryBaseCellModel
*
cellModel
;
-
(
void
)
initializeViews
NS_REQUIRES_SUPER
;
-
(
void
)
reloadData
:(
JXCategoryBaseCellModel
*
)
cellModel
NS_REQUIRES_SUPER
;
@end
GMBase/Classes/JXPagerView/JXCategoryView/Base/JXCategoryBaseCell.m
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryBaseCell.m
// UI系列测试
//
// Created by jiaxin on 2018/3/15.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryBaseCell.h"
@interface
JXCategoryBaseCell
()
@end
@implementation
JXCategoryBaseCell
-
(
instancetype
)
initWithFrame
:(
CGRect
)
frame
{
self
=
[
super
initWithFrame
:
frame
];
if
(
self
)
{
[
self
initializeViews
];
}
return
self
;
}
-
(
void
)
initializeViews
{
}
-
(
void
)
reloadData
:
(
JXCategoryBaseCellModel
*
)
cellModel
{
self
.
cellModel
=
cellModel
;
}
@end
GMBase/Classes/JXPagerView/JXCategoryView/Base/JXCategoryBaseCellModel.h
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryBaseCellModel.h
// UI系列测试
//
// Created by jiaxin on 2018/3/15.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface
JXCategoryBaseCellModel
:
NSObject
@property
(
nonatomic
,
assign
)
NSUInteger
index
;
@property
(
nonatomic
,
assign
)
BOOL
selected
;
@property
(
nonatomic
,
assign
)
CGFloat
cellWidth
;
@property
(
nonatomic
,
assign
)
CGFloat
cellSpacing
;
@property
(
nonatomic
,
assign
)
BOOL
cellWidthZoomEnabled
;
@property
(
nonatomic
,
assign
)
CGFloat
cellWidthZoomScale
;
@end
GMBase/Classes/JXPagerView/JXCategoryView/Base/JXCategoryBaseCellModel.m
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryBaseCellModel.m
// UI系列测试
//
// Created by jiaxin on 2018/3/15.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryBaseCellModel.h"
@implementation
JXCategoryBaseCellModel
-
(
CGFloat
)
cellWidth
{
if
(
_cellWidthZoomEnabled
)
{
return
_cellWidth
*
_cellWidthZoomScale
;
}
return
_cellWidth
;
}
@end
GMBase/Classes/JXPagerView/JXCategoryView/Base/JXCategoryBaseView.h
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryView.h
// UI系列测试
//
// Created by jiaxin on 2018/3/15.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "JXCategoryBaseCell.h"
#import "JXCategoryBaseCellModel.h"
#import "JXCategoryCollectionView.h"
#import "JXCategoryViewDefines.h"
@class
JXCategoryBaseView
;
@protocol
JXCategoryViewDelegate
<
NSObject
>
@optional
//为什么会把选中代理分为三个,因为有时候只关心点击选中的,有时候只关心滚动选中的,有时候只关心选中。所以具体情况,使用对应方法。
/**
点击选择或者滚动选中都会调用该方法,如果外部不关心具体是点击还是滚动选中的,只关心选中这个事件,就实现该方法。
@param categoryView categoryView description
@param index 选中的index
*/
-
(
void
)
categoryView
:
(
JXCategoryBaseView
*
)
categoryView
didSelectedItemAtIndex
:
(
NSInteger
)
index
;
/**
点击选中的情况才会调用该方法
@param categoryView categoryView description
@param index 选中的index
*/
-
(
void
)
categoryView
:(
JXCategoryBaseView
*
)
categoryView
didClickSelectedItemAtIndex
:(
NSInteger
)
index
;
/**
滚动选中的情况才会调用该方法
@param categoryView categoryView description
@param index 选中的index
*/
-
(
void
)
categoryView
:(
JXCategoryBaseView
*
)
categoryView
didScrollSelectedItemAtIndex
:(
NSInteger
)
index
;
/**
只有点击的切换才会调用!!!
因为用户点击,contentScrollView即将过渡到目标index的配置。内部默认实现`[self.contentScrollView setContentOffset:CGPointMake(targetIndex*self.contentScrollView.bounds.size.width, 0) animated:YES];`。如果实现该代理方法,以自定义实现为准。比如将animated设置为NO,点击切换时无需滚动效果。类似于今日头条APP。
@param categoryView categoryView description
@param index index description
*/
-
(
void
)
categoryView
:(
JXCategoryBaseView
*
)
categoryView
didClickedItemContentScrollViewTransitionToIndex
:(
NSInteger
)
index
;
/**
正在滚动中的回调
@param categoryView categoryView description
@param leftIndex 正在滚动中,相对位置处于左边的index
@param rightIndex 正在滚动中,相对位置处于右边的index
@param ratio 百分比
*/
-
(
void
)
categoryView
:(
JXCategoryBaseView
*
)
categoryView
scrollingFromLeftIndex
:(
NSInteger
)
leftIndex
toRightIndex
:(
NSInteger
)
rightIndex
ratio
:(
CGFloat
)
ratio
;
@end
@interface
JXCategoryBaseView
:
UIView
@property
(
nonatomic
,
strong
)
JXCategoryCollectionView
*
collectionView
;
@property
(
nonatomic
,
strong
)
NSArray
<
JXCategoryBaseCellModel
*>*
dataSource
;
@property
(
nonatomic
,
weak
)
id
<
JXCategoryViewDelegate
>
delegate
;
@property
(
nonatomic
,
strong
)
UIScrollView
*
contentScrollView
;
//需要关联的contentScrollView
@property
(
nonatomic
,
assign
)
NSInteger
defaultSelectedIndex
;
//修改初始化的时候默认选择的index
@property
(
nonatomic
,
assign
,
readonly
)
NSInteger
selectedIndex
;
@property
(
nonatomic
,
assign
)
CGFloat
contentEdgeInsetLeft
;
//整体内容的左边距,默认JXCategoryViewAutomaticDimension(等于cellSpacing)
@property
(
nonatomic
,
assign
)
CGFloat
contentEdgeInsetRight
;
//整体内容的右边距,默认JXCategoryViewAutomaticDimension(等于cellSpacing)
@property
(
nonatomic
,
assign
)
CGFloat
cellWidth
;
//默认JXCategoryViewAutomaticDimension
@property
(
nonatomic
,
assign
)
CGFloat
cellWidthIncrement
;
//cell宽度补偿。默认:0
@property
(
nonatomic
,
assign
)
CGFloat
cellSpacing
;
//cell之间的间距,默认20
@property
(
nonatomic
,
assign
)
BOOL
averageCellSpacingEnabled
;
//当item内容总宽度小于JXCategoryBaseView的宽度,是否将cellSpacing均分。默认为YES。
//----------------------cellWidthZoomEnabled-----------------------//
//cell宽度的缩放主要是为了腾讯视频、汽车之家效果打造的,一般情况下慎用,不太好控制。
@property
(
nonatomic
,
assign
)
BOOL
cellWidthZoomEnabled
;
//默认为NO
@property
(
nonatomic
,
assign
)
BOOL
cellWidthZoomScrollGradientEnabled
;
//手势滚动中,是否需要更新状态。默认为YES
@property
(
nonatomic
,
assign
)
CGFloat
cellWidthZoomScale
;
//默认1.2,cellWidthZoomEnabled为YES才生效
/**
代码调用选中了目标index的item
@param index 目标index
*/
-
(
void
)
selectItemAtIndex
:(
NSInteger
)
index
;
/**
初始化的时候无需调用。初始化之后更新其他配置属性,需要调用该方法,进行刷新。
*/
-
(
void
)
reloadData
;
/**
刷新指定的index的cell
@param index 指定cell的index
*/
-
(
void
)
reloadCellAtIndex
:(
NSInteger
)
index
;
#pragma mark - Subclass use
-
(
CGRect
)
getTargetCellFrame
:(
NSInteger
)
targetIndex
;
#pragma mark - Subclass Override
-
(
void
)
initializeData
NS_REQUIRES_SUPER
;
-
(
void
)
initializeViews
NS_REQUIRES_SUPER
;
/**
reloadData方法调用,重新生成数据源赋值到self.dataSource
*/
-
(
void
)
refreshDataSource
;
/**
reloadData方法调用,根据数据源重新刷新状态;
*/
-
(
void
)
refreshState
NS_REQUIRES_SUPER
;
/**
用户点击了某个item,刷新选中与取消选中的cellModel
@param selectedCellModel 选中的cellModel
@param unselectedCellModel 取消选中的cellModel
*/
-
(
void
)
refreshSelectedCellModel
:(
JXCategoryBaseCellModel
*
)
selectedCellModel
unselectedCellModel
:(
JXCategoryBaseCellModel
*
)
unselectedCellModel
NS_REQUIRES_SUPER
;
/**
关联的contentScrollView的contentOffset发生了改变
@param contentOffset 偏移量
*/
-
(
void
)
contentOffsetOfContentScrollViewDidChanged
:(
CGPoint
)
contentOffset
NS_REQUIRES_SUPER
;
/**
该方法用于子类重载,如果外部要选中某个index,请使用`- (void)selectItemAtIndex:(NSUInteger)index;`
点击某一个item,或者contentScrollView滚动到某一个item的时候调用。根据selectIndex刷新选中状态。
@param index 选中的index
@param isClicked YES:点击选中;NO:滚动选中。
@return 返回值为NO,表示触发内部某些判断(点击了同一个cell),子类无需后续操作。
*/
-
(
BOOL
)
selectCellAtIndex
:(
NSInteger
)
index
isClicked
:(
BOOL
)
isClicked
NS_REQUIRES_SUPER
;
/**
reloadData时,返回每个cell的宽度
@param index 目标index
@return cellWidth
*/
-
(
CGFloat
)
preferredCellWidthAtIndex
:(
NSInteger
)
index
;
/**
返回自定义cell的class
@return cell class
*/
-
(
Class
)
preferredCellClass
;
/**
refreshState时调用,重置cellModel的状态
@param cellModel 待重置的cellModel
@param index 目标index
*/
-
(
void
)
refreshCellModel
:(
JXCategoryBaseCellModel
*
)
cellModel
index
:(
NSInteger
)
index
;
@end
GMBase/Classes/JXPagerView/JXCategoryView/Base/JXCategoryBaseView.m
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryBaseView.m
// UI系列测试
//
// Created by jiaxin on 2018/3/15.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryBaseView.h"
#import "JXCategoryFactory.h"
struct
DelegateFlags
{
unsigned
int
didSelectedItemAtIndexFlag
:
1
;
unsigned
int
didClickSelectedItemAtIndexFlag
:
1
;
unsigned
int
didScrollSelectedItemAtIndexFlag
:
1
;
unsigned
int
didClickedItemContentScrollViewTransitionToIndexFlag
:
1
;
unsigned
int
scrollingFromLeftIndexToRightIndexFlag
:
1
;
};
@interface
JXCategoryBaseView
()
<
UICollectionViewDataSource
,
UICollectionViewDelegate
,
UICollectionViewDelegateFlowLayout
>
@property
(
nonatomic
,
assign
)
struct
DelegateFlags
delegateFlags
;
@property
(
nonatomic
,
assign
)
NSInteger
selectedIndex
;
@property
(
nonatomic
,
assign
)
CGFloat
innerCellSpacing
;
@property
(
nonatomic
,
assign
)
CGPoint
lastContentViewContentOffset
;
@end
@implementation
JXCategoryBaseView
-
(
void
)
dealloc
{
if
(
self
.
contentScrollView
)
{
[
self
.
contentScrollView
removeObserver
:
self
forKeyPath
:
@"contentOffset"
];
}
}
-
(
instancetype
)
initWithFrame
:
(
CGRect
)
frame
{
self
=
[
super
initWithFrame
:
frame
];
if
(
self
)
{
[
self
initializeData
];
[
self
initializeViews
];
}
return
self
;
}
-
(
instancetype
)
initWithCoder
:
(
NSCoder
*
)
coder
{
self
=
[
super
initWithCoder
:
coder
];
if
(
self
)
{
[
self
initializeData
];
[
self
initializeViews
];
}
return
self
;
}
-
(
void
)
setDelegate
:
(
id
<
JXCategoryViewDelegate
>
)
delegate
{
_delegate
=
delegate
;
_delegateFlags
.
didSelectedItemAtIndexFlag
=
[
delegate
respondsToSelector
:
@selector
(
categoryView
:
didSelectedItemAtIndex
:
)];
_delegateFlags
.
didClickSelectedItemAtIndexFlag
=
[
delegate
respondsToSelector
:
@selector
(
categoryView
:
didClickSelectedItemAtIndex
:
)];
_delegateFlags
.
didScrollSelectedItemAtIndexFlag
=
[
delegate
respondsToSelector
:
@selector
(
categoryView
:
didScrollSelectedItemAtIndex
:
)];
_delegateFlags
.
didClickedItemContentScrollViewTransitionToIndexFlag
=
[
delegate
respondsToSelector
:
@selector
(
categoryView
:
didClickedItemContentScrollViewTransitionToIndex
:
)];
_delegateFlags
.
scrollingFromLeftIndexToRightIndexFlag
=
[
delegate
respondsToSelector
:
@selector
(
categoryView
:
scrollingFromLeftIndex
:
toRightIndex
:
ratio
:
)];
}
-
(
void
)
initializeData
{
_dataSource
=
[
NSMutableArray
array
];
_selectedIndex
=
0
;
_cellWidth
=
JXCategoryViewAutomaticDimension
;
_cellWidthIncrement
=
0
;
_cellSpacing
=
20
;
_averageCellSpacingEnabled
=
YES
;
_cellWidthZoomEnabled
=
NO
;
_cellWidthZoomScale
=
1
.
2
;
_cellWidthZoomScrollGradientEnabled
=
YES
;
_contentEdgeInsetLeft
=
JXCategoryViewAutomaticDimension
;
_contentEdgeInsetRight
=
JXCategoryViewAutomaticDimension
;
_lastContentViewContentOffset
=
CGPointZero
;
}
-
(
void
)
initializeViews
{
self
.
collectionView
=
({
UICollectionViewFlowLayout
*
layout
=
[[
UICollectionViewFlowLayout
alloc
]
init
];
layout
.
scrollDirection
=
UICollectionViewScrollDirectionHorizontal
;
JXCategoryCollectionView
*
collectionView
=
[[
JXCategoryCollectionView
alloc
]
initWithFrame
:
self
.
bounds
collectionViewLayout
:
layout
];
collectionView
.
backgroundColor
=
[
UIColor
clearColor
];
collectionView
.
showsHorizontalScrollIndicator
=
NO
;
collectionView
.
showsVerticalScrollIndicator
=
NO
;
collectionView
.
scrollsToTop
=
NO
;
collectionView
.
dataSource
=
self
;
collectionView
.
delegate
=
self
;
[
collectionView
registerClass
:[
self
preferredCellClass
]
forCellWithReuseIdentifier
:
NSStringFromClass
([
self
preferredCellClass
])];
collectionView
.
autoresizingMask
=
UIViewAutoresizingFlexibleWidth
|
UIViewAutoresizingFlexibleHeight
;
collectionView
;
});
[
self
addSubview
:
self
.
collectionView
];
}
-
(
void
)
setDefaultSelectedIndex
:
(
NSInteger
)
defaultSelectedIndex
{
_defaultSelectedIndex
=
defaultSelectedIndex
;
self
.
selectedIndex
=
defaultSelectedIndex
;
}
-
(
void
)
setContentScrollView
:
(
UIScrollView
*
)
contentScrollView
{
if
(
_contentScrollView
!=
nil
)
{
[
_contentScrollView
removeObserver
:
self
forKeyPath
:
@"contentOffset"
];
}
_contentScrollView
=
contentScrollView
;
_contentScrollView
.
scrollsToTop
=
NO
;
[
contentScrollView
addObserver
:
self
forKeyPath
:
@"contentOffset"
options
:
NSKeyValueObservingOptionNew
context
:
nil
];
}
-
(
void
)
reloadData
{
[
self
refreshDataSource
];
[
self
refreshState
];
[
self
.
collectionView
.
collectionViewLayout
invalidateLayout
];
[
self
.
collectionView
reloadData
];
}
-
(
void
)
reloadCellAtIndex
:
(
NSInteger
)
index
{
if
(
index
>=
self
.
dataSource
.
count
)
{
return
;
}
JXCategoryBaseCellModel
*
cellModel
=
self
.
dataSource
[
index
];
[
self
refreshCellModel
:
cellModel
index
:
index
];
JXCategoryBaseCell
*
cell
=
(
JXCategoryBaseCell
*
)[
self
.
collectionView
cellForItemAtIndexPath
:[
NSIndexPath
indexPathForItem
:
index
inSection
:
0
]];
[
cell
reloadData
:
cellModel
];
}
-
(
void
)
selectItemAtIndex
:
(
NSInteger
)
index
{
[
self
selectCellAtIndex
:
index
isClicked
:
YES
];
}
-
(
void
)
layoutSubviews
{
[
super
layoutSubviews
];
[
self
reloadData
];
}
#pragma mark - Subclass Override
-
(
void
)
refreshDataSource
{
}
-
(
void
)
refreshState
{
if
(
self
.
selectedIndex
>=
self
.
dataSource
.
count
)
{
self
.
selectedIndex
=
0
;
}
self
.
innerCellSpacing
=
self
.
cellSpacing
;
__block
CGFloat
totalItemWidth
=
[
self
getContentEdgeInsetLeft
];
CGFloat
totalCellWidth
=
0
;
for
(
int
i
=
0
;
i
<
self
.
dataSource
.
count
;
i
++
)
{
JXCategoryBaseCellModel
*
cellModel
=
self
.
dataSource
[
i
];
cellModel
.
index
=
i
;
cellModel
.
cellWidth
=
[
self
preferredCellWidthAtIndex
:
i
]
+
self
.
cellWidthIncrement
;
totalCellWidth
+=
cellModel
.
cellWidth
;
cellModel
.
cellWidthZoomEnabled
=
self
.
cellWidthZoomEnabled
;
cellModel
.
cellWidthZoomScale
=
1
.
0
;
cellModel
.
cellSpacing
=
self
.
cellSpacing
;
if
(
i
==
self
.
dataSource
.
count
-
1
)
{
totalItemWidth
+=
cellModel
.
cellWidth
+
[
self
getContentEdgeInsetRight
];
}
else
{
totalItemWidth
+=
cellModel
.
cellWidth
+
self
.
cellSpacing
;
}
if
(
i
==
self
.
selectedIndex
)
{
cellModel
.
selected
=
YES
;
cellModel
.
cellWidthZoomScale
=
self
.
cellWidthZoomScale
;
}
else
{
cellModel
.
selected
=
NO
;
}
[
self
refreshCellModel
:
cellModel
index
:
i
];
}
if
(
self
.
averageCellSpacingEnabled
&&
totalItemWidth
<
self
.
bounds
.
size
.
width
)
{
//如果总的内容宽度都没有超过视图度,就将cellWidth等分
NSInteger
cellSpacingItemCount
=
self
.
dataSource
.
count
-
1
;
CGFloat
totalCellSpacingWidth
=
self
.
bounds
.
size
.
width
-
totalCellWidth
;
//如果内容左边距是Automatic,就加1
if
(
self
.
contentEdgeInsetLeft
==
JXCategoryViewAutomaticDimension
)
{
cellSpacingItemCount
+=
1
;
}
else
{
totalCellSpacingWidth
-=
self
.
contentEdgeInsetLeft
;
}
//如果内容右边距是Automatic,就加1
if
(
self
.
contentEdgeInsetRight
==
JXCategoryViewAutomaticDimension
)
{
cellSpacingItemCount
+=
1
;
}
else
{
totalCellSpacingWidth
-=
self
.
contentEdgeInsetRight
;
}
CGFloat
cellSpacing
=
0
;
if
(
cellSpacingItemCount
>
0
)
{
cellSpacing
=
totalCellSpacingWidth
/
cellSpacingItemCount
;
}
self
.
innerCellSpacing
=
cellSpacing
;
[
self
.
dataSource
enumerateObjectsUsingBlock
:
^
(
JXCategoryBaseCellModel
*
_Nonnull
obj
,
NSUInteger
idx
,
BOOL
*
_Nonnull
stop
)
{
obj
.
cellSpacing
=
cellSpacing
;
}];
}
__block
CGFloat
frameXOfSelectedCell
=
self
.
innerCellSpacing
;
__block
CGFloat
selectedCellWidth
=
0
;
totalItemWidth
=
self
.
innerCellSpacing
;
[
self
.
dataSource
enumerateObjectsUsingBlock
:
^
(
JXCategoryBaseCellModel
*
cellModel
,
NSUInteger
idx
,
BOOL
*
_Nonnull
stop
)
{
if
(
idx
<
self
.
selectedIndex
)
{
frameXOfSelectedCell
+=
cellModel
.
cellWidth
+
self
.
innerCellSpacing
;
}
else
if
(
idx
==
self
.
selectedIndex
)
{
selectedCellWidth
=
cellModel
.
cellWidth
;
}
totalItemWidth
+=
cellModel
.
cellWidth
+
self
.
innerCellSpacing
;
}];
CGFloat
minX
=
0
;
CGFloat
maxX
=
totalItemWidth
-
self
.
bounds
.
size
.
width
;
CGFloat
targetX
=
frameXOfSelectedCell
-
self
.
bounds
.
size
.
width
/
2
.
0
+
selectedCellWidth
/
2
.
0
;
[
self
.
collectionView
setContentOffset
:
CGPointMake
(
MAX
(
MIN
(
maxX
,
targetX
),
minX
),
0
)
animated
:
NO
];
if
(
CGRectEqualToRect
(
self
.
contentScrollView
.
frame
,
CGRectZero
)
&&
self
.
contentScrollView
.
superview
!=
nil
)
{
//某些情况、系统会出现JXCategoryView先布局,contentScrollView后布局。就会导致下面指定defaultSelectedIndex失效,所以发现frame为zero时,强行触发布局。
[
self
.
contentScrollView
.
superview
setNeedsLayout
];
[
self
.
contentScrollView
.
superview
layoutIfNeeded
];
}
[
self
.
contentScrollView
setContentOffset
:
CGPointMake
(
self
.
selectedIndex
*
self
.
contentScrollView
.
bounds
.
size
.
width
,
0
)
animated
:
NO
];
}
-
(
BOOL
)
selectCellAtIndex
:
(
NSInteger
)
targetIndex
isClicked
:
(
BOOL
)
isClicked
{
return
[
self
_selectCellAtIndex
:
targetIndex
isClicked
:
isClicked
];
}
-
(
BOOL
)
_selectCellAtIndex
:
(
NSInteger
)
targetIndex
isClicked
:
(
BOOL
)
isClicked
{
if
(
targetIndex
>=
self
.
dataSource
.
count
)
{
return
NO
;
}
if
(
self
.
selectedIndex
==
targetIndex
)
{
if
(
isClicked
)
{
if
(
self
.
delegateFlags
.
didClickSelectedItemAtIndexFlag
)
{
[
self
.
delegate
categoryView
:
self
didClickSelectedItemAtIndex
:
targetIndex
];
}
}
else
{
if
(
self
.
delegateFlags
.
didScrollSelectedItemAtIndexFlag
)
{
[
self
.
delegate
categoryView
:
self
didScrollSelectedItemAtIndex
:
targetIndex
];
}
}
if
(
self
.
delegateFlags
.
didSelectedItemAtIndexFlag
)
{
[
self
.
delegate
categoryView
:
self
didSelectedItemAtIndex
:
targetIndex
];
}
return
NO
;
}
JXCategoryBaseCellModel
*
lastCellModel
=
self
.
dataSource
[
self
.
selectedIndex
];
JXCategoryBaseCellModel
*
selectedCellModel
=
self
.
dataSource
[
targetIndex
];
[
self
refreshSelectedCellModel
:
selectedCellModel
unselectedCellModel
:
lastCellModel
];
JXCategoryBaseCell
*
lastCell
=
(
JXCategoryBaseCell
*
)[
self
.
collectionView
cellForItemAtIndexPath
:[
NSIndexPath
indexPathForItem
:
self
.
selectedIndex
inSection
:
0
]];
[
lastCell
reloadData
:
lastCellModel
];
JXCategoryBaseCell
*
selectedCell
=
(
JXCategoryBaseCell
*
)[
self
.
collectionView
cellForItemAtIndexPath
:[
NSIndexPath
indexPathForItem
:
targetIndex
inSection
:
0
]];
[
selectedCell
reloadData
:
selectedCellModel
];
if
(
self
.
cellWidthZoomEnabled
)
{
[
self
.
collectionView
.
collectionViewLayout
invalidateLayout
];
//延时为了解决cellwidth变化,点击最后几个cell,scrollToItem会出现位置偏移bug
dispatch_after
(
dispatch_time
(
DISPATCH_TIME_NOW
,
(
int64_t
)(
0
.
01
*
NSEC_PER_SEC
)),
dispatch_get_main_queue
(),
^
{
[
self
.
collectionView
scrollToItemAtIndexPath
:[
NSIndexPath
indexPathForItem
:
targetIndex
inSection
:
0
]
atScrollPosition
:
UICollectionViewScrollPositionCenteredHorizontally
animated
:
YES
];
});
}
else
{
[
self
.
collectionView
scrollToItemAtIndexPath
:[
NSIndexPath
indexPathForItem
:
targetIndex
inSection
:
0
]
atScrollPosition
:
UICollectionViewScrollPositionCenteredHorizontally
animated
:
YES
];
}
if
(
isClicked
)
{
if
(
self
.
delegateFlags
.
didClickedItemContentScrollViewTransitionToIndexFlag
)
{
[
self
.
delegate
categoryView
:
self
didClickedItemContentScrollViewTransitionToIndex
:
targetIndex
];
}
else
{
[
self
.
contentScrollView
setContentOffset
:
CGPointMake
(
targetIndex
*
self
.
contentScrollView
.
bounds
.
size
.
width
,
0
)
animated
:
YES
];
}
}
self
.
selectedIndex
=
targetIndex
;
if
(
isClicked
)
{
if
(
self
.
delegateFlags
.
didClickSelectedItemAtIndexFlag
)
{
[
self
.
delegate
categoryView
:
self
didClickSelectedItemAtIndex
:
targetIndex
];
}
}
else
{
if
(
self
.
delegateFlags
.
didScrollSelectedItemAtIndexFlag
)
{
[
self
.
delegate
categoryView
:
self
didScrollSelectedItemAtIndex
:
targetIndex
];
}
}
if
(
self
.
delegateFlags
.
didSelectedItemAtIndexFlag
)
{
[
self
.
delegate
categoryView
:
self
didSelectedItemAtIndex
:
targetIndex
];
}
return
YES
;
}
-
(
void
)
refreshSelectedCellModel
:
(
JXCategoryBaseCellModel
*
)
selectedCellModel
unselectedCellModel
:
(
JXCategoryBaseCellModel
*
)
unselectedCellModel
{
selectedCellModel
.
selected
=
YES
;
selectedCellModel
.
cellWidthZoomScale
=
self
.
cellWidthZoomScale
;
unselectedCellModel
.
selected
=
NO
;
unselectedCellModel
.
cellWidthZoomScale
=
1
.
0
;
}
-
(
void
)
contentOffsetOfContentScrollViewDidChanged
:
(
CGPoint
)
contentOffset
{
CGFloat
ratio
=
contentOffset
.
x
/
self
.
contentScrollView
.
bounds
.
size
.
width
;
if
(
ratio
>
self
.
dataSource
.
count
-
1
||
ratio
<
0
)
{
//超过了边界,不需要处理
return
;
}
if
(
contentOffset
.
x
==
0
&&
self
.
selectedIndex
==
0
&&
self
.
lastContentViewContentOffset
.
x
==
0
)
{
//滚动到了最左边,且已经选中了第一个,且之前的contentOffset.x为0
return
;
}
CGFloat
maxContentOffsetX
=
self
.
contentScrollView
.
contentSize
.
width
-
self
.
contentScrollView
.
bounds
.
size
.
width
;
if
(
contentOffset
.
x
==
maxContentOffsetX
&&
self
.
selectedIndex
==
self
.
dataSource
.
count
-
1
&&
self
.
lastContentViewContentOffset
.
x
==
maxContentOffsetX
)
{
//滚动到了最右边,且已经选中了最后一个,且之前的contentOffset.x为maxContentOffsetX
return
;
}
ratio
=
MAX
(
0
,
MIN
(
self
.
dataSource
.
count
-
1
,
ratio
));
NSInteger
baseIndex
=
floorf
(
ratio
);
CGFloat
remainderRatio
=
ratio
-
baseIndex
;
if
(
remainderRatio
==
0
)
{
//滑动翻页,需要更新选中状态
//滑动一小段距离,然后放开回到原位,contentOffset同样的值会回调多次。例如在index为1的情况,滑动放开回到原位,contentOffset会多次回调CGPoint(width, 0)
if
(
!
(
self
.
lastContentViewContentOffset
.
x
==
contentOffset
.
x
&&
self
.
selectedIndex
==
baseIndex
))
{
[
self
scrollselectItemAtIndex
:
baseIndex
];
}
}
else
{
//快速滑动翻页,当remainderRatio没有变成0,但是已经翻页了,需要通过下面的判断,触发选中
if
(
fabs
(
ratio
-
self
.
selectedIndex
)
>
1
)
{
NSInteger
targetIndex
=
baseIndex
;
if
(
ratio
<
self
.
selectedIndex
)
{
targetIndex
=
baseIndex
+
1
;
}
[
self
_selectCellAtIndex
:
targetIndex
isClicked
:
NO
];
}
if
(
self
.
cellWidthZoomEnabled
&&
self
.
cellWidthZoomScrollGradientEnabled
)
{
JXCategoryBaseCellModel
*
leftCellModel
=
(
JXCategoryBaseCellModel
*
)
self
.
dataSource
[
baseIndex
];
JXCategoryBaseCellModel
*
rightCellModel
=
(
JXCategoryBaseCellModel
*
)
self
.
dataSource
[
baseIndex
+
1
];
leftCellModel
.
cellWidthZoomScale
=
[
JXCategoryFactory
interpolationFrom
:
self
.
cellWidthZoomScale
to
:
1
.
0
percent
:
remainderRatio
];
rightCellModel
.
cellWidthZoomScale
=
[
JXCategoryFactory
interpolationFrom
:
1
.
0
to
:
self
.
cellWidthZoomScale
percent
:
remainderRatio
];
[
self
.
collectionView
.
collectionViewLayout
invalidateLayout
];
}
if
(
self
.
delegateFlags
.
scrollingFromLeftIndexToRightIndexFlag
)
{
[
self
.
delegate
categoryView
:
self
scrollingFromLeftIndex
:
baseIndex
toRightIndex
:
baseIndex
+
1
ratio
:
remainderRatio
];
}
}
}
-
(
CGFloat
)
preferredCellWidthAtIndex
:
(
NSInteger
)
index
{
return
0
;
}
-
(
Class
)
preferredCellClass
{
return
JXCategoryBaseCell
.
class
;
}
-
(
void
)
refreshCellModel
:
(
JXCategoryBaseCellModel
*
)
cellModel
index
:
(
NSInteger
)
index
{
}
#pragma mark - <UICollectionViewDataSource, UICollectionViewDelegate>
-
(
NSInteger
)
numberOfSectionsInCollectionView
:
(
UICollectionView
*
)
collectionView
{
return
1
;
}
-
(
NSInteger
)
collectionView
:
(
UICollectionView
*
)
collectionView
numberOfItemsInSection
:
(
NSInteger
)
section
{
return
self
.
dataSource
.
count
;
}
-
(
UICollectionViewCell
*
)
collectionView
:
(
UICollectionView
*
)
collectionView
cellForItemAtIndexPath
:
(
NSIndexPath
*
)
indexPath
{
return
[
collectionView
dequeueReusableCellWithReuseIdentifier
:
NSStringFromClass
([
self
preferredCellClass
])
forIndexPath
:
indexPath
];
}
-
(
void
)
collectionView
:
(
UICollectionView
*
)
collectionView
willDisplayCell
:
(
UICollectionViewCell
*
)
cell
forItemAtIndexPath
:
(
NSIndexPath
*
)
indexPath
{
JXCategoryBaseCell
*
categoryCell
=
(
JXCategoryBaseCell
*
)
cell
;
[
categoryCell
reloadData
:
self
.
dataSource
[
indexPath
.
item
]];
}
-
(
void
)
collectionView
:
(
UICollectionView
*
)
collectionView
didSelectItemAtIndexPath
:
(
NSIndexPath
*
)
indexPath
{
[
self
clickselectItemAtIndex
:
indexPath
.
row
];
}
#pragma mark - <UICollectionViewDelegateFlowLayout>
-
(
UIEdgeInsets
)
collectionView
:
(
UICollectionView
*
)
collectionView
layout
:
(
UICollectionViewLayout
*
)
collectionViewLayout
insetForSectionAtIndex
:
(
NSInteger
)
section
{
return
UIEdgeInsetsMake
(
0
,
[
self
getContentEdgeInsetLeft
],
0
,
[
self
getContentEdgeInsetRight
]);
}
-
(
CGSize
)
collectionView
:
(
UICollectionView
*
)
collectionView
layout
:
(
UICollectionViewLayout
*
)
collectionViewLayout
sizeForItemAtIndexPath
:
(
NSIndexPath
*
)
indexPath
{
JXCategoryBaseCellModel
*
cellModel
=
self
.
dataSource
[
indexPath
.
item
];
return
CGSizeMake
(
cellModel
.
cellWidth
,
self
.
bounds
.
size
.
height
);
}
-
(
CGFloat
)
collectionView
:
(
UICollectionView
*
)
collectionView
layout
:
(
UICollectionViewLayout
*
)
collectionViewLayout
minimumLineSpacingForSectionAtIndex
:
(
NSInteger
)
section
{
return
self
.
innerCellSpacing
;
}
-
(
CGFloat
)
collectionView
:
(
UICollectionView
*
)
collectionView
layout
:
(
UICollectionViewLayout
*
)
collectionViewLayout
minimumInteritemSpacingForSectionAtIndex
:
(
NSInteger
)
section
{
return
self
.
innerCellSpacing
;
}
#pragma mark - KVO
-
(
void
)
observeValueForKeyPath
:
(
NSString
*
)
keyPath
ofObject
:
(
id
)
object
change
:
(
NSDictionary
<
NSKeyValueChangeKey
,
id
>
*
)
change
context
:
(
void
*
)
context
{
if
([
keyPath
isEqualToString
:
@"contentOffset"
])
{
CGPoint
contentOffset
=
[
change
[
NSKeyValueChangeNewKey
]
CGPointValue
];
if
((
self
.
contentScrollView
.
isTracking
||
self
.
contentScrollView
.
isDecelerating
))
{
//用户滚动引起的contentOffset变化,才处理。
[
self
contentOffsetOfContentScrollViewDidChanged
:
contentOffset
];
}
self
.
lastContentViewContentOffset
=
contentOffset
;
}
}
#pragma mark - Other
-
(
CGRect
)
getTargetCellFrame
:
(
NSInteger
)
targetIndex
{
CGFloat
x
=
[
self
getContentEdgeInsetLeft
];
for
(
int
i
=
0
;
i
<
targetIndex
;
i
++
)
{
JXCategoryBaseCellModel
*
cellModel
=
self
.
dataSource
[
i
];
x
+=
cellModel
.
cellWidth
+
self
.
innerCellSpacing
;
}
CGFloat
width
=
self
.
dataSource
[
targetIndex
].
cellWidth
;
return
CGRectMake
(
x
,
0
,
width
,
self
.
bounds
.
size
.
height
);
}
#pragma mark - Private
-
(
CGFloat
)
getContentEdgeInsetLeft
{
if
(
self
.
contentEdgeInsetLeft
==
JXCategoryViewAutomaticDimension
)
{
return
self
.
innerCellSpacing
;
}
return
self
.
contentEdgeInsetLeft
;
}
-
(
CGFloat
)
getContentEdgeInsetRight
{
if
(
self
.
contentEdgeInsetRight
==
JXCategoryViewAutomaticDimension
)
{
return
self
.
innerCellSpacing
;
}
return
self
.
contentEdgeInsetRight
;
}
-
(
void
)
clickselectItemAtIndex
:
(
NSInteger
)
index
{
[
self
selectCellAtIndex
:
index
isClicked
:
YES
];
}
-
(
void
)
scrollselectItemAtIndex
:
(
NSInteger
)
index
{
[
self
selectCellAtIndex
:
index
isClicked
:
NO
];
}
@end
GMBase/Classes/JXPagerView/JXCategoryView/Common/JXCategoryCollectionView.h
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryCollectionView.h
// UI系列测试
//
// Created by jiaxin on 2018/3/21.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "JXCategoryIndicatorProtocol.h"
@interface
JXCategoryCollectionView
:
UICollectionView
@property
(
nonatomic
,
strong
)
NSArray
<
UIView
<
JXCategoryIndicatorProtocol
>
*>
*
indicators
;
@end
GMBase/Classes/JXPagerView/JXCategoryView/Common/JXCategoryCollectionView.m
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryCollectionView.m
// UI系列测试
//
// Created by jiaxin on 2018/3/21.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryCollectionView.h"
@implementation
JXCategoryCollectionView
-
(
void
)
layoutSubviews
{
[
super
layoutSubviews
];
for
(
UIView
<
JXCategoryIndicatorProtocol
>
*
view
in
self
.
indicators
)
{
[
self
sendSubviewToBack
:
view
];
}
}
@end
GMBase/Classes/JXPagerView/JXCategoryView/Common/JXCategoryFactory.h
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryFactory.h
// JXCategoryView
//
// Created by jiaxin on 2018/8/17.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface
JXCategoryFactory
:
NSObject
+
(
CGFloat
)
interpolationFrom
:(
CGFloat
)
from
to
:(
CGFloat
)
to
percent
:(
CGFloat
)
percent
;
+
(
UIColor
*
)
interpolationColorFrom
:(
UIColor
*
)
fromColor
to
:(
UIColor
*
)
toColor
percent
:(
CGFloat
)
percent
;
@end
GMBase/Classes/JXPagerView/JXCategoryView/Common/JXCategoryFactory.m
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryFactory.m
// JXCategoryView
//
// Created by jiaxin on 2018/8/17.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryFactory.h"
#import "UIColor+JXAdd.h"
@implementation
JXCategoryFactory
+
(
CGFloat
)
interpolationFrom
:(
CGFloat
)
from
to
:(
CGFloat
)
to
percent
:(
CGFloat
)
percent
{
percent
=
MAX
(
0
,
MIN
(
1
,
percent
));
NSLog
(
@"percent---%.2f"
,
percent
);
NSLog
(
@"from + (to - from)*---%.2f"
,
(
from
+
(
to
-
from
)
*
percent
));
return
from
+
(
to
-
from
)
*
percent
;
}
+
(
UIColor
*
)
interpolationColorFrom
:(
UIColor
*
)
fromColor
to
:(
UIColor
*
)
toColor
percent
:(
CGFloat
)
percent
{
CGFloat
red
=
[
self
interpolationFrom
:
fromColor
.
jx_red
to
:
toColor
.
jx_red
percent
:
percent
];
CGFloat
green
=
[
self
interpolationFrom
:
fromColor
.
jx_green
to
:
toColor
.
jx_green
percent
:
percent
];
CGFloat
blue
=
[
self
interpolationFrom
:
fromColor
.
jx_blue
to
:
toColor
.
jx_blue
percent
:
percent
];
CGFloat
alpha
=
[
self
interpolationFrom
:
fromColor
.
jx_alpha
to
:
toColor
.
jx_alpha
percent
:
percent
];
return
[
UIColor
colorWithRed
:
red
green
:
green
blue
:
blue
alpha
:
alpha
];
}
@end
GMBase/Classes/JXPagerView/JXCategoryView/Common/JXCategoryIndicatorParamsModel.h
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryIndicatorParamsModel.h
// JXCategoryView
//
// Created by jiaxin on 2018/12/13.
// Copyright © 2018 jiaxin. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
/**
指示器不同情况处理时传递的数据模型,不同情况会对不同的属性赋值,根据不同情况的api说明确认。
为什么会通过model传递数据,因为指示器处理逻辑以后会扩展不同的使用场景,会新增参数,如果不通过model传递,就会在api新增参数,一旦修改api该的地方就特别多了,而且会影响到之前自定义实现的开发者。
*/
@interface
JXCategoryIndicatorParamsModel
:
NSObject
@property
(
nonatomic
,
assign
)
NSInteger
selectedIndex
;
//当前选中的index
@property
(
nonatomic
,
assign
)
CGRect
selectedCellFrame
;
//当前选中的cellFrame
@property
(
nonatomic
,
assign
)
NSInteger
leftIndex
;
//正在过渡中的两个cell,相对位置在左边的cell的index
@property
(
nonatomic
,
assign
)
CGRect
leftCellFrame
;
//正在过渡中的两个cell,相对位置在左边的cell的frame
@property
(
nonatomic
,
assign
)
NSInteger
rightIndex
;
//正在过渡中的两个cell,相对位置在右边的cell的index
@property
(
nonatomic
,
assign
)
CGRect
rightCellFrame
;
//正在过渡中的两个cell,相对位置在右边的cell的frame
@property
(
nonatomic
,
assign
)
CGFloat
percent
;
//正在过渡中的两个cell,从左到右的百分比
@property
(
nonatomic
,
assign
)
NSInteger
lastSelectedIndex
;
//之前选中的index
@property
(
nonatomic
,
assign
)
BOOL
isClicked
;
//YES:通过点击选中;NO:通过滚动选中
@end
GMBase/Classes/JXPagerView/JXCategoryView/Common/JXCategoryIndicatorParamsModel.m
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryIndicatorParamsModel.m
// JXCategoryView
//
// Created by jiaxin on 2018/12/13.
// Copyright © 2018 jiaxin. All rights reserved.
//
#import "JXCategoryIndicatorParamsModel.h"
@implementation
JXCategoryIndicatorParamsModel
@end
GMBase/Classes/JXPagerView/JXCategoryView/Common/JXCategoryIndicatorProtocol.h
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryIndicatorProtocol.h
// JXCategoryView
//
// Created by jiaxin on 2018/8/17.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "JXCategoryViewDefines.h"
#import "JXCategoryIndicatorParamsModel.h"
@protocol
JXCategoryIndicatorProtocol
<
NSObject
>
/**
视图重置状态时调用
param selectedIndex 当前选中的index
param selectedCellFrame 当前选中的cellFrame
@param model 数据模型
*/
-
(
void
)
jx_refreshState
:
(
JXCategoryIndicatorParamsModel
*
)
model
;
/**
contentScrollView在进行手势滑动时,处理指示器跟随手势变化UI逻辑;
param selectedIndex 当前选中的index
param leftIndex 正在过渡中的两个cell,相对位置在左边的cell的index
param leftCellFrame 正在过渡中的两个cell,相对位置在左边的cell的frame
param rightIndex 正在过渡中的两个cell,相对位置在右边的cell的index
param rightCellFrame 正在过渡中的两个cell,相对位置在右边的cell的frame
param percent 过渡百分比
@param model 数据模型
*/
-
(
void
)
jx_contentScrollViewDidScroll
:(
JXCategoryIndicatorParamsModel
*
)
model
;
/**
点击选中了某一个cell
param lastSelectedIndex 之前选中的index
param selectedIndex 选中的index
param selectedCellFrame 选中的cellFrame
param isClicked YES:点击选中;NO:滚动选中。
@param model 数据模型
*/
-
(
void
)
jx_selectedCell
:(
JXCategoryIndicatorParamsModel
*
)
model
;
@end
GMBase/Classes/JXPagerView/JXCategoryView/Common/JXCategoryListContainerView.h
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryListScrollView.h
// JXCategoryView
//
// Created by jiaxin on 2018/9/12.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import <UIKit/UIKit.h>
@class
JXCategoryListContainerView
;
@protocol
JXCategoryListContentViewDelegate
<
NSObject
>
/**
如果列表是VC,就返回VC.view
如果列表是View,就返回View自己
@return 返回列表视图
*/
-
(
UIView
*
)
listView
;
@optional
/**
可选实现,列表逻辑层面显示的时候调用
*/
-
(
void
)
listDidAppear
;
/**
可选实现,列表逻辑层面消失的时候调用
*/
-
(
void
)
listDidDisappear
;
@end
@protocol
JXCategoryListContainerViewDelegate
<
NSObject
>
/**
返回list的数量
@param listContainerView 列表的容器视图
@return list的数量
*/
-
(
NSInteger
)
numberOfListsInlistContainerView
:
(
JXCategoryListContainerView
*
)
listContainerView
;
/**
根据index初始化对应的遵从JXCategoryListContentViewDelegate协议的list,注意是初始化哟,要new一个新的实例!!!
@param listContainerView 列表的容器视图
@param index 目标下标
@return 新的遵从JXCategoryListContentViewDelegate协议的list实例
*/
-
(
id
<
JXCategoryListContentViewDelegate
>
)
listContainerView
:(
JXCategoryListContainerView
*
)
listContainerView
initListForIndex
:(
NSInteger
)
index
;
@end
@interface
JXCategoryListContainerView
:
UIView
@property
(
nonatomic
,
strong
,
readonly
)
UIScrollView
*
scrollView
;
/**
滚动切换的时候,滚动距离超过一页的多少百分比,就认为切换了页面。默认0.5(即滚动超过了半屏,就认为翻页了)。范围0~1,开区间不包括0和1
*/
@property
(
nonatomic
,
assign
)
CGFloat
didAppearPercent
;
/**
需要和self.categoryView.defaultSelectedIndex保持一致
*/
@property
(
nonatomic
,
assign
)
NSInteger
defaultSelectedIndex
;
-
(
instancetype
)
init
NS_UNAVAILABLE
;
-
(
instancetype
)
initWithFrame
:(
CGRect
)
frame
NS_UNAVAILABLE
;
-
(
instancetype
)
initWithCoder
:(
NSCoder
*
)
aDecoder
NS_UNAVAILABLE
;
/**
指定的初始化器
@param parentVC 父vc
@param delegate JXCategoryListContainerViewDelegate代理
@return JXCategoryListContainerView实例
*/
-
(
instancetype
)
initWithParentVC
:(
UIViewController
*
)
parentVC
delegate
:(
id
<
JXCategoryListContainerViewDelegate
>
)
delegate
NS_DESIGNATED_INITIALIZER
;
-
(
void
)
reloadData
;
//必须调用,请按照demo示例那样调用
-
(
void
)
scrollingFromLeftIndex
:(
NSInteger
)
leftIndex
toRightIndex
:(
NSInteger
)
rightIndex
ratio
:(
CGFloat
)
ratio
selectedIndex
:(
NSInteger
)
selectedIndex
;
//必须调用,请按照demo示例那样调用(注意是是点击选中的回调,不是其他回调)
-
(
void
)
didClickSelectedItemAtIndex
:(
NSInteger
)
index
;
@end
GMBase/Classes/JXPagerView/JXCategoryView/Common/JXCategoryListContainerView.m
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryListContainerView.m
// JXCategoryView
//
// Created by jiaxin on 2018/9/12.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryListContainerView.h"
@interface
JXCategoryListContainerView
()
@property
(
nonatomic
,
weak
)
id
<
JXCategoryListContainerViewDelegate
>
delegate
;
@property
(
nonatomic
,
weak
)
UIViewController
*
parentViewController
;
@property
(
nonatomic
,
strong
)
UIScrollView
*
scrollView
;
@property
(
nonatomic
,
assign
)
NSInteger
currentIndex
;
@property
(
nonatomic
,
strong
)
NSMutableDictionary
<
NSNumber
*
,
id
<
JXCategoryListContentViewDelegate
>>
*
listVCDict
;
@property
(
nonatomic
,
assign
)
BOOL
isLayoutSubviewsed
;
@end
@implementation
JXCategoryListContainerView
-
(
instancetype
)
initWithParentVC
:(
UIViewController
*
)
parentVC
delegate
:(
id
<
JXCategoryListContainerViewDelegate
>
)
delegate
{
self
=
[
super
initWithFrame
:
CGRectZero
];
if
(
self
)
{
_didAppearPercent
=
0
.
5
;
_parentViewController
=
parentVC
;
_parentViewController
.
automaticallyAdjustsScrollViewInsets
=
NO
;
_delegate
=
delegate
;
_listVCDict
=
[
NSMutableDictionary
dictionary
];
[
self
initializeViews
];
}
return
self
;
}
-
(
void
)
initializeViews
{
_scrollView
=
[[
UIScrollView
alloc
]
init
];
self
.
scrollView
.
pagingEnabled
=
YES
;
self
.
scrollView
.
showsHorizontalScrollIndicator
=
NO
;
self
.
scrollView
.
showsHorizontalScrollIndicator
=
NO
;
self
.
scrollView
.
scrollsToTop
=
NO
;
self
.
scrollView
.
bounces
=
NO
;
if
(
@available
(
iOS
11
.
0
,
*
))
{
self
.
scrollView
.
contentInsetAdjustmentBehavior
=
UIScrollViewContentInsetAdjustmentNever
;
}
[
self
addSubview
:
self
.
scrollView
];
}
-
(
void
)
reloadData
{
for
(
id
<
JXCategoryListContentViewDelegate
>
list
in
self
.
listVCDict
.
allValues
)
{
[
list
.
listView
removeFromSuperview
];
}
[
self
.
listVCDict
removeAllObjects
];
self
.
scrollView
.
contentSize
=
CGSizeMake
(
self
.
scrollView
.
bounds
.
size
.
width
*
[
self
.
delegate
numberOfListsInlistContainerView
:
self
],
self
.
scrollView
.
bounds
.
size
.
height
);
[
self
listDidAppear
:
self
.
currentIndex
];
}
-
(
void
)
layoutSubviews
{
[
super
layoutSubviews
];
self
.
scrollView
.
frame
=
self
.
bounds
;
self
.
scrollView
.
contentSize
=
CGSizeMake
(
self
.
scrollView
.
bounds
.
size
.
width
*
[
self
.
delegate
numberOfListsInlistContainerView
:
self
],
self
.
scrollView
.
bounds
.
size
.
height
);
if
(
!
self
.
isLayoutSubviewsed
)
{
self
.
isLayoutSubviewsed
=
YES
;
//初始化第一次调用
[
self
listDidAppear
:
self
.
currentIndex
];
}
}
-
(
void
)
setDefaultSelectedIndex
:
(
NSInteger
)
defaultSelectedIndex
{
_defaultSelectedIndex
=
defaultSelectedIndex
;
self
.
currentIndex
=
defaultSelectedIndex
;
}
#pragma mark - JXCategoryBaseView回调
-
(
void
)
scrollingFromLeftIndex
:
(
NSInteger
)
leftIndex
toRightIndex
:
(
NSInteger
)
rightIndex
ratio
:
(
CGFloat
)
ratio
selectedIndex
:
(
NSInteger
)
selectedIndex
{
NSInteger
targetIndex
=
-
1
;
NSInteger
disappearIndex
=
-
1
;
if
(
rightIndex
==
selectedIndex
)
{
//当前选中的在右边,用户正在从右边往左边滑动
if
(
ratio
<
(
1
-
self
.
didAppearPercent
))
{
targetIndex
=
leftIndex
;
disappearIndex
=
rightIndex
;
}
}
else
{
//当前选中的在左边,用户正在从左边往右边滑动
if
(
ratio
>
self
.
didAppearPercent
)
{
targetIndex
=
rightIndex
;
disappearIndex
=
leftIndex
;
}
}
if
(
targetIndex
!=
-
1
&&
self
.
currentIndex
!=
targetIndex
)
{
[
self
listDidAppear
:
targetIndex
];
[
self
listDidDisappear
:
disappearIndex
];
}
}
-
(
void
)
didClickSelectedItemAtIndex
:
(
NSInteger
)
index
{
[
self
listDidDisappear
:
self
.
currentIndex
];
[
self
listDidAppear
:
index
];
}
#pragma mark - Private
-
(
void
)
listDidAppear
:
(
NSInteger
)
index
{
self
.
currentIndex
=
index
;
id
<
JXCategoryListContentViewDelegate
>
list
=
self
.
listVCDict
[
@
(
index
)];
if
(
list
==
nil
)
{
list
=
[
self
.
delegate
listContainerView
:
self
initListForIndex
:
index
];
}
if
(
list
.
listView
.
superview
==
nil
)
{
list
.
listView
.
frame
=
CGRectMake
(
index
*
self
.
scrollView
.
bounds
.
size
.
width
,
0
,
self
.
scrollView
.
bounds
.
size
.
width
,
self
.
scrollView
.
bounds
.
size
.
height
);
[
self
.
scrollView
addSubview
:
list
.
listView
];
self
.
listVCDict
[
@
(
index
)]
=
list
;
}
if
(
list
&&
[
list
respondsToSelector
:
@selector
(
listDidAppear
)])
{
[
list
listDidAppear
];
}
}
-
(
void
)
listDidDisappear
:
(
NSInteger
)
index
{
id
<
JXCategoryListContentViewDelegate
>
list
=
self
.
listVCDict
[
@
(
index
)];
if
(
list
&&
[
list
respondsToSelector
:
@selector
(
listDidDisappear
)])
{
[
list
listDidDisappear
];
}
}
@end
GMBase/Classes/JXPagerView/JXCategoryView/Common/JXCategoryListVCContainerView.h
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryListScrollView.h
// JXCategoryView
//
// Created by jiaxin on 2018/9/12.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import <UIKit/UIKit.h>
/**
此类已不再维护,推荐使用JXCategoryListContainerView类!!!
*/
@interface
JXCategoryListVCContainerView
:
UIView
@property
(
nonatomic
,
weak
)
UIViewController
*
parentViewController
;
@property
(
nonatomic
,
strong
,
readonly
)
UIScrollView
*
scrollView
;
@property
(
nonatomic
,
strong
)
NSArray
<
UIViewController
*>
*
listVCArray
;
//这个defaultSelectedIndex仅仅用于触发对应index的数据加载,如果要让categoryView和listView都处于对应的index。还应该添加后面这段代码:self.categoryView.defaultSelectedIndex = n
@property
(
nonatomic
,
assign
)
NSInteger
defaultSelectedIndex
;
-
(
void
)
reloadData
;
-
(
void
)
scrollingFromLeftIndex
:(
NSInteger
)
leftIndex
toRightIndex
:(
NSInteger
)
rightIndex
ratio
:(
CGFloat
)
ratio
;
-
(
void
)
didClickSelectedItemAtIndex
:(
NSInteger
)
index
;
-
(
void
)
didScrollSelectedItemAtIndex
:(
NSInteger
)
index
;
-
(
void
)
parentVCWillAppear
:(
BOOL
)
animated
;
-
(
void
)
parentVCDidAppear
:(
BOOL
)
animated
;
-
(
void
)
parentVCWillDisappear
:(
BOOL
)
animated
;
-
(
void
)
parentVCDidDisappear
:(
BOOL
)
animated
;
@end
GMBase/Classes/JXPagerView/JXCategoryView/Common/JXCategoryListVCContainerView.m
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryListContainerView.m
// JXCategoryView
//
// Created by jiaxin on 2018/9/12.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryListVCContainerView.h"
@interface
JXCategoryListVCContainerView
()
<
UIScrollViewDelegate
>
@property
(
nonatomic
,
strong
)
UIScrollView
*
scrollView
;
@property
(
nonatomic
,
assign
)
NSInteger
currentIndex
;
@property
(
nonatomic
,
assign
)
NSInteger
targetIndex
;
@end
@implementation
JXCategoryListVCContainerView
-
(
instancetype
)
initWithFrame
:(
CGRect
)
frame
{
self
=
[
super
initWithFrame
:
frame
];
if
(
self
)
{
[
self
initializeViews
];
}
return
self
;
}
-
(
instancetype
)
initWithCoder
:(
NSCoder
*
)
coder
{
self
=
[
super
initWithCoder
:
coder
];
if
(
self
)
{
[
self
initializeViews
];
}
return
self
;
}
-
(
void
)
initializeViews
{
_scrollView
=
[[
UIScrollView
alloc
]
init
];
self
.
scrollView
.
pagingEnabled
=
YES
;
self
.
scrollView
.
showsHorizontalScrollIndicator
=
NO
;
[
self
addSubview
:
self
.
scrollView
];
}
-
(
void
)
reloadData
{
[
self
listVCWillAppear
:
self
.
defaultSelectedIndex
];
[
self
listVCDidAppear
:
self
.
defaultSelectedIndex
];
}
-
(
void
)
layoutSubviews
{
[
super
layoutSubviews
];
self
.
scrollView
.
frame
=
self
.
bounds
;
//根据新的数据源重新添加listView
for
(
int
i
=
0
;
i
<
self
.
listVCArray
.
count
;
i
++
)
{
UIViewController
*
listVC
=
self
.
listVCArray
[
i
];
[
listVC
willMoveToParentViewController
:
self
.
parentViewController
];
[
self
.
parentViewController
addChildViewController
:
self
.
parentViewController
];
[
listVC
didMoveToParentViewController
:
self
.
parentViewController
];
listVC
.
view
.
frame
=
CGRectMake
(
i
*
self
.
scrollView
.
bounds
.
size
.
width
,
0
,
self
.
scrollView
.
bounds
.
size
.
width
,
self
.
scrollView
.
bounds
.
size
.
height
);
[
self
.
scrollView
addSubview
:
listVC
.
view
];
}
self
.
scrollView
.
contentSize
=
CGSizeMake
(
self
.
scrollView
.
bounds
.
size
.
width
*
self
.
listVCArray
.
count
,
self
.
scrollView
.
bounds
.
size
.
height
);
}
-
(
void
)
setListVCArray
:
(
NSArray
<
UIViewController
*>
*
)
listVCArray
{
for
(
UIViewController
*
vc
in
self
.
listVCArray
)
{
[
vc
.
view
removeFromSuperview
];
}
_listVCArray
=
listVCArray
;
[
self
setNeedsLayout
];
}
-
(
void
)
setDefaultSelectedIndex
:
(
NSInteger
)
defaultSelectedIndex
{
_defaultSelectedIndex
=
defaultSelectedIndex
;
self
.
currentIndex
=
defaultSelectedIndex
;
}
-
(
void
)
parentVCWillAppear
:
(
BOOL
)
animated
{
[
self
listVCWillAppear
:
self
.
currentIndex
];
}
-
(
void
)
parentVCDidAppear
:
(
BOOL
)
animated
{
[
self
listVCDidAppear
:
self
.
currentIndex
];
}
-
(
void
)
parentVCWillDisappear
:
(
BOOL
)
animated
{
[
self
listVCWillDisappear
:
self
.
currentIndex
];
}
-
(
void
)
parentVCDidDisappear
:
(
BOOL
)
animated
{
[
self
listVCDidDisappear
:
self
.
currentIndex
];
}
-
(
void
)
scrollingFromLeftIndex
:
(
NSInteger
)
leftIndex
toRightIndex
:
(
NSInteger
)
rightIndex
ratio
:
(
CGFloat
)
ratio
{
NSInteger
targetIndex
=
0
;
if
(
ratio
>
0
.
5
)
{
targetIndex
=
rightIndex
;
}
else
{
targetIndex
=
leftIndex
;
}
if
(
self
.
targetIndex
!=
targetIndex
)
{
[
self
listVCWillAppear
:
targetIndex
];
[
self
listVCDidAppear
:
targetIndex
];
//源代码
//[self listVCWillDisappear:self.currentIndex];
//[self listVCDidDisappear:self.currentIndex];
//add by wuna 解决了部分生命周期问题和标题跟页面正确对应问题
if
(
ratio
>
0
.
5
)
{
[
self
listVCWillDisappear
:
leftIndex
];
[
self
listVCDidDisappear
:
leftIndex
];
}
else
{
[
self
listVCWillDisappear
:
rightIndex
];
[
self
listVCDidDisappear
:
rightIndex
];
}
}
}
-
(
void
)
didScrollSelectedItemAtIndex
:
(
NSInteger
)
index
{
}
-
(
void
)
didClickSelectedItemAtIndex
:
(
NSInteger
)
index
{
[
self
listVCWillDisappear
:
self
.
currentIndex
];
[
self
listVCDidDisappear
:
self
.
currentIndex
];
[
self
listVCWillAppear
:
index
];
[
self
listVCDidAppear
:
index
];
}
#pragma mark - Private
-
(
void
)
listVCWillAppear
:
(
NSInteger
)
index
{
self
.
targetIndex
=
index
;
UIViewController
*
vc
=
self
.
listVCArray
[
index
];
[
vc
beginAppearanceTransition
:
YES
animated
:
YES
];
}
-
(
void
)
listVCDidAppear
:
(
NSInteger
)
index
{
self
.
currentIndex
=
index
;
UIViewController
*
vc
=
self
.
listVCArray
[
index
];
[
vc
endAppearanceTransition
];
}
-
(
void
)
listVCWillDisappear
:
(
NSInteger
)
index
{
UIViewController
*
vc
=
self
.
listVCArray
[
index
];
[
vc
beginAppearanceTransition
:
NO
animated
:
YES
];
}
-
(
void
)
listVCDidDisappear
:
(
NSInteger
)
index
{
UIViewController
*
vc
=
self
.
listVCArray
[
index
];
[
vc
endAppearanceTransition
];
}
@end
GMBase/Classes/JXPagerView/JXCategoryView/Common/JXCategoryViewDefines.h
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryViewDefines.h
// JXCategoryView
//
// Created by jiaxin on 2018/8/17.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
static
const
CGFloat
JXCategoryViewAutomaticDimension
=
-
1
;
typedef
NS_ENUM
(
NSUInteger
,
JXCategoryComponentPosition
)
{
JXCategoryComponentPosition_Bottom
,
JXCategoryComponentPosition_Top
,
};
typedef
NS_ENUM
(
NSUInteger
,
JXCategoryIndicatorScrollStyle
)
{
JXCategoryIndicatorScrollStyleSimple
,
//简单滚动,即从当前位置过渡到目标位置
JXCategoryIndicatorScrollStyleSameAsUserScroll
,
//和用户左右滚动列表时的效果一样
};
GMBase/Classes/JXPagerView/JXCategoryView/Common/UIColor+JXAdd.h
deleted
100755 → 0
View file @
1826794b
//
// UIColor+JXAdd.h
// UI系列测试
//
// Created by jiaxin on 2018/3/21.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface
UIColor
(
JXAdd
)
@property
(
nonatomic
,
assign
,
readonly
)
CGFloat
jx_red
;
@property
(
nonatomic
,
assign
,
readonly
)
CGFloat
jx_green
;
@property
(
nonatomic
,
assign
,
readonly
)
CGFloat
jx_blue
;
@property
(
nonatomic
,
assign
,
readonly
)
CGFloat
jx_alpha
;
@end
GMBase/Classes/JXPagerView/JXCategoryView/Common/UIColor+JXAdd.m
deleted
100755 → 0
View file @
1826794b
//
// UIColor+JXAdd.m
// UI系列测试
//
// Created by jiaxin on 2018/3/21.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "UIColor+JXAdd.h"
@implementation
UIColor
(
JXAdd
)
-
(
CGFloat
)
jx_red
{
CGFloat
r
=
0
,
g
,
b
,
a
;
[
self
getRed
:
&
r
green
:
&
g
blue
:&
b
alpha
:&
a
];
return
r
;
}
-
(
CGFloat
)
jx_green
{
CGFloat
r
,
g
=
0
,
b
,
a
;
[
self
getRed
:
&
r
green
:
&
g
blue
:&
b
alpha
:&
a
];
return
g
;
}
-
(
CGFloat
)
jx_blue
{
CGFloat
r
,
g
,
b
=
0
,
a
;
[
self
getRed
:
&
r
green
:
&
g
blue
:&
b
alpha
:&
a
];
return
b
;
}
-
(
CGFloat
)
jx_alpha
{
return
CGColorGetAlpha
(
self
.
CGColor
);
}
@end
GMBase/Classes/JXPagerView/JXCategoryView/Dot/JXCategoryDotCell.h
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryDotCell.h
// JXCategoryView
//
// Created by jiaxin on 2018/8/20.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryTitleCell.h"
@interface
JXCategoryDotCell
:
JXCategoryTitleCell
@end
GMBase/Classes/JXPagerView/JXCategoryView/Dot/JXCategoryDotCell.m
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryDotCell.m
// JXCategoryView
//
// Created by jiaxin on 2018/8/20.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryDotCell.h"
#import "JXCategoryDotCellModel.h"
@interface
JXCategoryDotCell
()
@property
(
nonatomic
,
strong
)
CALayer
*
dotLayer
;
@end
@implementation
JXCategoryDotCell
-
(
void
)
initializeViews
{
[
super
initializeViews
];
_dotLayer
=
[
CALayer
layer
];
[
self
.
contentView
.
layer
addSublayer
:
self
.
dotLayer
];
}
-
(
void
)
layoutSubviews
{
[
super
layoutSubviews
];
[
CATransaction
begin
];
[
CATransaction
setDisableActions
:
YES
];
JXCategoryDotCellModel
*
myCellModel
=
(
JXCategoryDotCellModel
*
)
self
.
cellModel
;
self
.
dotLayer
.
bounds
=
CGRectMake
(
0
,
0
,
myCellModel
.
dotSize
.
width
,
myCellModel
.
dotSize
.
height
);
switch
(
myCellModel
.
relativePosition
)
{
case
JXCategoryDotRelativePosition_TopLeft
:
{
self
.
dotLayer
.
position
=
CGPointMake
(
CGRectGetMinX
(
self
.
titleLabel
.
frame
),
CGRectGetMinY
(
self
.
titleLabel
.
frame
));
}
break
;
case
JXCategoryDotRelativePosition_TopRight
:
{
self
.
dotLayer
.
position
=
CGPointMake
(
CGRectGetMaxX
(
self
.
titleLabel
.
frame
),
CGRectGetMinY
(
self
.
titleLabel
.
frame
));
}
break
;
case
JXCategoryDotRelativePosition_BottomLeft
:
{
self
.
dotLayer
.
position
=
CGPointMake
(
CGRectGetMinX
(
self
.
titleLabel
.
frame
),
CGRectGetMaxY
(
self
.
titleLabel
.
frame
));
}
break
;
case
JXCategoryDotRelativePosition_BottomRight
:
{
self
.
dotLayer
.
position
=
CGPointMake
(
CGRectGetMaxX
(
self
.
titleLabel
.
frame
),
CGRectGetMaxY
(
self
.
titleLabel
.
frame
));
}
break
;
default
:
break
;
}
self
.
dotLayer
.
position
=
CGPointMake
(
CGRectGetMaxX
(
self
.
titleLabel
.
frame
),
CGRectGetMinY
(
self
.
titleLabel
.
frame
));
[
CATransaction
commit
];
}
-
(
void
)
reloadData
:
(
JXCategoryBaseCellModel
*
)
cellModel
{
[
super
reloadData
:
cellModel
];
JXCategoryDotCellModel
*
myCellModel
=
(
JXCategoryDotCellModel
*
)
cellModel
;
[
CATransaction
begin
];
[
CATransaction
setDisableActions
:
YES
];
self
.
dotLayer
.
hidden
=
!
myCellModel
.
dotHidden
;
self
.
dotLayer
.
backgroundColor
=
myCellModel
.
dotColor
.
CGColor
;
self
.
dotLayer
.
cornerRadius
=
myCellModel
.
dotCornerRadius
;
[
CATransaction
commit
];
[
self
setNeedsLayout
];
[
self
layoutIfNeeded
];
}
@end
GMBase/Classes/JXPagerView/JXCategoryView/Dot/JXCategoryDotCellModel.h
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryDotCellModel.h
// JXCategoryView
//
// Created by jiaxin on 2018/8/20.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryTitleCellModel.h"
typedef
NS_ENUM
(
NSUInteger
,
JXCategoryDotRelativePosition
)
{
JXCategoryDotRelativePosition_TopLeft
=
0
,
JXCategoryDotRelativePosition_TopRight
,
JXCategoryDotRelativePosition_BottomLeft
,
JXCategoryDotRelativePosition_BottomRight
,
};
@interface
JXCategoryDotCellModel
:
JXCategoryTitleCellModel
@property
(
nonatomic
,
assign
)
BOOL
dotHidden
;
@property
(
nonatomic
,
assign
)
JXCategoryDotRelativePosition
relativePosition
;
@property
(
nonatomic
,
assign
)
CGSize
dotSize
;
@property
(
nonatomic
,
assign
)
CGFloat
dotCornerRadius
;
@property
(
nonatomic
,
strong
)
UIColor
*
dotColor
;
@end
GMBase/Classes/JXPagerView/JXCategoryView/Dot/JXCategoryDotCellModel.m
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryDotCellModel.m
// JXCategoryView
//
// Created by jiaxin on 2018/8/20.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryDotCellModel.h"
@implementation
JXCategoryDotCellModel
@end
GMBase/Classes/JXPagerView/JXCategoryView/Dot/JXCategoryDotView.h
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryDotView.h
// JXCategoryView
//
// Created by jiaxin on 2018/8/20.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryTitleView.h"
#import "JXCategoryDotCell.h"
#import "JXCategoryDotCellModel.h"
@interface
JXCategoryDotView
:
JXCategoryTitleView
@property
(
nonatomic
,
assign
)
JXCategoryDotRelativePosition
relativePosition
;
//相对于titleLabel的位置,默认:JXCategoryDotRelativePosition_TopRight
@property
(
nonatomic
,
strong
)
NSArray
<
NSNumber
*>
*
dotStates
;
//@(布尔值),控制红点是否显示
@property
(
nonatomic
,
assign
)
CGSize
dotSize
;
//默认:CGSizeMake(10, 10)
@property
(
nonatomic
,
assign
)
CGFloat
dotCornerRadius
;
//默认:JXCategoryViewAutomaticDimension(self.dotSize.height/2)
@property
(
nonatomic
,
strong
)
UIColor
*
dotColor
;
//默认:[UIColor redColor]
@end
GMBase/Classes/JXPagerView/JXCategoryView/Dot/JXCategoryDotView.m
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryDotView.m
// JXCategoryView
//
// Created by jiaxin on 2018/8/20.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryDotView.h"
@implementation
JXCategoryDotView
-
(
void
)
initializeData
{
[
super
initializeData
];
_relativePosition
=
JXCategoryDotRelativePosition_TopRight
;
_dotSize
=
CGSizeMake
(
10
,
10
);
_dotCornerRadius
=
JXCategoryViewAutomaticDimension
;
_dotColor
=
[
UIColor
redColor
];
}
-
(
Class
)
preferredCellClass
{
return
[
JXCategoryDotCell
class
];
}
-
(
void
)
refreshDataSource
{
NSMutableArray
*
tempArray
=
[
NSMutableArray
array
];
for
(
int
i
=
0
;
i
<
self
.
titles
.
count
;
i
++
)
{
JXCategoryDotCellModel
*
cellModel
=
[[
JXCategoryDotCellModel
alloc
]
init
];
[
tempArray
addObject
:
cellModel
];
}
self
.
dataSource
=
tempArray
;
}
-
(
void
)
refreshCellModel
:
(
JXCategoryBaseCellModel
*
)
cellModel
index
:
(
NSInteger
)
index
{
[
super
refreshCellModel
:
cellModel
index
:
index
];
JXCategoryDotCellModel
*
myCellModel
=
(
JXCategoryDotCellModel
*
)
cellModel
;
myCellModel
.
dotHidden
=
[
self
.
dotStates
[
index
]
boolValue
];
myCellModel
.
relativePosition
=
self
.
relativePosition
;
myCellModel
.
dotSize
=
self
.
dotSize
;
myCellModel
.
dotColor
=
self
.
dotColor
;
if
(
self
.
dotCornerRadius
==
JXCategoryViewAutomaticDimension
)
{
myCellModel
.
dotCornerRadius
=
self
.
dotSize
.
height
/
2
;
}
else
{
myCellModel
.
dotCornerRadius
=
self
.
dotCornerRadius
;
}
}
@end
GMBase/Classes/JXPagerView/JXCategoryView/Image/JXCategoryImageCell.h
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryImageCell.h
// JXCategoryView
//
// Created by jiaxin on 2018/8/20.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryIndicatorCell.h"
@interface
JXCategoryImageCell
:
JXCategoryIndicatorCell
@property
(
nonatomic
,
strong
)
UIImageView
*
imageView
;
@end
GMBase/Classes/JXPagerView/JXCategoryView/Image/JXCategoryImageCell.m
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryImageCell.m
// JXCategoryView
//
// Created by jiaxin on 2018/8/20.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryImageCell.h"
#import "JXCategoryImageCellModel.h"
@implementation
JXCategoryImageCell
-
(
void
)
initializeViews
{
[
super
initializeViews
];
_imageView
=
[[
UIImageView
alloc
]
init
];
_imageView
.
contentMode
=
UIViewContentModeScaleAspectFit
;
_imageView
.
layer
.
masksToBounds
=
YES
;
[
self
.
contentView
addSubview
:
_imageView
];
}
-
(
void
)
layoutSubviews
{
[
super
layoutSubviews
];
JXCategoryImageCellModel
*
myCellModel
=
(
JXCategoryImageCellModel
*
)
self
.
cellModel
;
self
.
imageView
.
bounds
=
CGRectMake
(
0
,
0
,
myCellModel
.
imageSize
.
width
,
myCellModel
.
imageSize
.
height
);
self
.
imageView
.
center
=
self
.
contentView
.
center
;
self
.
imageView
.
layer
.
cornerRadius
=
myCellModel
.
imageCornerRadius
;
}
-
(
void
)
reloadData
:
(
JXCategoryBaseCellModel
*
)
cellModel
{
[
super
reloadData
:
cellModel
];
JXCategoryImageCellModel
*
myCellModel
=
(
JXCategoryImageCellModel
*
)
cellModel
;
if
(
myCellModel
.
imageName
!=
nil
)
{
self
.
imageView
.
image
=
[
UIImage
imageNamed
:
myCellModel
.
imageName
];
}
else
if
(
myCellModel
.
imageURL
!=
nil
)
{
if
(
myCellModel
.
loadImageCallback
!=
nil
)
{
myCellModel
.
loadImageCallback
(
self
.
imageView
,
myCellModel
.
imageURL
);
}
}
if
(
myCellModel
.
selected
)
{
if
(
myCellModel
.
selectedImageName
!=
nil
)
{
self
.
imageView
.
image
=
[
UIImage
imageNamed
:
myCellModel
.
selectedImageName
];
}
else
if
(
myCellModel
.
selectedImageURL
!=
nil
)
{
if
(
myCellModel
.
loadImageCallback
!=
nil
)
{
myCellModel
.
loadImageCallback
(
self
.
imageView
,
myCellModel
.
selectedImageURL
);
}
}
}
if
(
myCellModel
.
imageZoomEnabled
)
{
self
.
imageView
.
transform
=
CGAffineTransformMakeScale
(
myCellModel
.
imageZoomScale
,
myCellModel
.
imageZoomScale
);
}
else
{
self
.
imageView
.
transform
=
CGAffineTransformIdentity
;
}
}
@end
GMBase/Classes/JXPagerView/JXCategoryView/Image/JXCategoryImageCellModel.h
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryImageCellModel.h
// JXCategoryView
//
// Created by jiaxin on 2018/8/20.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryIndicatorCellModel.h"
@interface
JXCategoryImageCellModel
:
JXCategoryIndicatorCellModel
@property
(
nonatomic
,
copy
)
void
(
^
loadImageCallback
)(
UIImageView
*
imageView
,
NSURL
*
imageURL
);
@property
(
nonatomic
,
copy
)
NSString
*
imageName
;
//加载bundle内的图片
@property
(
nonatomic
,
strong
)
NSURL
*
imageURL
;
//图片URL
@property
(
nonatomic
,
copy
)
NSString
*
selectedImageName
;
@property
(
nonatomic
,
strong
)
NSURL
*
selectedImageURL
;
@property
(
nonatomic
,
assign
)
CGSize
imageSize
;
@property
(
nonatomic
,
assign
)
CGFloat
imageCornerRadius
;
@property
(
nonatomic
,
assign
)
BOOL
imageZoomEnabled
;
@property
(
nonatomic
,
assign
)
CGFloat
imageZoomScale
;
@end
GMBase/Classes/JXPagerView/JXCategoryView/Image/JXCategoryImageCellModel.m
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryImageCellModel.m
// JXCategoryView
//
// Created by jiaxin on 2018/8/20.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryImageCellModel.h"
@implementation
JXCategoryImageCellModel
@end
GMBase/Classes/JXPagerView/JXCategoryView/Image/JXCategoryImageView.h
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryImageView.h
// JXCategoryView
//
// Created by jiaxin on 2018/8/20.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryIndicatorView.h"
#import "JXCategoryImageCell.h"
#import "JXCategoryImageCellModel.h"
@interface
JXCategoryImageView
:
JXCategoryIndicatorView
@property
(
nonatomic
,
strong
)
NSArray
<
NSString
*>*
imageNames
;
@property
(
nonatomic
,
strong
)
NSArray
<
NSURL
*>*
imageURLs
;
@property
(
nonatomic
,
strong
)
NSArray
<
NSString
*>*
selectedImageNames
;
@property
(
nonatomic
,
strong
)
NSArray
<
NSURL
*>*
selectedImageURLs
;
@property
(
nonatomic
,
copy
)
void
(
^
loadImageCallback
)(
UIImageView
*
imageView
,
NSURL
*
imageURL
);
//使用imageURL从远端下载图片进行加载,建议使用SDWebImage等第三方库进行下载。
@property
(
nonatomic
,
assign
)
CGSize
imageSize
;
//默认CGSizeMake(20, 20)
@property
(
nonatomic
,
assign
)
CGFloat
imageCornerRadius
;
//图片圆角
@property
(
nonatomic
,
assign
)
BOOL
imageZoomEnabled
;
//默认为NO
@property
(
nonatomic
,
assign
)
CGFloat
imageZoomScale
;
//默认1.2,imageZoomEnabled为YES才生效
@end
GMBase/Classes/JXPagerView/JXCategoryView/Image/JXCategoryImageView.m
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryImageView.m
// JXCategoryView
//
// Created by jiaxin on 2018/8/20.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryImageView.h"
#import "JXCategoryFactory.h"
@implementation
JXCategoryImageView
-
(
void
)
dealloc
{
self
.
loadImageCallback
=
nil
;
}
-
(
void
)
initializeData
{
[
super
initializeData
];
_imageSize
=
CGSizeMake
(
20
,
20
);
_imageZoomEnabled
=
NO
;
_imageZoomScale
=
1
.
2
;
_imageCornerRadius
=
0
;
}
-
(
Class
)
preferredCellClass
{
return
[
JXCategoryImageCell
class
];
}
-
(
void
)
refreshDataSource
{
NSMutableArray
*
tempArray
=
[
NSMutableArray
array
];
NSUInteger
count
=
(
self
.
imageNames
.
count
>
0
)
?
self
.
imageNames
.
count
:
(
self
.
imageURLs
.
count
>
0
?
self
.
imageURLs
.
count
:
0
);
for
(
int
i
=
0
;
i
<
count
;
i
++
)
{
JXCategoryImageCellModel
*
cellModel
=
[[
JXCategoryImageCellModel
alloc
]
init
];
[
tempArray
addObject
:
cellModel
];
}
self
.
dataSource
=
tempArray
;
}
-
(
void
)
refreshSelectedCellModel
:
(
JXCategoryBaseCellModel
*
)
selectedCellModel
unselectedCellModel
:
(
JXCategoryBaseCellModel
*
)
unselectedCellModel
{
[
super
refreshSelectedCellModel
:
selectedCellModel
unselectedCellModel
:
unselectedCellModel
];
JXCategoryImageCellModel
*
myUnselectedCellModel
=
(
JXCategoryImageCellModel
*
)
unselectedCellModel
;
myUnselectedCellModel
.
imageZoomScale
=
1
.
0
;
JXCategoryImageCellModel
*
myselectedCellModel
=
(
JXCategoryImageCellModel
*
)
selectedCellModel
;
myselectedCellModel
.
imageZoomScale
=
self
.
imageZoomScale
;
}
-
(
void
)
refreshCellModel
:
(
JXCategoryBaseCellModel
*
)
cellModel
index
:
(
NSInteger
)
index
{
[
super
refreshCellModel
:
cellModel
index
:
index
];
JXCategoryImageCellModel
*
myCellModel
=
(
JXCategoryImageCellModel
*
)
cellModel
;
myCellModel
.
loadImageCallback
=
self
.
loadImageCallback
;
myCellModel
.
imageSize
=
self
.
imageSize
;
myCellModel
.
imageCornerRadius
=
self
.
imageCornerRadius
;
if
(
self
.
imageNames
!=
nil
)
{
myCellModel
.
imageName
=
self
.
imageNames
[
index
];
}
else
if
(
self
.
imageURLs
!=
nil
)
{
myCellModel
.
imageURL
=
self
.
imageURLs
[
index
];
}
if
(
self
.
selectedImageNames
!=
nil
)
{
myCellModel
.
selectedImageName
=
self
.
selectedImageNames
[
index
];
}
else
if
(
self
.
selectedImageURLs
!=
nil
)
{
myCellModel
.
selectedImageURL
=
self
.
selectedImageURLs
[
index
];
}
myCellModel
.
imageZoomEnabled
=
self
.
imageZoomEnabled
;
myCellModel
.
imageZoomScale
=
1
.
0
;
if
(
index
==
self
.
selectedIndex
)
{
myCellModel
.
imageZoomScale
=
self
.
imageZoomScale
;
}
}
-
(
void
)
refreshLeftCellModel
:
(
JXCategoryBaseCellModel
*
)
leftCellModel
rightCellModel
:
(
JXCategoryBaseCellModel
*
)
rightCellModel
ratio
:
(
CGFloat
)
ratio
{
[
super
refreshLeftCellModel
:
leftCellModel
rightCellModel
:
rightCellModel
ratio
:
ratio
];
JXCategoryImageCellModel
*
leftModel
=
(
JXCategoryImageCellModel
*
)
leftCellModel
;
JXCategoryImageCellModel
*
rightModel
=
(
JXCategoryImageCellModel
*
)
rightCellModel
;
if
(
self
.
imageZoomEnabled
)
{
leftModel
.
imageZoomScale
=
[
JXCategoryFactory
interpolationFrom
:
self
.
imageZoomScale
to
:
1
.
0
percent
:
ratio
];
rightModel
.
imageZoomScale
=
[
JXCategoryFactory
interpolationFrom
:
1
.
0
to
:
self
.
imageZoomScale
percent
:
ratio
];
}
}
-
(
CGFloat
)
preferredCellWidthAtIndex
:
(
NSInteger
)
index
{
return
self
.
imageSize
.
width
;
}
@end
GMBase/Classes/JXPagerView/JXCategoryView/Indicator/IndicatorViews/JXCategoryIndicatorBackgroundView.h
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryIndicatorBackgroundView.h
// JXCategoryView
//
// Created by jiaxin on 2018/8/17.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryIndicatorComponentView.h"
@interface
JXCategoryIndicatorBackgroundView
:
JXCategoryIndicatorComponentView
@property
(
nonatomic
,
assign
)
CGFloat
backgroundViewWidth
;
//默认JXCategoryViewAutomaticDimension(与cellWidth相等)
@property
(
nonatomic
,
assign
)
CGFloat
backgroundViewWidthIncrement
;
//宽度增量补偿,因为backgroundEllipseLayer一般会比实际内容大一些。默认10
@property
(
nonatomic
,
assign
)
CGFloat
backgroundViewHeight
;
//默认JXCategoryViewAutomaticDimension(与cell高度相等)
@property
(
nonatomic
,
assign
)
CGFloat
backgroundViewCornerRadius
;
//默认JXCategoryViewAutomaticDimension(即backgroundViewHeight/2)
@property
(
nonatomic
,
strong
)
UIColor
*
backgroundViewColor
;
//默认为[UIColor redColor]
@end
GMBase/Classes/JXPagerView/JXCategoryView/Indicator/IndicatorViews/JXCategoryIndicatorBackgroundView.m
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryIndicatorBackgroundView.m
// JXCategoryView
//
// Created by jiaxin on 2018/8/17.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryIndicatorBackgroundView.h"
#import "JXCategoryFactory.h"
@implementation
JXCategoryIndicatorBackgroundView
-
(
instancetype
)
initWithFrame
:(
CGRect
)
frame
{
self
=
[
super
initWithFrame
:
frame
];
if
(
self
)
{
_backgroundViewWidth
=
JXCategoryViewAutomaticDimension
;
_backgroundViewHeight
=
JXCategoryViewAutomaticDimension
;
_backgroundViewCornerRadius
=
JXCategoryViewAutomaticDimension
;
_backgroundViewColor
=
[
UIColor
lightGrayColor
];
_backgroundViewWidthIncrement
=
10
;
}
return
self
;
}
#pragma mark - JXCategoryIndicatorProtocol
-
(
void
)
jx_refreshState
:(
JXCategoryIndicatorParamsModel
*
)
model
{
self
.
layer
.
cornerRadius
=
[
self
getBackgroundViewCornerRadius
:
model
.
selectedCellFrame
];
self
.
backgroundColor
=
self
.
backgroundViewColor
;
CGFloat
width
=
[
self
getBackgroundViewWidth
:
model
.
selectedCellFrame
];
CGFloat
height
=
[
self
getBackgroundViewHeight
:
model
.
selectedCellFrame
];
CGFloat
x
=
model
.
selectedCellFrame
.
origin
.
x
+
(
model
.
selectedCellFrame
.
size
.
width
-
width
)
/
2
;
CGFloat
y
=
(
model
.
selectedCellFrame
.
size
.
height
-
height
)
/
2
;
self
.
frame
=
CGRectMake
(
x
,
y
,
width
,
height
);
}
-
(
void
)
jx_contentScrollViewDidScroll
:(
JXCategoryIndicatorParamsModel
*
)
model
{
CGRect
rightCellFrame
=
model
.
rightCellFrame
;
CGRect
leftCellFrame
=
model
.
leftCellFrame
;
CGFloat
percent
=
model
.
percent
;
CGFloat
targetX
=
0
;
CGFloat
targetWidth
=
[
self
getBackgroundViewWidth
:
leftCellFrame
];
if
(
percent
==
0
)
{
targetX
=
leftCellFrame
.
origin
.
x
+
(
leftCellFrame
.
size
.
width
-
targetWidth
)
/
2
.
0
;
}
else
{
CGFloat
leftWidth
=
targetWidth
;
CGFloat
rightWidth
=
[
self
getBackgroundViewWidth
:
rightCellFrame
];
CGFloat
leftX
=
leftCellFrame
.
origin
.
x
+
(
leftCellFrame
.
size
.
width
-
leftWidth
)
/
2
;
CGFloat
rightX
=
rightCellFrame
.
origin
.
x
+
(
rightCellFrame
.
size
.
width
-
rightWidth
)
/
2
;
targetX
=
[
JXCategoryFactory
interpolationFrom
:
leftX
to
:
rightX
percent
:
percent
];
if
(
self
.
backgroundViewWidth
==
JXCategoryViewAutomaticDimension
)
{
targetWidth
=
[
JXCategoryFactory
interpolationFrom
:
leftWidth
to
:
rightWidth
percent
:
percent
];
}
}
//允许变动frame的情况:1、允许滚动;2、不允许滚动,但是已经通过手势滚动切换一页内容了;
if
(
self
.
scrollEnabled
==
YES
||
(
self
.
scrollEnabled
==
NO
&&
percent
==
0
))
{
CGFloat
height
=
[
self
getBackgroundViewHeight
:
leftCellFrame
];
CGFloat
y
=
(
leftCellFrame
.
size
.
height
-
height
)
/
2
;
self
.
frame
=
CGRectMake
(
targetX
,
y
,
targetWidth
,
height
);
}
}
-
(
void
)
jx_selectedCell
:(
JXCategoryIndicatorParamsModel
*
)
model
{
CGFloat
width
=
[
self
getBackgroundViewWidth
:
model
.
selectedCellFrame
];
CGFloat
height
=
[
self
getBackgroundViewHeight
:
model
.
selectedCellFrame
];
CGFloat
x
=
model
.
selectedCellFrame
.
origin
.
x
+
(
model
.
selectedCellFrame
.
size
.
width
-
width
)
/
2
;
CGFloat
y
=
(
model
.
selectedCellFrame
.
size
.
height
-
height
)
/
2
;
CGRect
toFrame
=
CGRectMake
(
x
,
y
,
width
,
height
);
if
(
self
.
scrollEnabled
)
{
[
UIView
animateWithDuration
:
0
.
25
delay
:
0
options
:
UIViewAnimationOptionCurveLinear
animations
:^
{
self
.
frame
=
toFrame
;
}
completion
:^
(
BOOL
finished
)
{
}];
}
else
{
self
.
frame
=
toFrame
;
}
}
#pragma mark - Private
-
(
CGFloat
)
getBackgroundViewWidth
:(
CGRect
)
cellFrame
{
if
(
self
.
backgroundViewWidth
==
JXCategoryViewAutomaticDimension
)
{
return
cellFrame
.
size
.
width
+
self
.
backgroundViewWidthIncrement
;
}
return
self
.
backgroundViewWidth
+
self
.
backgroundViewWidthIncrement
;
}
-
(
CGFloat
)
getBackgroundViewHeight
:(
CGRect
)
cellFrame
{
if
(
self
.
backgroundViewHeight
==
JXCategoryViewAutomaticDimension
)
{
return
cellFrame
.
size
.
height
;
}
return
self
.
backgroundViewHeight
;
}
-
(
CGFloat
)
getBackgroundViewCornerRadius
:(
CGRect
)
cellFrame
{
if
(
self
.
backgroundViewCornerRadius
==
JXCategoryViewAutomaticDimension
)
{
return
[
self
getBackgroundViewHeight
:
cellFrame
]
/
2
;
}
return
self
.
backgroundViewCornerRadius
;
}
@end
GMBase/Classes/JXPagerView/JXCategoryView/Indicator/IndicatorViews/JXCategoryIndicatorBallView.h
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryIndicatorBallView.h
// JXCategoryView
//
// Created by jiaxin on 2018/8/21.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryIndicatorComponentView.h"
@interface
JXCategoryIndicatorBallView
:
JXCategoryIndicatorComponentView
@property
(
nonatomic
,
assign
)
CGSize
ballViewSize
;
//默认:CGSizeMake(15, 15)
@property
(
nonatomic
,
assign
)
CGFloat
ballScrollOffsetX
;
//小红点的偏移量 默认:20
@property
(
nonatomic
,
strong
)
UIColor
*
ballViewColor
;
//默认为[UIColor redColor]
@end
GMBase/Classes/JXPagerView/JXCategoryView/Indicator/IndicatorViews/JXCategoryIndicatorBallView.m
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryIndicatorBallView.m
// JXCategoryView
//
// Created by jiaxin on 2018/8/21.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryIndicatorBallView.h"
#import "JXCategoryFactory.h"
@interface
JXCategoryIndicatorBallView
()
@property
(
nonatomic
,
strong
)
UIView
*
smallBall
;
@property
(
nonatomic
,
strong
)
UIView
*
bigBall
;
@property
(
nonatomic
,
strong
)
CAShapeLayer
*
shapeLayer
;
@end
@implementation
JXCategoryIndicatorBallView
-
(
instancetype
)
initWithFrame
:(
CGRect
)
frame
{
self
=
[
super
initWithFrame
:
frame
];
if
(
self
)
{
_ballViewSize
=
CGSizeMake
(
15
,
15
);
_ballScrollOffsetX
=
20
;
_ballViewColor
=
[
UIColor
redColor
];
_smallBall
=
[[
UIView
alloc
]
init
];
[
self
addSubview
:
self
.
smallBall
];
_bigBall
=
[[
UIView
alloc
]
init
];
[
self
addSubview
:
self
.
bigBall
];
_shapeLayer
=
[
CAShapeLayer
layer
];
[
self
.
layer
addSublayer
:
self
.
shapeLayer
];
}
return
self
;
}
#pragma mark - JXCategoryIndicatorProtocol
-
(
void
)
jx_refreshState
:(
JXCategoryIndicatorParamsModel
*
)
model
{
[
CATransaction
begin
];
[
CATransaction
setDisableActions
:
YES
];
self
.
shapeLayer
.
fillColor
=
self
.
ballViewColor
.
CGColor
;
[
CATransaction
commit
];
self
.
smallBall
.
backgroundColor
=
self
.
ballViewColor
;
self
.
smallBall
.
layer
.
cornerRadius
=
self
.
ballViewSize
.
height
/
2
;
self
.
bigBall
.
backgroundColor
=
self
.
ballViewColor
;
self
.
bigBall
.
layer
.
cornerRadius
=
self
.
ballViewSize
.
height
/
2
;
CGFloat
x
=
model
.
selectedCellFrame
.
origin
.
x
+
(
model
.
selectedCellFrame
.
size
.
width
-
self
.
ballViewSize
.
width
)
/
2
;
CGFloat
y
=
self
.
superview
.
bounds
.
size
.
height
-
self
.
ballViewSize
.
height
-
self
.
verticalMargin
;
if
(
self
.
componentPosition
==
JXCategoryComponentPosition_Top
)
{
y
=
self
.
verticalMargin
;
}
self
.
smallBall
.
frame
=
CGRectMake
(
x
,
y
,
self
.
ballViewSize
.
width
,
self
.
ballViewSize
.
height
);
self
.
bigBall
.
frame
=
CGRectMake
(
x
,
y
,
self
.
ballViewSize
.
width
,
self
.
ballViewSize
.
height
);
}
-
(
void
)
jx_contentScrollViewDidScroll
:(
JXCategoryIndicatorParamsModel
*
)
model
{
CGRect
rightCellFrame
=
model
.
rightCellFrame
;
CGRect
leftCellFrame
=
model
.
leftCellFrame
;
CGFloat
percent
=
model
.
percent
;
CGFloat
targetXOfBigBall
=
0
;
CGFloat
targetXOfSmallBall
=
leftCellFrame
.
origin
.
x
+
(
leftCellFrame
.
size
.
width
-
self
.
ballViewSize
.
width
)
/
2
;
CGFloat
targetWidthOfSmallBall
=
self
.
ballViewSize
.
width
;
if
(
percent
==
0
)
{
targetXOfBigBall
=
leftCellFrame
.
origin
.
x
+
(
leftCellFrame
.
size
.
width
-
self
.
ballViewSize
.
width
)
/
2
.
0
;
targetXOfSmallBall
=
leftCellFrame
.
origin
.
x
+
(
leftCellFrame
.
size
.
width
-
targetWidthOfSmallBall
)
/
2
.
0
;
}
else
{
CGFloat
leftX
=
leftCellFrame
.
origin
.
x
+
(
leftCellFrame
.
size
.
width
-
self
.
ballViewSize
.
width
)
/
2
;
CGFloat
rightX
=
rightCellFrame
.
origin
.
x
+
(
rightCellFrame
.
size
.
width
-
self
.
ballViewSize
.
width
)
/
2
;
//前50%,移动bigBall的x,缩小smallBall;后50%,移动bigBall的x,缩小smallBall,移动smallBall的x
if
(
percent
<=
0
.
5
)
{
targetXOfBigBall
=
[
JXCategoryFactory
interpolationFrom
:
leftX
to
:(
rightX
-
self
.
ballScrollOffsetX
)
percent
:
percent
*
2
];
targetWidthOfSmallBall
=
[
JXCategoryFactory
interpolationFrom
:
self
.
ballViewSize
.
width
to
:
self
.
ballViewSize
.
width
/
2
percent
:
percent
*
2
];
}
else
{
targetXOfBigBall
=
[
JXCategoryFactory
interpolationFrom
:(
rightX
-
self
.
ballScrollOffsetX
)
to
:
rightX
percent
:
(
percent
-
0
.
5
)
*
2
];
targetWidthOfSmallBall
=
[
JXCategoryFactory
interpolationFrom
:
self
.
ballViewSize
.
width
/
2
to
:
0
percent
:
(
percent
-
0
.
5
)
*
2
];
targetXOfSmallBall
=
[
JXCategoryFactory
interpolationFrom
:
leftX
to
:
rightX
percent
:
(
percent
-
0
.
5
)
*
2
];
}
}
//允许变动frame的情况:1、允许滚动;2、不允许滚动,但是已经通过手势滚动切换一页内容了;
if
(
self
.
scrollEnabled
==
YES
||
(
self
.
scrollEnabled
==
NO
&&
percent
==
0
))
{
CGRect
bigBallFrame
=
self
.
bigBall
.
frame
;
bigBallFrame
.
origin
.
x
=
targetXOfBigBall
;
self
.
bigBall
.
frame
=
bigBallFrame
;
self
.
bigBall
.
layer
.
cornerRadius
=
bigBallFrame
.
size
.
height
/
2
;
CGFloat
targetYOfSmallBall
=
self
.
superview
.
bounds
.
size
.
height
-
self
.
ballViewSize
.
height
/
2
-
targetWidthOfSmallBall
/
2
-
self
.
verticalMargin
;
if
(
self
.
componentPosition
==
JXCategoryComponentPosition_Top
)
{
targetYOfSmallBall
=
self
.
ballViewSize
.
height
/
2
-
targetWidthOfSmallBall
/
2
+
self
.
verticalMargin
;
}
self
.
smallBall
.
frame
=
CGRectMake
(
targetXOfSmallBall
,
targetYOfSmallBall
,
targetWidthOfSmallBall
,
targetWidthOfSmallBall
);
self
.
smallBall
.
layer
.
cornerRadius
=
targetWidthOfSmallBall
/
2
;
[
CATransaction
begin
];
[
CATransaction
setDisableActions
:
YES
];
self
.
shapeLayer
.
path
=
[
self
getBezierPathWithSmallCir
:
self
.
smallBall
andBigCir
:
self
.
bigBall
].
CGPath
;
[
CATransaction
commit
];
}
}
-
(
void
)
jx_selectedCell
:(
JXCategoryIndicatorParamsModel
*
)
model
{
CGFloat
x
=
model
.
selectedCellFrame
.
origin
.
x
+
(
model
.
selectedCellFrame
.
size
.
width
-
self
.
ballViewSize
.
width
)
/
2
;
CGFloat
y
=
self
.
superview
.
bounds
.
size
.
height
-
self
.
ballViewSize
.
height
-
self
.
verticalMargin
;
if
(
self
.
componentPosition
==
JXCategoryComponentPosition_Top
)
{
y
=
self
.
verticalMargin
;
}
CGRect
toFrame
=
CGRectMake
(
x
,
y
,
self
.
ballViewSize
.
width
,
self
.
ballViewSize
.
height
);
if
(
self
.
scrollEnabled
)
{
[
UIView
animateWithDuration
:
0
.
25
delay
:
0
options
:
UIViewAnimationOptionCurveEaseOut
animations
:^
{
self
.
smallBall
.
frame
=
toFrame
;
self
.
bigBall
.
frame
=
toFrame
;
self
.
smallBall
.
layer
.
cornerRadius
=
self
.
ballViewSize
.
height
/
2
;
self
.
bigBall
.
layer
.
cornerRadius
=
self
.
ballViewSize
.
height
/
2
;
}
completion
:^
(
BOOL
finished
)
{
}];
}
else
{
self
.
smallBall
.
frame
=
toFrame
;
self
.
bigBall
.
frame
=
toFrame
;
self
.
smallBall
.
layer
.
cornerRadius
=
self
.
ballViewSize
.
height
/
2
;
self
.
bigBall
.
layer
.
cornerRadius
=
self
.
ballViewSize
.
height
/
2
;
}
}
-
(
UIBezierPath
*
)
getBezierPathWithSmallCir
:(
UIView
*
)
smallCir
andBigCir
:(
UIView
*
)
bigCir
{
// 获取最小的圆
if
(
bigCir
.
frame
.
size
.
width
<
smallCir
.
frame
.
size
.
width
)
{
UIView
*
view
=
bigCir
;
bigCir
=
smallCir
;
smallCir
=
view
;
}
// 获取小圆的信息
CGFloat
d
=
self
.
bigBall
.
center
.
x
-
self
.
smallBall
.
center
.
x
;
if
(
d
==
0
)
{
return
nil
;
}
CGFloat
x1
=
smallCir
.
center
.
x
;
CGFloat
y1
=
smallCir
.
center
.
y
;
CGFloat
r1
=
smallCir
.
bounds
.
size
.
width
/
2
;
// 获取大圆的信息
CGFloat
x2
=
bigCir
.
center
.
x
;
CGFloat
y2
=
bigCir
.
center
.
y
;
CGFloat
r2
=
bigCir
.
bounds
.
size
.
width
/
2
;
// 获取三角函数
CGFloat
sinA
=
(
y2
-
y1
)
/
d
;
CGFloat
cosA
=
(
x2
-
x1
)
/
d
;
// 获取矩形四个点
CGPoint
pointA
=
CGPointMake
(
x1
-
sinA
*
r1
,
y1
+
cosA
*
r1
);
CGPoint
pointB
=
CGPointMake
(
x1
+
sinA
*
r1
,
y1
-
cosA
*
r1
);
CGPoint
pointC
=
CGPointMake
(
x2
+
sinA
*
r2
,
y2
-
cosA
*
r2
);
CGPoint
pointD
=
CGPointMake
(
x2
-
sinA
*
r2
,
y2
+
cosA
*
r2
);
// 获取控制点,以便画出曲线
CGPoint
pointO
=
CGPointMake
(
pointA
.
x
+
d
/
2
*
cosA
,
pointA
.
y
+
d
/
2
*
sinA
);
CGPoint
pointP
=
CGPointMake
(
pointB
.
x
+
d
/
2
*
cosA
,
pointB
.
y
+
d
/
2
*
sinA
);
// 创建路径
UIBezierPath
*
path
=
[
UIBezierPath
bezierPath
];
[
path
moveToPoint
:
pointA
];
[
path
addLineToPoint
:
pointB
];
[
path
addQuadCurveToPoint
:
pointC
controlPoint
:
pointP
];
[
path
addLineToPoint
:
pointD
];
[
path
addQuadCurveToPoint
:
pointA
controlPoint
:
pointO
];
return
path
;
}
@end
GMBase/Classes/JXPagerView/JXCategoryView/Indicator/IndicatorViews/JXCategoryIndicatorComponentView.h
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryComponentBaseView.h
// JXCategoryView
//
// Created by jiaxin on 2018/8/17.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "JXCategoryIndicatorProtocol.h"
#import "JXCategoryViewDefines.h"
@interface
JXCategoryIndicatorComponentView
:
UIView
<
JXCategoryIndicatorProtocol
>
/**
指示器的位置。底部或者顶部
*/
@property
(
nonatomic
,
assign
)
JXCategoryComponentPosition
componentPosition
;
/**
默认JXCategoryViewAutomaticDimension(与cell的宽度相等)。内部通过`- (CGFloat)indicatorWidthValue:(CGRect)cellFrame`方法获取实际的值
*/
@property
(
nonatomic
,
assign
)
CGFloat
indicatorWidth
;
/**
指示器的宽度增量。比如需求是指示器宽度比cell宽度多10 point。就可以将该属性赋值为10。最终指示器的宽度=indicatorWidth+indicatorWidthIncrement
*/
@property
(
nonatomic
,
assign
)
CGFloat
indicatorWidthIncrement
;
/**
默认:3。内部通过`- (CGFloat)indicatorHeightValue:(CGRect)cellFrame`方法获取实际的值
*/
@property
(
nonatomic
,
assign
)
CGFloat
indicatorHeight
;
/**
默认JXCategoryViewAutomaticDimension (等于indicatorHeight/2)。内部通过`- (CGFloat)indicatorCornerRadiusValue:(CGRect)cellFrame`方法获取实际的值
*/
@property
(
nonatomic
,
assign
)
CGFloat
indicatorCornerRadius
;
/**
指示器的颜色
*/
@property
(
nonatomic
,
strong
)
UIColor
*
indicatorColor
;
/**
垂直方向偏移。数值越大越靠近中心。默认:0。
*/
@property
(
nonatomic
,
assign
)
CGFloat
verticalMargin
;
/**
手势滚动、点击切换的时候,是否允许滚动,默认YES
*/
@property
(
nonatomic
,
assign
,
getter
=
isScrollEnabled
)
BOOL
scrollEnabled
;
/**
手势滚动、点击切换的时候,如果允许滚动,分为简单滚动和复杂滚动。默认为:JXCategoryIndicatorScrollStyleSimple
目前仅JXCategoryIndicatorLineView、JXCategoryIndicatorDotLineView支持,其他子类暂不支持。
*/
@property
(
nonatomic
,
assign
)
JXCategoryIndicatorScrollStyle
scrollStyle
;
/**
滚动动画的时间。默认0.25
*/
@property
(
nonatomic
,
assign
)
NSTimeInterval
scrollAnimationDuration
;
/**
传入cellFrame获取指示器的最终宽度
@param cellFrame cellFrame
@return 指示器的最终宽度
*/
-
(
CGFloat
)
indicatorWidthValue
:(
CGRect
)
cellFrame
;
/**
传入cellFrame获取指示器的最终高度
@param cellFrame cellFrame
@return 指示器的最终高度
*/
-
(
CGFloat
)
indicatorHeightValue
:(
CGRect
)
cellFrame
;
/**
传入cellFrame获取指示器的最终圆角
@param cellFrame cellFrame
@return 指示器的最终圆角
*/
-
(
CGFloat
)
indicatorCornerRadiusValue
:(
CGRect
)
cellFrame
;
@end
GMBase/Classes/JXPagerView/JXCategoryView/Indicator/IndicatorViews/JXCategoryIndicatorComponentView.m
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryComponentBaseView.m
// JXCategoryView
//
// Created by jiaxin on 2018/8/17.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryIndicatorComponentView.h"
@implementation
JXCategoryIndicatorComponentView
-
(
instancetype
)
initWithFrame
:(
CGRect
)
frame
{
self
=
[
super
initWithFrame
:
frame
];
if
(
self
)
{
_componentPosition
=
JXCategoryComponentPosition_Bottom
;
_scrollEnabled
=
YES
;
_verticalMargin
=
0
;
_scrollAnimationDuration
=
0
.
25
;
_indicatorWidth
=
JXCategoryViewAutomaticDimension
;
_indicatorWidthIncrement
=
0
;
_indicatorHeight
=
3
;
_indicatorCornerRadius
=
JXCategoryViewAutomaticDimension
;
_indicatorColor
=
[
UIColor
redColor
];
_scrollStyle
=
JXCategoryIndicatorScrollStyleSimple
;
}
return
self
;
}
-
(
instancetype
)
initWithCoder
:(
NSCoder
*
)
coder
{
self
=
[
super
initWithCoder
:
coder
];
if
(
self
)
{
NSAssert
(
NO
,
@"Use initWithFrame"
);
}
return
self
;
}
-
(
CGFloat
)
indicatorWidthValue
:(
CGRect
)
cellFrame
{
if
(
self
.
indicatorWidth
==
JXCategoryViewAutomaticDimension
)
{
return
cellFrame
.
size
.
width
+
self
.
indicatorWidthIncrement
;
}
return
self
.
indicatorWidth
+
self
.
indicatorWidthIncrement
;
}
-
(
CGFloat
)
indicatorHeightValue
:(
CGRect
)
cellFrame
{
if
(
self
.
indicatorHeight
==
JXCategoryViewAutomaticDimension
)
{
return
cellFrame
.
size
.
height
;
}
return
self
.
indicatorHeight
;
}
-
(
CGFloat
)
indicatorCornerRadiusValue
:(
CGRect
)
cellFrame
{
if
(
self
.
indicatorCornerRadius
==
JXCategoryViewAutomaticDimension
)
{
return
[
self
indicatorHeightValue
:
cellFrame
]
/
2
;
}
return
self
.
indicatorCornerRadius
;
}
#pragma mark - JXCategoryIndicatorProtocol
-
(
void
)
jx_refreshState
:(
JXCategoryIndicatorParamsModel
*
)
model
{
}
-
(
void
)
jx_contentScrollViewDidScroll
:(
JXCategoryIndicatorParamsModel
*
)
model
{
}
-
(
void
)
jx_selectedCell
:(
JXCategoryIndicatorParamsModel
*
)
model
{
}
@end
GMBase/Classes/JXPagerView/JXCategoryView/Indicator/IndicatorViews/JXCategoryIndicatorImageView.h
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryIndicatorImageView.h
// JXCategoryView
//
// Created by jiaxin on 2018/8/17.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryIndicatorComponentView.h"
@interface
JXCategoryIndicatorImageView
:
JXCategoryIndicatorComponentView
@property
(
nonatomic
,
strong
,
readonly
)
UIImageView
*
indicatorImageView
;
@property
(
nonatomic
,
assign
)
BOOL
indicatorImageViewRollEnabled
;
//默认NO
@property
(
nonatomic
,
assign
)
CGSize
indicatorImageViewSize
;
//默认:CGSizeMake(30, 20)
@end
GMBase/Classes/JXPagerView/JXCategoryView/Indicator/IndicatorViews/JXCategoryIndicatorImageView.m
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryIndicatorImageView.m
// JXCategoryView
//
// Created by jiaxin on 2018/8/17.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryIndicatorImageView.h"
#import "JXCategoryFactory.h"
@implementation
JXCategoryIndicatorImageView
-
(
instancetype
)
initWithFrame
:(
CGRect
)
frame
{
self
=
[
super
initWithFrame
:
frame
];
if
(
self
)
{
_indicatorImageViewSize
=
CGSizeMake
(
30
,
20
);
_indicatorImageViewRollEnabled
=
NO
;
_indicatorImageView
=
[[
UIImageView
alloc
]
init
];
self
.
indicatorImageView
.
frame
=
CGRectMake
(
0
,
0
,
self
.
indicatorImageViewSize
.
width
,
self
.
indicatorImageViewSize
.
height
);
self
.
indicatorImageView
.
contentMode
=
UIViewContentModeScaleAspectFit
;
[
self
addSubview
:
self
.
indicatorImageView
];
}
return
self
;
}
-
(
void
)
setIndicatorImageViewSize
:(
CGSize
)
indicatorImageViewSize
{
_indicatorImageViewSize
=
indicatorImageViewSize
;
self
.
indicatorImageView
.
frame
=
CGRectMake
(
0
,
0
,
self
.
indicatorImageViewSize
.
width
,
self
.
indicatorImageViewSize
.
height
);
}
#pragma mark - JXCategoryIndicatorProtocol
-
(
void
)
jx_refreshState
:(
JXCategoryIndicatorParamsModel
*
)
model
{
CGFloat
x
=
model
.
selectedCellFrame
.
origin
.
x
+
(
model
.
selectedCellFrame
.
size
.
width
-
self
.
indicatorImageViewSize
.
width
)
/
2
;
CGFloat
y
=
self
.
superview
.
bounds
.
size
.
height
-
self
.
indicatorImageViewSize
.
height
-
self
.
verticalMargin
;
if
(
self
.
componentPosition
==
JXCategoryComponentPosition_Top
)
{
y
=
self
.
verticalMargin
;
}
self
.
frame
=
CGRectMake
(
x
,
y
,
self
.
indicatorImageViewSize
.
width
,
self
.
indicatorImageViewSize
.
height
);
}
-
(
void
)
jx_contentScrollViewDidScroll
:(
JXCategoryIndicatorParamsModel
*
)
model
{
CGRect
rightCellFrame
=
model
.
rightCellFrame
;
CGRect
leftCellFrame
=
model
.
leftCellFrame
;
CGFloat
percent
=
model
.
percent
;
CGFloat
targetWidth
=
self
.
indicatorImageViewSize
.
width
;
CGFloat
targetX
=
0
;
if
(
percent
==
0
)
{
targetX
=
leftCellFrame
.
origin
.
x
+
(
leftCellFrame
.
size
.
width
-
targetWidth
)
/
2
.
0
;
}
else
{
CGFloat
leftX
=
leftCellFrame
.
origin
.
x
+
(
leftCellFrame
.
size
.
width
-
targetWidth
)
/
2
;
CGFloat
rightX
=
rightCellFrame
.
origin
.
x
+
(
rightCellFrame
.
size
.
width
-
targetWidth
)
/
2
;
targetX
=
[
JXCategoryFactory
interpolationFrom
:
leftX
to
:
rightX
percent
:
percent
];
}
//允许变动frame的情况:1、允许滚动;2、不允许滚动,但是已经通过手势滚动切换一页内容了;
if
(
self
.
scrollEnabled
==
YES
||
(
self
.
scrollEnabled
==
NO
&&
percent
==
0
))
{
CGRect
frame
=
self
.
frame
;
frame
.
origin
.
x
=
targetX
;
self
.
frame
=
frame
;
if
(
self
.
indicatorImageViewRollEnabled
)
{
self
.
indicatorImageView
.
transform
=
CGAffineTransformMakeRotation
(
M_PI
*
2
*
percent
);
}
}
}
-
(
void
)
jx_selectedCell
:(
JXCategoryIndicatorParamsModel
*
)
model
{
CGRect
toFrame
=
self
.
frame
;
toFrame
.
origin
.
x
=
model
.
selectedCellFrame
.
origin
.
x
+
(
model
.
selectedCellFrame
.
size
.
width
-
self
.
indicatorImageViewSize
.
width
)
/
2
;
if
(
self
.
scrollEnabled
)
{
[
UIView
animateWithDuration
:
0
.
25
delay
:
0
options
:
UIViewAnimationOptionCurveLinear
animations
:^
{
self
.
frame
=
toFrame
;
}
completion
:^
(
BOOL
finished
)
{
}];
if
(
self
.
indicatorImageViewRollEnabled
&&
model
.
isClicked
)
{
[
self
.
indicatorImageView
.
layer
removeAnimationForKey
:
@"rotate"
];
CABasicAnimation
*
rotateAnimation
=
[
CABasicAnimation
animationWithKeyPath
:
@"transform.rotation.z"
];
if
(
model
.
selectedIndex
>
model
.
lastSelectedIndex
)
{
rotateAnimation
.
fromValue
=
@
(
0
);
rotateAnimation
.
toValue
=
@
(
M_PI
*
2
);
}
else
{
rotateAnimation
.
fromValue
=
@
(
M_PI
*
2
);
rotateAnimation
.
toValue
=
@
(
0
);
}
rotateAnimation
.
fillMode
=
kCAFillModeBackwards
;
rotateAnimation
.
removedOnCompletion
=
YES
;
rotateAnimation
.
duration
=
0
.
25
;
[
self
.
indicatorImageView
.
layer
addAnimation
:
rotateAnimation
forKey
:
@"rotate"
];
}
}
else
{
self
.
frame
=
toFrame
;
}
}
@end
GMBase/Classes/JXPagerView/JXCategoryView/Indicator/IndicatorViews/JXCategoryIndicatorLineView.h
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryIndicatorLineView.h
// JXCategoryView
//
// Created by jiaxin on 2018/8/17.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryIndicatorComponentView.h"
typedef
NS_ENUM
(
NSUInteger
,
JXCategoryIndicatorLineStyle
)
{
JXCategoryIndicatorLineStyle_Normal
=
0
,
JXCategoryIndicatorLineStyle_Lengthen
=
1
,
JXCategoryIndicatorLineStyle_LengthenOffset
=
2
,
};
@interface
JXCategoryIndicatorLineView
:
JXCategoryIndicatorComponentView
@property
(
nonatomic
,
assign
)
JXCategoryIndicatorLineStyle
lineStyle
;
/**
line滚动时x的偏移量,默认为10;
lineStyle为JXCategoryIndicatorLineStyle_LengthenOffset有用;
*/
@property
(
nonatomic
,
assign
)
CGFloat
lineScrollOffsetX
;
@end
GMBase/Classes/JXPagerView/JXCategoryView/Indicator/IndicatorViews/JXCategoryIndicatorLineView.m
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryIndicatorLineView.m
// JXCategoryView
//
// Created by jiaxin on 2018/8/17.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryIndicatorLineView.h"
#import "JXCategoryFactory.h"
#import "JXCategoryViewDefines.h"
#import "JXCategoryViewAnimator.h"
@interface
JXCategoryIndicatorLineView
()
@property
(
nonatomic
,
strong
)
JXCategoryViewAnimator
*
animator
;
@end
@implementation
JXCategoryIndicatorLineView
-
(
instancetype
)
initWithFrame
:(
CGRect
)
frame
{
self
=
[
super
initWithFrame
:
frame
];
if
(
self
)
{
_lineStyle
=
JXCategoryIndicatorLineStyle_Normal
;
_lineScrollOffsetX
=
10
;
self
.
indicatorHeight
=
3
;
}
return
self
;
}
#pragma mark - JXCategoryIndicatorProtocol
-
(
void
)
jx_refreshState
:(
JXCategoryIndicatorParamsModel
*
)
model
{
self
.
backgroundColor
=
self
.
indicatorColor
;
self
.
layer
.
cornerRadius
=
[
self
indicatorCornerRadiusValue
:
model
.
selectedCellFrame
];
CGFloat
selectedLineWidth
=
[
self
indicatorWidthValue
:
model
.
selectedCellFrame
];
CGFloat
x
=
model
.
selectedCellFrame
.
origin
.
x
+
(
model
.
selectedCellFrame
.
size
.
width
-
selectedLineWidth
)
/
2
;
CGFloat
y
=
self
.
superview
.
bounds
.
size
.
height
-
[
self
indicatorHeightValue
:
model
.
selectedCellFrame
]
-
self
.
verticalMargin
;
if
(
self
.
componentPosition
==
JXCategoryComponentPosition_Top
)
{
y
=
self
.
verticalMargin
;
}
self
.
frame
=
CGRectMake
(
x
,
y
,
selectedLineWidth
,
[
self
indicatorHeightValue
:
model
.
selectedCellFrame
]);
}
-
(
void
)
jx_contentScrollViewDidScroll
:(
JXCategoryIndicatorParamsModel
*
)
model
{
if
(
self
.
animator
.
isExecuting
)
{
[
self
.
animator
invalid
];
self
.
animator
=
nil
;
}
CGRect
rightCellFrame
=
model
.
rightCellFrame
;
CGRect
leftCellFrame
=
model
.
leftCellFrame
;
CGFloat
percent
=
model
.
percent
;
CGFloat
targetX
=
leftCellFrame
.
origin
.
x
;
CGFloat
targetWidth
=
[
self
indicatorWidthValue
:
leftCellFrame
];
CGFloat
leftWidth
=
targetWidth
;
CGFloat
rightWidth
=
[
self
indicatorWidthValue
:
rightCellFrame
];
CGFloat
leftX
=
leftCellFrame
.
origin
.
x
+
(
leftCellFrame
.
size
.
width
-
leftWidth
)
/
2
;
CGFloat
rightX
=
rightCellFrame
.
origin
.
x
+
(
rightCellFrame
.
size
.
width
-
rightWidth
)
/
2
;
if
(
self
.
lineStyle
==
JXCategoryIndicatorLineStyle_Normal
)
{
targetX
=
[
JXCategoryFactory
interpolationFrom
:
leftX
to
:
rightX
percent
:
0
];
NSLog
(
@"targetX--%.2f"
,
targetX
);
if
(
self
.
indicatorWidth
==
JXCategoryViewAutomaticDimension
)
{
targetWidth
=
[
JXCategoryFactory
interpolationFrom
:
leftWidth
to
:
rightWidth
percent
:
percent
];
NSLog
(
@"targetWidth--%.2f"
,
targetX
);
}
}
else
if
(
self
.
lineStyle
==
JXCategoryIndicatorLineStyle_Lengthen
)
{
CGFloat
maxWidth
=
rightX
-
leftX
+
rightWidth
;
//前50%,只增加width;后50%,移动x并减小width
if
(
percent
<=
0
.
5
)
{
targetX
=
leftX
;
targetWidth
=
[
JXCategoryFactory
interpolationFrom
:
leftWidth
to
:
maxWidth
percent
:
percent
*
2
];
}
else
{
targetX
=
[
JXCategoryFactory
interpolationFrom
:
leftX
to
:
rightX
percent
:
(
percent
-
0
.
5
)
*
2
];
NSLog
(
@"targetX--%.2f"
,
targetX
);
targetWidth
=
[
JXCategoryFactory
interpolationFrom
:
maxWidth
to
:
rightWidth
percent
:
(
percent
-
0
.
5
)
*
2
];
NSLog
(
@"targetWidth--%.2f"
,
targetWidth
);
}
}
else
if
(
self
.
lineStyle
==
JXCategoryIndicatorLineStyle_LengthenOffset
)
{
//前50%,增加width,并少量移动x;后50%,少量移动x并减小width
CGFloat
offsetX
=
self
.
lineScrollOffsetX
;
//x的少量偏移量
CGFloat
maxWidth
=
rightX
-
leftX
+
rightWidth
-
offsetX
*
2
;
if
(
percent
<=
0
.
5
)
{
targetX
=
[
JXCategoryFactory
interpolationFrom
:
leftX
to
:
leftX
+
offsetX
percent
:
percent
*
2
];;
targetWidth
=
[
JXCategoryFactory
interpolationFrom
:
leftWidth
to
:
maxWidth
percent
:
percent
*
2
];
}
else
{
targetX
=
[
JXCategoryFactory
interpolationFrom
:(
leftX
+
offsetX
)
to
:
rightX
percent
:
(
percent
-
0
.
5
)
*
2
];
targetWidth
=
[
JXCategoryFactory
interpolationFrom
:
maxWidth
to
:
rightWidth
percent
:
(
percent
-
0
.
5
)
*
2
];
}
}
//允许变动frame的情况:1、允许滚动;2、不允许滚动,但是已经通过手势滚动切换一页内容了;
if
(
self
.
isScrollEnabled
==
YES
||
(
self
.
isScrollEnabled
==
NO
&&
percent
==
0
))
{
CGRect
frame
=
self
.
frame
;
frame
.
origin
.
x
=
targetX
;
frame
.
size
.
width
=
targetWidth
;
self
.
frame
=
frame
;
}
}
-
(
void
)
jx_selectedCell
:(
JXCategoryIndicatorParamsModel
*
)
model
{
CGRect
targetIndicatorFrame
=
self
.
frame
;
CGFloat
targetIndicatorWidth
=
[
self
indicatorWidthValue
:
model
.
selectedCellFrame
];
targetIndicatorFrame
.
origin
.
x
=
model
.
selectedCellFrame
.
origin
.
x
+
(
model
.
selectedCellFrame
.
size
.
width
-
targetIndicatorWidth
)
/
2
.
0
;
targetIndicatorFrame
.
size
.
width
=
targetIndicatorWidth
;
if
(
self
.
isScrollEnabled
)
{
if
(
self
.
scrollStyle
==
JXCategoryIndicatorScrollStyleSameAsUserScroll
)
{
if
(
self
.
animator
.
isExecuting
)
{
[
self
.
animator
invalid
];
self
.
animator
=
nil
;
}
CGFloat
leftX
=
0
;
CGFloat
rightX
=
0
;
CGFloat
leftWidth
=
0
;
CGFloat
rightWidth
=
0
;
BOOL
isNeedReversePercent
=
NO
;
if
(
self
.
frame
.
origin
.
x
>
model
.
selectedCellFrame
.
origin
.
x
)
{
leftWidth
=
[
self
indicatorWidthValue
:
model
.
selectedCellFrame
];
rightWidth
=
self
.
frame
.
size
.
width
;
leftX
=
model
.
selectedCellFrame
.
origin
.
x
+
(
model
.
selectedCellFrame
.
size
.
width
-
leftWidth
)
/
2
;;
rightX
=
self
.
frame
.
origin
.
x
;
isNeedReversePercent
=
YES
;
}
else
{
leftWidth
=
self
.
frame
.
size
.
width
;
rightWidth
=
[
self
indicatorWidthValue
:
model
.
selectedCellFrame
];
leftX
=
self
.
frame
.
origin
.
x
;
rightX
=
model
.
selectedCellFrame
.
origin
.
x
+
(
model
.
selectedCellFrame
.
size
.
width
-
rightWidth
)
/
2
;
}
__weak
typeof
(
self
)
weakSelf
=
self
;
if
(
self
.
lineStyle
==
JXCategoryIndicatorLineStyle_Normal
)
{
[
UIView
animateWithDuration
:
self
.
scrollAnimationDuration
delay
:
0
options
:
UIViewAnimationOptionCurveEaseOut
animations
:^
{
self
.
frame
=
targetIndicatorFrame
;
}
completion
:
nil
];
}
else
if
(
self
.
lineStyle
==
JXCategoryIndicatorLineStyle_Lengthen
)
{
CGFloat
maxWidth
=
rightX
-
leftX
+
rightWidth
;
//前50%,只增加width;后50%,移动x并减小width
self
.
animator
=
[[
JXCategoryViewAnimator
alloc
]
init
];
self
.
animator
.
progressCallback
=
^
(
CGFloat
percent
)
{
if
(
isNeedReversePercent
)
{
percent
=
1
-
percent
;
}
CGFloat
targetX
=
0
;
CGFloat
targetWidth
=
0
;
if
(
percent
<=
0
.
5
)
{
targetX
=
leftX
;
targetWidth
=
[
JXCategoryFactory
interpolationFrom
:
leftWidth
to
:
maxWidth
percent
:
percent
*
2
];
}
else
{
targetX
=
[
JXCategoryFactory
interpolationFrom
:
leftX
to
:
rightX
percent
:
(
percent
-
0
.
5
)
*
2
];
targetWidth
=
[
JXCategoryFactory
interpolationFrom
:
maxWidth
to
:
rightWidth
percent
:
(
percent
-
0
.
5
)
*
2
];
}
CGRect
toFrame
=
weakSelf
.
frame
;
toFrame
.
origin
.
x
=
targetX
;
toFrame
.
size
.
width
=
targetWidth
;
weakSelf
.
frame
=
toFrame
;
};
[
self
.
animator
start
];
}
else
if
(
self
.
lineStyle
==
JXCategoryIndicatorLineStyle_LengthenOffset
)
{
//前50%,增加width,并少量移动x;后50%,少量移动x并减小width
CGFloat
offsetX
=
self
.
lineScrollOffsetX
;
//x的少量偏移量
CGFloat
maxWidth
=
rightX
-
leftX
+
rightWidth
-
offsetX
*
2
;
self
.
animator
=
[[
JXCategoryViewAnimator
alloc
]
init
];
self
.
animator
.
progressCallback
=
^
(
CGFloat
percent
)
{
if
(
isNeedReversePercent
)
{
percent
=
1
-
percent
;
}
CGFloat
targetX
=
0
;
CGFloat
targetWidth
=
0
;
if
(
percent
<=
0
.
5
)
{
targetX
=
[
JXCategoryFactory
interpolationFrom
:
leftX
to
:
leftX
+
offsetX
percent
:
percent
*
2
];;
targetWidth
=
[
JXCategoryFactory
interpolationFrom
:
leftWidth
to
:
maxWidth
percent
:
percent
*
2
];
}
else
{
targetX
=
[
JXCategoryFactory
interpolationFrom
:(
leftX
+
offsetX
)
to
:
rightX
percent
:
(
percent
-
0
.
5
)
*
2
];
targetWidth
=
[
JXCategoryFactory
interpolationFrom
:
maxWidth
to
:
rightWidth
percent
:
(
percent
-
0
.
5
)
*
2
];
}
CGRect
toFrame
=
weakSelf
.
frame
;
toFrame
.
origin
.
x
=
targetX
;
toFrame
.
size
.
width
=
targetWidth
;
weakSelf
.
frame
=
toFrame
;
};
[
self
.
animator
start
];
}
}
else
if
(
self
.
scrollStyle
==
JXCategoryIndicatorScrollStyleSimple
)
{
[
UIView
animateWithDuration
:
self
.
scrollAnimationDuration
delay
:
0
options
:
UIViewAnimationOptionCurveEaseOut
animations
:^
{
self
.
frame
=
targetIndicatorFrame
;
}
completion
:
nil
];
}
}
else
{
self
.
frame
=
targetIndicatorFrame
;
}
}
@end
GMBase/Classes/JXPagerView/JXCategoryView/Indicator/IndicatorViews/JXCategoryIndicatorRainbowLineView.h
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryIndicatorRainbowLineView.h
// JXCategoryView
//
// Created by jiaxin on 2018/12/13.
// Copyright © 2018 jiaxin. All rights reserved.
//
#import "JXCategoryIndicatorLineView.h"
NS_ASSUME_NONNULL_BEGIN
/**
会无视JXCategoryIndicatorLineView的indicatorLineViewColor属性,以indicatorColors为准
*/
@interface
JXCategoryIndicatorRainbowLineView
:
JXCategoryIndicatorLineView
@property
(
nonatomic
,
strong
)
NSArray
<
UIColor
*>
*
indicatorColors
;
//数量需要与cell的数量相等。没有提供默认值,必须要赋值该属性。categoryView在reloadData的时候,也要一并更新该属性,不然会出现数组越界。
@end
NS_ASSUME_NONNULL_END
GMBase/Classes/JXPagerView/JXCategoryView/Indicator/IndicatorViews/JXCategoryIndicatorRainbowLineView.m
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryIndicatorRainbowLineView.m
// JXCategoryView
//
// Created by jiaxin on 2018/12/13.
// Copyright © 2018 jiaxin. All rights reserved.
//
#import "JXCategoryIndicatorRainbowLineView.h"
#import "JXCategoryFactory.h"
@implementation
JXCategoryIndicatorRainbowLineView
-
(
void
)
jx_refreshState
:(
JXCategoryIndicatorParamsModel
*
)
model
{
[
super
jx_refreshState
:
model
];
UIColor
*
color
=
self
.
indicatorColors
[
model
.
selectedIndex
];
self
.
backgroundColor
=
color
;
}
-
(
void
)
jx_contentScrollViewDidScroll
:(
JXCategoryIndicatorParamsModel
*
)
model
{
[
super
jx_contentScrollViewDidScroll
:
model
];
UIColor
*
leftColor
=
self
.
indicatorColors
[
model
.
leftIndex
];
UIColor
*
rightColor
=
self
.
indicatorColors
[
model
.
rightIndex
];
UIColor
*
color
=
[
JXCategoryFactory
interpolationColorFrom
:
leftColor
to
:
rightColor
percent
:
model
.
percent
];
self
.
backgroundColor
=
color
;
}
-
(
void
)
jx_selectedCell
:(
JXCategoryIndicatorParamsModel
*
)
model
{
[
super
jx_selectedCell
:
model
];
UIColor
*
color
=
self
.
indicatorColors
[
model
.
selectedIndex
];
self
.
backgroundColor
=
color
;
}
@end
GMBase/Classes/JXPagerView/JXCategoryView/Indicator/IndicatorViews/JXCategoryIndicatorTriangleView.h
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryIndicatorTriangleView.h
// JXCategoryView
//
// Created by jiaxin on 2018/8/17.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryIndicatorComponentView.h"
@interface
JXCategoryIndicatorTriangleView
:
JXCategoryIndicatorComponentView
@property
(
nonatomic
,
assign
)
CGSize
triangleViewSize
;
//默认:CGSizeMake(14, 10)
@property
(
nonatomic
,
strong
)
UIColor
*
triangleViewColor
;
//默认:[UIColor redColor]
@end
GMBase/Classes/JXPagerView/JXCategoryView/Indicator/IndicatorViews/JXCategoryIndicatorTriangleView.m
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryIndicatorTriangleView.m
// JXCategoryView
//
// Created by jiaxin on 2018/8/17.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryIndicatorTriangleView.h"
#import "JXCategoryFactory.h"
@interface
JXCategoryIndicatorTriangleView
()
@property
(
nonatomic
,
strong
)
CAShapeLayer
*
triangleLayer
;
@end
@implementation
JXCategoryIndicatorTriangleView
-
(
instancetype
)
initWithFrame
:(
CGRect
)
frame
{
self
=
[
super
initWithFrame
:
frame
];
if
(
self
)
{
_triangleViewSize
=
CGSizeMake
(
14
,
10
);
_triangleViewColor
=
[
UIColor
redColor
];
_triangleLayer
=
[
CAShapeLayer
layer
];
[
self
.
layer
addSublayer
:
self
.
triangleLayer
];
}
return
self
;
}
#pragma mark - JXCategoryIndicatorProtocol
-
(
void
)
jx_refreshState
:(
JXCategoryIndicatorParamsModel
*
)
model
{
CGFloat
x
=
model
.
selectedCellFrame
.
origin
.
x
+
(
model
.
selectedCellFrame
.
size
.
width
-
self
.
triangleViewSize
.
width
)
/
2
;
CGFloat
y
=
self
.
superview
.
bounds
.
size
.
height
-
self
.
triangleViewSize
.
height
-
self
.
verticalMargin
;
if
(
self
.
componentPosition
==
JXCategoryComponentPosition_Top
)
{
y
=
self
.
verticalMargin
;
}
self
.
frame
=
CGRectMake
(
x
,
y
,
self
.
triangleViewSize
.
width
,
self
.
triangleViewSize
.
height
);
[
CATransaction
begin
];
[
CATransaction
setDisableActions
:
NO
];
self
.
triangleLayer
.
fillColor
=
self
.
triangleViewColor
.
CGColor
;
self
.
triangleLayer
.
frame
=
self
.
bounds
;
UIBezierPath
*
path
=
[
UIBezierPath
bezierPath
];
if
(
self
.
componentPosition
==
JXCategoryComponentPosition_Bottom
)
{
[
path
moveToPoint
:
CGPointMake
(
self
.
bounds
.
size
.
width
/
2
,
0
)];
[
path
addLineToPoint
:
CGPointMake
(
0
,
self
.
bounds
.
size
.
height
)];
[
path
addLineToPoint
:
CGPointMake
(
self
.
bounds
.
size
.
width
,
self
.
bounds
.
size
.
height
)];
}
else
{
[
path
moveToPoint
:
CGPointMake
(
0
,
0
)];
[
path
addLineToPoint
:
CGPointMake
(
self
.
bounds
.
size
.
width
,
0
)];
[
path
addLineToPoint
:
CGPointMake
(
self
.
bounds
.
size
.
width
/
2
,
self
.
bounds
.
size
.
height
)];
}
[
path
closePath
];
self
.
triangleLayer
.
path
=
path
.
CGPath
;
[
CATransaction
commit
];
}
-
(
void
)
jx_contentScrollViewDidScroll
:(
JXCategoryIndicatorParamsModel
*
)
model
{
CGRect
rightCellFrame
=
model
.
rightCellFrame
;
CGRect
leftCellFrame
=
model
.
leftCellFrame
;
CGFloat
percent
=
model
.
percent
;
CGFloat
targetWidth
=
self
.
triangleViewSize
.
width
;
CGFloat
targetX
=
0
;
if
(
percent
==
0
)
{
targetX
=
leftCellFrame
.
origin
.
x
+
(
leftCellFrame
.
size
.
width
-
targetWidth
)
/
2
.
0
;
}
else
{
CGFloat
leftX
=
leftCellFrame
.
origin
.
x
+
(
leftCellFrame
.
size
.
width
-
targetWidth
)
/
2
;
CGFloat
rightX
=
rightCellFrame
.
origin
.
x
+
(
rightCellFrame
.
size
.
width
-
targetWidth
)
/
2
;
targetX
=
[
JXCategoryFactory
interpolationFrom
:
leftX
to
:
rightX
percent
:
percent
];
}
//允许变动frame的情况:1、允许滚动;2、不允许滚动,但是已经通过手势滚动切换一页内容了;
if
(
self
.
scrollEnabled
==
YES
||
(
self
.
scrollEnabled
==
NO
&&
percent
==
0
))
{
CGRect
frame
=
self
.
frame
;
frame
.
origin
.
x
=
targetX
;
self
.
frame
=
frame
;
}
}
-
(
void
)
jx_selectedCell
:(
JXCategoryIndicatorParamsModel
*
)
model
{
CGRect
toFrame
=
self
.
frame
;
toFrame
.
origin
.
x
=
model
.
selectedCellFrame
.
origin
.
x
+
(
model
.
selectedCellFrame
.
size
.
width
-
self
.
triangleViewSize
.
width
)
/
2
;
if
(
self
.
scrollEnabled
)
{
[
UIView
animateWithDuration
:
0
.
25
delay
:
0
options
:
UIViewAnimationOptionCurveLinear
animations
:^
{
self
.
frame
=
toFrame
;
}
completion
:^
(
BOOL
finished
)
{
}];
}
else
{
self
.
frame
=
toFrame
;
}
}
@end
GMBase/Classes/JXPagerView/JXCategoryView/Indicator/IndicatorViews/JXCategoryViewAnimator.h
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryViewAnimator.h
// JXCategoryView
//
// Created by jiaxin on 2019/1/24.
// Copyright © 2019 jiaxin. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface
JXCategoryViewAnimator
:
NSObject
@property
(
nonatomic
,
assign
)
NSTimeInterval
duration
;
@property
(
nonatomic
,
copy
)
void
(
^
progressCallback
)(
CGFloat
percent
);
@property
(
nonatomic
,
copy
)
void
(
^
completeCallback
)(
void
);
@property
(
readonly
,
getter
=
isExecuting
)
BOOL
executing
;
-
(
void
)
start
;
-
(
void
)
stop
;
-
(
void
)
invalid
;
@end
GMBase/Classes/JXPagerView/JXCategoryView/Indicator/IndicatorViews/JXCategoryViewAnimator.m
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryViewAnimator.m
// JXCategoryView
//
// Created by jiaxin on 2019/1/24.
// Copyright © 2019 jiaxin. All rights reserved.
//
#import "JXCategoryViewAnimator.h"
@interface
JXCategoryViewAnimator
()
@property
(
nonatomic
,
strong
)
CADisplayLink
*
displayLink
;
@property
(
nonatomic
,
assign
)
CFTimeInterval
firstTimestamp
;
@property
(
readwrite
,
getter
=
isExecuting
)
BOOL
executing
;
@end
@implementation
JXCategoryViewAnimator
-
(
void
)
dealloc
{
self
.
progressCallback
=
nil
;
self
.
completeCallback
=
nil
;
}
-
(
instancetype
)
init
{
self
=
[
super
init
];
if
(
self
)
{
_executing
=
NO
;
_duration
=
0
.
25
;
_displayLink
=
[
CADisplayLink
displayLinkWithTarget
:
self
selector
:
@selector
(
processDisplayLink
:
)];
}
return
self
;
}
-
(
void
)
start
{
[
self
.
displayLink
addToRunLoop
:[
NSRunLoop
mainRunLoop
]
forMode
:
NSRunLoopCommonModes
];
self
.
executing
=
YES
;
}
-
(
void
)
stop
{
!
self
.
progressCallback
?:
self
.
progressCallback
(
1
);
[
self
.
displayLink
invalidate
];
!
self
.
completeCallback
?:
self
.
completeCallback
();
self
.
executing
=
NO
;
}
-
(
void
)
invalid
{
[
self
.
displayLink
invalidate
];
!
self
.
completeCallback
?:
self
.
completeCallback
();
self
.
executing
=
NO
;
}
-
(
void
)
processDisplayLink
:
(
CADisplayLink
*
)
sender
{
if
(
self
.
firstTimestamp
==
0
)
{
self
.
firstTimestamp
=
sender
.
timestamp
;
return
;
}
CGFloat
percent
=
(
sender
.
timestamp
-
self
.
firstTimestamp
)
/
self
.
duration
;
if
(
percent
>=
1
)
{
!
self
.
progressCallback
?:
self
.
progressCallback
(
percent
);
[
self
.
displayLink
invalidate
];
!
self
.
completeCallback
?:
self
.
completeCallback
();
self
.
executing
=
NO
;
}
else
{
!
self
.
progressCallback
?:
self
.
progressCallback
(
percent
);
self
.
executing
=
YES
;
}
}
@end
GMBase/Classes/JXPagerView/JXCategoryView/Indicator/JXCategoryIndicatorCell.h
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryComponetCell.h
// DQGuess
//
// Created by jiaxin on 2018/7/25.
// Copyright © 2018年 jingbo. All rights reserved.
//
#import "JXCategoryBaseCell.h"
@interface
JXCategoryIndicatorCell
:
JXCategoryBaseCell
@end
GMBase/Classes/JXPagerView/JXCategoryView/Indicator/JXCategoryIndicatorCell.m
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryComponetCell.m
// DQGuess
//
// Created by jiaxin on 2018/7/25.
// Copyright © 2018年 jingbo. All rights reserved.
//
#import "JXCategoryIndicatorCell.h"
#import "JXCategoryIndicatorCellModel.h"
@interface
JXCategoryIndicatorCell
()
@property
(
nonatomic
,
strong
)
UIView
*
separatorLine
;
@end
@implementation
JXCategoryIndicatorCell
-
(
void
)
initializeViews
{
[
super
initializeViews
];
self
.
separatorLine
=
[[
UIView
alloc
]
init
];
self
.
separatorLine
.
hidden
=
YES
;
[
self
.
contentView
addSubview
:
self
.
separatorLine
];
}
-
(
void
)
layoutSubviews
{
[
super
layoutSubviews
];
JXCategoryIndicatorCellModel
*
model
=
(
JXCategoryIndicatorCellModel
*
)
self
.
cellModel
;
CGFloat
lineWidth
=
model
.
separatorLineSize
.
width
;
CGFloat
lineHeight
=
model
.
separatorLineSize
.
height
;
self
.
separatorLine
.
frame
=
CGRectMake
(
self
.
bounds
.
size
.
width
-
lineWidth
+
self
.
cellModel
.
cellSpacing
/
2
,
(
self
.
bounds
.
size
.
height
-
lineHeight
)
/
2
.
0
,
lineWidth
,
lineHeight
);
}
-
(
void
)
reloadData
:
(
JXCategoryBaseCellModel
*
)
cellModel
{
[
super
reloadData
:
cellModel
];
JXCategoryIndicatorCellModel
*
model
=
(
JXCategoryIndicatorCellModel
*
)
cellModel
;
self
.
separatorLine
.
backgroundColor
=
model
.
separatorLineColor
;
self
.
separatorLine
.
hidden
=
!
model
.
sepratorLineShowEnabled
;
if
(
model
.
cellBackgroundColorGradientEnabled
)
{
if
(
model
.
selected
)
{
self
.
contentView
.
backgroundColor
=
model
.
cellBackgroundSelectedColor
;
}
else
{
self
.
contentView
.
backgroundColor
=
model
.
cellBackgroundUnselectedColor
;
}
}
}
@end
GMBase/Classes/JXPagerView/JXCategoryView/Indicator/JXCategoryIndicatorCellModel.h
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryComponentCellModel.h
// DQGuess
//
// Created by jiaxin on 2018/7/25.
// Copyright © 2018年 jingbo. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "JXCategoryBaseCellModel.h"
@interface
JXCategoryIndicatorCellModel
:
JXCategoryBaseCellModel
@property
(
nonatomic
,
assign
)
BOOL
sepratorLineShowEnabled
;
@property
(
nonatomic
,
strong
)
UIColor
*
separatorLineColor
;
@property
(
nonatomic
,
assign
)
CGSize
separatorLineSize
;
@property
(
nonatomic
,
assign
)
CGRect
backgroundViewMaskFrame
;
@property
(
nonatomic
,
assign
)
BOOL
cellBackgroundColorGradientEnabled
;
@property
(
nonatomic
,
strong
)
UIColor
*
cellBackgroundUnselectedColor
;
@property
(
nonatomic
,
strong
)
UIColor
*
cellBackgroundSelectedColor
;
@end
GMBase/Classes/JXPagerView/JXCategoryView/Indicator/JXCategoryIndicatorCellModel.m
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryComponentCellModel.m
// DQGuess
//
// Created by jiaxin on 2018/7/25.
// Copyright © 2018年 jingbo. All rights reserved.
//
#import "JXCategoryIndicatorCellModel.h"
@implementation
JXCategoryIndicatorCellModel
@end
GMBase/Classes/JXPagerView/JXCategoryView/Indicator/JXCategoryIndicatorView.h
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryComponentView.h
// DQGuess
//
// Created by jiaxin on 2018/7/25.
// Copyright © 2018年 jingbo. All rights reserved.
//
#import "JXCategoryBaseView.h"
#import "JXCategoryIndicatorCell.h"
#import "JXCategoryIndicatorCellModel.h"
#import "JXCategoryIndicatorProtocol.h"
@interface
JXCategoryIndicatorView
:
JXCategoryBaseView
@property
(
nonatomic
,
strong
)
NSArray
<
UIView
<
JXCategoryIndicatorProtocol
>
*>
*
indicators
;
//----------------------ellBackgroundColor-----------------------//
@property
(
nonatomic
,
assign
)
BOOL
cellBackgroundColorGradientEnabled
;
//默认:NO
@property
(
nonatomic
,
strong
)
UIColor
*
cellBackgroundUnselectedColor
;
//默认:[UIColor clearColor]
@property
(
nonatomic
,
strong
)
UIColor
*
cellBackgroundSelectedColor
;
//默认:[UIColor grayColor]
//----------------------separatorLine-----------------------//
@property
(
nonatomic
,
assign
)
BOOL
separatorLineShowEnabled
;
//默认为NO
@property
(
nonatomic
,
strong
)
UIColor
*
separatorLineColor
;
//默认为[UIColor lightGrayColor]
@property
(
nonatomic
,
assign
)
CGSize
separatorLineSize
;
//默认为CGSizeMake(1/[UIScreen mainScreen].scale, 20)
/**
当contentScrollView滚动时候,处理跟随手势的过渡效果。
根据cellModel的左右位置、是否选中、ratio进行过滤数据计算。
@param leftCellModel 左边的cellModel
@param rightCellModel 右边的cellModel
@param ratio 从左往右方向计算的百分比
*/
-
(
void
)
refreshLeftCellModel
:(
JXCategoryBaseCellModel
*
)
leftCellModel
rightCellModel
:(
JXCategoryBaseCellModel
*
)
rightCellModel
ratio
:(
CGFloat
)
ratio
NS_REQUIRES_SUPER
;
@end
GMBase/Classes/JXPagerView/JXCategoryView/Indicator/JXCategoryIndicatorView.m
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryComponentView.m
// DQGuess
//
// Created by jiaxin on 2018/7/25.
// Copyright © 2018年 jingbo. All rights reserved.
//
#import "JXCategoryIndicatorView.h"
#import "JXCategoryIndicatorBackgroundView.h"
#import "JXCategoryFactory.h"
@interface
JXCategoryIndicatorView
()
@property
(
nonatomic
,
strong
)
CALayer
*
backgroundEllipseLayer
;
@end
@implementation
JXCategoryIndicatorView
-
(
void
)
initializeData
{
[
super
initializeData
];
_separatorLineShowEnabled
=
NO
;
_separatorLineColor
=
[
UIColor
lightGrayColor
];
_separatorLineSize
=
CGSizeMake
(
1
/
[
UIScreen
mainScreen
].
scale
,
20
);
_cellBackgroundColorGradientEnabled
=
NO
;
_cellBackgroundUnselectedColor
=
[
UIColor
whiteColor
];
_cellBackgroundSelectedColor
=
[
UIColor
lightGrayColor
];
}
-
(
void
)
initializeViews
{
[
super
initializeViews
];
}
-
(
void
)
setIndicators
:
(
NSArray
<
UIView
<
JXCategoryIndicatorProtocol
>
*>
*
)
indicators
{
for
(
UIView
*
component
in
self
.
indicators
)
{
//先移除之前的component
[
component
removeFromSuperview
];
}
_indicators
=
indicators
;
for
(
UIView
*
component
in
self
.
indicators
)
{
[
self
.
collectionView
addSubview
:
component
];
}
self
.
collectionView
.
indicators
=
indicators
;
}
-
(
void
)
refreshState
{
[
super
refreshState
];
CGRect
selectedCellFrame
=
CGRectZero
;
JXCategoryIndicatorCellModel
*
selectedCellModel
=
nil
;
for
(
int
i
=
0
;
i
<
self
.
dataSource
.
count
;
i
++
)
{
JXCategoryIndicatorCellModel
*
cellModel
=
(
JXCategoryIndicatorCellModel
*
)
self
.
dataSource
[
i
];
cellModel
.
sepratorLineShowEnabled
=
self
.
separatorLineShowEnabled
;
cellModel
.
separatorLineColor
=
self
.
separatorLineColor
;
cellModel
.
separatorLineSize
=
self
.
separatorLineSize
;
cellModel
.
backgroundViewMaskFrame
=
CGRectZero
;
cellModel
.
cellBackgroundColorGradientEnabled
=
self
.
cellBackgroundColorGradientEnabled
;
cellModel
.
cellBackgroundSelectedColor
=
self
.
cellBackgroundSelectedColor
;
cellModel
.
cellBackgroundUnselectedColor
=
self
.
cellBackgroundUnselectedColor
;
if
(
i
==
self
.
dataSource
.
count
-
1
)
{
cellModel
.
sepratorLineShowEnabled
=
NO
;
}
if
(
i
==
self
.
selectedIndex
)
{
selectedCellModel
=
cellModel
;
cellModel
.
selected
=
YES
;
selectedCellFrame
=
[
self
getTargetCellFrame
:
i
];
}
}
for
(
UIView
<
JXCategoryIndicatorProtocol
>
*
component
in
self
.
indicators
)
{
if
(
self
.
dataSource
.
count
<=
0
)
{
component
.
hidden
=
YES
;
}
else
{
component
.
hidden
=
NO
;
JXCategoryIndicatorParamsModel
*
indicatorParamsModel
=
[[
JXCategoryIndicatorParamsModel
alloc
]
init
];
indicatorParamsModel
.
selectedIndex
=
self
.
selectedIndex
;
indicatorParamsModel
.
selectedCellFrame
=
selectedCellFrame
;
[
component
jx_refreshState
:
indicatorParamsModel
];
if
([
component
isKindOfClass
:[
JXCategoryIndicatorBackgroundView
class
]])
{
CGRect
maskFrame
=
component
.
frame
;
maskFrame
.
origin
.
x
=
maskFrame
.
origin
.
x
-
selectedCellFrame
.
origin
.
x
;
selectedCellModel
.
backgroundViewMaskFrame
=
maskFrame
;
}
}
}
}
-
(
void
)
refreshSelectedCellModel
:
(
JXCategoryBaseCellModel
*
)
selectedCellModel
unselectedCellModel
:
(
JXCategoryBaseCellModel
*
)
unselectedCellModel
{
[
super
refreshSelectedCellModel
:
selectedCellModel
unselectedCellModel
:
unselectedCellModel
];
JXCategoryIndicatorCellModel
*
myUnselectedCellModel
=
(
JXCategoryIndicatorCellModel
*
)
unselectedCellModel
;
myUnselectedCellModel
.
backgroundViewMaskFrame
=
CGRectZero
;
myUnselectedCellModel
.
cellBackgroundUnselectedColor
=
self
.
cellBackgroundUnselectedColor
;
myUnselectedCellModel
.
cellBackgroundSelectedColor
=
self
.
cellBackgroundSelectedColor
;
JXCategoryIndicatorCellModel
*
myselectedCellModel
=
(
JXCategoryIndicatorCellModel
*
)
selectedCellModel
;
myselectedCellModel
.
cellBackgroundUnselectedColor
=
self
.
cellBackgroundUnselectedColor
;
myselectedCellModel
.
cellBackgroundSelectedColor
=
self
.
cellBackgroundSelectedColor
;
}
-
(
void
)
contentOffsetOfContentScrollViewDidChanged
:
(
CGPoint
)
contentOffset
{
[
super
contentOffsetOfContentScrollViewDidChanged
:
contentOffset
];
CGFloat
ratio
=
contentOffset
.
x
/
self
.
contentScrollView
.
bounds
.
size
.
width
;
if
(
ratio
>
self
.
dataSource
.
count
-
1
||
ratio
<
0
)
{
//超过了边界,不需要处理
return
;
}
ratio
=
MAX
(
0
,
MIN
(
self
.
dataSource
.
count
-
1
,
ratio
));
NSInteger
baseIndex
=
floorf
(
ratio
);
if
(
baseIndex
+
1
>=
self
.
dataSource
.
count
)
{
//右边越界了,不需要处理
return
;
}
CGFloat
remainderRatio
=
ratio
-
baseIndex
;
CGRect
leftCellFrame
=
[
self
getTargetCellFrame
:
baseIndex
];
CGRect
rightCellFrame
=
[
self
getTargetCellFrame
:
baseIndex
+
1
];
JXCategoryIndicatorParamsModel
*
indicatorParamsModel
=
[[
JXCategoryIndicatorParamsModel
alloc
]
init
];
indicatorParamsModel
.
selectedIndex
=
self
.
selectedIndex
;
indicatorParamsModel
.
leftIndex
=
baseIndex
;
indicatorParamsModel
.
leftCellFrame
=
leftCellFrame
;
indicatorParamsModel
.
rightIndex
=
baseIndex
+
1
;
indicatorParamsModel
.
rightCellFrame
=
rightCellFrame
;
indicatorParamsModel
.
percent
=
remainderRatio
;
if
(
remainderRatio
==
0
)
{
for
(
UIView
<
JXCategoryIndicatorProtocol
>
*
component
in
self
.
indicators
)
{
[
component
jx_contentScrollViewDidScroll
:
indicatorParamsModel
];
}
}
else
{
JXCategoryIndicatorCellModel
*
leftCellModel
=
(
JXCategoryIndicatorCellModel
*
)
self
.
dataSource
[
baseIndex
];
JXCategoryIndicatorCellModel
*
rightCellModel
=
(
JXCategoryIndicatorCellModel
*
)
self
.
dataSource
[
baseIndex
+
1
];
[
self
refreshLeftCellModel
:
leftCellModel
rightCellModel
:
rightCellModel
ratio
:
remainderRatio
];
for
(
UIView
<
JXCategoryIndicatorProtocol
>
*
component
in
self
.
indicators
)
{
[
component
jx_contentScrollViewDidScroll
:
indicatorParamsModel
];
if
([
component
isKindOfClass
:[
JXCategoryIndicatorBackgroundView
class
]])
{
CGRect
leftMaskFrame
=
component
.
frame
;
leftMaskFrame
.
origin
.
x
=
leftMaskFrame
.
origin
.
x
-
leftCellFrame
.
origin
.
x
;
leftCellModel
.
backgroundViewMaskFrame
=
leftMaskFrame
;
CGRect
rightMaskFrame
=
component
.
frame
;
rightMaskFrame
.
origin
.
x
=
rightMaskFrame
.
origin
.
x
-
rightCellFrame
.
origin
.
x
;
rightCellModel
.
backgroundViewMaskFrame
=
rightMaskFrame
;
}
}
JXCategoryBaseCell
*
leftCell
=
(
JXCategoryBaseCell
*
)[
self
.
collectionView
cellForItemAtIndexPath
:[
NSIndexPath
indexPathForItem
:
baseIndex
inSection
:
0
]];
[
leftCell
reloadData
:
leftCellModel
];
JXCategoryBaseCell
*
rightCell
=
(
JXCategoryBaseCell
*
)[
self
.
collectionView
cellForItemAtIndexPath
:[
NSIndexPath
indexPathForItem
:
baseIndex
+
1
inSection
:
0
]];
[
rightCell
reloadData
:
rightCellModel
];
}
}
-
(
BOOL
)
selectCellAtIndex
:
(
NSInteger
)
index
isClicked
:
(
BOOL
)
isClicked
{
NSInteger
lastSelectedIndex
=
self
.
selectedIndex
;
BOOL
result
=
[
super
selectCellAtIndex
:
index
isClicked
:
isClicked
];
if
(
!
result
)
{
return
NO
;
}
CGRect
clickedCellFrame
=
[
self
getTargetCellFrame
:
index
];
JXCategoryIndicatorCellModel
*
selectedCellModel
=
(
JXCategoryIndicatorCellModel
*
)
self
.
dataSource
[
index
];
for
(
UIView
<
JXCategoryIndicatorProtocol
>
*
component
in
self
.
indicators
)
{
JXCategoryIndicatorParamsModel
*
indicatorParamsModel
=
[[
JXCategoryIndicatorParamsModel
alloc
]
init
];
indicatorParamsModel
.
lastSelectedIndex
=
lastSelectedIndex
;
indicatorParamsModel
.
selectedIndex
=
index
;
indicatorParamsModel
.
selectedCellFrame
=
clickedCellFrame
;
indicatorParamsModel
.
isClicked
=
isClicked
;
[
component
jx_selectedCell
:
indicatorParamsModel
];
if
([
component
isKindOfClass
:[
JXCategoryIndicatorBackgroundView
class
]])
{
CGRect
maskFrame
=
component
.
frame
;
maskFrame
.
origin
.
x
=
maskFrame
.
origin
.
x
-
clickedCellFrame
.
origin
.
x
;
selectedCellModel
.
backgroundViewMaskFrame
=
maskFrame
;
}
}
JXCategoryIndicatorCell
*
selectedCell
=
(
JXCategoryIndicatorCell
*
)[
self
.
collectionView
cellForItemAtIndexPath
:[
NSIndexPath
indexPathForItem
:
index
inSection
:
0
]];
[
selectedCell
reloadData
:
selectedCellModel
];
return
YES
;
}
-
(
void
)
refreshLeftCellModel
:
(
JXCategoryBaseCellModel
*
)
leftCellModel
rightCellModel
:
(
JXCategoryBaseCellModel
*
)
rightCellModel
ratio
:
(
CGFloat
)
ratio
{
if
(
self
.
cellBackgroundColorGradientEnabled
)
{
//处理cell背景色渐变
JXCategoryIndicatorCellModel
*
leftModel
=
(
JXCategoryIndicatorCellModel
*
)
leftCellModel
;
JXCategoryIndicatorCellModel
*
rightModel
=
(
JXCategoryIndicatorCellModel
*
)
rightCellModel
;
if
(
leftModel
.
selected
)
{
leftModel
.
cellBackgroundSelectedColor
=
[
JXCategoryFactory
interpolationColorFrom
:
self
.
cellBackgroundSelectedColor
to
:
self
.
cellBackgroundUnselectedColor
percent
:
ratio
];
leftModel
.
cellBackgroundUnselectedColor
=
self
.
cellBackgroundUnselectedColor
;
}
else
{
leftModel
.
cellBackgroundUnselectedColor
=
[
JXCategoryFactory
interpolationColorFrom
:
self
.
cellBackgroundSelectedColor
to
:
self
.
cellBackgroundUnselectedColor
percent
:
ratio
];
leftModel
.
cellBackgroundSelectedColor
=
self
.
cellBackgroundSelectedColor
;
}
if
(
rightModel
.
selected
)
{
rightModel
.
cellBackgroundSelectedColor
=
[
JXCategoryFactory
interpolationColorFrom
:
self
.
cellBackgroundUnselectedColor
to
:
self
.
cellBackgroundSelectedColor
percent
:
ratio
];
rightModel
.
cellBackgroundUnselectedColor
=
self
.
cellBackgroundUnselectedColor
;
}
else
{
rightModel
.
cellBackgroundUnselectedColor
=
[
JXCategoryFactory
interpolationColorFrom
:
self
.
cellBackgroundUnselectedColor
to
:
self
.
cellBackgroundSelectedColor
percent
:
ratio
];
rightModel
.
cellBackgroundSelectedColor
=
self
.
cellBackgroundSelectedColor
;
}
}
}
@end
GMBase/Classes/JXPagerView/JXCategoryView/JXCategoryView.h
deleted
100755 → 0
View file @
1826794b
#import "JXCategoryBaseView.h"
#import "JXCategoryIndicatorView.h"
#import "JXCategoryTitleView.h"
#import "JXCategoryImageView.h"
#import "JXCategoryTitleImageView.h"
#import "JXCategoryNumberView.h"
#import "JXCategoryDotView.h"
#import "JXCategoryFactory.h"
#import "JXCategoryIndicatorProtocol.h"
#import "JXCategoryViewDefines.h"
#import "JXCategoryListVCContainerView.h"
#import "JXCategoryListContainerView.h"
#import "JXCategoryIndicatorComponentView.h"
#import "JXCategoryIndicatorLineView.h"
#import "JXCategoryIndicatorTriangleView.h"
#import "JXCategoryIndicatorImageView.h"
#import "JXCategoryIndicatorBackgroundView.h"
#import "JXCategoryIndicatorBallView.h"
#import "JXCategoryIndicatorRainbowLineView.h"
GMBase/Classes/JXPagerView/JXCategoryView/Number/JXCategoryNumberCell.h
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryNumberCell.h
// DQGuess
//
// Created by jiaxin on 2018/4/9.
// Copyright © 2018年 jingbo. All rights reserved.
//
#import "JXCategoryTitleCell.h"
@interface
JXCategoryNumberCell
:
JXCategoryTitleCell
@property
(
nonatomic
,
strong
)
UILabel
*
numberLabel
;
@end
GMBase/Classes/JXPagerView/JXCategoryView/Number/JXCategoryNumberCell.m
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryNumberCell.m
// DQGuess
//
// Created by jiaxin on 2018/4/9.
// Copyright © 2018年 jingbo. All rights reserved.
//
#import "JXCategoryNumberCell.h"
#import "JXCategoryNumberCellModel.h"
@interface
JXCategoryNumberCell
()
@end
@implementation
JXCategoryNumberCell
-
(
void
)
initializeViews
{
[
super
initializeViews
];
self
.
numberLabel
=
({
UILabel
*
label
=
[[
UILabel
alloc
]
init
];
label
.
textAlignment
=
NSTextAlignmentCenter
;
label
.
layer
.
masksToBounds
=
YES
;
label
;
});
[
self
.
contentView
addSubview
:
self
.
numberLabel
];
}
-
(
void
)
layoutSubviews
{
[
super
layoutSubviews
];
[
self
.
numberLabel
sizeToFit
];
JXCategoryNumberCellModel
*
myCellModel
=
(
JXCategoryNumberCellModel
*
)
self
.
cellModel
;
self
.
numberLabel
.
bounds
=
CGRectMake
(
0
,
0
,
self
.
numberLabel
.
bounds
.
size
.
width
+
myCellModel
.
numberLabelWidthIncrement
,
myCellModel
.
numberLabelHeight
);
self
.
numberLabel
.
layer
.
cornerRadius
=
myCellModel
.
numberLabelHeight
/
2
.
0
;
self
.
numberLabel
.
center
=
CGPointMake
(
CGRectGetMaxX
(
self
.
titleLabel
.
frame
),
CGRectGetMinY
(
self
.
titleLabel
.
frame
));
}
-
(
void
)
reloadData
:
(
JXCategoryBaseCellModel
*
)
cellModel
{
[
super
reloadData
:
cellModel
];
JXCategoryNumberCellModel
*
myCellModel
=
(
JXCategoryNumberCellModel
*
)
cellModel
;
self
.
numberLabel
.
hidden
=
myCellModel
.
count
==
0
;
self
.
numberLabel
.
backgroundColor
=
myCellModel
.
numberBackgroundColor
;
self
.
numberLabel
.
font
=
myCellModel
.
numberLabelFont
;
self
.
numberLabel
.
textColor
=
myCellModel
.
numberTitleColor
;
self
.
numberLabel
.
text
=
[
NSString
stringWithFormat
:
@"%ld"
,
(
long
)
myCellModel
.
count
];
if
(
myCellModel
.
count
>=
1000
)
{
self
.
numberLabel
.
text
=
@"999+"
;
}
[
self
setNeedsLayout
];
[
self
layoutIfNeeded
];
}
@end
GMBase/Classes/JXPagerView/JXCategoryView/Number/JXCategoryNumberCellModel.h
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryNumberCellModel.h
// DQGuess
//
// Created by jiaxin on 2018/4/24.
// Copyright © 2018年 jingbo. All rights reserved.
//
#import "JXCategoryTitleCellModel.h"
@interface
JXCategoryNumberCellModel
:
JXCategoryTitleCellModel
@property
(
nonatomic
,
assign
)
NSInteger
count
;
@property
(
nonatomic
,
strong
)
UIColor
*
numberBackgroundColor
;
@property
(
nonatomic
,
strong
)
UIColor
*
numberTitleColor
;
@property
(
nonatomic
,
assign
)
CGFloat
numberLabelWidthIncrement
;
@property
(
nonatomic
,
assign
)
CGFloat
numberLabelHeight
;
@property
(
nonatomic
,
strong
)
UIFont
*
numberLabelFont
;
@end
GMBase/Classes/JXPagerView/JXCategoryView/Number/JXCategoryNumberCellModel.m
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryNumberCellModel.m
// DQGuess
//
// Created by jiaxin on 2018/4/24.
// Copyright © 2018年 jingbo. All rights reserved.
//
#import "JXCategoryNumberCellModel.h"
@implementation
JXCategoryNumberCellModel
@end
GMBase/Classes/JXPagerView/JXCategoryView/Number/JXCategoryNumberView.h
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryNumberView.h
// DQGuess
//
// Created by jiaxin on 2018/4/9.
// Copyright © 2018年 jingbo. All rights reserved.
//
#import "JXCategoryTitleView.h"
#import "JXCategoryNumberCell.h"
#import "JXCategoryNumberCellModel.h"
@interface
JXCategoryNumberView
:
JXCategoryTitleView
/**
需要与titles的count对应
*/
@property
(
nonatomic
,
strong
)
NSArray
<
NSNumber
*>
*
counts
;
/**
numberLabel的font,默认:[UIFont systemFontOfSize:11]
*/
@property
(
nonatomic
,
strong
)
UIFont
*
numberLabelFont
;
/**
数字的背景色,默认:[UIColor colorWithRed:241/255.0 green:147/255.0 blue:95/255.0 alpha:1]
*/
@property
(
nonatomic
,
strong
)
UIColor
*
numberBackgroundColor
;
/**
数字的title颜色,默认:[UIColor whiteColor]
*/
@property
(
nonatomic
,
strong
)
UIColor
*
numberTitleColor
;
/**
numberLabel的宽度补偿,label真实的宽度是文字内容的宽度加上补偿的宽度,默认:10
*/
@property
(
nonatomic
,
assign
)
CGFloat
numberLabelWidthIncrement
;
/**
numberLabel的高度,默认:14
*/
@property
(
nonatomic
,
assign
)
CGFloat
numberLabelHeight
;
@end
GMBase/Classes/JXPagerView/JXCategoryView/Number/JXCategoryNumberView.m
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryNumberView.m
// DQGuess
//
// Created by jiaxin on 2018/4/9.
// Copyright © 2018年 jingbo. All rights reserved.
//
#import "JXCategoryNumberView.h"
@implementation
JXCategoryNumberView
-
(
void
)
initializeData
{
[
super
initializeData
];
self
.
cellSpacing
=
25
;
_numberTitleColor
=
[
UIColor
whiteColor
];
_numberBackgroundColor
=
[
UIColor
colorWithRed
:
241
/
255
.
0
green
:
147
/
255
.
0
blue
:
95
/
255
.
0
alpha
:
1
];
_numberLabelHeight
=
14
;
_numberLabelWidthIncrement
=
10
;
_numberLabelFont
=
[
UIFont
systemFontOfSize
:
11
];
}
-
(
Class
)
preferredCellClass
{
return
[
JXCategoryNumberCell
class
];
}
-
(
void
)
refreshDataSource
{
NSMutableArray
*
tempArray
=
[
NSMutableArray
array
];
for
(
int
i
=
0
;
i
<
self
.
titles
.
count
;
i
++
)
{
JXCategoryNumberCellModel
*
cellModel
=
[[
JXCategoryNumberCellModel
alloc
]
init
];
[
tempArray
addObject
:
cellModel
];
}
self
.
dataSource
=
tempArray
;
}
-
(
void
)
refreshCellModel
:
(
JXCategoryBaseCellModel
*
)
cellModel
index
:
(
NSInteger
)
index
{
[
super
refreshCellModel
:
cellModel
index
:
index
];
JXCategoryNumberCellModel
*
myCellModel
=
(
JXCategoryNumberCellModel
*
)
cellModel
;
myCellModel
.
count
=
[
self
.
counts
[
index
]
integerValue
];
myCellModel
.
numberBackgroundColor
=
self
.
numberBackgroundColor
;
myCellModel
.
numberTitleColor
=
self
.
numberTitleColor
;
myCellModel
.
numberLabelHeight
=
self
.
numberLabelHeight
;
myCellModel
.
numberLabelWidthIncrement
=
self
.
numberLabelWidthIncrement
;
myCellModel
.
numberLabelFont
=
self
.
numberLabelFont
;
}
@end
GMBase/Classes/JXPagerView/JXCategoryView/Title/JXCategoryTitleCell.h
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryTitleCell.h
// UI系列测试
//
// Created by jiaxin on 2018/3/15.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryIndicatorCell.h"
@interface
JXCategoryTitleCell
:
JXCategoryIndicatorCell
@property
(
nonatomic
,
strong
)
UILabel
*
titleLabel
;
@property
(
nonatomic
,
strong
)
UILabel
*
maskTitleLabel
;
@end
GMBase/Classes/JXPagerView/JXCategoryView/Title/JXCategoryTitleCell.m
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryTitleCell.m
// UI系列测试
//
// Created by jiaxin on 2018/3/15.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryTitleCell.h"
#import "JXCategoryTitleCellModel.h"
@interface
JXCategoryTitleCell
()
@property
(
nonatomic
,
strong
)
CALayer
*
maskLayer
;
@end
@implementation
JXCategoryTitleCell
-
(
void
)
initializeViews
{
[
super
initializeViews
];
_titleLabel
=
[[
UILabel
alloc
]
init
];
self
.
titleLabel
.
textAlignment
=
NSTextAlignmentCenter
;
[
self
.
contentView
addSubview
:
self
.
titleLabel
];
_maskTitleLabel
=
[[
UILabel
alloc
]
init
];
_maskTitleLabel
.
hidden
=
YES
;
self
.
maskTitleLabel
.
textAlignment
=
NSTextAlignmentCenter
;
[
self
.
contentView
addSubview
:
self
.
maskTitleLabel
];
_maskLayer
=
[
CALayer
layer
];
self
.
maskLayer
.
backgroundColor
=
[
UIColor
redColor
].
CGColor
;
self
.
maskTitleLabel
.
layer
.
mask
=
self
.
maskLayer
;
}
-
(
void
)
layoutSubviews
{
[
super
layoutSubviews
];
self
.
titleLabel
.
center
=
self
.
contentView
.
center
;
self
.
maskTitleLabel
.
center
=
self
.
contentView
.
center
;
}
-
(
void
)
reloadData
:
(
JXCategoryBaseCellModel
*
)
cellModel
{
[
super
reloadData
:
cellModel
];
JXCategoryTitleCellModel
*
myCellModel
=
(
JXCategoryTitleCellModel
*
)
cellModel
;
CGFloat
pointSize
=
myCellModel
.
titleFont
.
pointSize
;
UIFontDescriptor
*
fontDescriptor
=
myCellModel
.
titleFont
.
fontDescriptor
;
if
(
myCellModel
.
selected
)
{
fontDescriptor
=
myCellModel
.
titleSelectedFont
.
fontDescriptor
;
pointSize
=
myCellModel
.
titleSelectedFont
.
pointSize
;
}
if
(
myCellModel
.
titleLabelZoomEnabled
)
{
self
.
titleLabel
.
font
=
[
UIFont
fontWithDescriptor
:
fontDescriptor
size
:
pointSize
*
myCellModel
.
titleLabelZoomScale
];
self
.
maskTitleLabel
.
font
=
[
UIFont
fontWithDescriptor
:
fontDescriptor
size
:
pointSize
*
myCellModel
.
titleLabelZoomScale
];
}
else
{
self
.
titleLabel
.
font
=
[
UIFont
fontWithDescriptor
:
fontDescriptor
size
:
pointSize
];
self
.
maskTitleLabel
.
font
=
[
UIFont
fontWithDescriptor
:
fontDescriptor
size
:
pointSize
];
}
NSString
*
titleString
=
myCellModel
.
title
?
myCellModel
.
title
:
@""
;
NSMutableAttributedString
*
attriString
=
[[
NSMutableAttributedString
alloc
]
initWithString
:
titleString
];
if
(
myCellModel
.
titleLabelStrokeWidthEnabled
)
{
[
attriString
addAttribute
:
NSStrokeWidthAttributeName
value
:
@
(
myCellModel
.
titleLabelSelectedStrokeWidth
)
range
:
NSMakeRange
(
0
,
myCellModel
.
title
.
length
)];
}
self
.
maskTitleLabel
.
hidden
=
!
myCellModel
.
titleLabelMaskEnabled
;
if
(
myCellModel
.
titleLabelMaskEnabled
)
{
self
.
titleLabel
.
textColor
=
myCellModel
.
titleColor
;
self
.
maskTitleLabel
.
font
=
myCellModel
.
titleFont
;
self
.
maskTitleLabel
.
textColor
=
myCellModel
.
titleSelectedColor
;
self
.
maskTitleLabel
.
attributedText
=
attriString
;
[
self
.
maskTitleLabel
sizeToFit
];
CGRect
frame
=
myCellModel
.
backgroundViewMaskFrame
;
frame
.
origin
.
x
-=
(
self
.
contentView
.
bounds
.
size
.
width
-
self
.
maskTitleLabel
.
bounds
.
size
.
width
)
/
2
;
frame
.
origin
.
y
=
0
;
[
CATransaction
begin
];
[
CATransaction
setDisableActions
:
YES
];
self
.
maskLayer
.
frame
=
frame
;
[
CATransaction
commit
];
}
else
{
if
(
myCellModel
.
selected
)
{
self
.
titleLabel
.
textColor
=
myCellModel
.
titleSelectedColor
;
}
else
{
self
.
titleLabel
.
textColor
=
myCellModel
.
titleColor
;
}
}
self
.
titleLabel
.
attributedText
=
attriString
;
[
self
.
titleLabel
sizeToFit
];
[
self
setNeedsLayout
];
[
self
layoutIfNeeded
];
}
@end
GMBase/Classes/JXPagerView/JXCategoryView/Title/JXCategoryTitleCellModel.h
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryTitleCellModel.h
// UI系列测试
//
// Created by jiaxin on 2018/3/15.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryIndicatorCellModel.h"
#import <UIKit/UIKit.h>
@interface
JXCategoryTitleCellModel
:
JXCategoryIndicatorCellModel
@property
(
nonatomic
,
copy
)
NSString
*
title
;
@property
(
nonatomic
,
strong
)
UIColor
*
titleColor
;
@property
(
nonatomic
,
strong
)
UIColor
*
titleSelectedColor
;
@property
(
nonatomic
,
strong
)
UIFont
*
titleFont
;
@property
(
nonatomic
,
strong
)
UIFont
*
titleSelectedFont
;
@property
(
nonatomic
,
assign
)
BOOL
titleLabelMaskEnabled
;
@property
(
nonatomic
,
strong
)
CALayer
*
backgroundEllipseLayer
;
@property
(
nonatomic
,
assign
)
BOOL
titleLabelZoomEnabled
;
@property
(
nonatomic
,
assign
)
CGFloat
titleLabelZoomScale
;
@property
(
nonatomic
,
assign
)
CGFloat
titleLabelStrokeWidthEnabled
;
@property
(
nonatomic
,
assign
)
CGFloat
titleLabelSelectedStrokeWidth
;
@end
GMBase/Classes/JXPagerView/JXCategoryView/Title/JXCategoryTitleCellModel.m
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryTitleCellModel.m
// UI系列测试
//
// Created by jiaxin on 2018/3/15.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryTitleCellModel.h"
@implementation
JXCategoryTitleCellModel
@end
GMBase/Classes/JXPagerView/JXCategoryView/Title/JXCategoryTitleView.h
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryView.h
// UI系列测试
//
// Created by jiaxin on 2018/3/15.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryIndicatorView.h"
#import "JXCategoryTitleCell.h"
#import "JXCategoryTitleCellModel.h"
@interface
JXCategoryTitleView
:
JXCategoryIndicatorView
@property
(
nonatomic
,
strong
)
NSArray
<
NSString
*>*
titles
;
@property
(
nonatomic
,
strong
)
UIColor
*
titleColor
;
//默认:[UIColor blackColor]
@property
(
nonatomic
,
strong
)
UIColor
*
titleSelectedColor
;
//默认:[UIColor redColor]
@property
(
nonatomic
,
strong
)
UIFont
*
titleFont
;
//默认:[UIFont systemFontOfSize:15]
@property
(
nonatomic
,
strong
)
UIFont
*
titleSelectedFont
;
//文字被选中的字体。默认:与titleFont一样
@property
(
nonatomic
,
assign
)
BOOL
titleColorGradientEnabled
;
//默认:NO,title的颜色是否渐变过渡
@property
(
nonatomic
,
assign
)
BOOL
titleLabelMaskEnabled
;
//默认:NO,titleLabel是否遮罩过滤。(需要backgroundEllipseLayerShowEnabled = YES)
//----------------------titleLabelZoomEnabled-----------------------//
@property
(
nonatomic
,
assign
)
BOOL
titleLabelZoomEnabled
;
//默认为NO
@property
(
nonatomic
,
assign
)
BOOL
titleLabelZoomScrollGradientEnabled
;
//手势滚动中,是否需要更新状态。默认为YES
@property
(
nonatomic
,
assign
)
CGFloat
titleLabelZoomScale
;
//默认1.2,titleLabelZoomEnabled为YES才生效
//----------------------titleLabelStrokeWidth-----------------------//
@property
(
nonatomic
,
assign
)
CGFloat
titleLabelStrokeWidthEnabled
;
//默认:NO
@property
(
nonatomic
,
assign
)
CGFloat
titleLabelSelectedStrokeWidth
;
//默认:-3,用于控制字体的粗细(底层通过NSStrokeWidthAttributeName实现)。使用该属性,务必让titleFont和titleSelectedFont设置为一样的!!!
@end
GMBase/Classes/JXPagerView/JXCategoryView/Title/JXCategoryTitleView.m
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryView.m
// UI系列测试
//
// Created by jiaxin on 2018/3/15.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryTitleView.h"
#import "JXCategoryFactory.h"
@interface
JXCategoryTitleView
()
@end
@implementation
JXCategoryTitleView
-
(
void
)
initializeData
{
[
super
initializeData
];
_titleLabelZoomEnabled
=
NO
;
_titleLabelZoomScale
=
1
.
2
;
_titleColor
=
[
UIColor
blackColor
];
_titleSelectedColor
=
[
UIColor
redColor
];
_titleFont
=
[
UIFont
systemFontOfSize
:
15
];
_titleColorGradientEnabled
=
NO
;
_titleLabelMaskEnabled
=
NO
;
_titleLabelZoomScrollGradientEnabled
=
YES
;
_titleLabelStrokeWidthEnabled
=
NO
;
_titleLabelSelectedStrokeWidth
=
-
3
;
}
-
(
UIFont
*
)
titleSelectedFont
{
if
(
_titleSelectedFont
!=
nil
)
{
return
_titleSelectedFont
;
}
return
self
.
titleFont
;
}
#pragma mark - Override
-
(
Class
)
preferredCellClass
{
return
[
JXCategoryTitleCell
class
];
}
-
(
void
)
refreshDataSource
{
NSMutableArray
*
tempArray
=
[
NSMutableArray
array
];
for
(
int
i
=
0
;
i
<
self
.
titles
.
count
;
i
++
)
{
JXCategoryTitleCellModel
*
cellModel
=
[[
JXCategoryTitleCellModel
alloc
]
init
];
[
tempArray
addObject
:
cellModel
];
}
self
.
dataSource
=
tempArray
;
}
-
(
void
)
refreshSelectedCellModel
:
(
JXCategoryBaseCellModel
*
)
selectedCellModel
unselectedCellModel
:
(
JXCategoryBaseCellModel
*
)
unselectedCellModel
{
[
super
refreshSelectedCellModel
:
selectedCellModel
unselectedCellModel
:
unselectedCellModel
];
JXCategoryTitleCellModel
*
myUnselectedCellModel
=
(
JXCategoryTitleCellModel
*
)
unselectedCellModel
;
myUnselectedCellModel
.
titleColor
=
self
.
titleColor
;
myUnselectedCellModel
.
titleSelectedColor
=
self
.
titleSelectedColor
;
myUnselectedCellModel
.
titleLabelZoomScale
=
1
.
0
;
myUnselectedCellModel
.
titleLabelSelectedStrokeWidth
=
0
;
JXCategoryTitleCellModel
*
myselectedCellModel
=
(
JXCategoryTitleCellModel
*
)
selectedCellModel
;
myselectedCellModel
.
titleColor
=
self
.
titleColor
;
myselectedCellModel
.
titleSelectedColor
=
self
.
titleSelectedColor
;
myselectedCellModel
.
titleLabelZoomScale
=
self
.
titleLabelZoomScale
;
myselectedCellModel
.
titleLabelSelectedStrokeWidth
=
self
.
titleLabelSelectedStrokeWidth
;
}
-
(
void
)
refreshLeftCellModel
:
(
JXCategoryBaseCellModel
*
)
leftCellModel
rightCellModel
:
(
JXCategoryBaseCellModel
*
)
rightCellModel
ratio
:
(
CGFloat
)
ratio
{
[
super
refreshLeftCellModel
:
leftCellModel
rightCellModel
:
rightCellModel
ratio
:
ratio
];
JXCategoryTitleCellModel
*
leftModel
=
(
JXCategoryTitleCellModel
*
)
leftCellModel
;
JXCategoryTitleCellModel
*
rightModel
=
(
JXCategoryTitleCellModel
*
)
rightCellModel
;
if
(
self
.
titleLabelZoomEnabled
&&
self
.
titleLabelZoomScrollGradientEnabled
)
{
leftModel
.
titleLabelZoomScale
=
[
JXCategoryFactory
interpolationFrom
:
self
.
titleLabelZoomScale
to
:
1
.
0
percent
:
ratio
];
rightModel
.
titleLabelZoomScale
=
[
JXCategoryFactory
interpolationFrom
:
1
.
0
to
:
self
.
titleLabelZoomScale
percent
:
ratio
];
}
if
(
self
.
titleLabelStrokeWidthEnabled
)
{
leftModel
.
titleLabelSelectedStrokeWidth
=
[
JXCategoryFactory
interpolationFrom
:
self
.
titleLabelSelectedStrokeWidth
to
:
0
percent
:
ratio
];
rightModel
.
titleLabelSelectedStrokeWidth
=
[
JXCategoryFactory
interpolationFrom
:
0
to
:
self
.
titleLabelSelectedStrokeWidth
percent
:
ratio
];
}
if
(
self
.
titleColorGradientEnabled
)
{
//处理颜色渐变
if
(
leftModel
.
selected
)
{
leftModel
.
titleSelectedColor
=
[
JXCategoryFactory
interpolationColorFrom
:
self
.
titleSelectedColor
to
:
self
.
titleColor
percent
:
ratio
];
leftModel
.
titleColor
=
self
.
titleColor
;
}
else
{
leftModel
.
titleColor
=
[
JXCategoryFactory
interpolationColorFrom
:
self
.
titleSelectedColor
to
:
self
.
titleColor
percent
:
ratio
];
leftModel
.
titleSelectedColor
=
self
.
titleSelectedColor
;
}
if
(
rightModel
.
selected
)
{
rightModel
.
titleSelectedColor
=
[
JXCategoryFactory
interpolationColorFrom
:
self
.
titleColor
to
:
self
.
titleSelectedColor
percent
:
ratio
];
rightModel
.
titleColor
=
self
.
titleColor
;
}
else
{
rightModel
.
titleColor
=
[
JXCategoryFactory
interpolationColorFrom
:
self
.
titleColor
to
:
self
.
titleSelectedColor
percent
:
ratio
];
rightModel
.
titleSelectedColor
=
self
.
titleSelectedColor
;
}
}
}
-
(
CGFloat
)
preferredCellWidthAtIndex
:
(
NSInteger
)
index
{
if
(
self
.
cellWidth
==
JXCategoryViewAutomaticDimension
)
{
return
ceilf
([
self
.
titles
[
index
]
boundingRectWithSize
:
CGSizeMake
(
MAXFLOAT
,
self
.
bounds
.
size
.
height
)
options
:
NSStringDrawingUsesLineFragmentOrigin
|
NSStringDrawingUsesFontLeading
attributes
:
@{
NSFontAttributeName
:
self
.
titleFont
}
context
:
nil
].
size
.
width
);
}
else
{
return
self
.
cellWidth
;
}
}
-
(
void
)
refreshCellModel
:
(
JXCategoryBaseCellModel
*
)
cellModel
index
:
(
NSInteger
)
index
{
[
super
refreshCellModel
:
cellModel
index
:
index
];
JXCategoryTitleCellModel
*
model
=
(
JXCategoryTitleCellModel
*
)
cellModel
;
model
.
titleFont
=
self
.
titleFont
;
model
.
titleSelectedFont
=
self
.
titleSelectedFont
;
model
.
titleColor
=
self
.
titleColor
;
model
.
titleSelectedColor
=
self
.
titleSelectedColor
;
model
.
title
=
self
.
titles
[
index
];
model
.
titleLabelMaskEnabled
=
self
.
titleLabelMaskEnabled
;
model
.
titleLabelZoomEnabled
=
self
.
titleLabelZoomEnabled
;
model
.
titleLabelZoomScale
=
1
.
0
;
model
.
titleLabelStrokeWidthEnabled
=
self
.
titleLabelStrokeWidthEnabled
;
model
.
titleLabelSelectedStrokeWidth
=
0
;
if
(
index
==
self
.
selectedIndex
)
{
model
.
titleLabelZoomScale
=
self
.
titleLabelZoomScale
;
model
.
titleLabelSelectedStrokeWidth
=
self
.
titleLabelSelectedStrokeWidth
;
}
}
@end
GMBase/Classes/JXPagerView/JXCategoryView/Title/TitleImage/JXCategoryTitleImageCell.h
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryImageCell.h
// JXCategoryView
//
// Created by jiaxin on 2018/8/8.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryTitleCell.h"
@interface
JXCategoryTitleImageCell
:
JXCategoryTitleCell
@property
(
nonatomic
,
strong
)
UIImageView
*
imageView
;
@end
GMBase/Classes/JXPagerView/JXCategoryView/Title/TitleImage/JXCategoryTitleImageCell.m
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryImageCell.m
// JXCategoryView
//
// Created by jiaxin on 2018/8/8.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryTitleImageCell.h"
#import "JXCategoryTitleImageCellModel.h"
@interface
JXCategoryTitleImageCell
()
@end
@implementation
JXCategoryTitleImageCell
-
(
void
)
initializeViews
{
[
super
initializeViews
];
_imageView
=
[[
UIImageView
alloc
]
init
];
_imageView
.
contentMode
=
UIViewContentModeScaleAspectFit
;
[
self
.
contentView
addSubview
:
_imageView
];
}
-
(
void
)
layoutSubviews
{
[
super
layoutSubviews
];
JXCategoryTitleImageCellModel
*
myCellModel
=
(
JXCategoryTitleImageCellModel
*
)
self
.
cellModel
;
self
.
titleLabel
.
hidden
=
NO
;
self
.
imageView
.
hidden
=
NO
;
CGSize
imageSize
=
myCellModel
.
imageSize
;
self
.
imageView
.
bounds
=
CGRectMake
(
0
,
0
,
imageSize
.
width
,
imageSize
.
height
);
switch
(
myCellModel
.
imageType
)
{
case
JXCategoryTitleImageType_TopImage
:
{
CGFloat
contentHeight
=
imageSize
.
height
+
myCellModel
.
titleImageSpacing
+
self
.
titleLabel
.
bounds
.
size
.
height
;
self
.
imageView
.
center
=
CGPointMake
(
self
.
contentView
.
center
.
x
,
(
self
.
contentView
.
bounds
.
size
.
height
-
contentHeight
)
/
2
+
imageSize
.
height
/
2
);
self
.
titleLabel
.
center
=
CGPointMake
(
self
.
contentView
.
center
.
x
,
CGRectGetMaxY
(
self
.
imageView
.
frame
)
+
myCellModel
.
titleImageSpacing
+
self
.
titleLabel
.
bounds
.
size
.
height
/
2
);
}
break
;
case
JXCategoryTitleImageType_LeftImage
:
{
CGFloat
contentWidth
=
imageSize
.
width
+
myCellModel
.
titleImageSpacing
+
self
.
titleLabel
.
bounds
.
size
.
width
;
self
.
imageView
.
center
=
CGPointMake
((
self
.
contentView
.
bounds
.
size
.
width
-
contentWidth
)
/
2
+
imageSize
.
width
/
2
,
self
.
contentView
.
center
.
y
);
self
.
titleLabel
.
center
=
CGPointMake
(
CGRectGetMaxX
(
self
.
imageView
.
frame
)
+
myCellModel
.
titleImageSpacing
+
self
.
titleLabel
.
bounds
.
size
.
width
/
2
,
self
.
contentView
.
center
.
y
);
}
break
;
case
JXCategoryTitleImageType_BottomImage
:
{
CGFloat
contentHeight
=
imageSize
.
height
+
myCellModel
.
titleImageSpacing
+
self
.
titleLabel
.
bounds
.
size
.
height
;
self
.
titleLabel
.
center
=
CGPointMake
(
self
.
contentView
.
center
.
x
,
(
self
.
contentView
.
bounds
.
size
.
height
-
contentHeight
)
/
2
+
self
.
titleLabel
.
bounds
.
size
.
height
/
2
);
self
.
imageView
.
center
=
CGPointMake
(
self
.
contentView
.
center
.
x
,
CGRectGetMaxY
(
self
.
titleLabel
.
frame
)
+
myCellModel
.
titleImageSpacing
+
imageSize
.
height
/
2
);
}
break
;
case
JXCategoryTitleImageType_RightImage
:
{
CGFloat
contentWidth
=
imageSize
.
width
+
myCellModel
.
titleImageSpacing
+
self
.
titleLabel
.
bounds
.
size
.
width
;
self
.
titleLabel
.
center
=
CGPointMake
((
self
.
contentView
.
bounds
.
size
.
width
-
contentWidth
)
/
2
+
self
.
titleLabel
.
bounds
.
size
.
width
/
2
,
self
.
contentView
.
center
.
y
);
self
.
imageView
.
center
=
CGPointMake
(
CGRectGetMaxX
(
self
.
titleLabel
.
frame
)
+
myCellModel
.
titleImageSpacing
+
imageSize
.
width
/
2
,
self
.
contentView
.
center
.
y
);
}
break
;
case
JXCategoryTitleImageType_OnlyImage
:
{
self
.
titleLabel
.
hidden
=
YES
;
self
.
imageView
.
center
=
self
.
contentView
.
center
;
}
break
;
case
JXCategoryTitleImageType_OnlyTitle
:
{
self
.
imageView
.
hidden
=
YES
;
self
.
titleLabel
.
center
=
self
.
contentView
.
center
;
}
break
;
default
:
break
;
}
}
-
(
void
)
reloadData
:
(
JXCategoryBaseCellModel
*
)
cellModel
{
[
super
reloadData
:
cellModel
];
JXCategoryTitleImageCellModel
*
myCellModel
=
(
JXCategoryTitleImageCellModel
*
)
cellModel
;
if
(
myCellModel
.
imageName
!=
nil
)
{
self
.
imageView
.
image
=
[
UIImage
imageNamed
:
myCellModel
.
imageName
];
}
else
if
(
myCellModel
.
imageURL
!=
nil
)
{
if
(
myCellModel
.
loadImageCallback
!=
nil
)
{
myCellModel
.
loadImageCallback
(
self
.
imageView
,
myCellModel
.
imageURL
);
}
}
if
(
myCellModel
.
selected
)
{
if
(
myCellModel
.
selectedImageName
!=
nil
)
{
self
.
imageView
.
image
=
[
UIImage
imageNamed
:
myCellModel
.
selectedImageName
];
}
else
if
(
myCellModel
.
selectedImageURL
!=
nil
)
{
if
(
myCellModel
.
loadImageCallback
!=
nil
)
{
myCellModel
.
loadImageCallback
(
self
.
imageView
,
myCellModel
.
selectedImageURL
);
}
}
}
if
(
myCellModel
.
imageZoomEnabled
)
{
self
.
imageView
.
transform
=
CGAffineTransformMakeScale
(
myCellModel
.
imageZoomScale
,
myCellModel
.
imageZoomScale
);
}
else
{
self
.
imageView
.
transform
=
CGAffineTransformIdentity
;
}
[
self
setNeedsLayout
];
[
self
layoutIfNeeded
];
}
@end
GMBase/Classes/JXPagerView/JXCategoryView/Title/TitleImage/JXCategoryTitleImageCellModel.h
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryTitleImageCellModel.h
// JXCategoryView
//
// Created by jiaxin on 2018/8/8.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryTitleCellModel.h"
typedef
NS_ENUM
(
NSUInteger
,
JXCategoryTitleImageType
)
{
JXCategoryTitleImageType_TopImage
=
0
,
JXCategoryTitleImageType_LeftImage
,
JXCategoryTitleImageType_BottomImage
,
JXCategoryTitleImageType_RightImage
,
JXCategoryTitleImageType_OnlyImage
,
JXCategoryTitleImageType_OnlyTitle
,
};
@interface
JXCategoryTitleImageCellModel
:
JXCategoryTitleCellModel
@property
(
nonatomic
,
assign
)
JXCategoryTitleImageType
imageType
;
@property
(
nonatomic
,
copy
)
void
(
^
loadImageCallback
)(
UIImageView
*
imageView
,
NSURL
*
imageURL
);
@property
(
nonatomic
,
copy
)
NSString
*
imageName
;
//加载bundle内的图片
@property
(
nonatomic
,
strong
)
NSURL
*
imageURL
;
//图片URL
@property
(
nonatomic
,
copy
)
NSString
*
selectedImageName
;
@property
(
nonatomic
,
strong
)
NSURL
*
selectedImageURL
;
@property
(
nonatomic
,
assign
)
CGSize
imageSize
;
//默认CGSizeMake(20, 20)
@property
(
nonatomic
,
assign
)
CGFloat
titleImageSpacing
;
//titleLabel和ImageView的间距,默认5
@property
(
nonatomic
,
assign
)
BOOL
imageZoomEnabled
;
@property
(
nonatomic
,
assign
)
CGFloat
imageZoomScale
;
@end
GMBase/Classes/JXPagerView/JXCategoryView/Title/TitleImage/JXCategoryTitleImageCellModel.m
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryTitleImageCellModel.m
// JXCategoryView
//
// Created by jiaxin on 2018/8/8.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryTitleImageCellModel.h"
@implementation
JXCategoryTitleImageCellModel
@end
GMBase/Classes/JXPagerView/JXCategoryView/Title/TitleImage/JXCategoryTitleImageView.h
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryImageView.h
// JXCategoryView
//
// Created by jiaxin on 2018/8/8.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryTitleView.h"
#import "JXCategoryTitleImageCell.h"
#import "JXCategoryTitleImageCellModel.h"
@interface
JXCategoryTitleImageView
:
JXCategoryTitleView
@property
(
nonatomic
,
strong
)
NSArray
<
NSString
*>*
imageNames
;
@property
(
nonatomic
,
strong
)
NSArray
<
NSURL
*>*
imageURLs
;
@property
(
nonatomic
,
strong
)
NSArray
<
NSString
*>*
selectedImageNames
;
@property
(
nonatomic
,
strong
)
NSArray
<
NSURL
*>*
selectedImageURLs
;
@property
(
nonatomic
,
strong
)
NSArray
<
NSNumber
*>
*
imageTypes
;
//默认JXCategoryTitleImageType_LeftImage
@property
(
nonatomic
,
copy
)
void
(
^
loadImageCallback
)(
UIImageView
*
imageView
,
NSURL
*
imageURL
);
//使用imageURL从远端下载图片进行加载,建议使用SDWebImage等第三方库进行下载。
@property
(
nonatomic
,
assign
)
CGSize
imageSize
;
//默认CGSizeMake(20, 20)
@property
(
nonatomic
,
assign
)
CGFloat
titleImageSpacing
;
//titleLabel和ImageView的间距,默认5
@property
(
nonatomic
,
assign
)
BOOL
imageZoomEnabled
;
//默认为NO
@property
(
nonatomic
,
assign
)
CGFloat
imageZoomScale
;
//默认1.2,imageZoomEnabled为YES才生效
@end
GMBase/Classes/JXPagerView/JXCategoryView/Title/TitleImage/JXCategoryTitleImageView.m
deleted
100755 → 0
View file @
1826794b
//
// JXCategoryImageView.m
// JXCategoryView
//
// Created by jiaxin on 2018/8/8.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryTitleImageView.h"
#import "JXCategoryTitleImageCell.h"
#import "JXCategoryTitleImageCellModel.h"
#import "JXCategoryFactory.h"
@implementation
JXCategoryTitleImageView
-
(
void
)
dealloc
{
self
.
loadImageCallback
=
nil
;
}
-
(
void
)
initializeData
{
[
super
initializeData
];
_imageSize
=
CGSizeMake
(
20
,
20
);
_titleImageSpacing
=
5
;
_imageZoomEnabled
=
NO
;
_imageZoomScale
=
1
.
2
;
}
-
(
Class
)
preferredCellClass
{
return
[
JXCategoryTitleImageCell
class
];
}
-
(
void
)
refreshDataSource
{
NSMutableArray
*
tempArray
=
[
NSMutableArray
array
];
for
(
int
i
=
0
;
i
<
self
.
titles
.
count
;
i
++
)
{
JXCategoryTitleImageCellModel
*
cellModel
=
[[
JXCategoryTitleImageCellModel
alloc
]
init
];
[
tempArray
addObject
:
cellModel
];
}
if
(
self
.
imageTypes
==
nil
||
self
.
imageTypes
.
count
==
0
)
{
NSMutableArray
*
types
=
[
NSMutableArray
array
];
for
(
int
i
=
0
;
i
<
self
.
titles
.
count
;
i
++
)
{
[
types
addObject
:
@
(
JXCategoryTitleImageType_LeftImage
)];
}
self
.
imageTypes
=
types
;
}
self
.
dataSource
=
tempArray
;
}
-
(
void
)
refreshCellModel
:
(
JXCategoryBaseCellModel
*
)
cellModel
index
:
(
NSInteger
)
index
{
[
super
refreshCellModel
:
cellModel
index
:
index
];
JXCategoryTitleImageCellModel
*
myCellModel
=
(
JXCategoryTitleImageCellModel
*
)
cellModel
;
myCellModel
.
loadImageCallback
=
self
.
loadImageCallback
;
myCellModel
.
imageType
=
[
self
.
imageTypes
[
index
]
integerValue
];
myCellModel
.
imageSize
=
self
.
imageSize
;
myCellModel
.
titleImageSpacing
=
self
.
titleImageSpacing
;
if
(
self
.
imageNames
!=
nil
)
{
myCellModel
.
imageName
=
self
.
imageNames
[
index
];
}
else
if
(
self
.
imageURLs
!=
nil
)
{
myCellModel
.
imageURL
=
self
.
imageURLs
[
index
];
}
if
(
self
.
selectedImageNames
!=
nil
)
{
myCellModel
.
selectedImageName
=
self
.
selectedImageNames
[
index
];
}
else
if
(
self
.
selectedImageURLs
!=
nil
)
{
myCellModel
.
selectedImageURL
=
self
.
selectedImageURLs
[
index
];
}
myCellModel
.
imageZoomEnabled
=
self
.
imageZoomEnabled
;
myCellModel
.
imageZoomScale
=
1
.
0
;
if
(
index
==
self
.
selectedIndex
)
{
myCellModel
.
imageZoomScale
=
self
.
imageZoomScale
;
}
}
-
(
void
)
refreshSelectedCellModel
:
(
JXCategoryBaseCellModel
*
)
selectedCellModel
unselectedCellModel
:
(
JXCategoryBaseCellModel
*
)
unselectedCellModel
{
[
super
refreshSelectedCellModel
:
selectedCellModel
unselectedCellModel
:
unselectedCellModel
];
JXCategoryTitleImageCellModel
*
myUnselectedCellModel
=
(
JXCategoryTitleImageCellModel
*
)
unselectedCellModel
;
myUnselectedCellModel
.
imageZoomScale
=
1
.
0
;
JXCategoryTitleImageCellModel
*
myselectedCellModel
=
(
JXCategoryTitleImageCellModel
*
)
selectedCellModel
;
myselectedCellModel
.
imageZoomScale
=
self
.
imageZoomScale
;
}
-
(
void
)
refreshLeftCellModel
:
(
JXCategoryBaseCellModel
*
)
leftCellModel
rightCellModel
:
(
JXCategoryBaseCellModel
*
)
rightCellModel
ratio
:
(
CGFloat
)
ratio
{
[
super
refreshLeftCellModel
:
leftCellModel
rightCellModel
:
rightCellModel
ratio
:
ratio
];
JXCategoryTitleImageCellModel
*
leftModel
=
(
JXCategoryTitleImageCellModel
*
)
leftCellModel
;
JXCategoryTitleImageCellModel
*
rightModel
=
(
JXCategoryTitleImageCellModel
*
)
rightCellModel
;
if
(
self
.
imageZoomEnabled
)
{
leftModel
.
imageZoomScale
=
[
JXCategoryFactory
interpolationFrom
:
self
.
imageZoomScale
to
:
1
.
0
percent
:
ratio
];
rightModel
.
imageZoomScale
=
[
JXCategoryFactory
interpolationFrom
:
1
.
0
to
:
self
.
imageZoomScale
percent
:
ratio
];
}
}
-
(
CGFloat
)
preferredCellWidthAtIndex
:
(
NSInteger
)
index
{
CGFloat
titleWidth
=
[
super
preferredCellWidthAtIndex
:
index
];
JXCategoryTitleImageType
type
=
[
self
.
imageTypes
[
index
]
integerValue
];
CGFloat
cellWidth
=
0
;
switch
(
type
)
{
case
JXCategoryTitleImageType_OnlyTitle
:
cellWidth
=
titleWidth
;
break
;
case
JXCategoryTitleImageType_OnlyImage
:
cellWidth
=
self
.
imageSize
.
width
;
break
;
case
JXCategoryTitleImageType_LeftImage
:
case
JXCategoryTitleImageType_RightImage
:
cellWidth
=
titleWidth
+
self
.
titleImageSpacing
+
self
.
imageSize
.
width
;
break
;
case
JXCategoryTitleImageType_TopImage
:
case
JXCategoryTitleImageType_BottomImage
:
cellWidth
=
MAX
(
titleWidth
,
self
.
imageSize
.
width
);
break
;
}
return
cellWidth
;
}
@end
GMBase/Classes/JXPagerView/JXPagerCollectionViewCell.h
deleted
100644 → 0
View file @
1826794b
//
// JXPagerCollectionViewCell.h
// Gengmei
//
// Created by 卢悦明 on 2019/5/15.
// Copyright © 2019 更美互动信息科技有限公司. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface
JXPagerCollectionViewCell
:
UICollectionViewCell
@property
(
nonatomic
,
strong
)
UIView
*
backView
;
@end
NS_ASSUME_NONNULL_END
GMBase/Classes/JXPagerView/JXPagerCollectionViewCell.m
deleted
100644 → 0
View file @
1826794b
//
// JXPagerCollectionViewCell.m
// Gengmei
//
// Created by 卢悦明 on 2019/5/15.
// Copyright © 2019 更美互动信息科技有限公司. All rights reserved.
//
#import "JXPagerCollectionViewCell.h"
@implementation
JXPagerCollectionViewCell
-
(
void
)
setBackView
:(
UIView
*
)
backView
{
if
(
backView
!=
_backView
)
{
[
_backView
removeFromSuperview
];
_backView
=
backView
;
[
self
addSubview
:
_backView
];
}
}
-
(
void
)
layoutSubviews
{
self
.
backView
.
frame
=
self
.
bounds
;
}
@end
GMBase/Classes/JXPagerView/JXPagerListContainerView.h
deleted
100755 → 0
View file @
1826794b
//
// JXPagingListContainerView.h
// JXPagingView
//
// Created by jiaxin on 2018/8/27.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import <UIKit/UIKit.h>
@class
JXPagerMainTableView
;
@class
JXPagerListContainerView
;
@class
JXPagerListContainerCollectionView
;
@protocol
JXPagerListContainerCollectionViewGestureDelegate
<
NSObject
>
-
(
BOOL
)
pagerListContainerCollectionViewGestureRecognizerShouldBegin
:
(
JXPagerListContainerCollectionView
*
)
collectionView
gestureRecognizer
:
(
UIGestureRecognizer
*
)
gestureRecognizer
;
@end
@interface
JXPagerListContainerCollectionView
:
UICollectionView
<
UIGestureRecognizerDelegate
>
@property
(
nonatomic
,
assign
)
BOOL
isNestEnabled
;
@property
(
nonatomic
,
weak
)
id
<
JXPagerListContainerCollectionViewGestureDelegate
>
gestureDelegate
;
@end
@protocol
JXPagerListContainerViewDelegate
<
NSObject
>
-
(
NSInteger
)
numberOfRowsInListContainerView
:
(
JXPagerListContainerView
*
)
listContainerView
;
-
(
UIView
*
)
listContainerView
:(
JXPagerListContainerView
*
)
listContainerView
listViewInRow
:(
NSInteger
)
row
;
-
(
void
)
listContainerView
:(
JXPagerListContainerView
*
)
listContainerView
willDisplayCellAtRow
:(
NSInteger
)
row
;
-
(
void
)
listContainerView
:(
JXPagerListContainerView
*
)
listContainerView
didScroll
:(
NSInteger
)
row
;
@end
@interface
JXPagerListContainerView
:
UIView
@property
(
nonatomic
,
strong
,
readonly
)
JXPagerListContainerCollectionView
*
collectionView
;
@property
(
nonatomic
,
weak
)
id
<
JXPagerListContainerViewDelegate
>
delegate
;
@property
(
nonatomic
,
weak
)
JXPagerMainTableView
*
mainTableView
;
-
(
instancetype
)
initWithDelegate
:(
id
<
JXPagerListContainerViewDelegate
>
)
delegate
NS_DESIGNATED_INITIALIZER
;
-
(
instancetype
)
init
NS_UNAVAILABLE
;
-
(
instancetype
)
initWithFrame
:(
CGRect
)
frame
NS_UNAVAILABLE
;
-
(
instancetype
)
initWithCoder
:(
NSCoder
*
)
aDecoder
NS_UNAVAILABLE
;
-
(
void
)
reloadData
;
@end
GMBase/Classes/JXPagerView/JXPagerListContainerView.m
deleted
100755 → 0
View file @
1826794b
//
// JXPagerListContainerView.m
// JXPagerView
//
// Created by jiaxin on 2018/8/27.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXPagerListContainerView.h"
#import "JXPagerMainTableView.h"
@import
GMKit
;
@interface
JXPagerListContainerView
()
<
UICollectionViewDataSource
,
UICollectionViewDelegate
,
UICollectionViewDelegateFlowLayout
>
@property
(
nonatomic
,
strong
)
JXPagerListContainerCollectionView
*
collectionView
;
@property
(
nonatomic
,
strong
)
UICollectionViewFlowLayout
*
layout
;
@end
@implementation
JXPagerListContainerView
-
(
instancetype
)
initWithDelegate
:(
id
<
JXPagerListContainerViewDelegate
>
)
delegate
{
self
=
[
super
initWithFrame
:
CGRectZero
];
if
(
self
)
{
_delegate
=
delegate
;
[
self
initializeViews
];
}
return
self
;
}
-
(
void
)
initializeViews
{
UICollectionViewFlowLayout
*
layout
=
[[
UICollectionViewFlowLayout
alloc
]
init
];
layout
.
minimumLineSpacing
=
0
;
layout
.
minimumInteritemSpacing
=
0
;
layout
.
scrollDirection
=
UICollectionViewScrollDirectionHorizontal
;
self
.
layout
=
layout
;
_collectionView
=
[[
JXPagerListContainerCollectionView
alloc
]
initWithFrame
:
CGRectZero
collectionViewLayout
:
self
.
layout
];
self
.
collectionView
.
showsHorizontalScrollIndicator
=
NO
;
self
.
collectionView
.
showsVerticalScrollIndicator
=
NO
;
self
.
collectionView
.
pagingEnabled
=
YES
;
self
.
collectionView
.
scrollsToTop
=
NO
;
self
.
collectionView
.
bounces
=
NO
;
self
.
collectionView
.
delegate
=
self
;
self
.
collectionView
.
dataSource
=
self
;
[
self
.
collectionView
registerClass
:[
UICollectionViewCell
class
]
forCellWithReuseIdentifier
:
@"cell"
];
if
(
@available
(
iOS
10
.
0
,
*
))
{
self
.
collectionView
.
prefetchingEnabled
=
NO
;
}
if
(
@available
(
iOS
11
.
0
,
*
))
{
self
.
collectionView
.
contentInsetAdjustmentBehavior
=
UIScrollViewContentInsetAdjustmentNever
;
}
[
self
addSubview
:
self
.
collectionView
];
}
-
(
void
)
layoutSubviews
{
[
super
layoutSubviews
];
self
.
collectionView
.
frame
=
self
.
bounds
;
self
.
layout
.
itemSize
=
self
.
bounds
.
size
;
}
-
(
void
)
reloadData
{
[
self
.
collectionView
reloadData
];
}
#pragma mark - UICollectionViewDataSource, UICollectionViewDelegate
-
(
NSInteger
)
collectionView
:
(
UICollectionView
*
)
collectionView
numberOfItemsInSection
:
(
NSInteger
)
section
{
return
[
self
.
delegate
numberOfRowsInListContainerView
:
self
];
}
-
(
UICollectionViewCell
*
)
collectionView
:
(
UICollectionView
*
)
collectionView
cellForItemAtIndexPath
:
(
NSIndexPath
*
)
indexPath
{
UICollectionViewCell
*
cell
=
[
collectionView
dequeueReusableCellWithReuseIdentifier
:
@"cell"
forIndexPath
:
indexPath
];
for
(
UIView
*
view
in
cell
.
contentView
.
subviews
)
{
[
view
removeFromSuperview
];
}
UIView
*
listView
=
[
self
.
delegate
listContainerView
:
self
listViewInRow
:
indexPath
.
item
];
listView
.
frame
=
cell
.
contentView
.
bounds
;
[
cell
.
contentView
addSubview
:
listView
];
return
cell
;
}
-
(
void
)
collectionView
:
(
UICollectionView
*
)
collectionView
willDisplayCell
:
(
UICollectionViewCell
*
)
cell
forItemAtIndexPath
:
(
NSIndexPath
*
)
indexPath
{
[
self
.
delegate
listContainerView
:
self
willDisplayCellAtRow
:
indexPath
.
item
];
}
-
(
BOOL
)
collectionView
:
(
UICollectionView
*
)
collectionView
shouldHighlightItemAtIndexPath
:
(
NSIndexPath
*
)
indexPath
{
return
false
;
}
-
(
void
)
scrollViewDidEndDecelerating
:
(
UIScrollView
*
)
scrollView
{
self
.
mainTableView
.
scrollEnabled
=
YES
;
if
([
self
.
delegate
respondsToSelector
:
@selector
(
listContainerView
:
didScroll
:
)])
{
NSInteger
index
=
(
self
.
collectionView
.
contentOffset
.
x
/
MAINSCREEN_WIDTH
+
0
.
5
);
[
self
.
delegate
listContainerView
:
self
didScroll
:
index
];
}
}
-
(
void
)
scrollViewDidEndDragging
:
(
UIScrollView
*
)
scrollView
willDecelerate
:
(
BOOL
)
decelerate
{
if
([
self
.
delegate
respondsToSelector
:
@selector
(
listContainerView
:
didScroll
:
)])
{
NSInteger
index
=
(
self
.
collectionView
.
contentOffset
.
x
/
MAINSCREEN_WIDTH
+
0
.
5
);
[
self
.
delegate
listContainerView
:
self
didScroll
:
index
];
}
self
.
mainTableView
.
scrollEnabled
=
YES
;
}
-
(
void
)
scrollViewDidEndScrollingAnimation
:
(
UIScrollView
*
)
scrollView
{
self
.
mainTableView
.
scrollEnabled
=
YES
;
}
-
(
void
)
scrollViewDidScroll
:
(
UIScrollView
*
)
scrollView
{
if
(
scrollView
.
isTracking
||
scrollView
.
isDecelerating
)
{
self
.
mainTableView
.
scrollEnabled
=
NO
;
}
}
@end
@interface
JXPagerListContainerCollectionView
()
@end
@implementation
JXPagerListContainerCollectionView
-
(
BOOL
)
gestureRecognizerShouldBegin
:(
UIGestureRecognizer
*
)
gestureRecognizer
{
if
(
self
.
gestureDelegate
)
{
return
[
self
.
gestureDelegate
pagerListContainerCollectionViewGestureRecognizerShouldBegin
:
self
gestureRecognizer
:
gestureRecognizer
];
}
else
{
if
(
self
.
isNestEnabled
)
{
if
([
gestureRecognizer
isMemberOfClass
:
NSClassFromString
(
@"UIScrollViewPanGestureRecognizer"
)])
{
CGFloat
velocityX
=
[(
UIPanGestureRecognizer
*
)
gestureRecognizer
velocityInView
:
gestureRecognizer
.
view
].
x
;
//x大于0就是往右滑
if
(
velocityX
>
0
)
{
if
(
self
.
contentOffset
.
x
==
0
)
{
return
NO
;
}
}
else
if
(
velocityX
<
0
)
{
//x小于0就是往左滑
if
(
self
.
contentOffset
.
x
+
self
.
bounds
.
size
.
width
==
self
.
contentSize
.
width
)
{
return
NO
;
}
}
}
}
}
return
YES
;
}
@end
GMBase/Classes/JXPagerView/JXPagerListRefreshView.h
deleted
100755 → 0
View file @
1826794b
//
// JXPagingListRefreshView.h
// JXPagingView
//
// Created by jiaxin on 2018/8/28.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "JXPagerView.h"
@interface
JXPagerListRefreshView
:
JXPagerView
@end
GMBase/Classes/JXPagerView/JXPagerListRefreshView.m
deleted
100755 → 0
View file @
1826794b
//
// JXPagerListRefreshView.m
// JXPagerView
//
// Created by jiaxin on 2018/8/28.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXPagerListRefreshView.h"
@interface
JXPagerListRefreshView
()
@property
(
nonatomic
,
assign
)
CGFloat
lastScrollingListViewContentOffsetY
;
@end
@implementation
JXPagerListRefreshView
-
(
void
)
initializeViews
{
[
super
initializeViews
];
self
.
mainTableView
.
bounces
=
NO
;
}
-
(
void
)
preferredProcessListViewDidScroll
:
(
UIScrollView
*
)
scrollView
{
BOOL
shouldProcess
=
YES
;
if
(
self
.
currentScrollingListView
.
contentOffset
.
y
>
self
.
lastScrollingListViewContentOffsetY
)
{
//往上滚动
}
else
{
//往下滚动
if
(
self
.
mainTableView
.
contentOffset
.
y
==
0
)
{
shouldProcess
=
NO
;
}
else
{
if
(
self
.
mainTableView
.
contentOffset
.
y
<
[
self
.
delegate
tableHeaderViewHeightInPagerView
:
self
])
{
//mainTableView的header还没有消失,让listScrollView一直为0
if
(
self
.
currentList
&&
[
self
.
currentList
respondsToSelector
:
@selector
(
listScrollViewWillResetContentOffset
)])
{
[
self
.
currentList
listScrollViewWillResetContentOffset
];
}
self
.
currentScrollingListView
.
contentOffset
=
CGPointZero
;
self
.
currentScrollingListView
.
showsVerticalScrollIndicator
=
false
;
}
}
}
if
(
shouldProcess
)
{
if
(
self
.
mainTableView
.
contentOffset
.
y
<
[
self
.
delegate
tableHeaderViewHeightInPagerView
:
self
])
{
//处于下拉刷新的状态,scrollView.contentOffset.y为负数,就重置为0
if
(
self
.
currentScrollingListView
.
contentOffset
.
y
>
0
)
{
//mainTableView的header还没有消失,让listScrollView一直为0
if
(
self
.
currentList
&&
[
self
.
currentList
respondsToSelector
:
@selector
(
listScrollViewWillResetContentOffset
)])
{
[
self
.
currentList
listScrollViewWillResetContentOffset
];
}
self
.
currentScrollingListView
.
contentOffset
=
CGPointZero
;
self
.
currentScrollingListView
.
showsVerticalScrollIndicator
=
false
;
}
}
else
{
//mainTableView的header刚好消失,固定mainTableView的位置,显示listScrollView的滚动条
self
.
mainTableView
.
contentOffset
=
CGPointMake
(
0
,
[
self
.
delegate
tableHeaderViewHeightInPagerView
:
self
]);
self
.
currentScrollingListView
.
showsVerticalScrollIndicator
=
true
;
}
}
self
.
lastScrollingListViewContentOffsetY
=
self
.
currentScrollingListView
.
contentOffset
.
y
;
}
-
(
void
)
preferredProcessMainTableViewDidScroll
:
(
UIScrollView
*
)
scrollView
{
if
(
self
.
currentScrollingListView
!=
nil
&&
self
.
currentScrollingListView
.
contentOffset
.
y
>
0
)
{
//mainTableView的header已经滚动不见,开始滚动某一个listView,那么固定mainTableView的contentOffset,让其不动
self
.
mainTableView
.
contentOffset
=
CGPointMake
(
0
,
[
self
.
delegate
tableHeaderViewHeightInPagerView
:
self
]);
}
if
(
scrollView
.
contentOffset
.
y
<
[
self
.
delegate
tableHeaderViewHeightInPagerView
:
self
])
{
//mainTableView已经显示了header,listView的contentOffset需要重置
for
(
id
<
JXPagerViewListViewDelegate
>
list
in
self
.
validListDict
.
allValues
)
{
//正在下拉刷新时,不需要重置
UIScrollView
*
listScrollView
=
[
list
listScrollView
];
if
(
listScrollView
.
contentOffset
.
y
>
0
)
{
if
([
list
respondsToSelector
:
@selector
(
listScrollViewWillResetContentOffset
)])
{
[
list
listScrollViewWillResetContentOffset
];
}
listScrollView
.
contentOffset
=
CGPointZero
;
}
}
}
}
@end
GMBase/Classes/JXPagerView/JXPagerMainTableView.h
deleted
100755 → 0
View file @
1826794b
//
// JXPagingMainTableView.h
// JXPagingView
//
// Created by jiaxin on 2018/8/27.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import <UIKit/UIKit.h>
@protocol
JXPagerMainTableViewGestureDelegate
<
NSObject
>
-
(
BOOL
)
mainTableViewGestureRecognizer
:
(
UIGestureRecognizer
*
)
gestureRecognizer
shouldRecognizeSimultaneouslyWithGestureRecognizer
:
(
UIGestureRecognizer
*
)
otherGestureRecognizer
;
@end
@interface
JXPagerMainTableView
:
UITableView
@property
(
nonatomic
,
weak
)
id
<
JXPagerMainTableViewGestureDelegate
>
gestureDelegate
;
@end
GMBase/Classes/JXPagerView/JXPagerMainTableView.m
deleted
100755 → 0
View file @
1826794b
//
// JXPagerMainTableView.m
// JXPagerView
//
// Created by jiaxin on 2018/8/27.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXPagerMainTableView.h"
@interface
JXPagerMainTableView
()
<
UIGestureRecognizerDelegate
>
@end
@implementation
JXPagerMainTableView
-
(
BOOL
)
gestureRecognizer
:(
UIGestureRecognizer
*
)
gestureRecognizer
shouldRecognizeSimultaneouslyWithGestureRecognizer
:(
UIGestureRecognizer
*
)
otherGestureRecognizer
{
if
(
self
.
gestureDelegate
&&
[
self
.
gestureDelegate
respondsToSelector
:
@selector
(
mainTableViewGestureRecognizer
:
shouldRecognizeSimultaneouslyWithGestureRecognizer
:
)])
{
return
[
self
.
gestureDelegate
mainTableViewGestureRecognizer
:
gestureRecognizer
shouldRecognizeSimultaneouslyWithGestureRecognizer
:
otherGestureRecognizer
];
}
else
{
return
[
gestureRecognizer
isKindOfClass
:[
UIPanGestureRecognizer
class
]]
&&
[
otherGestureRecognizer
isKindOfClass
:[
UIPanGestureRecognizer
class
]];
}
}
@end
GMBase/Classes/JXPagerView/JXPagerView.h
deleted
100755 → 0
View file @
1826794b
//
// JXPagerView.h
// JXPagerView
//
// Created by jiaxin on 2018/8/27.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "JXPagerMainTableView.h"
#import "JXPagerListContainerView.h"
@class
JXPagerView
;
/**
该协议主要用于mainTableView已经显示了header,listView的contentOffset需要重置时,内部需要访问到外部传入进来的listView内的scrollView
*/
@protocol
JXPagerViewListViewDelegate
<
NSObject
>
/**
返回listView。如果是vc包裹的就是vc.view;如果是自定义view包裹的,就是自定义view自己。
@return UIView
*/
-
(
UIView
*
)
listView
;
/**
返回listView内部持有的UIScrollView或UITableView或UICollectionView
主要用于mainTableView已经显示了header,listView的contentOffset需要重置时,内部需要访问到外部传入进来的listView内的scrollView
@return listView内部持有的UIScrollView或UITableView或UICollectionView
*/
-
(
UIScrollView
*
)
listScrollView
;
/**
当listView内部持有的UIScrollView或UITableView或UICollectionView的代理方法`scrollViewDidScroll`回调时,需要调用该代理方法传入的callback
@param callback `scrollViewDidScroll`回调时调用的callback
*/
-
(
void
)
listViewDidScrollCallback
:(
void
(
^
)(
UIScrollView
*
scrollView
))
callback
;
@optional
/**
将要重置listScrollView的contentOffset
*/
-
(
void
)
listScrollViewWillResetContentOffset
;
@end
@protocol
JXPagerViewDelegate
<
NSObject
>
/**
返回tableHeaderView的高度,因为内部需要比对判断,只能是整型数
@param pagerView pagerView description
@return return tableHeaderView的高度
*/
-
(
NSUInteger
)
tableHeaderViewHeightInPagerView
:
(
JXPagerView
*
)
pagerView
;
/**
返回tableHeaderView
@param pagerView pagerView description
@return tableHeaderView
*/
-
(
UIView
*
)
tableHeaderViewInPagerView
:(
JXPagerView
*
)
pagerView
;
/**
返回悬浮HeaderView的高度,因为内部需要比对判断,只能是整型数
@param pagerView pagerView description
@return 悬浮HeaderView的高度
*/
-
(
NSUInteger
)
heightForPinSectionHeaderInPagerView
:(
JXPagerView
*
)
pagerView
;
/**
返回悬浮HeaderView。我用的是自己封装的JXCategoryView(Github:https://github.com/pujiaxin33/JXCategoryView),你也可以选择其他的三方库或者自己写
@param pagerView pagerView description
@return 悬浮HeaderView
*/
-
(
UIView
*
)
viewForPinSectionHeaderInPagerView
:(
JXPagerView
*
)
pagerView
;
/**
返回列表的数量
@param pagerView pagerView description
@return 列表的数量
*/
-
(
NSInteger
)
numberOfListsInPagerView
:(
JXPagerView
*
)
pagerView
;
/**
根据index初始化一个对应列表实例。注意:一定要是新生成的实例!!!
只要遵循JXPagerViewListViewDelegate即可,无论你返回的是UIView还是UIViewController都可以。
@param pagerView pagerView description
@param index index description
@return 新生成的列表实例
*/
-
(
id
<
JXPagerViewListViewDelegate
>
)
pagerView
:(
JXPagerView
*
)
pagerView
initListAtIndex
:(
NSInteger
)
index
;
-
(
void
)
pagerView
:(
JXPagerView
*
)
pagerView
didScroll
:(
NSInteger
)
row
;
@optional
/**
返回tableHeaderView 距离pagerView顶部的距离 默认为 0
*/
-
(
CGFloat
)
tableViewSectionHeaderViewContentYInPagerView
:
(
JXPagerView
*
)
pagerView
;
/**
mainTableView的滚动回调,用于实现头图跟随缩放
@param scrollView mainTableView
*/
-
(
void
)
mainTableViewDidScroll
:(
UIScrollView
*
)
scrollView
;
-
(
void
)
mainTableViewDidEndDecelerating
:(
UIScrollView
*
)
scrollView
;
-
(
void
)
mainTableViewDidEndDragging
:(
UIScrollView
*
)
scrollView
willDecelerate
:(
BOOL
)
decelerate
;
-
(
void
)
mainTableViewWillBeginDragging
:(
UIScrollView
*
)
scrollView
;
/**
@param 由于 mainTableViewDidScroll 滚动偏移量返回的最大值为headerView的高度, 这个偏移量加上子ScrollView的偏移量。
*/
-
(
void
)
listAndMainScrollViewDidScroll
:(
CGFloat
)
contentOffsetY
;
@end
@interface
JXPagerView
:
UIView
@property
(
nonatomic
,
weak
)
id
<
JXPagerViewDelegate
>
delegate
;
@property
(
nonatomic
,
strong
)
JXPagerMainTableView
*
mainTableView
;
@property
(
nonatomic
,
strong
,
readonly
)
JXPagerListContainerView
*
listContainerView
;
-
(
instancetype
)
initWithDelegate
:(
id
<
JXPagerViewDelegate
>
)
delegate
NS_DESIGNATED_INITIALIZER
;
@property
(
nonatomic
,
assign
)
BOOL
isListHorizontalScrollEnabled
;
//是否允许列表左右滑动。默认:YES
@property
(
nonatomic
,
assign
,
readonly
)
CGFloat
mainViewScrollOffsetY
;
@property
(
nonatomic
,
assign
,
readonly
)
BOOL
isListScroll
;
-
(
instancetype
)
init
NS_UNAVAILABLE
;
-
(
instancetype
)
initWithFrame
:(
CGRect
)
frame
NS_UNAVAILABLE
;
-
(
instancetype
)
initWithCoder
:(
NSCoder
*
)
aDecoder
NS_UNAVAILABLE
;
-
(
void
)
initializeViews
NS_REQUIRES_SUPER
;
-
(
void
)
reloadData
;
-
(
void
)
refreshTableHeaderView
;
#pragma mark - Subclass
@property
(
nonatomic
,
strong
,
readonly
)
UIScrollView
*
currentScrollingListView
;
//暴露给子类使用,请勿直接使用该属性!
@property
(
nonatomic
,
weak
,
readonly
)
id
<
JXPagerViewListViewDelegate
>
currentList
;
//暴露给子类使用,请勿直接使用该属性!
@property
(
nonatomic
,
strong
,
readonly
)
NSDictionary
<
NSNumber
*
,
id
<
JXPagerViewListViewDelegate
>>
*
validListDict
;
//暴露给子类使用,请勿直接使用该属性!当前已经加载过可用的列表字典,key就是index值,value是对应的列表。
-
(
void
)
preferredProcessListViewDidScroll
:(
UIScrollView
*
)
scrollView
;
-
(
void
)
preferredProcessMainTableViewDidScroll
:(
UIScrollView
*
)
scrollView
;
@end
GMBase/Classes/JXPagerView/JXPagerView.m
deleted
100755 → 0
View file @
1826794b
//
// JXPagerView.m
// JXPagerView
//
// Created by jiaxin on 2018/8/27.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXPagerView.h"
@import
GMRefresh
;
@interface
JXPagerView
()
<
UITableViewDataSource
,
UITableViewDelegate
,
JXPagerListContainerViewDelegate
>
//@property (nonatomic, strong) JXPagerMainTableView *mainTableView;
@property
(
nonatomic
,
strong
)
JXPagerListContainerView
*
listContainerView
;
@property
(
nonatomic
,
strong
)
UIScrollView
*
currentScrollingListView
;
@property
(
nonatomic
,
weak
)
id
<
JXPagerViewListViewDelegate
>
currentList
;
@property
(
nonatomic
,
strong
)
NSMutableDictionary
<
NSNumber
*
,
id
<
JXPagerViewListViewDelegate
>>
*
validListDict
;
@property
(
nonatomic
,
assign
)
CGFloat
mainViewScrollOffsetY
;
@property
(
nonatomic
,
assign
)
BOOL
isListScroll
;
@end
@implementation
JXPagerView
-
(
instancetype
)
initWithDelegate
:(
id
<
JXPagerViewDelegate
>
)
delegate
{
self
=
[
super
initWithFrame
:
CGRectZero
];
if
(
self
)
{
_delegate
=
delegate
;
_validListDict
=
[
NSMutableDictionary
dictionary
];
[
self
initializeViews
];
}
return
self
;
}
-
(
void
)
initializeViews
{
_mainTableView
=
[[
JXPagerMainTableView
alloc
]
initWithFrame
:
CGRectZero
style
:
UITableViewStylePlain
];
self
.
mainTableView
.
showsVerticalScrollIndicator
=
NO
;
self
.
mainTableView
.
showsHorizontalScrollIndicator
=
NO
;
self
.
mainTableView
.
separatorStyle
=
UITableViewCellSeparatorStyleNone
;
self
.
mainTableView
.
scrollsToTop
=
NO
;
self
.
mainTableView
.
dataSource
=
self
;
self
.
mainTableView
.
delegate
=
self
;
[
self
refreshTableHeaderView
];
[
self
.
mainTableView
registerClass
:[
UITableViewCell
class
]
forCellReuseIdentifier
:
@"cell"
];
if
(
@available
(
iOS
11
.
0
,
*
))
{
self
.
mainTableView
.
contentInsetAdjustmentBehavior
=
UIScrollViewContentInsetAdjustmentNever
;
}
[
self
addSubview
:
self
.
mainTableView
];
_listContainerView
=
[[
JXPagerListContainerView
alloc
]
initWithDelegate
:
self
];
self
.
listContainerView
.
mainTableView
=
self
.
mainTableView
;
self
.
isListHorizontalScrollEnabled
=
YES
;
}
-
(
void
)
layoutSubviews
{
[
super
layoutSubviews
];
self
.
mainTableView
.
frame
=
self
.
bounds
;
}
-
(
void
)
setIsListHorizontalScrollEnabled
:
(
BOOL
)
isListHorizontalScrollEnabled
{
_isListHorizontalScrollEnabled
=
isListHorizontalScrollEnabled
;
self
.
listContainerView
.
collectionView
.
scrollEnabled
=
isListHorizontalScrollEnabled
;
}
-
(
void
)
reloadData
{
self
.
currentList
=
nil
;
self
.
currentScrollingListView
=
nil
;
for
(
id
<
JXPagerViewListViewDelegate
>
list
in
self
.
validListDict
.
allValues
)
{
[
list
.
listView
removeFromSuperview
];
}
[
_validListDict
removeAllObjects
];
[
self
refreshTableHeaderView
];
[
self
.
mainTableView
reloadData
];
[
self
.
listContainerView
reloadData
];
}
-
(
void
)
refreshTableHeaderView
{
UIView
*
tableHeaderView
=
[
self
.
delegate
tableHeaderViewInPagerView
:
self
];
// UIView *containerView = [[UIView alloc] initWithFrame:tableHeaderView.bounds];
// [containerView addSubview:tableHeaderView];
self
.
mainTableView
.
tableHeaderView
=
tableHeaderView
;
}
-
(
void
)
preferredProcessListViewDidScroll
:
(
UIScrollView
*
)
scrollView
{
CGFloat
listScrollOffsetY
=
scrollView
.
contentOffset
.
y
;
if
([
self
.
delegate
respondsToSelector
:
@selector
(
listAndMainScrollViewDidScroll
:)])
{
[
self
.
delegate
listAndMainScrollViewDidScroll
:(
listScrollOffsetY
+
self
.
mainViewScrollOffsetY
)];
}
if
(
self
.
mainTableView
.
contentOffset
.
y
<
[
self
.
delegate
tableHeaderViewHeightInPagerView
:
self
])
{
//mainTableView的header还没有消失,让listScrollView一直为0
if
(
self
.
currentList
&&
[
self
.
currentList
respondsToSelector
:
@selector
(
listScrollViewWillResetContentOffset
)])
{
[
self
.
currentList
listScrollViewWillResetContentOffset
];
}
scrollView
.
contentOffset
=
CGPointZero
;
scrollView
.
showsVerticalScrollIndicator
=
NO
;
}
else
{
//mainTableView的header刚好消失,固定mainTableView的位置,显示listScrollView的滚动条
self
.
mainTableView
.
contentOffset
=
CGPointMake
(
0
,
[
self
.
delegate
tableHeaderViewHeightInPagerView
:
self
]);
scrollView
.
showsVerticalScrollIndicator
=
YES
;
}
}
-
(
void
)
preferredProcessMainTableViewDidScroll
:
(
UIScrollView
*
)
scrollView
{
if
(
self
.
currentScrollingListView
!=
nil
&&
self
.
currentScrollingListView
.
contentOffset
.
y
>
0
)
{
//mainTableView的header已经滚动不见,开始滚动某一个listView,那么固定mainTableView的contentOffset,让其不动
self
.
mainTableView
.
contentOffset
=
CGPointMake
(
0
,
[
self
.
delegate
tableHeaderViewHeightInPagerView
:
self
]);
}
if
(
scrollView
.
contentOffset
.
y
<
[
self
.
delegate
tableHeaderViewHeightInPagerView
:
self
])
{
//mainTableView已经显示了header,listView的contentOffset需要重置
for
(
id
<
JXPagerViewListViewDelegate
>
list
in
self
.
validListDict
.
allValues
)
{
if
([
list
respondsToSelector
:
@selector
(
listScrollViewWillResetContentOffset
)])
{
[
list
listScrollViewWillResetContentOffset
];
}
[
list
listScrollView
].
contentOffset
=
CGPointZero
;
}
}
if
(
scrollView
.
contentOffset
.
y
>
[
self
.
delegate
tableHeaderViewHeightInPagerView
:
self
]
&&
self
.
currentScrollingListView
.
contentOffset
.
y
==
0
)
{
//当往上滚动mainTableView的headerView时,滚动到底时,修复listView往上小幅度滚动
self
.
mainTableView
.
contentOffset
=
CGPointMake
(
0
,
[
self
.
delegate
tableHeaderViewHeightInPagerView
:
self
]);
}
}
#pragma mark - Private
-
(
void
)
listViewDidScroll
:
(
UIScrollView
*
)
scrollView
{
self
.
currentScrollingListView
=
scrollView
;
[
self
preferredProcessListViewDidScroll
:
scrollView
];
}
#pragma mark - UITableViewDataSource, UITableViewDelegate
-
(
NSInteger
)
numberOfSectionsInTableView
:
(
UITableView
*
)
tableView
{
return
1
;
}
-
(
NSInteger
)
tableView
:
(
UITableView
*
)
tableView
numberOfRowsInSection
:
(
NSInteger
)
section
{
return
1
;
}
-
(
CGFloat
)
tableView
:
(
UITableView
*
)
tableView
heightForRowAtIndexPath
:
(
NSIndexPath
*
)
indexPath
{
return
self
.
bounds
.
size
.
height
-
[
self
.
delegate
heightForPinSectionHeaderInPagerView
:
self
];
}
-
(
UITableViewCell
*
)
tableView
:
(
UITableView
*
)
tableView
cellForRowAtIndexPath
:
(
NSIndexPath
*
)
indexPath
{
UITableViewCell
*
cell
=
[
tableView
dequeueReusableCellWithIdentifier
:
@"cell"
forIndexPath
:
indexPath
];
for
(
UIView
*
view
in
cell
.
contentView
.
subviews
)
{
[
view
removeFromSuperview
];
}
self
.
listContainerView
.
frame
=
cell
.
contentView
.
bounds
;
[
cell
.
contentView
addSubview
:
self
.
listContainerView
];
return
cell
;
}
-
(
CGFloat
)
tableView
:
(
UITableView
*
)
tableView
heightForHeaderInSection
:
(
NSInteger
)
section
{
return
[
self
.
delegate
heightForPinSectionHeaderInPagerView
:
self
];
}
-
(
UIView
*
)
tableView
:
(
UITableView
*
)
tableView
viewForHeaderInSection
:
(
NSInteger
)
section
{
return
[
self
.
delegate
viewForPinSectionHeaderInPagerView
:
self
];
}
-
(
CGFloat
)
tableView
:
(
UITableView
*
)
tableView
heightForFooterInSection
:
(
NSInteger
)
section
{
return
1
;
}
-
(
UIView
*
)
tableView
:
(
UITableView
*
)
tableView
viewForFooterInSection
:
(
NSInteger
)
section
{
UIView
*
footer
=
[[
UIView
alloc
]
initWithFrame
:
CGRectZero
];
footer
.
backgroundColor
=
[
UIColor
clearColor
];
return
footer
;
}
-
(
void
)
scrollViewDidScroll
:
(
UIScrollView
*
)
scrollView
{
if
(
self
.
mainTableView
.
mj_header
.
refreshing
)
{
return
;
}
CGFloat
sectionHeaderHeight
=
[
self
.
delegate
heightForPinSectionHeaderInPagerView
:
self
];
CGFloat
sectionHeaderContentY
=
0
;
if
([
self
.
delegate
respondsToSelector
:
@selector
(
tableViewSectionHeaderViewContentYInPagerView
:)])
{
sectionHeaderContentY
=
[
self
.
delegate
tableViewSectionHeaderViewContentYInPagerView
:
self
];
}
CGFloat
ceilPositon
=
[
self
.
delegate
tableHeaderViewHeightInPagerView
:
self
]
-
sectionHeaderHeight
-
sectionHeaderContentY
;
if
(
scrollView
.
contentOffset
.
y
<
sectionHeaderHeight
)
{
scrollView
.
contentInset
=
UIEdgeInsetsMake
(
0
,
0
,
0
,
0
);
}
if
(
scrollView
.
contentOffset
.
y
>=
ceilPositon
&&
scrollView
.
contentOffset
.
y
>=
sectionHeaderHeight
)
{
scrollView
.
contentInset
=
UIEdgeInsetsMake
(
sectionHeaderContentY
,
0
,
0
,
0
);
}
CGFloat
offsetY
=
scrollView
.
contentOffset
.
y
;
self
.
mainViewScrollOffsetY
=
offsetY
;
if
([
self
.
delegate
respondsToSelector
:
@selector
(
mainTableViewDidScroll
:)])
{
[
self
.
delegate
mainTableViewDidScroll
:
scrollView
];
}
if
(
scrollView
.
isTracking
&&
self
.
isListHorizontalScrollEnabled
)
{
self
.
listContainerView
.
collectionView
.
scrollEnabled
=
NO
;
}
[
self
preferredProcessMainTableViewDidScroll
:
scrollView
];
}
-
(
void
)
scrollViewDidEndDecelerating
:
(
UIScrollView
*
)
scrollView
{
if
(
self
.
isListHorizontalScrollEnabled
)
{
self
.
listContainerView
.
collectionView
.
scrollEnabled
=
YES
;
}
if
([
self
.
delegate
respondsToSelector
:
@selector
(
mainTableViewDidEndDecelerating
:)])
{
if
(
_isListScroll
)
{
[
self
.
delegate
mainTableViewDidEndDecelerating
:
self
.
currentScrollingListView
];
}
else
{
[
self
.
delegate
mainTableViewDidEndDecelerating
:
scrollView
];
}
}
}
-
(
void
)
scrollViewDidEndDragging
:
(
UIScrollView
*
)
scrollView
willDecelerate
:
(
BOOL
)
decelerate
{
if
(
self
.
isListHorizontalScrollEnabled
)
{
self
.
listContainerView
.
collectionView
.
scrollEnabled
=
YES
;
}
if
([
self
.
delegate
respondsToSelector
:
@selector
(
mainTableViewDidEndDragging
:
willDecelerate
:
)])
{
if
(
_isListScroll
)
{
[
self
.
delegate
mainTableViewDidEndDragging
:
self
.
currentScrollingListView
willDecelerate
:
decelerate
];
}
else
{
[
self
.
delegate
mainTableViewDidEndDragging
:
scrollView
willDecelerate
:
decelerate
];
}
}
}
-
(
void
)
scrollViewWillBeginDragging
:
(
UIScrollView
*
)
scrollView
{
if
([
self
.
delegate
respondsToSelector
:
@selector
(
mainTableViewWillBeginDragging
:)])
{
if
(
self
.
currentScrollingListView
!=
nil
&&
self
.
currentScrollingListView
.
contentOffset
.
y
>
0
)
{
_isListScroll
=
YES
;
// 为了前后判断滑动的view是否一致
[
self
.
delegate
mainTableViewWillBeginDragging
:
self
.
currentScrollingListView
];
}
else
{
_isListScroll
=
NO
;
[
self
.
delegate
mainTableViewWillBeginDragging
:
scrollView
];
}
}
}
-
(
void
)
scrollViewDidEndScrollingAnimation
:
(
UIScrollView
*
)
scrollView
{
if
(
self
.
isListHorizontalScrollEnabled
)
{
self
.
listContainerView
.
collectionView
.
scrollEnabled
=
YES
;
}
}
#pragma mark - JXPagingListContainerViewDelegate
-
(
NSInteger
)
numberOfRowsInListContainerView
:
(
JXPagerListContainerView
*
)
listContainerView
{
return
[
self
.
delegate
numberOfListsInPagerView
:
self
];
}
-
(
UIView
*
)
listContainerView
:
(
JXPagerListContainerView
*
)
listContainerView
listViewInRow
:
(
NSInteger
)
row
{
id
<
JXPagerViewListViewDelegate
>
list
=
self
.
validListDict
[
@
(
row
)];
if
(
list
==
nil
)
{
list
=
[
self
.
delegate
pagerView
:
self
initListAtIndex
:
row
];
__weak
typeof
(
self
)
weakSelf
=
self
;
__weak
typeof
(
id
<
JXPagerViewListViewDelegate
>
)
weakList
=
list
;
[
list
listViewDidScrollCallback
:
^
(
UIScrollView
*
scrollView
)
{
weakSelf
.
currentList
=
weakList
;
[
weakSelf
listViewDidScroll
:
scrollView
];
}];
_validListDict
[
@
(
row
)]
=
list
;
}
return
[
list
listView
];
}
-
(
void
)
listContainerView
:
(
JXPagerListContainerView
*
)
listContainerView
willDisplayCellAtRow
:
(
NSInteger
)
row
{
self
.
currentScrollingListView
=
[
self
.
validListDict
[
@
(
row
)]
listScrollView
];
}
-
(
void
)
listContainerView
:
(
JXPagerListContainerView
*
)
listContainerView
didScroll
:
(
NSInteger
)
row
{
if
([
self
.
delegate
respondsToSelector
:
@selector
(
pagerView
:
didScroll
:
)])
{
[
self
.
delegate
pagerView
:
self
didScroll
:
row
];
}
}
@end
GMBase/Classes/JXPagerView/PageListView/JXPageListContainerView.h
deleted
100755 → 0
View file @
1826794b
//
// JXPagingListContainerView.h
// JXPagingView
//
// Created by jiaxin on 2018/8/27.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import <UIKit/UIKit.h>
@class
JXPageListMainTableView
;
@class
JXPageListContainerView
;
@protocol
JXPageListContainerViewDelegate
<
NSObject
>
-
(
NSInteger
)
numberOfRowsInListContainerView
:
(
JXPageListContainerView
*
)
listContainerView
;
-
(
UIView
*
)
listContainerView
:(
JXPageListContainerView
*
)
listContainerView
listViewInRow
:(
NSInteger
)
row
;
-
(
void
)
listContainerView
:(
JXPageListContainerView
*
)
listContainerView
willDisplayCellAtRow
:(
NSInteger
)
row
;
@end
@interface
JXPageListContainerView
:
UIView
@property
(
nonatomic
,
strong
,
readonly
)
UICollectionView
*
collectionView
;
@property
(
nonatomic
,
weak
)
id
<
JXPageListContainerViewDelegate
>
delegate
;
@property
(
nonatomic
,
weak
)
JXPageListMainTableView
*
mainTableView
;
-
(
instancetype
)
initWithDelegate
:(
id
<
JXPageListContainerViewDelegate
>
)
delegate
NS_DESIGNATED_INITIALIZER
;
-
(
instancetype
)
init
NS_UNAVAILABLE
;
-
(
instancetype
)
initWithFrame
:(
CGRect
)
frame
NS_UNAVAILABLE
;
-
(
instancetype
)
initWithCoder
:(
NSCoder
*
)
aDecoder
NS_UNAVAILABLE
;
-
(
void
)
reloadData
;
@end
GMBase/Classes/JXPagerView/PageListView/JXPageListContainerView.m
deleted
100755 → 0
View file @
1826794b
//
// JXPagerListContainerView.m
//
// Created by jiaxin on 2018/8/27.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXPageListContainerView.h"
#import "JXPageListMainTableView.h"
@interface
JXPageListContainerView
()
<
UICollectionViewDataSource
,
UICollectionViewDelegate
,
UICollectionViewDelegateFlowLayout
>
@property
(
nonatomic
,
strong
)
UICollectionView
*
collectionView
;
@end
@implementation
JXPageListContainerView
-
(
instancetype
)
initWithDelegate
:(
id
<
JXPageListContainerViewDelegate
>
)
delegate
{
self
=
[
super
initWithFrame
:
CGRectZero
];
if
(
self
)
{
_delegate
=
delegate
;
[
self
initializeViews
];
}
return
self
;
}
-
(
void
)
initializeViews
{
UICollectionViewFlowLayout
*
layout
=
[[
UICollectionViewFlowLayout
alloc
]
init
];
layout
.
minimumLineSpacing
=
0
;
layout
.
minimumInteritemSpacing
=
0
;
layout
.
scrollDirection
=
UICollectionViewScrollDirectionHorizontal
;
_collectionView
=
[[
UICollectionView
alloc
]
initWithFrame
:
CGRectZero
collectionViewLayout
:
layout
];
self
.
collectionView
.
showsHorizontalScrollIndicator
=
NO
;
self
.
collectionView
.
showsVerticalScrollIndicator
=
NO
;
self
.
collectionView
.
pagingEnabled
=
YES
;
self
.
collectionView
.
bounces
=
NO
;
self
.
collectionView
.
delegate
=
self
;
self
.
collectionView
.
dataSource
=
self
;
[
self
.
collectionView
registerClass
:[
UICollectionViewCell
class
]
forCellWithReuseIdentifier
:
@"cell"
];
[
self
addSubview
:
self
.
collectionView
];
}
-
(
void
)
layoutSubviews
{
[
super
layoutSubviews
];
self
.
collectionView
.
frame
=
self
.
bounds
;
}
-
(
void
)
reloadData
{
[
self
.
collectionView
reloadData
];
}
#pragma mark - UICollectionViewDataSource, UICollectionViewDelegate
-
(
NSInteger
)
collectionView
:
(
UICollectionView
*
)
collectionView
numberOfItemsInSection
:
(
NSInteger
)
section
{
return
[
self
.
delegate
numberOfRowsInListContainerView
:
self
];
}
-
(
UICollectionViewCell
*
)
collectionView
:
(
UICollectionView
*
)
collectionView
cellForItemAtIndexPath
:
(
NSIndexPath
*
)
indexPath
{
UICollectionViewCell
*
cell
=
[
collectionView
dequeueReusableCellWithReuseIdentifier
:
@"cell"
forIndexPath
:
indexPath
];
for
(
UIView
*
view
in
cell
.
contentView
.
subviews
)
{
[
view
removeFromSuperview
];
}
UIView
*
listView
=
[
self
.
delegate
listContainerView
:
self
listViewInRow
:
indexPath
.
item
];
listView
.
frame
=
cell
.
contentView
.
bounds
;
[
cell
.
contentView
addSubview
:
listView
];
return
cell
;
}
-
(
void
)
collectionView
:
(
UICollectionView
*
)
collectionView
willDisplayCell
:
(
UICollectionViewCell
*
)
cell
forItemAtIndexPath
:
(
NSIndexPath
*
)
indexPath
{
[
self
.
delegate
listContainerView
:
self
willDisplayCellAtRow
:
indexPath
.
item
];
}
-
(
void
)
scrollViewDidEndDecelerating
:
(
UIScrollView
*
)
scrollView
{
self
.
mainTableView
.
scrollEnabled
=
YES
;
}
-
(
void
)
scrollViewDidEndDragging
:
(
UIScrollView
*
)
scrollView
willDecelerate
:
(
BOOL
)
decelerate
{
self
.
mainTableView
.
scrollEnabled
=
YES
;
}
-
(
void
)
scrollViewDidEndScrollingAnimation
:
(
UIScrollView
*
)
scrollView
{
self
.
mainTableView
.
scrollEnabled
=
YES
;
}
-
(
void
)
scrollViewDidScroll
:
(
UIScrollView
*
)
scrollView
{
if
(
scrollView
.
isTracking
||
scrollView
.
isDecelerating
)
{
self
.
mainTableView
.
scrollEnabled
=
NO
;
}
}
#pragma mark - UICollectionViewDelegateFlowLayout
-
(
CGSize
)
collectionView
:
(
UICollectionView
*
)
collectionView
layout
:
(
UICollectionViewLayout
*
)
collectionViewLayout
sizeForItemAtIndexPath
:
(
NSIndexPath
*
)
indexPath
{
return
self
.
bounds
.
size
;
}
@end
GMBase/Classes/JXPagerView/PageListView/JXPageListMainTableView.h
deleted
100755 → 0
View file @
1826794b
//
// JXPagingMainTableView.h
// JXPagingView
//
// Created by jiaxin on 2018/8/27.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface
JXPageListMainTableView
:
UITableView
@end
GMBase/Classes/JXPagerView/PageListView/JXPageListMainTableView.m
deleted
100755 → 0
View file @
1826794b
//
// JXPagerMainTableView.m
//
// Created by jiaxin on 2018/8/27.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXPageListMainTableView.h"
@interface
JXPageListMainTableView
()
<
UIGestureRecognizerDelegate
>
@end
@implementation
JXPageListMainTableView
-
(
BOOL
)
gestureRecognizer
:(
UIGestureRecognizer
*
)
gestureRecognizer
shouldRecognizeSimultaneouslyWithGestureRecognizer
:(
UIGestureRecognizer
*
)
otherGestureRecognizer
{
return
[
gestureRecognizer
isKindOfClass
:[
UIPanGestureRecognizer
class
]]
&&
[
otherGestureRecognizer
isKindOfClass
:[
UIPanGestureRecognizer
class
]];
}
@end
GMBase/Classes/JXPagerView/PageListView/JXPageListView.h
deleted
100755 → 0
View file @
1826794b
//
// JXPageView.h
//
// Created by jiaxin on 2018/9/13.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "JXPageListMainTableView.h"
#import "JXPageListContainerView.h"
#import "JXCategoryView.h"
@class
JXPageListView
;
@protocol
JXPageListViewListDelegate
<
NSObject
>
/**
返回listView内部持有的UIScrollView或UITableView或UICollectionView
主要用于mainTableView已经显示了顶部内容,listView的contentOffset需要重置时,内部需要访问到外部传入进来的listView内的scrollView
@return listView内部持有的UIScrollView或UITableView或UICollectionView
*/
-
(
UIScrollView
*
)
listScrollView
;
/**
当listView内部持有的UIScrollView或UITableView或UICollectionView的代理方法`scrollViewDidScroll`回调时,需要调用该代理方法传入的callback
@param callback `scrollViewDidScroll`回调时调用的callback
*/
-
(
void
)
listViewDidScrollCallback
:(
void
(
^
)(
UIScrollView
*
scrollView
))
callback
;
/**
选中listView之后触发数据加载。会多次回调,所以listView内部要做个标志,第一次才触发数据加载。
*/
-
(
void
)
listViewLoadDataIfNeeded
;
@end
@protocol
JXPageListViewDelegate
<
NSObject
>
/**
返回listViews,数组的item需要是UIView的子类,且要遵循JXPageListViewListDelegate。
数组item要求返回一个UIView而不是一个UIScrollView,因为列表的UIScrollView一般是被包装到一个view里面,里面会处理数据源和其他逻辑。
@param pageListView pageListView description
@return listViews
*/
-
(
NSArray
<
UIView
<
JXPageListViewListDelegate
>*>*
)
listViewsInPageListView
:
(
JXPageListView
*
)
pageListView
;
@optional
/**
悬浮分类视图选中某个index的回调
@param pinCategoryView 悬浮分类视图
@param index index
*/
-
(
void
)
pinCategoryView
:
(
JXCategoryBaseView
*
)
pinCategoryView
didSelectedItemAtIndex
:
(
NSInteger
)
index
;
@end
/**
按照demo工程PageViewController里面的tips使用,把最后一个section留给listContainerCell。其余的,你就把mainTableView当做普通的tableView来处理就行。上面想添加多少cell都随你。
*/
@interface
JXPageListView
:
UIView
@property
(
nonatomic
,
strong
,
readonly
)
JXCategoryTitleView
*
pinCategoryView
;
@property
(
nonatomic
,
strong
,
readonly
)
JXPageListMainTableView
*
mainTableView
;
@property
(
nonatomic
,
assign
,
getter
=
isListViewScrollStateSaveEnabled
)
BOOL
listViewScrollStateSaveEnabled
;
//是否保存底部滚动列表视图的滚动状态,默认YES。设置为YES,表示A列表被滚动一定距离后,切换到B列表,当B列表往上滚动到最顶部的时候,再切换到A列表,A列表保存了它之前的滚动距离;设置为NO,表示A列表被滚动一定距离后,切换到B列表,当B列表往上滚动到最顶部的时候,再切换到A列表,A列表也同步被滚动到最顶部了;具体可以参考demo效果。
@property
(
nonatomic
,
assign
)
CGFloat
pinCategoryViewHeight
;
//顶部固定悬浮categoryView的高度
@property
(
nonatomic
,
assign
)
CGFloat
pinCategoryViewVerticalOffset
;
//顶部固定sectionHeader的垂直偏移量。数值越大越往下沉。
-
(
instancetype
)
initWithDelegate
:(
id
<
JXPageListViewDelegate
>
)
delegate
NS_DESIGNATED_INITIALIZER
;
-
(
instancetype
)
init
NS_UNAVAILABLE
;
-
(
instancetype
)
initWithFrame
:(
CGRect
)
frame
NS_UNAVAILABLE
;
-
(
instancetype
)
initWithCoder
:(
NSCoder
*
)
aDecoder
NS_UNAVAILABLE
;
/**
通过服务器获取到数据之后,再调用reloadData方法刷新
*/
-
(
void
)
reloadData
;
/**
返回列表容器cell的高度
*/
-
(
CGFloat
)
listContainerCellHeight
;
/**
返回列表容器cell
*/
-
(
UITableViewCell
*
)
listContainerCellForRowAtIndexPath
:(
NSIndexPath
*
)
indexPath
;
/**
mainTableView的代理方法`scrollViewDidScroll`回调时需要调用该方法
*/
-
(
void
)
mainTableViewDidScroll
:(
UIScrollView
*
)
scrollView
;
@end
GMBase/Classes/JXPagerView/PageListView/JXPageListView.m
deleted
100755 → 0
View file @
1826794b
//
// JXPageView.m
//
// Created by jiaxin on 2018/9/13.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXPageListView.h"
#import "JXPageListContainerView.h"
static
NSString
*
const
kListContainerCellIdentifier
=
@"jx_kListContainerCellIdentifier"
;
@interface
JXPageListView
()
<
JXPageListContainerViewDelegate
,
JXCategoryViewDelegate
>
@property
(
nonatomic
,
strong
)
JXCategoryTitleView
*
pinCategoryView
;
@property
(
nonatomic
,
weak
)
id
<
JXPageListViewDelegate
>
delegate
;
@property
(
nonatomic
,
strong
)
JXPageListMainTableView
*
mainTableView
;
@property
(
nonatomic
,
strong
)
JXPageListContainerView
*
listContainerView
;
@property
(
nonatomic
,
strong
)
UIScrollView
*
currentScrollingListView
;
@property
(
nonatomic
,
strong
)
UITableViewCell
*
listContainerCell
;
@property
(
nonatomic
,
strong
)
NSArray
*
originalListViews
;
@end
@implementation
JXPageListView
-
(
instancetype
)
initWithDelegate
:(
id
<
JXPageListViewDelegate
>
)
delegate
{
self
=
[
super
initWithFrame
:
CGRectZero
];
if
(
self
)
{
_delegate
=
delegate
;
[
self
initializeViews
];
}
return
self
;
}
-
(
void
)
initializeViews
{
_listViewScrollStateSaveEnabled
=
YES
;
_pinCategoryViewVerticalOffset
=
0
;
self
.
pinCategoryView
=
[[
JXCategoryTitleView
alloc
]
initWithFrame
:
CGRectZero
];
self
.
pinCategoryView
.
backgroundColor
=
[
UIColor
whiteColor
];
self
.
pinCategoryView
.
delegate
=
self
;
self
.
pinCategoryView
.
titleSelectedColor
=
[
UIColor
colorWithRed
:
105
/
255
.
0
green
:
144
/
255
.
0
blue
:
239
/
255
.
0
alpha
:
1
];
self
.
pinCategoryView
.
titleColor
=
[
UIColor
blackColor
];
self
.
pinCategoryView
.
titleColorGradientEnabled
=
YES
;
self
.
pinCategoryView
.
titleLabelZoomEnabled
=
YES
;
JXCategoryIndicatorLineView
*
lineView
=
[[
JXCategoryIndicatorLineView
alloc
]
init
];
lineView
.
indicatorColor
=
[
UIColor
colorWithRed
:
105
/
255
.
0
green
:
144
/
255
.
0
blue
:
239
/
255
.
0
alpha
:
1
];
lineView
.
indicatorWidth
=
30
;
self
.
pinCategoryView
.
indicators
=
@[
lineView
];
_mainTableView
=
[[
JXPageListMainTableView
alloc
]
initWithFrame
:
CGRectZero
style
:
UITableViewStylePlain
];
self
.
mainTableView
.
showsVerticalScrollIndicator
=
NO
;
self
.
mainTableView
.
tableFooterView
=
[
UIView
new
];
[
self
.
mainTableView
registerClass
:[
UITableViewCell
class
]
forCellReuseIdentifier
:
kListContainerCellIdentifier
];
if
(
@available
(
iOS
11
.
0
,
*
))
{
self
.
mainTableView
.
contentInsetAdjustmentBehavior
=
UIScrollViewContentInsetAdjustmentNever
;
}
[
self
addSubview
:
self
.
mainTableView
];
_listContainerView
=
[[
JXPageListContainerView
alloc
]
initWithDelegate
:
self
];
self
.
listContainerView
.
mainTableView
=
self
.
mainTableView
;
self
.
pinCategoryView
.
contentScrollView
=
self
.
listContainerView
.
collectionView
;
[
self
configListViewDidScrollCallback
];
}
-
(
void
)
layoutSubviews
{
[
super
layoutSubviews
];
self
.
mainTableView
.
frame
=
self
.
bounds
;
}
-
(
void
)
reloadData
{
//先移除以前的listView
for
(
UIView
*
listView
in
self
.
originalListViews
)
{
[
listView
removeFromSuperview
];
}
[
self
configListViewDidScrollCallback
];
[
self
.
mainTableView
reloadData
];
[
self
.
listContainerView
reloadData
];
[
self
.
pinCategoryView
reloadData
];
}
-
(
CGFloat
)
listContainerCellHeight
{
return
self
.
bounds
.
size
.
height
-
self
.
pinCategoryViewVerticalOffset
;
}
-
(
UITableViewCell
*
)
listContainerCellForRowAtIndexPath
:
(
NSIndexPath
*
)
indexPath
{
dispatch_after
(
dispatch_time
(
DISPATCH_TIME_NOW
,
(
int64_t
)(
0
.
25
*
NSEC_PER_SEC
)),
dispatch_get_main_queue
(),
^
{
//触发第一个列表的下拉刷新
NSArray
*
listViews
=
[
self
.
delegate
listViewsInPageListView
:
self
];
if
(
listViews
.
count
>
0
)
{
[
listViews
[
self
.
pinCategoryView
.
selectedIndex
]
listViewLoadDataIfNeeded
];
}
});
UITableViewCell
*
cell
=
[
self
.
mainTableView
dequeueReusableCellWithIdentifier
:
kListContainerCellIdentifier
forIndexPath
:
indexPath
];
cell
.
selectionStyle
=
UITableViewCellSelectionStyleNone
;
self
.
listContainerCell
=
cell
;
for
(
UIView
*
view
in
cell
.
contentView
.
subviews
)
{
[
view
removeFromSuperview
];
}
self
.
pinCategoryView
.
frame
=
CGRectMake
(
0
,
0
,
cell
.
contentView
.
bounds
.
size
.
width
,
self
.
pinCategoryViewHeight
);
if
(
self
.
pinCategoryView
.
superview
!=
cell
.
contentView
)
{
//首次使用pinCategoryView的时候,把pinCategoryView添加到它上面。
[
cell
.
contentView
addSubview
:
self
.
pinCategoryView
];
}
self
.
listContainerView
.
frame
=
CGRectMake
(
0
,
self
.
pinCategoryViewHeight
,
cell
.
contentView
.
bounds
.
size
.
width
,
cell
.
contentView
.
bounds
.
size
.
height
-
self
.
pinCategoryViewHeight
);
[
cell
.
contentView
addSubview
:
self
.
listContainerView
];
return
cell
;
}
-
(
void
)
mainTableViewDidScroll
:
(
UIScrollView
*
)
scrollView
{
//处理当页面滚动在最底部pageView的时候,页面需要立即停住,没有回弹效果。给用户一种切换到pageView浏览模式了
if
(
scrollView
.
contentOffset
.
y
>
10
)
{
scrollView
.
bounces
=
NO
;
}
else
{
scrollView
.
bounces
=
YES
;
}
CGFloat
topContentY
=
[
self
mainTableViewMaxContentOffsetY
];
if
(
scrollView
.
contentOffset
.
y
>=
topContentY
)
{
//当滚动的contentOffset.y大于了指定sectionHeader的y值,且还没有被添加到self.view上的时候,就需要切换superView
if
(
self
.
pinCategoryView
.
superview
!=
self
)
{
CGRect
frame
=
self
.
pinCategoryView
.
frame
;
frame
.
origin
.
y
=
self
.
pinCategoryViewVerticalOffset
;
self
.
pinCategoryView
.
frame
=
frame
;
[
self
addSubview
:
self
.
pinCategoryView
];
}
}
else
if
(
self
.
pinCategoryView
.
superview
!=
self
.
listContainerCell
.
contentView
)
{
//当滚动的contentOffset.y小于了指定sectionHeader的y值,且还没有被添加到sectionCategoryHeaderView上的时候,就需要切换superView
CGRect
frame
=
self
.
pinCategoryView
.
frame
;
frame
.
origin
.
y
=
0
;
self
.
pinCategoryView
.
frame
=
frame
;
[
self
.
listContainerCell
.
contentView
addSubview
:
self
.
pinCategoryView
];
}
if
(
scrollView
.
isTracking
||
scrollView
.
isDecelerating
)
{
//用户滚动的才处理
if
(
self
.
currentScrollingListView
!=
nil
&&
self
.
currentScrollingListView
.
contentOffset
.
y
>
0
)
{
self
.
mainTableView
.
contentOffset
=
CGPointMake
(
self
.
mainTableView
.
contentOffset
.
x
,
topContentY
);
}
}
if
(
!
self
.
isListViewScrollStateSaveEnabled
)
{
if
(
scrollView
.
contentOffset
.
y
<
topContentY
)
{
//mainTableView已经显示了header,listView的contentOffset需要重置
NSArray
*
listViews
=
[
self
.
delegate
listViewsInPageListView
:
self
];
CGFloat
insetTop
=
scrollView
.
contentInset
.
top
;
if
(
@available
(
iOS
11
.
0
,
*
))
{
insetTop
=
scrollView
.
adjustedContentInset
.
top
;
}
for
(
UIView
<
JXPageListViewListDelegate
>*
listView
in
listViews
)
{
[
listView
listScrollView
].
contentOffset
=
CGPointMake
(
self
.
mainTableView
.
contentOffset
.
x
,
-
insetTop
);
}
}
}
}
#pragma mark - Private
-
(
void
)
configListViewDidScrollCallback
{
NSArray
*
listViews
=
[
self
.
delegate
listViewsInPageListView
:
self
];
self
.
originalListViews
=
listViews
;
for
(
UIView
<
JXPageListViewListDelegate
>*
listView
in
listViews
)
{
__weak
typeof
(
self
)
weakSelf
=
self
;
[
listView
listViewDidScrollCallback
:
^
(
UIScrollView
*
scrollView
)
{
[
weakSelf
listViewDidScroll
:
scrollView
];
}];
}
}
-
(
void
)
listViewDidSelectedAtIndex
:
(
NSInteger
)
index
{
UIView
<
JXPageListViewListDelegate
>
*
listContainerView
=
[
self
.
delegate
listViewsInPageListView
:
self
][
index
];
if
([
listContainerView
listScrollView
].
contentOffset
.
y
>
0
)
{
//当前列表视图已经滚动显示了内容
[
self
.
mainTableView
setContentOffset
:
CGPointMake
(
self
.
mainTableView
.
contentOffset
.
x
,
[
self
mainTableViewMaxContentOffsetY
])
animated
:
YES
];
}
}
-
(
CGFloat
)
mainTableViewMaxContentOffsetY
{
return
floor
(
self
.
mainTableView
.
contentSize
.
height
)
-
self
.
bounds
.
size
.
height
;
}
-
(
void
)
listViewDidScroll
:
(
UIScrollView
*
)
scrollView
{
self
.
currentScrollingListView
=
scrollView
;
if
(
scrollView
.
isTracking
==
NO
&&
scrollView
.
isDecelerating
==
NO
)
{
return
;
}
CGFloat
topContentHeight
=
[
self
mainTableViewMaxContentOffsetY
];
if
(
self
.
mainTableView
.
contentOffset
.
y
<
topContentHeight
)
{
//mainTableView的header还没有消失,让listScrollView固定
CGFloat
insetTop
=
scrollView
.
contentInset
.
top
;
if
(
@available
(
iOS
11
.
0
,
*
))
{
insetTop
=
scrollView
.
adjustedContentInset
.
top
;
}
scrollView
.
contentOffset
=
CGPointMake
(
scrollView
.
contentOffset
.
x
,
-
insetTop
);
}
else
{
//mainTableView的header刚好消失,固定mainTableView的位置,显示listScrollView的滚动条
self
.
mainTableView
.
contentOffset
=
CGPointMake
(
self
.
mainTableView
.
contentOffset
.
x
,
topContentHeight
);
}
}
#pragma mark - JXPagingListContainerViewDelegate
-
(
NSInteger
)
numberOfRowsInListContainerView
:
(
JXPageListContainerView
*
)
listContainerView
{
NSArray
*
listViews
=
[
self
.
delegate
listViewsInPageListView
:
self
];
return
listViews
.
count
;
}
-
(
UIView
*
)
listContainerView
:
(
JXPageListContainerView
*
)
listContainerView
listViewInRow
:
(
NSInteger
)
row
{
NSArray
*
listViews
=
[
self
.
delegate
listViewsInPageListView
:
self
];
return
listViews
[
row
];
}
-
(
void
)
listContainerView
:
(
JXPageListContainerView
*
)
listContainerView
willDisplayCellAtRow
:
(
NSInteger
)
row
{
NSArray
*
listViews
=
[
self
.
delegate
listViewsInPageListView
:
self
];
self
.
currentScrollingListView
=
[
listViews
[
row
]
listScrollView
];
}
#pragma mark - JXCategoryViewDelegate
-
(
void
)
categoryView
:
(
JXCategoryBaseView
*
)
categoryView
didSelectedItemAtIndex
:
(
NSInteger
)
index
{
if
([
self
.
delegate
respondsToSelector
:
@selector
(
pinCategoryView
:
didSelectedItemAtIndex
:
)])
{
[
self
.
delegate
pinCategoryView
:
categoryView
didSelectedItemAtIndex
:
index
];
}
NSArray
*
listViews
=
[
self
.
delegate
listViewsInPageListView
:
self
];
[
listViews
[
index
]
listViewLoadDataIfNeeded
];
}
-
(
void
)
categoryView
:
(
JXCategoryBaseView
*
)
categoryView
didClickSelectedItemAtIndex
:
(
NSInteger
)
index
{
//点击选中,会立马回调该方法。但是page还在左右切换。所以延迟0.25秒等左右切换结束再处理。
dispatch_after
(
dispatch_time
(
DISPATCH_TIME_NOW
,
(
int64_t
)(
0
.
25
*
NSEC_PER_SEC
)),
dispatch_get_main_queue
(),
^
{
[
self
listViewDidSelectedAtIndex
:
index
];
});
}
-
(
void
)
categoryView
:
(
JXCategoryBaseView
*
)
categoryView
didScrollSelectedItemAtIndex
:
(
NSInteger
)
index
{
[
self
listViewDidSelectedAtIndex
:
index
];
}
@end
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment