Repository: ChenYilong/CYLTabBarController
Branch: master
Commit: ea46eb68f712
Files: 156
Total size: 560.0 KB
Directory structure:
gitextract_oavmoe9b/
├── .gitattributes
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── -en-bug-report--cn-bug---.md
│ │ ├── -en-feature-request--cn---------.md
│ │ └── qa----.md
│ ├── issue_template.md
│ └── pull_request_template.md
├── .gitignore
├── CHANGELOG.md
├── CYLTabBarController/
│ ├── CAAnimation+CYLBadgeExtention.h
│ ├── CAAnimation+CYLBadgeExtention.m
│ ├── CYLBadgeProtocol.h
│ ├── CYLBaseNavigationController.h
│ ├── CYLBaseNavigationController.m
│ ├── CYLBaseTableViewController.h
│ ├── CYLBaseTableViewController.m
│ ├── CYLBaseViewController.h
│ ├── CYLBaseViewController.m
│ ├── CYLConstants.h
│ ├── CYLPlusButton.h
│ ├── CYLPlusButton.m
│ ├── CYLTabBar+CYLTabBarControllerExtention.h
│ ├── CYLTabBar+CYLTabBarControllerExtention.m
│ ├── CYLTabBar.h
│ ├── CYLTabBar.m
│ ├── CYLTabBarController.h
│ ├── CYLTabBarController.m
│ ├── NSObject+CYLTabBarControllerExtention.h
│ ├── NSObject+CYLTabBarControllerExtention.m
│ ├── UIBarButtonItem+CYLBadgeExtention.h
│ ├── UIBarButtonItem+CYLBadgeExtention.m
│ ├── UIColor+CYLTabBarControllerExtention.h
│ ├── UIColor+CYLTabBarControllerExtention.m
│ ├── UIControl+CYLTabBarControllerExtention.h
│ ├── UIControl+CYLTabBarControllerExtention.m
│ ├── UIImage+CYLTabBarControllerExtention.h
│ ├── UIImage+CYLTabBarControllerExtention.m
│ ├── UITabBarItem+CYLBadgeExtention.h
│ ├── UITabBarItem+CYLBadgeExtention.m
│ ├── UITabBarItem+CYLTabBarControllerExtention.h
│ ├── UITabBarItem+CYLTabBarControllerExtention.m
│ ├── UIView+CYLBadgeExtention.h
│ ├── UIView+CYLBadgeExtention.m
│ ├── UIView+CYLTabBarControllerExtention.h
│ ├── UIView+CYLTabBarControllerExtention.m
│ ├── UIViewController+CYLNavigationControllerExtention.h
│ ├── UIViewController+CYLNavigationControllerExtention.m
│ ├── UIViewController+CYLTabBarControllerExtention.h
│ └── UIViewController+CYLTabBarControllerExtention.m
├── CYLTabBarController.podspec
├── CYLTabBarController.xcodeproj/
│ ├── project.pbxproj
│ └── xcshareddata/
│ └── xcschemes/
│ └── CYLTabBarController.xcscheme
├── CYLTabBarControllerTests/
│ ├── CYLTabBarControllerTests.m
│ └── Info.plist
├── Example/
│ ├── AppDelegate.h
│ ├── AppDelegate.m
│ ├── Base.lproj/
│ │ ├── LaunchScreen.xib
│ │ └── Main.storyboard
│ ├── CYLMainRootViewController.h
│ ├── CYLMainRootViewController.m
│ ├── Classes/
│ │ ├── Module/
│ │ │ ├── Home/
│ │ │ │ ├── CYLHomeViewController.h
│ │ │ │ └── CYLHomeViewController.m
│ │ │ ├── Message/
│ │ │ │ ├── CYLMessageViewController.h
│ │ │ │ └── CYLMessageViewController.m
│ │ │ ├── Mine/
│ │ │ │ ├── CYLMineViewController.h
│ │ │ │ └── CYLMineViewController.m
│ │ │ ├── Other/
│ │ │ │ ├── CYLPlusDemoChildViewController.h
│ │ │ │ └── CYLPlusDemoChildViewController.m
│ │ │ └── SameCity/
│ │ │ ├── CYLDetailsViewController.h
│ │ │ ├── CYLDetailsViewController.m
│ │ │ ├── CYLSameCityViewController.h
│ │ │ └── CYLSameCityViewController.m
│ │ ├── Other/
│ │ │ └── LottieResources/
│ │ │ ├── gray_tabbar_home_animation.json
│ │ │ ├── gray_tabbar_me_animation.json
│ │ │ ├── gray_tabbar_message_animation.json
│ │ │ ├── green_lottie_tab_discover.json
│ │ │ ├── green_lottie_tab_home.json
│ │ │ ├── green_lottie_tab_mine.json
│ │ │ ├── green_lottie_tab_news.json
│ │ │ ├── tab_home_animate.json
│ │ │ ├── tab_me_animate.json
│ │ │ ├── tab_message_animate.json
│ │ │ └── tab_search_animate.json
│ │ └── View/
│ │ ├── CYLPlusButtonSubclass.h
│ │ └── CYLPlusButtonSubclass.m
│ ├── Images.xcassets/
│ │ ├── AppIcon.appiconset/
│ │ │ └── Contents.json
│ │ ├── Contents.json
│ │ ├── LaunchImage.launchimage/
│ │ │ └── Contents.json
│ │ ├── NavBar/
│ │ │ ├── Contents.json
│ │ │ ├── home_bar_scan.imageset/
│ │ │ │ └── Contents.json
│ │ │ ├── home_title_slogan.imageset/
│ │ │ │ └── Contents.json
│ │ │ └── icon_search.imageset/
│ │ │ └── Contents.json
│ │ ├── TabBarIcon/
│ │ │ ├── Contents.json
│ │ │ ├── TabBar_Bg_Shadow.imageset/
│ │ │ │ └── Contents.json
│ │ │ ├── account/
│ │ │ │ ├── Contents.json
│ │ │ │ ├── account_highlight.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ └── account_normal.imageset/
│ │ │ │ └── Contents.json
│ │ │ ├── fishpond/
│ │ │ │ ├── Contents.json
│ │ │ │ ├── fishpond_highlight.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ └── fishpond_normal.imageset/
│ │ │ │ └── Contents.json
│ │ │ ├── home/
│ │ │ │ ├── Contents.json
│ │ │ │ ├── home_highlight.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ └── home_normal.imageset/
│ │ │ │ └── Contents.json
│ │ │ ├── home_select_cover.imageset/
│ │ │ │ └── Contents.json
│ │ │ ├── lottie_placeholder/
│ │ │ │ ├── Contents.json
│ │ │ │ ├── gray_tabbar_home_animation_lottie_placeholder.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── gray_tabbar_me_animation_lottie_placeholder.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ └── gray_tabbar_message_animation_lottie_placeholder.imageset/
│ │ │ │ └── Contents.json
│ │ │ ├── message/
│ │ │ │ ├── Contents.json
│ │ │ │ ├── message_highlight.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ └── message_normal.imageset/
│ │ │ │ └── Contents.json
│ │ │ ├── post/
│ │ │ │ ├── Contents.json
│ │ │ │ ├── post_highlight.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ └── post_normal.imageset/
│ │ │ │ └── Contents.json
│ │ │ ├── tabbarBg.imageset/
│ │ │ │ └── Contents.json
│ │ │ ├── tabbar_background.imageset/
│ │ │ │ └── Contents.json
│ │ │ ├── tapbar_top_line.imageset/
│ │ │ │ └── Contents.json
│ │ │ └── videoback.imageset/
│ │ │ └── Contents.json
│ │ ├── home-float-icon.imageset/
│ │ │ └── Contents.json
│ │ ├── icon_tabbar_plus.imageset/
│ │ │ └── Contents.json
│ │ └── navigationbar_background_tall.imageset/
│ │ └── Contents.json
│ ├── Info.plist
│ ├── MainTabBarController.h
│ ├── MainTabBarController.m
│ └── main.m
├── Example-Swift/
│ ├── AppDelegate.swift
│ ├── CYLTabbarController-Swift.xcodeproj/
│ │ └── project.pbxproj
│ ├── MainTabBarController.swift
│ ├── Module/
│ │ ├── Connection/
│ │ │ └── Controller/
│ │ │ └── ConnectionViewController.swift
│ │ ├── Home/
│ │ │ └── Controller/
│ │ │ └── HomeViewController.swift
│ │ ├── Message/
│ │ │ └── Controller/
│ │ │ └── MessageViewController.swift
│ │ ├── Personal/
│ │ │ └── Controller/
│ │ │ └── PersonalViewController.swift
│ │ └── Publish/
│ │ └── Controller/
│ │ └── PublishViewController.swift
│ ├── Other/
│ │ ├── Assets.xcassets/
│ │ │ ├── AppIcon.appiconset/
│ │ │ │ └── Contents.json
│ │ │ ├── Contents.json
│ │ │ ├── LaunchImage.launchimage/
│ │ │ │ └── Contents.json
│ │ │ └── TabBarIcon/
│ │ │ ├── Contents.json
│ │ │ ├── account_highlight.imageset/
│ │ │ │ └── Contents.json
│ │ │ ├── account_normal.imageset/
│ │ │ │ └── Contents.json
│ │ │ ├── home_highlight.imageset/
│ │ │ │ └── Contents.json
│ │ │ ├── home_normal.imageset/
│ │ │ │ └── Contents.json
│ │ │ ├── message_highlight.imageset/
│ │ │ │ └── Contents.json
│ │ │ ├── message_normal.imageset/
│ │ │ │ └── Contents.json
│ │ │ ├── mycity_highlight.imageset/
│ │ │ │ └── Contents.json
│ │ │ ├── mycity_normal.imageset/
│ │ │ │ └── Contents.json
│ │ │ ├── post_normal.imageset/
│ │ │ │ └── Contents.json
│ │ │ ├── tabbar_background.imageset/
│ │ │ │ └── Contents.json
│ │ │ └── tapbar_top_line.imageset/
│ │ │ └── Contents.json
│ │ ├── Base.lproj/
│ │ │ ├── LaunchScreen.storyboard
│ │ │ └── Main.storyboard
│ │ └── Info.plist
│ ├── Podfile
│ └── View/
│ └── CYLPlusButtonSubclass.swift
├── LICENSE
├── Podfile
├── README.md
└── package.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitattributes
================================================
*.h linguist-detectable=false
*.m linguist-detectable=false
================================================
FILE: .github/ISSUE_TEMPLATE/-en-bug-report--cn-bug---.md
================================================
---
name: "[EN]Bug report.[CN]bug反馈."
about: Create a report to help us improve
title: "[bug]:"
labels: bug
assignees: ChenYilong
---
--------------------------------------------
--------------------------------------------
## Base Info for this issue
1. Version:Latest Version as [here](https://github.com/ChenYilong/CYLTabBarController/blob/master/CYLTabBarController.podspec)
2. Language of App :Objective-C/Swift
4. iOS System Version:iOS12
5. Prototype(是否是真机):YES
6. Issue Type:Crash、Bug、Enhancement(希望能支持一个新需求)、Q-A
## 1. How to reproduce the problem.
## 2. Please help me in this way.
## 3. Here is a Demo.
## 4. Here is my Debug log
----------
================================================
FILE: .github/ISSUE_TEMPLATE/-en-feature-request--cn---------.md
================================================
---
name: "[EN]Feature request.[CN]希望添加新功能."
about: Suggest an idea for this project
title: "[Feature request]希望添加新功能:"
labels: enhancement
assignees: ChenYilong
---
--------------------------------------------
--------------------------------------------
**Is your feature request related to a problem? Please describe.**
**Describe the solution you'd like**
**Describe alternatives you've considered**
**Additional context**
================================================
FILE: .github/ISSUE_TEMPLATE/qa----.md
================================================
---
name: QA问题询问
about: 使用方法或者不确定是否为bug,可选用本模版
title: "[Q-A]使用方法询问:"
labels: Q-A
assignees: ChenYilong
---
--------------------------------------------
--------------------------------------------
## My issue:
================================================
FILE: .github/issue_template.md
================================================

----------
----------
## Base Info for this issue
1. Version:Latest Version as [here](https://github.com/ChenYilong/CYLTabBarController/blob/master/CYLTabBarController.podspec)
2. Language of App :Objective-C/Swift
4. iOS System Version:iOS12
5. Prototype(是否是真机):YES
6. Issue Type:Crash、Bug、Enhancement(希望能支持一个新需求)、Q-A
## 1. How to reproduce the problem.
## 2. Please help me in this way.
## 3. Here is a Demo.
## 4. Here is my Debug log
----------
================================================
FILE: .github/pull_request_template.md
================================================
--------------------------------------------
--------------------------------------------
## My issue:
## What I have done:
================================================
FILE: .gitignore
================================================
.DS_Store
CYLTabBarController.xcodeproj/project.xcworkspace/xcuserdata/chenyilong.xcuserdatad/UserInterfaceState.xcuserstate
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
!default.xcworkspace
xcuserdata
*.moved-aside
*.mobileprovision
DerivedData
.idea/
Pods
Podfile.lock
*.xcworkspace
CYLTabBarController.xcodeproj/xcuserdata/chenyilong.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
*.xcuserstate
*.xcbkptlist
*.xcuserstate
*.xcbkptlist
================================================
FILE: CHANGELOG.md
================================================
================================================
FILE: CYLTabBarController/CAAnimation+CYLBadgeExtention.h
================================================
/*
// CYLTabBarController
// CYLTabBarController
//
// Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 03/06/19.
// Copyright © 2019 https://github.com/ChenYilong . All rights reserved.
*/
#import
#import
NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM(NSUInteger, CYLAxis) {
CYLAxisX = 0,
CYLAxisY,
CYLAxisZ
};
// Degrees to radians
#define CYL_DEGREES_TO_RADIANS(angle) ((angle) / 180.0 * M_PI)
#define CYL_RADIANS_TO_DEGREES(radians) ((radians) * (180.0 / M_PI))
@interface CAAnimation (CYLBadgeExtention)
/**
* breathing forever
*
* @param time duritaion, from clear to fully seen
*
* @return animation obj
*/
+ (CABasicAnimation *)cyl_opacityForever_Animation:(float)time;
/**
* breathing with fixed repeated times
*
* @param repeatTimes times
* @param time duritaion, from clear to fully seen
*
* @return animation obj
*/
+ (CABasicAnimation *)cyl_opacityTimes_Animation:(float)repeatTimes durTimes:(float)time;
/**
* //rotate
*
* @param dur duration
* @param degree rotate degree in radian(弧度)
* @param axis axis
* @param repeatCount repeat count
*
* @return animation obj
*/
+ (CABasicAnimation *)cyl_rotation:(float)dur degree:(float)degree direction:(CYLAxis)axis repeatCount:(int)repeatCount;
/**
* scale animation
*
* @param fromScale the original scale value, 1.0 by default
* @param toScale target scale
* @param time duration
* @param repeatTimes repeat counts
*
* @return animaiton obj
*/
+ (CABasicAnimation *)cyl_scaleFrom:(CGFloat)fromScale toScale:(CGFloat)toScale durTimes:(float)time rep:(float)repeatTimes;
/**
* shake
*
* @param repeatTimes time
* @param time duration
* @param obj always be CALayer at present
* @return aniamtion obj
*/
+ (CAKeyframeAnimation *)cyl_shake_AnimationRepeatTimes:(float)repeatTimes durTimes:(float)time forObj:(id)obj;
/**
* bounce
*
* @param repeatTimes time
* @param time duration
* @param obj always be CALayer at present
* @return aniamtion obj
*/
+ (CAKeyframeAnimation *)cyl_bounce_AnimationRepeatTimes:(float)repeatTimes durTimes:(float)time forObj:(id)obj;
@end
NS_ASSUME_NONNULL_END
================================================
FILE: CYLTabBarController/CAAnimation+CYLBadgeExtention.m
================================================
/*
// CYLTabBarController
// CYLTabBarController
//
// Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 03/06/19.
// Copyright © 2019 https://github.com/ChenYilong . All rights reserved.
*/
#import "CAAnimation+CYLBadgeExtention.h"
#import
@implementation CAAnimation (CYLBadgeExtention)
/**
* breathing forever
*
* @param time duritaion, from clear to fully seen
*
* @return animation obj
*/
+ (CABasicAnimation *)cyl_opacityForever_Animation:(float)time {
CABasicAnimation *animation=[CABasicAnimation animationWithKeyPath:@"opacity"];
animation.fromValue=[NSNumber numberWithFloat:1.0];
animation.toValue=[NSNumber numberWithFloat:0.1];
animation.autoreverses=YES;
animation.duration=time;
animation.repeatCount=FLT_MAX;
animation.removedOnCompletion=NO;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
animation.fillMode=kCAFillModeForwards;
return animation;
}
/**
* breathing with fixed repeated times
*
* @param repeatTimes times
* @param time duritaion, from clear to fully seen
*
* @return animation obj
*/
+ (CABasicAnimation *)cyl_opacityTimes_Animation:(float)repeatTimes durTimes:(float)time {
CABasicAnimation *animation=[CABasicAnimation animationWithKeyPath:@"opacity"];
animation.fromValue=[NSNumber numberWithFloat:1.0];
animation.toValue=[NSNumber numberWithFloat:0.4];
animation.repeatCount=repeatTimes;
animation.duration=time;
animation.removedOnCompletion=NO;
animation.fillMode=kCAFillModeForwards;
animation.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
animation.autoreverses=YES;
return animation;
}
/**
* //rotate
*
* @param dur duration
* @param degree rotate degree in radian(弧度)
* @param axis axis
* @param repeatCount repeat count
*
* @return animation obj
*/
+ (CABasicAnimation *)cyl_rotation:(float)dur degree:(float)degree direction:(CYLAxis)axis repeatCount:(int)repeatCount {
CABasicAnimation* animation;
NSArray *axisArr = @[@"transform.rotation.x", @"transform.rotation.y", @"transform.rotation.z"];
animation = [CABasicAnimation animationWithKeyPath:axisArr[axis]];
animation.fromValue = [NSNumber numberWithFloat:0];
animation.toValue= [NSNumber numberWithFloat:degree];
animation.duration= dur;
animation.autoreverses= NO;
animation.cumulative= YES;
animation.removedOnCompletion=NO;
animation.fillMode=kCAFillModeForwards;
animation.repeatCount= repeatCount;
return animation;
}
/**
* scale animation
*
* @param fromScale the original scale value, 1.0 by default
* @param toScale target scale
* @param time duration
* @param repeatTimes repeat counts
*
* @return animaiton obj
*/
+ (CABasicAnimation *)cyl_scaleFrom:(CGFloat)fromScale toScale:(CGFloat)toScale durTimes:(float)time rep:(float)repeatTimes {
CABasicAnimation *animation=[CABasicAnimation animationWithKeyPath:@"transform.scale"];
animation.fromValue = @(fromScale);
animation.toValue = @(toScale);
animation.duration = time;
animation.autoreverses = YES;
animation.repeatCount = repeatTimes;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
return animation;
}
/**
* shake
*
* @param repeatTimes time
* @param time duration
* @param obj always be CALayer
* @return aniamtion obj
*/
+ (CAKeyframeAnimation *)cyl_shake_AnimationRepeatTimes:(float)repeatTimes durTimes:(float)time forObj:(id)obj {
NSAssert([obj isKindOfClass:[CALayer class]] , @"invalid target");
CGPoint originPos = CGPointZero;
CGSize originSize = CGSizeZero;
if ([obj isKindOfClass:[CALayer class]]) {
originPos = [(CALayer *)obj position];
originSize = [(CALayer *)obj bounds].size;
}
CGFloat hOffset = originSize.width / 4;
CAKeyframeAnimation* anim=[CAKeyframeAnimation animation];
anim.keyPath=@"position";
anim.values=@[
[NSValue valueWithCGPoint:CGPointMake(originPos.x, originPos.y)],
[NSValue valueWithCGPoint:CGPointMake(originPos.x-hOffset, originPos.y)],
[NSValue valueWithCGPoint:CGPointMake(originPos.x, originPos.y)],
[NSValue valueWithCGPoint:CGPointMake(originPos.x+hOffset, originPos.y)],
[NSValue valueWithCGPoint:CGPointMake(originPos.x, originPos.y)]
];
anim.repeatCount = repeatTimes;
anim.duration = time;
anim.fillMode = kCAFillModeForwards;
return anim;
}
/**
* bounce
*
* @param repeatTimes time
* @param time duration
* @param obj always be CALayer
* @return aniamtion obj
*/
+ (CAKeyframeAnimation *)cyl_bounce_AnimationRepeatTimes:(float)repeatTimes durTimes:(float)time forObj:(id)obj {
NSAssert([obj isKindOfClass:[CALayer class]] , @"invalid target");
CGPoint originPos = CGPointZero;
CGSize originSize = CGSizeZero;
if ([obj isKindOfClass:[CALayer class]]) {
originPos = [(CALayer *)obj position];
originSize = [(CALayer *)obj bounds].size;
}
CGFloat hOffset = originSize.height / 4;
CAKeyframeAnimation* anim=[CAKeyframeAnimation animation];
anim.keyPath=@"position";
anim.values=@[
[NSValue valueWithCGPoint:CGPointMake(originPos.x, originPos.y)],
[NSValue valueWithCGPoint:CGPointMake(originPos.x, originPos.y-hOffset)],
[NSValue valueWithCGPoint:CGPointMake(originPos.x, originPos.y)],
[NSValue valueWithCGPoint:CGPointMake(originPos.x, originPos.y+hOffset)],
[NSValue valueWithCGPoint:CGPointMake(originPos.x, originPos.y)]
];
anim.repeatCount=repeatTimes;
anim.duration=time;
anim.fillMode = kCAFillModeForwards;
return anim;
}
@end
================================================
FILE: CYLTabBarController/CYLBadgeProtocol.h
================================================
/*
// CYLTabBarController
// CYLTabBarController
//
// Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 03/06/19.
// Copyright © 2019 https://github.com/ChenYilong . All rights reserved.
*/
//CYLBadgeProtocol is a protocol which any Class supported (such UIView and UIBarButtonItem) should confirm
//At present, there are two classes support CYLBadgeExtention(UIView and UIBarButtonItem). However, there may be more classes to support. Thus, it is necessary to abstract a protocol. 20150812.
#ifndef CYLBadgeDemo_CYLBadgeProtocol_h
#define CYLBadgeDemo_CYLBadgeProtocol_h
#pragma mark -- types definition
#define CYLBadgeBreatheAnimationKey @"breathe"
#define CYLBadgeRotateAnimationKey @"rotate"
#define CYLBadgeShakeAnimationKey @"shake"
#define CYLBadgeScaleAnimationKey @"scale"
#define CYLBadgeBounceAnimationKey @"bounce"
typedef NS_ENUM(NSUInteger, CYLBadgeStyle) {
CYLBadgeStyleRedDot = 1, /* red dot style */
CYLBadgeStyleNumber, /* badge with number */
CYLBadgeStyleNew, /* badge with a fixed text "new" */
CYLBadgeStyleOther /* badge with a fixed text */
};
typedef NS_ENUM(NSUInteger, CYLBadgeAnimationType) {
CYLBadgeAnimationTypeNone = 0, /* without animation, badge stays still */
CYLBadgeAnimationTypeScale, /* scale effect */
CYLBadgeAnimationTypeShake, /* shaking effect */
CYLBadgeAnimationTypeBounce, /* bouncing effect */
CYLBadgeAnimationTypeBreathe /* breathing light effect, which makes badge more attractive */
};
#pragma mark -- protocol definition
@protocol CYLBadgeProtocol
@required
@property (nonatomic, strong, getter=cyl_badge, setter=cyl_setBadge:) UILabel *cyl_badge; /* badge entity, which is adviced not to set manually */
@property (nonatomic, strong, getter=cyl_badgeFont, setter=cyl_setBadgeFont:) UIFont *cyl_badgeFont; /* [UIFont boldSystemFontOfSize:9] by default if not set */
@property (nonatomic, strong, getter=cyl_badgeBackgroundColor, setter=cyl_setBadgeBackgroundColor:) UIColor *cyl_badgeBackgroundColor; /* red color by default if not set */
@property (nonatomic, strong, getter=cyl_badgeTextColor, setter=cyl_setBadgeTextColor:) UIColor *cyl_badgeTextColor; /* white color by default if not set */
@property (nonatomic, assign, getter=cyl_badgeFrame, setter=cyl_setBadgeFrame:) CGRect cyl_badgeFrame; /* we have optimized the badge frame and center.
This property is adviced not to set manually */
@property (nonatomic, assign, getter=cyl_badgeCenterOffset, setter=cyl_setBadgeCenterOffset:) CGPoint cyl_badgeCenterOffset; /* offset from right-top corner. {0,0} by default */
/* For x, negative number means left offset
For y, negative number means bottom offset */
@property (nonatomic, assign, getter=cyl_badgeAnimationType, setter=cyl_setBadgeAnimationType:) CYLBadgeAnimationType cyl_badgeAnimationType;/* NOTE that this is not animation type of badge's
// appearing, nor hidding*/
@property (nonatomic, assign, getter=cyl_badgeMaximumBadgeNumber, setter=cyl_setBadgeMaximumBadgeNumber:) NSInteger cyl_badgeMaximumBadgeNumber; /*for CYLBadgeStyleNumber style badge,
if badge value is above badgeMaximumBadgeNumber,
"badgeMaximumBadgeNumber+" will be printed. */
@property (nonatomic, assign, getter=cyl_badgeRadius, setter=cyl_setBadgeRadius:) CGFloat cyl_badgeRadius;
@property (nonatomic, assign, getter=cyl_badgeMargin, setter=cyl_setBadgeMargin:) CGFloat cyl_badgeMargin; /**< // normal use for text and number style of badge */
@property (nonatomic, assign, getter=cyl_badgeCornerRadius, setter=cyl_setBadgeCornerRadius:) CGFloat cyl_badgeCornerRadius;
- (BOOL)cyl_isShowBadge;
/**
* show badge with red dot style and CYLBadgeAnimationTypeNone by default.
*/
- (void)cyl_showBadge;
/**
*
* @param value String value, default is `nil`. if value equal @"" means red dot style.
* @param animationType animationType
* @attention
- 调用该方法前已经添加了系统的角标,调用该方法后,系统的角标并未被移除,只是被隐藏,调用 `-cyl_removeTabBadgePoint` 后会重新展示。
- 不支持 CYLPlusChildViewController 对应的 TabBarItem 角标设置,调用会被忽略。
*/
- (void)cyl_showBadgeValue:(NSString *)value
animationType:(CYLBadgeAnimationType)animationType;
/**
* clear badge(hide badge)
*/
- (void)cyl_clearBadge;
/**
* make bage(if existing) not hiden
*/
- (void)cyl_resumeBadge;
- (BOOL)cyl_isPauseBadge;
@end
#endif
================================================
FILE: CYLTabBarController/CYLBaseNavigationController.h
================================================
/*
// CYLTabBarController
// CYLTabBarController
//
// Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 03/06/19.
// Copyright © 2019 https://github.com/ChenYilong . All rights reserved.
*/
#import
NS_ASSUME_NONNULL_BEGIN
@interface CYLBaseNavigationController : UINavigationController
@end
NS_ASSUME_NONNULL_END
================================================
FILE: CYLTabBarController/CYLBaseNavigationController.m
================================================
/*
// CYLTabBarController
// CYLTabBarController
//
// Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 03/06/19.
// Copyright © 2019 https://github.com/ChenYilong . All rights reserved.
*/
#import "CYLBaseNavigationController.h"
@interface CYLBaseNavigationController ()
@end
@implementation CYLBaseNavigationController
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
// 当前导航栏, 只有第一个viewController push的时候设置隐藏
if (self.viewControllers.count == 1) {
viewController.hidesBottomBarWhenPushed = YES;
} else {
viewController.hidesBottomBarWhenPushed = NO;
}
[super pushViewController:viewController animated:animated];
}
//fix https://github.com/ChenYilong/CYLTabBarController/issues/483
- (void)setViewControllers:(NSArray *)viewControllers animated:(BOOL)animated {
if (self.viewControllers.count > 1) {
UIViewController *viewController = [self.viewControllers lastObject];
viewController.hidesBottomBarWhenPushed = YES;
}
[super setViewControllers:viewControllers animated:animated];
}
@end
================================================
FILE: CYLTabBarController/CYLBaseTableViewController.h
================================================
/*
// CYLTabBarController
// CYLTabBarController
//
// Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 03/06/19.
// Copyright © 2019 https://github.com/ChenYilong . All rights reserved.
*/
#import
NS_ASSUME_NONNULL_BEGIN
@interface CYLBaseTableViewController : UITableViewController
@end
NS_ASSUME_NONNULL_END
================================================
FILE: CYLTabBarController/CYLBaseTableViewController.m
================================================
/*
// CYLTabBarController
// CYLTabBarController
//
// Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 03/06/19.
// Copyright © 2019 https://github.com/ChenYilong . All rights reserved.
*/
#import "CYLBaseTableViewController.h"
#import "CYLTabBarController.h"
@interface CYLBaseTableViewController ()
@end
@implementation CYLBaseTableViewController
#pragma mark -
#pragma mark - UIViewController Life
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self cyl_viewWillAppearNavigationSetting:animated];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self cyl_viewDidAppearNavigationSetting:animated];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self cyl_viewWillDisappearNavigationSetting:animated];
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
[self cyl_viewDidDisappearNavigationSetting:animated];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void)dealloc {
[self cyl_deallocNavigationSetting];
}
@end
================================================
FILE: CYLTabBarController/CYLBaseViewController.h
================================================
/*
// CYLTabBarController
// CYLTabBarController
//
// Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 03/06/19.
// Copyright © 2019 https://github.com/ChenYilong . All rights reserved.
*/
#import
NS_ASSUME_NONNULL_BEGIN
@interface CYLBaseViewController : UIViewController
@end
NS_ASSUME_NONNULL_END
================================================
FILE: CYLTabBarController/CYLBaseViewController.m
================================================
/*
// CYLTabBarController
// CYLTabBarController
//
// Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 03/06/19.
// Copyright © 2019 https://github.com/ChenYilong . All rights reserved.
*/
#import "CYLBaseViewController.h"
#import "CYLTabBarController.h"
@interface CYLBaseViewController ()
@end
@implementation CYLBaseViewController
#pragma mark -
#pragma mark - UIViewController Life
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self cyl_viewWillAppearNavigationSetting:animated];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self cyl_viewDidAppearNavigationSetting:animated];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self cyl_viewWillDisappearNavigationSetting:animated];
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
[self cyl_viewDidDisappearNavigationSetting:animated];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void)dealloc {
[self cyl_deallocNavigationSetting];
}
@end
================================================
FILE: CYLTabBarController/CYLConstants.h
================================================
//
// CYLTabBarController.h
// CYLTabBarController
//
// v1.21.x Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 10/20/15.
// Copyright © 2018 https://github.com/ChenYilong . All rights reserved.
//
#ifndef CYLConstants_h
#define CYLConstants_h
#define CYL_DEPRECATED(explain) __attribute__((deprecated(explain)))
#define CYL_IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define CYL_IS_IOS_11 ([[[UIDevice currentDevice] systemVersion] floatValue] >= 11.f)
#define CYL_IS_IPHONE_X (CYL_IS_IOS_11 && CYL_IS_IPHONE && (MIN([UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height) >= 375 && MAX([UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height) >= 812))
#define CYL_SYSTEM_VERSION_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
#define CYL_SYSTEM_VERSION_GREATER_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
#define CYL_SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
#define CYL_SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
#define CYL_SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)
#endif /* CYLConstants_h */
================================================
FILE: CYLTabBarController/CYLPlusButton.h
================================================
//
// CYLPlusButton.h
// CYLTabBarController
//
// v1.21.x Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 10/20/15.
// Copyright © 2018 https://github.com/ChenYilong . All rights reserved.
//
#import
#import "CYLConstants.h"
NS_ASSUME_NONNULL_BEGIN
@class CYLPlusButton;
@protocol CYLPlusButtonSubclassing
@required
+ (id)plusButton;
@optional
/*!
* 用来自定义加号按钮的位置,如果不实现默认居中。
* @attention 以下两种情况下,必须实现该协议方法,否则 CYLTabBarController 会抛出 exception 来进行提示:
1. 添加了 PlusButton 且 TabBarItem 的个数是奇数。
2. 实现了 `+plusChildViewController`。
* @return 用来自定义加号按钮在 TabBar 中的位置。
*
*/
+ (NSUInteger)indexOfPlusButtonInTabBar;
/*!
* 该方法是为了调整 PlusButton 中心点Y轴方向的位置,建议在按钮超出了 tabbar 的边界时实现该方法。
* @attention 如果不实现该方法,内部会自动进行比对,预设一个较为合适的位置,如果实现了该方法,预设的逻辑将失效。
* @return 返回值是自定义按钮中心点Y轴方向的坐标除以 tabbar 的高度,
内部实现时,会使用该返回值来设置 PlusButton 的 centerY 坐标,公式如下:
`PlusButtonCenterY = multiplierOfTabBarHeight * tabBarHeight + constantOfPlusButtonCenterYOffset;`
也就是说:如果 constantOfPlusButtonCenterYOffset 为0,同时 multiplierOfTabBarHeight 的值是0.5,表示 PlusButton 居中,小于0.5表示 PlusButton 偏上,大于0.5则表示偏下。
*
*/
+ (CGFloat)multiplierOfTabBarHeight:(CGFloat)tabBarHeight;
/*!
* 见 `+multiplierOfTabBarHeight:` 注释:
* `PlusButtonCenterY = multiplierOfTabBarHeight * tabBarHeight + constantOfPlusButtonCenterYOffset;`
* 也就是说: constantOfPlusButtonCenterYOffset 大于0会向下偏移,小于0会向上偏移。
* @attention 实现了该方法,但没有实现 `+multiplierOfTabBarHeight:` 方法,在这种情况下,会在预设逻辑的基础上进行偏移。
*/
+ (CGFloat)constantOfPlusButtonCenterYOffsetForTabBarHeight:(CGFloat)tabBarHeight;
/*!
* 实现该方法后,能让 PlusButton 的点击效果与跟点击其他 TabBar 按钮效果一样,跳转到该方法指定的 UIViewController 。
* @attention 必须同时实现 `+indexOfPlusButtonInTabBar` 来指定 PlusButton 的位置。
* @return 指定 PlusButton 点击后跳转的 UIViewController。
*
*/
+ (UIViewController *)plusChildViewController;
/*!
*
Asks the delegate whether the specified view controller should be made active.
Return YES if the view controller’s tab should be selected or NO if the current tab should remain active.
Returns YES true if the view controller’s tab should be selected or
NO false if the current tab should remain active.
*/
+ (BOOL)shouldSelectPlusChildViewController;
#pragma mark - Deprecated API
+ (CGFloat)multiplerInCenterY CYL_DEPRECATED("Deprecated in 1.6.0. Use `+multiplierOfTabBarHeight:` instead.");
+ (NSString *)tabBarContext;
@end
@class CYLTabBar;
FOUNDATION_EXTERN UIButton *CYLExternPlusButton;
FOUNDATION_EXTERN UIViewController *CYLPlusChildViewController;
@interface CYLPlusButton : UIButton
+ (void)registerPlusButton;
+ (void)removePlusButton;
- (void)plusChildViewControllerButtonClicked:(UIButton *)sender;
@end
#pragma mark - Deprecated API
@interface CYLPlusButton (CYLPlusButtonDeprecated)
+ (void)registerSubclass CYL_DEPRECATED("Deprecated in 1.6.0. Use `+[CYLPlusButton registerPlusButton]` instead.");
@end
NS_ASSUME_NONNULL_END
================================================
FILE: CYLTabBarController/CYLPlusButton.m
================================================
//
// CYLPlusButton.m
// CYLTabBarController
//
// v1.21.x Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 10/20/15.
// Copyright © 2018 https://github.com/ChenYilong . All rights reserved.
//
#import "CYLPlusButton.h"
#import "CYLTabBarController.h"
#import "UIViewController+CYLTabBarControllerExtention.h"
CGFloat CYLPlusButtonWidth = 0.0f;
UIButton *CYLExternPlusButton = nil;
UIViewController *CYLPlusChildViewController = nil;
@implementation CYLPlusButton
#pragma mark -
#pragma mark - public Methods
+ (void)registerPlusButton {
if (![self conformsToProtocol:@protocol(CYLPlusButtonSubclassing)]) {
return;
}
Class class = self;
UIButton *plusButton = [class plusButton];
CYLExternPlusButton = plusButton;
CYLPlusButtonWidth = plusButton.frame.size.width;
if ([[self class] respondsToSelector:@selector(plusChildViewController)]) {
CYLPlusChildViewController = [class plusChildViewController];
if ([[self class] respondsToSelector:@selector(tabBarContext)]) {
NSString *tabBarContext = [class tabBarContext];
if (tabBarContext && tabBarContext.length) {
[CYLPlusChildViewController cyl_setContext:tabBarContext];
}
} else {
[CYLPlusChildViewController cyl_setContext:NSStringFromClass([CYLTabBarController class])];
}
[[self class] addSelectViewControllerTarget:plusButton];
if ([[self class] respondsToSelector:@selector(indexOfPlusButtonInTabBar)]) {
CYLPlusButtonIndex = [[self class] indexOfPlusButtonInTabBar];
} else {
[NSException raise:NSStringFromClass([CYLTabBarController class]) format:@"If you want to add PlusChildViewController, you must realizse `+indexOfPlusButtonInTabBar` in your custom plusButton class.【Chinese】如果你想使用PlusChildViewController样式,你必须同时在你自定义的plusButton中实现 `+indexOfPlusButtonInTabBar`,来指定plusButton的位置"];
}
}
}
+ (void)removePlusButton {
CYLExternPlusButton = nil;
[CYLPlusChildViewController cyl_setPlusViewControllerEverAdded:NO];
CYLPlusChildViewController = nil;
}
+ (void)registerSubclass {
[self registerPlusButton];
}
- (void)plusChildViewControllerButtonClicked:(UIButton *)sender {
BOOL notNeedConfigureSelectionStatus = [[self class] respondsToSelector:@selector(shouldSelectPlusChildViewController)] && ![[self class] shouldSelectPlusChildViewController];
if (notNeedConfigureSelectionStatus) {
return;
}
CYLTabBarController *tabBarController = [sender cyl_tabBarController];
NSInteger index = [tabBarController.viewControllers indexOfObject:CYLPlusChildViewController];
if (NSNotFound != index && (index < tabBarController.viewControllers.count)) {
[tabBarController setSelectedIndex:index];
}
}
#pragma mark -
#pragma mark - Private Methods
+ (void)addSelectViewControllerTarget:(UIButton *)plusButton {
id target = self;
NSArray *selectorNamesArray = [plusButton actionsForTarget:target forControlEvent:UIControlEventTouchUpInside];
if (selectorNamesArray.count == 0) {
target = plusButton;
selectorNamesArray = [plusButton actionsForTarget:target forControlEvent:UIControlEventTouchUpInside];
}
[selectorNamesArray enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
SEL selector = NSSelectorFromString(obj);
[plusButton removeTarget:target action:selector forControlEvents:UIControlEventTouchUpInside];
}];
[plusButton addTarget:plusButton action:@selector(plusChildViewControllerButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
}
/**
* 按钮选中状态下点击先显示normal状态的颜色,松开时再回到selected状态下颜色。
* 重写此方法即不会出现上述情况,与 UITabBarButton 相似
*/
- (void)setHighlighted:(BOOL)highlighted {}
@end
================================================
FILE: CYLTabBarController/CYLTabBar+CYLTabBarControllerExtention.h
================================================
/*
// CYLTabBarController
// CYLTabBarController
//
// Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 03/06/19.
// Copyright © 2019 https://github.com/ChenYilong . All rights reserved.
*/
#import
#import "CYLTabBar.h"
NS_ASSUME_NONNULL_BEGIN
@interface CYLTabBar (CYLTabBarControllerExtention)
- (NSArray *)cyl_visibleControls;
- (NSArray *)cyl_subTabBarButtons;
- (NSArray *)cyl_subTabBarButtonsWithoutPlusButton;
- (UIControl *)cyl_tabBarButtonWithTabIndex:(NSUInteger)tabIndex;
- (void)cyl_animationLottieImageWithSelectedControl:(UIControl *)selectedControl
lottieURL:(NSURL *)lottieURL
size:(CGSize)size
defaultSelected:(BOOL)defaultSelected;
- (void)cyl_stopAnimationOfAllLottieView;
- (NSArray *)cyl_originalTabBarButtons;
- (BOOL)cyl_hasPlusChildViewController;
@end
NS_ASSUME_NONNULL_END
================================================
FILE: CYLTabBarController/CYLTabBar+CYLTabBarControllerExtention.m
================================================
/*
// CYLTabBarController
// CYLTabBarController
//
// Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 03/06/19.
// Copyright © 2019 https://github.com/ChenYilong . All rights reserved.
*/
#import "CYLTabBar+CYLTabBarControllerExtention.h"
#import "UIView+CYLTabBarControllerExtention.h"
#import "UIControl+CYLTabBarControllerExtention.h"
#import "CYLTabBarController.h"
#import
#import "CYLTabBar.h"
#if __has_include()
#import
#else
#endif
@implementation CYLTabBar (CYLTabBarControllerExtention)
- (BOOL)cyl_hasPlusChildViewController {
NSString *context = CYLPlusChildViewController.cyl_context;
BOOL isSameContext = [context isEqualToString:self.context] && (context && (context.length > 0) && self.context && self.context.length > 0);
BOOL isAdded = [[self cyl_tabBarController].viewControllers containsObject:CYLPlusChildViewController];
BOOL isEverAdded = CYLPlusChildViewController.cyl_plusViewControllerEverAdded;
if (CYLPlusChildViewController && isSameContext && isAdded && isEverAdded) {
return YES;
}
return NO;
}
- (NSArray *)cyl_originalTabBarButtons {
NSArray *tabBarButtons = [self cyl_tabBarButtonFromTabBarSubviews:[self cyl_sortedSubviews]];
return tabBarButtons;
}
- (NSArray *)cyl_sortedSubviews {
if (self.subviews.count == 0) {
return self.subviews;
}
NSMutableArray *tabBarButtonArray = [NSMutableArray arrayWithCapacity:self.subviews.count];
[self.subviews enumerateObjectsUsingBlock:^(__kindof UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([obj cyl_isTabButton]) {
[tabBarButtonArray addObject:obj];
}
}];
NSArray *sortedSubviews = [[tabBarButtonArray copy] sortedArrayUsingComparator:^NSComparisonResult(UIView * formerView, UIView * latterView) {
CGFloat formerViewX = formerView.frame.origin.x;
CGFloat latterViewX = latterView.frame.origin.x;
return (formerViewX > latterViewX) ? NSOrderedDescending : NSOrderedAscending;
}];
return sortedSubviews;
}
- (NSArray *)cyl_tabBarButtonFromTabBarSubviews:(NSArray *)tabBarSubviews {
if (tabBarSubviews.count == 0) {
return tabBarSubviews;
}
NSMutableArray *tabBarButtonMutableArray = [NSMutableArray arrayWithCapacity:tabBarSubviews.count];
[tabBarSubviews enumerateObjectsUsingBlock:^(UIControl * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([obj cyl_isTabButton]) {
[tabBarButtonMutableArray addObject:obj];
[obj cyl_setTabBarChildViewControllerIndex:idx];
}
}];
if ([self cyl_hasPlusChildViewController]) {
@try {
UIControl *control = tabBarButtonMutableArray[CYLPlusButtonIndex];
control.userInteractionEnabled = NO;
control.hidden = YES;
} @catch (NSException *exception) {}
}
return [tabBarButtonMutableArray copy];
}
- (NSArray *)cyl_visibleControls {
NSMutableArray *originalTabBarButtons = [NSMutableArray arrayWithArray:[self.cyl_originalTabBarButtons copy]];
BOOL notAdded = (NSNotFound == [originalTabBarButtons indexOfObject:CYLExternPlusButton]);
if (CYLExternPlusButton && notAdded) {
[originalTabBarButtons addObject:CYLExternPlusButton];
}
if (originalTabBarButtons.count == 0) {
return nil;
}
NSMutableArray *tabBarButtonArray = [NSMutableArray arrayWithCapacity:originalTabBarButtons.count];
[originalTabBarButtons enumerateObjectsUsingBlock:^(__kindof UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
CGFloat width = obj.frame.size.width;
BOOL isInvisiable = obj.cyl_canNotResponseEvent;
BOOL isNotSubView = (width < 10);
BOOL canNotResponseEvent = isInvisiable || isNotSubView ;
if (canNotResponseEvent) {
return;
}
if (([obj cyl_isTabButton] || [obj cyl_isPlusButton] ) ) {
[tabBarButtonArray addObject:obj];
}
}];
NSArray *sortedSubviews = [[tabBarButtonArray copy] sortedArrayUsingComparator:^NSComparisonResult(UIView * formerView, UIView * latterView) {
CGFloat formerViewX = formerView.frame.origin.x;
CGFloat latterViewX = latterView.frame.origin.x;
return (formerViewX > latterViewX) ? NSOrderedDescending : NSOrderedAscending;
}];
return sortedSubviews;
}
- (NSArray *)cyl_subTabBarButtons {
NSMutableArray *subControls = [NSMutableArray arrayWithCapacity:self.cyl_visibleControls.count];
[self.cyl_visibleControls enumerateObjectsUsingBlock:^(UIControl * _Nonnull control, NSUInteger idx, BOOL * _Nonnull stop) {
if ([control cyl_isPlusButton] && !CYLPlusChildViewController.cyl_plusViewControllerEverAdded) {
return;
}
[subControls addObject:control];
}];
return subControls;
}
- (NSArray *)cyl_subTabBarButtonsWithoutPlusButton {
NSMutableArray *subControls = [NSMutableArray arrayWithCapacity:self.cyl_visibleControls.count];
[self.cyl_visibleControls enumerateObjectsUsingBlock:^(UIControl * _Nonnull control, NSUInteger idx, BOOL * _Nonnull stop) {
if ([control cyl_isPlusButton]) {
return;
}
[subControls addObject:control];
}];
return subControls;
}
- (UIControl *)cyl_tabBarButtonWithTabIndex:(NSUInteger)tabIndex {
UIControl *selectedControl = [self cyl_visibleControlWithIndex:tabIndex];
NSInteger plusViewControllerIndex = [self.cyl_tabBarController.viewControllers indexOfObject:CYLPlusChildViewController];
BOOL isPlusViewControllerAdded = CYLPlusChildViewController.cyl_plusViewControllerEverAdded && (plusViewControllerIndex != NSNotFound);
if (isPlusViewControllerAdded) {
return selectedControl;
}
@try {
selectedControl = [self cyl_subTabBarButtonsWithoutPlusButton][tabIndex];
} @catch (NSException *exception) {
NSLog(@"🔴类名与方法名:%@(在第%@行),描述:%@", @(__PRETTY_FUNCTION__), @(__LINE__), exception.reason);
}
return selectedControl;
}
- (UIControl *)cyl_visibleControlWithIndex:(NSUInteger)index {
UIControl *selectedControl;
@try {
NSArray *subControls = self.cyl_visibleControls;
selectedControl = subControls[index];
} @catch (NSException *exception) {
NSLog(@"🔴类名与方法名:%@(在第%@行),描述:%@", @(__PRETTY_FUNCTION__), @(__LINE__), exception.reason);
}
return selectedControl;
}
- (void)cyl_animationLottieImageWithSelectedControl:(UIControl *)selectedControl
lottieURL:(NSURL *)lottieURL
size:(CGSize)size
defaultSelected:(BOOL)defaultSelected {
#if __has_include()
[selectedControl cyl_addLottieImageWithLottieURL:lottieURL size:size];
[self cyl_stopAnimationOfAllLottieView];
LOTAnimationView *lottieView = selectedControl.cyl_lottieAnimationView;
if (!lottieView) {
[selectedControl cyl_addLottieImageWithLottieURL:lottieURL size:size];
}
if (lottieView && [lottieView isKindOfClass:[LOTAnimationView class]]) {
if (defaultSelected) {
lottieView.animationProgress = 1;
[lottieView forceDrawingUpdate];
return;
}
lottieView.animationProgress = 0;
[lottieView play];
}
#else
#endif
}
- (void)cyl_stopAnimationOfAllLottieView {
#if __has_include()
[self.cyl_visibleControls enumerateObjectsUsingBlock:^(UIControl * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[obj.cyl_lottieAnimationView stop];
}];
#else
#endif
}
@end
================================================
FILE: CYLTabBarController/CYLTabBar.h
================================================
//
// CYLTabBar.h
// CYLTabBarController
//
// v1.21.x Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 10/20/15.
// Copyright © 2018 https://github.com/ChenYilong . All rights reserved.
//
#import
NS_ASSUME_NONNULL_BEGIN
@interface CYLTabBar : UITabBar
/*!
* 让 `TabImageView` 垂直居中时,所需要的默认偏移量。
* @attention 该值将在设置 top 和 bottom 时被同时使用,具体的操作等价于如下行为:
* `viewController.tabBarItem.imageInsets = UIEdgeInsetsMake(tabImageViewDefaultOffset, 0, -tabImageViewDefaultOffset, 0);`
*/
@property (nonatomic, assign, readonly) CGFloat tabImageViewDefaultOffset;
@property (nonatomic, copy) NSString *context;
@end
NS_ASSUME_NONNULL_END
================================================
FILE: CYLTabBarController/CYLTabBar.m
================================================
//
// CYLTabBar.m
// CYLTabBarController
//
// v1.21.x Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 10/20/15.
// Copyright © 2018 https://github.com/ChenYilong . All rights reserved.
//
#import "CYLTabBar.h"
#import "CYLPlusButton.h"
#import "CYLTabBarController.h"
#import "CYLConstants.h"
#import
#import "UIControl+CYLTabBarControllerExtention.h"
#import "CYLTabBar+CYLTabBarControllerExtention.h"
static void *const CYLTabBarContext = (void*)&CYLTabBarContext;
@interface CYLTabBar ()
/** 发布按钮 */
@property (nonatomic, strong) UIButton *plusButton;
@property (nonatomic, assign) CGFloat tabBarItemWidth;
@property (nonatomic, copy) NSArray *tabBarButtonArray;
@property (nonatomic, assign, getter=hasAddPlusButton) BOOL addPlusButton;
@end
@implementation CYLTabBar
@synthesize plusButton = _plusButton;
#pragma mark -
#pragma mark - LifeCycle Method
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self = [self sharedInit];
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
self = [self sharedInit];
}
return self;
}
- (void)setPlusButton:(UIButton *)plusButton {
if (!plusButton) {
return;
}
_plusButton = plusButton;
if (!self.hasAddPlusButton) {
NSString *tabBarContext = self.plusButtonTabBarContext;
BOOL isFirstAdded = (_plusButton.superview == nil);
BOOL isSameContext = [tabBarContext isEqualToString:self.context] && (tabBarContext && self.context);
if (_plusButton && isSameContext && isFirstAdded) {
[self addSubview:(UIButton *)_plusButton];
self.addPlusButton = YES;
[_plusButton cyl_setTabBarController:[self cyl_tabBarController]];
}
}
}
- (void)setContext:(NSString *)context {
_context = context;
self.plusButton = CYLExternPlusButton;
}
- (instancetype)sharedInit {
// KVO注册监听
_tabBarItemWidth = CYLTabBarItemWidth;
[self addObserver:self forKeyPath:@"tabBarItemWidth" options:NSKeyValueObservingOptionNew context:CYLTabBarContext];
return self;
}
- (CGSize)sizeThatFits:(CGSize)size {
CGSize sizeThatFits = [super sizeThatFits:size];
CGFloat height = [self cyl_tabBarController].tabBarHeight;
if (height > 0) {
sizeThatFits.height = height;
}
return sizeThatFits;
}
/**
* lazy load tabBarButtonArray
*
* @return NSArray
*/
- (NSArray *)tabBarButtonArray {
if (_tabBarButtonArray == nil) {
_tabBarButtonArray = @[];
}
return _tabBarButtonArray;
}
- (NSString *)plusButtonTabBarContext {
NSString *tabBarContext;
if ([[_plusButton class] respondsToSelector:@selector(tabBarContext)]) {
tabBarContext = [[_plusButton class] tabBarContext];
}
if (tabBarContext && tabBarContext.length > 0) {
return tabBarContext;
}
tabBarContext = NSStringFromClass([CYLTabBarController class]);
return tabBarContext;
}
- (UIButton *)plusButton {
if (!CYLExternPlusButton || !_plusButton) {
return nil;
}
NSString *plusButtonTabBarContext = self.plusButtonTabBarContext;
BOOL addedToTabBar = [_plusButton.superview isEqual:self];
BOOL isSameContext = [plusButtonTabBarContext isEqualToString:self.context] && (plusButtonTabBarContext && self.context);//|| (!tabBarContext && !self.context);
if (_plusButton && addedToTabBar && isSameContext) {
return _plusButton;
}
return nil;
}
- (void)presetUnselectedItemTintColor {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
if (self.unselectedItemTintColor) {
return;
}
__block UIColor *tabLabelTextColor = nil;//for iOS13+
tabLabelTextColor = [UIColor cyl_systemGrayColor];
[self.tabBarButtonArray enumerateObjectsUsingBlock:^(UIControl * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
UIControl *childView = obj;
if (childView.selected) {
return;
}
if (childView.cyl_tabEffectView && childView.cyl_tabLabel ) {
tabLabelTextColor = childView.cyl_tabLabel.textColor;
}
}];
self.unselectedItemTintColor = tabLabelTextColor;
}
#endif
}
- (void)layoutSubviews {
[super layoutSubviews];
self.tabBarButtonArray = [self cyl_originalTabBarButtons];
if (self.tabBarButtonArray.count == 0) {
return;
}
[self presetUnselectedItemTintColor];
[self setupTabImageViewDefaultOffset:self.tabBarButtonArray[0]];
CGFloat tabBarWidth = self.bounds.size.width;
CGFloat tabBarHeight = self.bounds.size.height;
if (!self.addPlusButton) {
return;
}
BOOL addedToTabBar = [_plusButton.superview isEqual:self];
if (!addedToTabBar) {
CYLTabBarItemWidth = (tabBarWidth) / CYLTabbarItemsCount;
[self.tabBarButtonArray enumerateObjectsUsingBlock:^(UIControl * _Nonnull childView, NSUInteger buttonIndex, BOOL * _Nonnull stop) {
//仅修改childView的x和宽度,yh值不变
CGFloat childViewX = buttonIndex * CYLTabBarItemWidth;
[self changeXForChildView:childView
childViewX:childViewX
tabBarItemWidth:CYLTabBarItemWidth
index:buttonIndex
];
}];
return;
}
CYLTabBarItemWidth = (tabBarWidth - CYLPlusButtonWidth) / CYLTabbarItemsCount;
CGFloat multiplierOfTabBarHeight = [self multiplierOfTabBarHeight:tabBarHeight];
CGFloat constantOfPlusButtonCenterYOffset = [self constantOfPlusButtonCenterYOffsetForTabBarHeight:tabBarHeight];
_plusButton.center = CGPointMake(tabBarWidth * 0.5, tabBarHeight * multiplierOfTabBarHeight + constantOfPlusButtonCenterYOffset);
NSUInteger plusButtonIndex = [self plusButtonIndex];
[self.tabBarButtonArray enumerateObjectsUsingBlock:^(UIControl * _Nonnull childView, NSUInteger buttonIndex, BOOL * _Nonnull stop) {
//调整UITabBarItem的位置
CGFloat childViewX;
CGFloat visiableTabIndex = buttonIndex;
CGFloat tabBarItemWidth = CYLTabBarItemWidth;
if ([self cyl_hasPlusChildViewController]) {
if (buttonIndex <= plusButtonIndex) {
childViewX = buttonIndex * CYLTabBarItemWidth;
} else {
childViewX = (buttonIndex - 1) * CYLTabBarItemWidth + CYLPlusButtonWidth;
}
if (buttonIndex == plusButtonIndex) {
tabBarItemWidth = CYLPlusButtonWidth;
}
} else {
if (buttonIndex >= plusButtonIndex) {
childViewX = buttonIndex * CYLTabBarItemWidth + CYLPlusButtonWidth;
visiableTabIndex = buttonIndex + 1;
} else {
childViewX = buttonIndex * CYLTabBarItemWidth;
}
}
[childView cyl_setTabBarChildViewControllerIndex:buttonIndex];
[self changeXForChildView:childView
childViewX:childViewX
tabBarItemWidth:tabBarItemWidth
index:visiableTabIndex
];
//仅修改childView的x和宽度,yh值不变
}];
//bring the plus button to top
[self bringSubviewToFront:_plusButton];
}
- (void)changeXForChildView:(UIControl *)childView
childViewX:(CGFloat)childViewX
tabBarItemWidth:(CGFloat)tabBarItemWidth
index:(NSUInteger)index {
//仅修改childView的x和宽度,yh值不变
childView.frame = CGRectMake(childViewX,
CGRectGetMinY(childView.frame),
tabBarItemWidth,
CGRectGetHeight(childView.frame)
);
[childView cyl_setTabBarItemVisibleIndex:index];
}
#pragma mark -
#pragma mark - Private Methods
+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key {
return NO;
}
// KVO监听执行
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if(context != CYLTabBarContext) {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
return;
}
if(context == CYLTabBarContext) {
[[NSNotificationCenter defaultCenter] postNotificationName:CYLTabBarItemWidthDidChangeNotification object:self];
if (CYL_IS_IPHONE_X) {
[self layoutIfNeeded];
}
}
}
- (void)dealloc {
// KVO反注册
[self removeObserver:self forKeyPath:@"tabBarItemWidth"];
}
- (void)setTabBarItemWidth:(CGFloat )tabBarItemWidth {
if (_tabBarItemWidth != tabBarItemWidth) {
[self willChangeValueForKey:@"tabBarItemWidth"];
_tabBarItemWidth = tabBarItemWidth;
[self didChangeValueForKey:@"tabBarItemWidth"];
}
}
- (void)setTabImageViewDefaultOffset:(CGFloat)tabImageViewDefaultOffset {
if (tabImageViewDefaultOffset != 0.f) {
[self willChangeValueForKey:@"tabImageViewDefaultOffset"];
_tabImageViewDefaultOffset = tabImageViewDefaultOffset;
[self didChangeValueForKey:@"tabImageViewDefaultOffset"];
}
}
- (CGFloat)multiplierOfTabBarHeight:(CGFloat)tabBarHeight {
CGFloat multiplierOfTabBarHeight;
if ([[self.plusButton class] respondsToSelector:@selector(multiplierOfTabBarHeight:)]) {
multiplierOfTabBarHeight = [[self.plusButton class] multiplierOfTabBarHeight:tabBarHeight];
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
else if ([[self.plusButton class] respondsToSelector:@selector(multiplerInCenterY)]) {
multiplierOfTabBarHeight = [[self.plusButton class] multiplerInCenterY];
}
#pragma clang diagnostic pop
else {
CGSize sizeOfPlusButton = self.plusButton.frame.size;
CGFloat heightDifference = sizeOfPlusButton.height - self.bounds.size.height;
if (heightDifference < 0) {
multiplierOfTabBarHeight = 0.5;
} else {
CGPoint center = CGPointMake(self.bounds.size.height * 0.5, self.bounds.size.height * 0.5);
center.y = center.y - heightDifference * 0.5;
multiplierOfTabBarHeight = center.y / self.bounds.size.height;
}
}
return multiplierOfTabBarHeight;
}
- (CGFloat)constantOfPlusButtonCenterYOffsetForTabBarHeight:(CGFloat)tabBarHeight {
CGFloat constantOfPlusButtonCenterYOffset = 0.f;
if ([[self.plusButton class] respondsToSelector:@selector(constantOfPlusButtonCenterYOffsetForTabBarHeight:)]) {
constantOfPlusButtonCenterYOffset = [[self.plusButton class] constantOfPlusButtonCenterYOffsetForTabBarHeight:tabBarHeight];
}
return constantOfPlusButtonCenterYOffset;
}
- (NSUInteger)plusButtonIndex {
NSUInteger plusButtonIndex;
if ([[self.plusButton class] respondsToSelector:@selector(indexOfPlusButtonInTabBar)]) {
plusButtonIndex = [[self.plusButton class] indexOfPlusButtonInTabBar];
} else {
if (CYLTabbarItemsCount % 2 != 0) {
[NSException raise:NSStringFromClass([CYLTabBarController class]) format:@"If the count of CYLTabbarControllers is odd,you must realizse `+indexOfPlusButtonInTabBar` in your custom plusButton class.【Chinese】如果CYLTabbarControllers的个数是奇数,你必须在你自定义的plusButton中实现`+indexOfPlusButtonInTabBar`,来指定plusButton的位置"];
}
plusButtonIndex = CYLTabbarItemsCount * 0.5;
}
CGFloat childViewX = plusButtonIndex * CYLTabBarItemWidth;
CGFloat tabBarItemWidth = CGRectGetWidth(self.plusButton.frame);
[self changeXForChildView:self.plusButton
childViewX:childViewX
tabBarItemWidth:tabBarItemWidth
index:plusButtonIndex
];
CYLPlusButtonIndex = plusButtonIndex;
return plusButtonIndex;
}
- (void)setupTabImageViewDefaultOffset:(UIView *)tabBarButton {
if (self.tabImageViewDefaultOffset > 0) {
return;
}
__block BOOL shouldCustomizeImageView = YES;
__block CGFloat tabImageViewDefaultOffset = 0.f;
CGFloat tabButtonCenterY = tabBarButton.center.y;
[tabBarButton.subviews enumerateObjectsUsingBlock:^(__kindof UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([obj cyl_isTabLabel]) {
shouldCustomizeImageView = NO;
}
CGFloat tabImageViewCenterY = obj.center.y;
BOOL isTabImageView = [obj cyl_isTabImageView];
if (isTabImageView) {
tabImageViewDefaultOffset = (tabButtonCenterY - tabImageViewCenterY) * 0.5;
}
if (isTabImageView && tabImageViewDefaultOffset == 0.f) {
shouldCustomizeImageView = NO;
}
}];
if (shouldCustomizeImageView) {
self.tabImageViewDefaultOffset = tabImageViewDefaultOffset;
}
}
/*!
* Capturing touches on a subview outside the frame of its superview.
*/
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
//1. 边界情况:不能响应点击事件
BOOL canNotResponseEvent = self.cyl_canNotResponseEvent;
if (canNotResponseEvent) {
return [super hitTest:point withEvent:event];
}
//2. 优先处理 PlusButton (包括其突出的部分)、TabBarItems 未凸出的部分
//这一步主要是在处理只有两个 TabBarItems 的场景。
// 2.1先考虑clipsToBounds情况:子view超出部分没有显示出来
if (self.clipsToBounds && ![self pointInside:point withEvent:event]) {
return [super hitTest:point withEvent:event];
}
if (self.plusButton) {
CGRect plusButtonFrame = self.plusButton.frame;
BOOL isInPlusButtonFrame = CGRectContainsPoint(plusButtonFrame, point);
if (isInPlusButtonFrame) {
return self.plusButton;
}
}
NSArray *tabBarButtons = self.tabBarButtonArray;
if (self.tabBarButtonArray.count == 0) {
tabBarButtons = [self cyl_visibleControls];
}
for (NSUInteger index = 0; index < tabBarButtons.count; index++) {
UIView *selectedTabBarButton = tabBarButtons[index];
CGRect selectedTabBarButtonFrame = selectedTabBarButton.frame;
BOOL isTabBarButtonFrame = CGRectContainsPoint(selectedTabBarButtonFrame, point);
if (isTabBarButtonFrame && !selectedTabBarButton.hidden) {
return selectedTabBarButton;
}
}
//3. 最后处理 TabBarItems 凸出的部分、添加到 TabBar 上的自定义视图、点击到 TabBar 上的空白区域
UIView *result = [super hitTest:point withEvent:event];
if (result) {
return result;
}
for (UIView *subview in self.subviews.reverseObjectEnumerator) {
CGPoint subPoint = [subview convertPoint:point fromView:self];
result = [subview hitTest:subPoint withEvent:event];
if (result) {
return result;
}
}
return [super hitTest:point withEvent:event];
}
@end
================================================
FILE: CYLTabBarController/CYLTabBarController.h
================================================
//
// CYLTabBarController.h
// CYLTabBarController
//
// v1.21.x Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 10/20/15.
// Copyright © 2018 https://github.com/ChenYilong . All rights reserved.
//
#import "CYLPlusButton.h"
#import "UIViewController+CYLTabBarControllerExtention.h"
#import "UIViewController+CYLNavigationControllerExtention.h"
#import "UIView+CYLTabBarControllerExtention.h"
#import "UITabBarItem+CYLTabBarControllerExtention.h"
#import "UIControl+CYLTabBarControllerExtention.h"
#import "CYLBaseViewController.h"
#import "CYLBaseTableViewController.h"
#import "CYLBaseNavigationController.h"
#import "CYLTabBar+CYLTabBarControllerExtention.h"
#import "UITabBarItem+CYLBadgeExtention.h"
#import "UIBarButtonItem+CYLBadgeExtention.h"
#import "UIView+CYLBadgeExtention.h"
#import "NSObject+CYLTabBarControllerExtention.h"
#import "UIColor+CYLTabBarControllerExtention.h"
NS_ASSUME_NONNULL_BEGIN
@class CYLTabBarController;
typedef void(^CYLViewDidLayoutSubViewsBlock)(CYLTabBarController *tabBarController);
FOUNDATION_EXTERN NSString *const CYLTabBarItemTitle;
FOUNDATION_EXTERN NSString *const CYLTabBarItemImage;
FOUNDATION_EXTERN NSString *const CYLTabBarItemSelectedImage;
FOUNDATION_EXTERN NSString *const CYLTabBarLottieURL;
FOUNDATION_EXTERN NSString *const CYLTabBarLottieSize;
FOUNDATION_EXTERN NSString *const CYLTabBarItemImageInsets;
FOUNDATION_EXTERN NSString *const CYLTabBarItemTitlePositionAdjustment;
FOUNDATION_EXTERN NSUInteger CYLTabbarItemsCount;
FOUNDATION_EXTERN NSUInteger CYLPlusButtonIndex;
FOUNDATION_EXTERN CGFloat CYLPlusButtonWidth;
FOUNDATION_EXTERN CGFloat CYLTabBarItemWidth;
FOUNDATION_EXTERN CGFloat CYLTabBarHeight;
@protocol CYLTabBarControllerDelegate
@optional
/*!
* @param tabBarController The tab bar controller containing viewController.
* @param control Selected UIControl in TabBar.
*/
- (void)tabBarController:(UITabBarController *)tabBarController didSelectControl:(UIControl *)control;
@end
@interface CYLTabBarController : UITabBarController
@property (nonatomic, copy) CYLViewDidLayoutSubViewsBlock viewDidLayoutSubviewsBlock;
- (void)setViewDidLayoutSubViewsBlock:(CYLViewDidLayoutSubViewsBlock)viewDidLayoutSubviewsBlock;
- (void)setViewDidLayoutSubViewsBlockInvokeOnce:(BOOL)invokeOnce block:(CYLViewDidLayoutSubViewsBlock)viewDidLayoutSubviewsBlock;
/*!
* An array of the root view controllers displayed by the tab bar interface.
*/
@property (nonatomic, readwrite, copy) NSArray *viewControllers;
/*!
* The Attributes of items which is displayed on the tab bar.
*/
@property (nonatomic, readwrite, copy) NSArray *tabBarItemsAttributes;
/*!
* Customize UITabBar height
*/
@property (nonatomic, assign) CGFloat tabBarHeight;
/*!
* To set both UIBarItem image view attributes in the tabBar,
* default is UIEdgeInsetsZero.
*/
@property (nonatomic, readonly, assign) UIEdgeInsets imageInsets;
@property (nonatomic, strong) CYLTabBar *tabBar;
/*!
* To set both UIBarItem label text attributes in the tabBar,
* use the following to tweak the relative position of the label within the tab button (for handling visual centering corrections if needed because of custom text attributes)
*/
@property (nonatomic, readonly, assign) UIOffset titlePositionAdjustment;
@property (nonatomic, readonly, copy) NSString *context;
- (instancetype)initWithViewControllers:(NSArray *)viewControllers
tabBarItemsAttributes:(NSArray *)tabBarItemsAttributes;
+ (instancetype)tabBarControllerWithViewControllers:(NSArray *)viewControllers
tabBarItemsAttributes:(NSArray *)tabBarItemsAttributes;
- (instancetype)initWithViewControllers:(NSArray *)viewControllers
tabBarItemsAttributes:(NSArray *)tabBarItemsAttributes
imageInsets:(UIEdgeInsets)imageInsets
titlePositionAdjustment:(UIOffset)titlePositionAdjustment;
+ (instancetype)tabBarControllerWithViewControllers:(NSArray *)viewControllers
tabBarItemsAttributes:(NSArray *)tabBarItemsAttributes
imageInsets:(UIEdgeInsets)imageInsets
titlePositionAdjustment:(UIOffset)titlePositionAdjustment;
- (instancetype)initWithViewControllers:(NSArray *)viewControllers
tabBarItemsAttributes:(NSArray *)tabBarItemsAttributes
imageInsets:(UIEdgeInsets)imageInsets
titlePositionAdjustment:(UIOffset)titlePositionAdjustment
context:(NSString *)context;
+ (instancetype)tabBarControllerWithViewControllers:(NSArray *)viewControllers
tabBarItemsAttributes:(NSArray *)tabBarItemsAttributes
imageInsets:(UIEdgeInsets)imageInsets
titlePositionAdjustment:(UIOffset)titlePositionAdjustment
context:(NSString *)context;
- (void)updateSelectionStatusIfNeededForTabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController;
- (void)updateSelectionStatusIfNeededForTabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController shouldSelect:(BOOL)shouldSelect;
- (void)hideTabBarShadowImageView;
- (void)setTintColor:(UIColor *)tintColor;
/*!
* Judge if there is plus button.
*/
+ (BOOL)havePlusButton;
/*!
* @attention Include plusButton if exists.
*/
+ (NSUInteger)allItemsInTabBarCount;
- (id)appDelegate;
- (UIWindow *)rootWindow;
@end
@interface NSObject (CYLTabBarControllerReferenceExtension)
/*!
* If `self` is kind of `UIViewController`, this method will return the nearest ancestor in the view controller hierarchy that is a tab bar controller. If `self` is not kind of `UIViewController`, it will return the `rootViewController` of the `rootWindow` as long as you have set the `CYLTabBarController` as the `rootViewController`. Otherwise return nil. (read-only)
*/
@property (nonatomic, setter=cyl_setTabBarController:) CYLTabBarController *cyl_tabBarController;
@end
#pragma mark - Deprecated API
@interface CYLTabBarController (CYLTabBarControllerDeprecated)
- (void)hideTabBadgeBackgroundSeparator CYL_DEPRECATED("Deprecated in 1.27.0. Use `-[CYLTabBarController hideTabBarShadowImageView]` instead.");
@end
FOUNDATION_EXTERN NSString *const CYLTabBarItemWidthDidChangeNotification;
NS_ASSUME_NONNULL_END
================================================
FILE: CYLTabBarController/CYLTabBarController.m
================================================
//
// CYLTabBarController.m
// CYLTabBarController
//
// v1.21.x Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 10/20/15.
// Copyright © 2018 https://github.com/ChenYilong . All rights reserved.
//
#import "CYLTabBarController.h"
#import "CYLTabBar.h"
#import
#import "UIViewController+CYLTabBarControllerExtention.h"
#import "UIControl+CYLTabBarControllerExtention.h"
#import "UIImage+CYLTabBarControllerExtention.h"
#if __has_include()
#import
#else
#endif
NSString *const CYLTabBarItemTitle = @"CYLTabBarItemTitle";
NSString *const CYLTabBarItemImage = @"CYLTabBarItemImage";
NSString *const CYLTabBarItemSelectedImage = @"CYLTabBarItemSelectedImage";
NSString *const CYLTabBarItemImageInsets = @"CYLTabBarItemImageInsets";
NSString *const CYLTabBarItemTitlePositionAdjustment = @"CYLTabBarItemTitlePositionAdjustment";
NSString *const CYLTabBarLottieURL = @"CYLTabBarLottieURL";
NSString *const CYLTabBarLottieSize = @"CYLTabBarLottieSize";
NSUInteger CYLTabbarItemsCount = 0;
NSUInteger CYLPlusButtonIndex = 0;
CGFloat CYLTabBarItemWidth = 0.0f;
CGFloat CYLTabBarHeight = 0.0f;
NSString *const CYLTabBarItemWidthDidChangeNotification = @"CYLTabBarItemWidthDidChangeNotification";
static void * const CYLTabImageViewDefaultOffsetContext = (void*)&CYLTabImageViewDefaultOffsetContext;
@interface CYLTabBarController ()
@property (nonatomic, assign, getter=isObservingTabImageViewDefaultOffset) BOOL observingTabImageViewDefaultOffset;
@property (nonatomic, assign, getter=shouldInvokeOnceViewDidLayoutSubViewsBlock) BOOL invokeOnceViewDidLayoutSubViewsBlock;
@property (nonatomic, strong) NSMutableArray *lottieURLs;
@property (nonatomic, strong) NSMutableArray *lottieSizes;
@property (nonatomic, assign, getter=isLottieViewAdded) BOOL lottieViewAdded;
@property (nonatomic, strong) UIImage *tabItemPlaceholderImage;
@end
@implementation CYLTabBarController
@synthesize viewControllers = _viewControllers;
#pragma mark -
#pragma mark - Life Cycle
- (void)viewDidLoad {
[super viewDidLoad];
if (CYL_IS_IPHONE_X) {
self.tabBarHeight = 83;
}
// 处理tabBar,使用自定义 tabBar 添加 发布按钮
[self setUpTabBar];
// KVO注册监听
if (!self.isObservingTabImageViewDefaultOffset) {
[self.tabBar addObserver:self forKeyPath:@"tabImageViewDefaultOffset" options:NSKeyValueObservingOptionNew context:CYLTabImageViewDefaultOffsetContext];
self.observingTabImageViewDefaultOffset = YES;
}
}
- (void)setSelectedIndex:(NSUInteger)selectedIndex {
[super setSelectedIndex:selectedIndex];
[self updateSelectionStatusIfNeededForTabBarController:nil shouldSelectViewController:nil];
UIControl *selectedControl = [self.tabBar cyl_tabBarButtonWithTabIndex:selectedIndex];
if (selectedControl) {
[self didSelectControl:selectedControl];
}
}
- (void)setViewDidLayoutSubViewsBlockInvokeOnce:(BOOL)invokeOnce block:(CYLViewDidLayoutSubViewsBlock)viewDidLayoutSubviewsBlock {
self.viewDidLayoutSubviewsBlock = viewDidLayoutSubviewsBlock;
self.invokeOnceViewDidLayoutSubViewsBlock = YES;
}
- (void)setViewDidLayoutSubViewsBlock:(CYLViewDidLayoutSubViewsBlock)viewDidLayoutSubviewsBlock {
_viewDidLayoutSubviewsBlock = viewDidLayoutSubviewsBlock;
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
[self.tabBar layoutSubviews];//Fix issue #93 #392
CYLTabBar *tabBar = (CYLTabBar *)self.tabBar;
// add callback for visiable control, included all plusButton.
[tabBar.cyl_visibleControls enumerateObjectsUsingBlock:^(UIControl * _Nonnull control, NSUInteger idx, BOOL * _Nonnull stop) {
//to avoid invoking didSelectControl twice, because plusChildViewControllerButtonClicked will invoke setSelectedIndex
if ([control cyl_isChildViewControllerPlusButton]) {
return;
}
UILabel *tabLabel = control.cyl_tabLabel;
tabLabel.textAlignment = NSTextAlignmentCenter;
SEL actin = @selector(didSelectControl:);
[control addTarget:self action:actin forControlEvents:UIControlEventTouchUpInside];
if (idx == self.selectedIndex && ![control isKindOfClass:[CYLPlusButton class]]) {
control.selected = YES;
}
}];
do {
if (self.isLottieViewAdded) {
break;
}
//FIXME:
NSArray *subTabBarButtonsWithoutPlusButton = tabBar.cyl_subTabBarButtonsWithoutPlusButton;
BOOL isLottieEnabled = [self isLottieEnabled];
if(!isLottieEnabled || (subTabBarButtonsWithoutPlusButton.count != self.lottieURLs.count)) {
self.lottieViewAdded = YES;
break;
}
dispatch_async(dispatch_get_main_queue(),^{
[subTabBarButtonsWithoutPlusButton enumerateObjectsUsingBlock:^(UIControl * _Nonnull control, NSUInteger idx, BOOL * _Nonnull stop) {
UIControl *tabButton = control;
BOOL defaultSelected = NO;
if (idx == self.selectedIndex) {
defaultSelected = YES;
}
[self addLottieImageWithControl:tabButton animation:defaultSelected defaultSelected:defaultSelected];
}];
self.lottieViewAdded = YES;
});
break;
} while (NO);
if (self.shouldInvokeOnceViewDidLayoutSubViewsBlock) {
//在对象生命周期内,不添加 flag 属性的情况下,防止多次调进这个方法
if (objc_getAssociatedObject(self, _cmd)) {
return;
} else {
!self.viewDidLayoutSubviewsBlock ?: self.viewDidLayoutSubviewsBlock(self);
objc_setAssociatedObject(self, _cmd, @"shouldInvokeOnceViewDidLayoutSubViewsBlock", OBJC_ASSOCIATION_RETAIN);
}
return;
}
!self.viewDidLayoutSubviewsBlock ?: self.viewDidLayoutSubviewsBlock(self);
}
- (void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
if (!(self.tabBarHeight > 0)) {
return;
}
self.tabBar.frame = ({
CGRect frame = self.tabBar.frame;
CGFloat tabBarHeight = self.tabBarHeight;
frame.size.height = tabBarHeight;
frame.origin.y = self.view.frame.size.height - tabBarHeight;
frame;
});
}
- (void)setTabBarHeight:(CGFloat)tabBarHeight {
_tabBarHeight = tabBarHeight;
CYLTabBarHeight = tabBarHeight;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
UIViewController *controller = self.selectedViewController;
if ([controller isKindOfClass:[UINavigationController class]]) {
UINavigationController *navigationController = (UINavigationController *)controller;
return navigationController.topViewController.supportedInterfaceOrientations;
} else {
return controller.supportedInterfaceOrientations;
}
}
- (void)dealloc {
UIButton *plusButton = CYLExternPlusButton;
if (plusButton.superview && (plusButton.superview == self.tabBar)) {
plusButton.selected = NO;
[plusButton removeFromSuperview];
}
BOOL isAdded = [self isPlusViewControllerAdded:_viewControllers];
BOOL hasPlusChildViewController = [self hasPlusChildViewController] && isAdded;
if (isAdded && hasPlusChildViewController && CYLPlusChildViewController.cyl_plusViewControllerEverAdded == YES) {
[CYLPlusChildViewController cyl_setPlusViewControllerEverAdded:NO];
}
// KVO反注册
if (self.tabBar && self.isObservingTabImageViewDefaultOffset) {
@try {
[self.tabBar removeObserver:self forKeyPath:@"tabImageViewDefaultOffset"];
} @catch(NSException *e) { }
}
}
#pragma mark -
#pragma mark - public Methods
- (instancetype)initWithViewControllers:(NSArray *)viewControllers tabBarItemsAttributes:(NSArray *)tabBarItemsAttributes {
return [self initWithViewControllers:viewControllers
tabBarItemsAttributes:tabBarItemsAttributes
imageInsets:UIEdgeInsetsZero
titlePositionAdjustment:UIOffsetZero
context:nil];
}
- (instancetype)initWithViewControllers:(NSArray *)viewControllers
tabBarItemsAttributes:(NSArray *)tabBarItemsAttributes
imageInsets:(UIEdgeInsets)imageInsets
titlePositionAdjustment:(UIOffset)titlePositionAdjustment {
return [self initWithViewControllers:viewControllers
tabBarItemsAttributes:tabBarItemsAttributes
imageInsets:imageInsets
titlePositionAdjustment:titlePositionAdjustment
context:nil];
}
- (instancetype)initWithViewControllers:(NSArray *)viewControllers
tabBarItemsAttributes:(NSArray *)tabBarItemsAttributes
imageInsets:(UIEdgeInsets)imageInsets
titlePositionAdjustment:(UIOffset)titlePositionAdjustment
context:(NSString *)context {
if (self = [super init]) {
_imageInsets = imageInsets;
_titlePositionAdjustment = titlePositionAdjustment;
_tabBarItemsAttributes = tabBarItemsAttributes;
self.context = context;
self.viewControllers = viewControllers;
}
return self;
}
- (void)setContext:(NSString *)context {
if (context && context.length > 0) {
_context = [context copy];
} else {
_context = NSStringFromClass([CYLTabBarController class]);
}
[self.tabBar setValue:_context forKey:@"context"];
}
+ (instancetype)tabBarControllerWithViewControllers:(NSArray *)viewControllers
tabBarItemsAttributes:(NSArray *)tabBarItemsAttributes
imageInsets:(UIEdgeInsets)imageInsets
titlePositionAdjustment:(UIOffset)titlePositionAdjustment
context:(NSString *)context {
return [[self alloc] initWithViewControllers:viewControllers
tabBarItemsAttributes:tabBarItemsAttributes
imageInsets:imageInsets
titlePositionAdjustment:titlePositionAdjustment
context:context];
}
+ (instancetype)tabBarControllerWithViewControllers:(NSArray *)viewControllers
tabBarItemsAttributes:(NSArray *)tabBarItemsAttributes
imageInsets:(UIEdgeInsets)imageInsets
titlePositionAdjustment:(UIOffset)titlePositionAdjustment {
return [[self alloc] initWithViewControllers:viewControllers
tabBarItemsAttributes:tabBarItemsAttributes
imageInsets:imageInsets
titlePositionAdjustment:titlePositionAdjustment
context:nil];
}
+ (instancetype)tabBarControllerWithViewControllers:(NSArray *)viewControllers tabBarItemsAttributes:(NSArray *)tabBarItemsAttributes {
return [self tabBarControllerWithViewControllers:viewControllers
tabBarItemsAttributes:tabBarItemsAttributes
imageInsets:UIEdgeInsetsZero
titlePositionAdjustment:UIOffsetZero];
}
- (void)hideTabBadgeBackgroundSeparator {
[self hideTabBarShadowImageView];
}
- (void)hideTabBarShadowImageView {
[self.tabBar layoutIfNeeded];
UIImageView *imageView = self.tabBar.cyl_tabShadowImageView;
imageView.hidden = YES;//iOS13+
imageView.alpha = 0;
}
+ (BOOL)havePlusButton {
if (CYLExternPlusButton) {
return YES;
}
return NO;
}
+ (NSUInteger)allItemsInTabBarCount {
NSUInteger allItemsInTabBar = CYLTabbarItemsCount;
if ([CYLTabBarController havePlusButton]) {
allItemsInTabBar += 1;
}
return allItemsInTabBar;
}
- (id)appDelegate {
return [UIApplication sharedApplication].delegate;
}
- (UIWindow *)rootWindow {
UIWindow *result = nil;
do {
if ([self.appDelegate respondsToSelector:@selector(window)]) {
result = [self.appDelegate window];
}
if (result) {
break;
}
} while (NO);
return result;
}
#pragma mark -
#pragma mark - Private Methods
/**
* 利用 KVC 把系统的 tabBar 类型改为自定义类型。
*/
- (void)setUpTabBar {
CYLTabBar *tabBar = [[CYLTabBar alloc] init];
[self setValue:tabBar forKey:@"tabBar"];
[tabBar cyl_setTabBarController:self];
}
- (BOOL)hasPlusChildViewController {
NSString *context = CYLPlusChildViewController.cyl_context;
BOOL isSameContext = [context isEqualToString:self.context] && (context && self.context); // || (!context && !self.context);
BOOL hasPlusChildViewController = CYLPlusChildViewController && isSameContext;//&& !isAdded;
return hasPlusChildViewController;
}
- (BOOL)isPlusViewControllerAdded:(NSArray *)viewControllers {
if ([_viewControllers containsObject:CYLPlusChildViewController]) {
return YES;
}
__block BOOL isAdded = NO;
[_viewControllers enumerateObjectsUsingBlock:^(UIViewController * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([self isEqualViewController:obj compairedViewController:CYLPlusChildViewController]) {
isAdded = YES;
*stop = YES;
return;
}
}];
return isAdded;;
}
- (void)setViewControllers:(NSArray *)viewControllers {
if (_viewControllers && _viewControllers.count) {
for (UIViewController *viewController in _viewControllers) {
[viewController willMoveToParentViewController:nil];
[viewController.view removeFromSuperview];
[viewController removeFromParentViewController];
}
BOOL isAdded = [self isPlusViewControllerAdded:_viewControllers];
BOOL hasPlusChildViewController = [self hasPlusChildViewController] && !isAdded;
if (hasPlusChildViewController) {
[CYLPlusChildViewController willMoveToParentViewController:nil];
[CYLPlusChildViewController.view removeFromSuperview];
[CYLPlusChildViewController removeFromParentViewController];
}
}
if (viewControllers && [viewControllers isKindOfClass:[NSArray class]]) {
if ((!_tabBarItemsAttributes) || (_tabBarItemsAttributes.count != viewControllers.count)) {
[NSException raise:NSStringFromClass([CYLTabBarController class]) format:@"The count of CYLTabBarControllers is not equal to the count of tabBarItemsAttributes.【Chinese】设置_tabBarItemsAttributes属性时,请确保元素个数与控制器的个数相同,并在方法`-setViewControllers:`之前设置"];
}
BOOL isAdded = [self isPlusViewControllerAdded:_viewControllers];
BOOL addedFlag = [CYLPlusChildViewController cyl_plusViewControllerEverAdded];
BOOL hasPlusChildViewController = [self hasPlusChildViewController] && !isAdded && !addedFlag;
if (hasPlusChildViewController) {
NSMutableArray *viewControllersWithPlusButton = [NSMutableArray arrayWithArray:viewControllers];
[viewControllersWithPlusButton insertObject:CYLPlusChildViewController atIndex:CYLPlusButtonIndex];
_viewControllers = [viewControllersWithPlusButton copy];
[CYLPlusChildViewController cyl_setPlusViewControllerEverAdded:YES];
[CYLExternPlusButton cyl_setTabBarChildViewControllerIndex:CYLPlusButtonIndex];
} else {
_viewControllers = [viewControllers copy];
[CYLExternPlusButton cyl_setTabBarChildViewControllerIndex:NSNotFound];
}
CYLTabbarItemsCount = [viewControllers count];
CYLTabBarItemWidth = ([UIScreen mainScreen].bounds.size.width - CYLPlusButtonWidth) / (CYLTabbarItemsCount);
NSUInteger idx = 0;
for (UIViewController *viewController in _viewControllers) {
NSString *title = nil;
id normalImageInfo = nil;
id selectedImageInfo = nil;
UIOffset titlePositionAdjustment = UIOffsetZero;
UIEdgeInsets imageInsets = UIEdgeInsetsZero;
NSURL *lottieURL = nil;
NSValue *lottieSizeValue = nil;
if (viewController != CYLPlusChildViewController) {
if (@available(iOS 13.0, *)) {
//fix https://github.com/ChenYilong/CYLTabBarController/issues/437
title = _tabBarItemsAttributes[idx][CYLTabBarItemTitle] ?: @"";
} else {
title = _tabBarItemsAttributes[idx][CYLTabBarItemTitle];
}
normalImageInfo = _tabBarItemsAttributes[idx][CYLTabBarItemImage];
selectedImageInfo = _tabBarItemsAttributes[idx][CYLTabBarItemSelectedImage];
lottieURL = _tabBarItemsAttributes[idx][CYLTabBarLottieURL];
lottieSizeValue = _tabBarItemsAttributes[idx][CYLTabBarLottieSize];
NSValue *offsetValue = _tabBarItemsAttributes[idx][CYLTabBarItemTitlePositionAdjustment];
UIOffset offset = [offsetValue UIOffsetValue];
titlePositionAdjustment = offset;
NSValue *insetsValue = _tabBarItemsAttributes[idx][CYLTabBarItemImageInsets];
UIEdgeInsets insets = [insetsValue UIEdgeInsetsValue];
imageInsets = insets;
} else {
idx--;
/**如果是CYLPlusChildViewController ,title设置为空字符串,解决把第一个tabbarItem设置成plusButton后,其他的
tabbarItem会不显示title问题
见: https://github.com/ChenYilong/CYLTabBarController/issues/563
**/
title = @"";
}
[self addOneChildViewController:viewController
WithTitle:title
normalImageInfo:normalImageInfo
selectedImageInfo:selectedImageInfo
titlePositionAdjustment:titlePositionAdjustment
imageInsets:imageInsets
lottieURL:lottieURL
lottieSizeValue:lottieSizeValue
];
[[viewController cyl_getViewControllerInsteadOfNavigationController] cyl_setTabBarController:self];
idx++;
}
} else {
for (UIViewController *viewController in _viewControllers) {
[[viewController cyl_getViewControllerInsteadOfNavigationController] cyl_setTabBarController:nil];
}
_viewControllers = nil;
}
}
- (void)setTintColor:(UIColor *)tintColor {
if ([[[UIDevice currentDevice] systemVersion] floatValue] < 8.f) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[self.tabBar setSelectedImageTintColor:tintColor];
#pragma clang diagnostic pop
}
self.tabBar.tintColor = tintColor;
}
/**
* lazy load tabItemPlaceholderImage
*
* @return UIImage
*/
- (UIImage *)tabItemPlaceholderImage {
if (_tabItemPlaceholderImage == nil) {
CGSize placeholderSize = CGSizeMake(22, 22);
UIImage *placeholderImage = [UIImage cyl_imageWithColor:[UIColor whiteColor] size:placeholderSize];
UIImage *tabItemPlaceholderImage = placeholderImage;
_tabItemPlaceholderImage = tabItemPlaceholderImage;
}
return _tabItemPlaceholderImage;
}
/**
* 添加一个子控制器
*
* @param viewController 控制器
* @param title 标题
* @param normalImageInfo 图片
* @param selectedImageInfo 选中图片
*/
- (void)addOneChildViewController:(UIViewController *)viewController
WithTitle:(NSString *)title
normalImageInfo:(id)normalImageInfo
selectedImageInfo:(id)selectedImageInfo
titlePositionAdjustment:(UIOffset)titlePositionAdjustment
imageInsets:(UIEdgeInsets)imageInsets
lottieURL:(NSURL *)lottieURL
lottieSizeValue:(NSValue *)lottieSizeValue {
viewController.tabBarItem.title = title;
UIImage *normalImage = nil;
if (normalImageInfo) {
normalImage = [self getImageFromImageInfo:normalImageInfo];
} else {
normalImage = self.tabItemPlaceholderImage;
}
viewController.tabBarItem.image = normalImage;
UIImage *selectedImage = nil;
if (selectedImageInfo) {
selectedImage = [self getImageFromImageInfo:selectedImageInfo];
} else {
selectedImage = self.tabItemPlaceholderImage;
}
viewController.tabBarItem.selectedImage = selectedImage;
if (self.shouldCustomizeImageInsets || ([self isNOTEmptyForImageInsets:imageInsets])) {
UIEdgeInsets insets = (([self isNOTEmptyForImageInsets:imageInsets]) ? imageInsets : self.imageInsets);
viewController.tabBarItem.imageInsets = insets;
}
if (self.shouldCustomizeTitlePositionAdjustment || [self isNOTEmptyForTitlePositionAdjustment:titlePositionAdjustment]) {
UIOffset offset = (([self isNOTEmptyForTitlePositionAdjustment:titlePositionAdjustment]) ? titlePositionAdjustment : self.titlePositionAdjustment);
viewController.tabBarItem.titlePositionAdjustment = offset;
}
if (lottieURL) {
[self.lottieURLs addObject:lottieURL];
NSValue *tureLottieSizeValue = nil;
do {
if (!CGSizeEqualToSize(CGSizeZero, [lottieSizeValue CGSizeValue])) {
tureLottieSizeValue = lottieSizeValue;
break;
}
if (normalImage && !CGSizeEqualToSize(CGSizeZero, normalImage.size)) {
tureLottieSizeValue = [NSValue valueWithCGSize:normalImage.size];
break;
}
CGSize placeholderSize = CGSizeMake(22, 22);
tureLottieSizeValue = [NSValue valueWithCGSize:placeholderSize];
break;
} while (NO);
[self.lottieSizes addObject:tureLottieSizeValue];
}
[self addChildViewController:viewController];
}
- (UIImage *)getImageFromImageInfo:(id)imageInfo {
UIImage *image = nil;
if ([imageInfo isKindOfClass:[NSString class]]) {
image = [UIImage imageNamed:imageInfo];
image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
} else if ([imageInfo isKindOfClass:[UIImage class]]) {
image = (UIImage *)imageInfo;
}
return image;
}
- (BOOL)shouldCustomizeImageInsets {
BOOL shouldCustomizeImageInsets = [self isNOTEmptyForImageInsets:self.imageInsets];
return shouldCustomizeImageInsets;
}
- (BOOL)shouldCustomizeTitlePositionAdjustment {
BOOL shouldCustomizeTitlePositionAdjustment = [self isNOTEmptyForTitlePositionAdjustment:self.titlePositionAdjustment];
return shouldCustomizeTitlePositionAdjustment;
}
- (BOOL)isNOTEmptyForImageInsets:(UIEdgeInsets)imageInsets {
if (imageInsets.top != 0 || imageInsets.left != 0 || imageInsets.bottom != 0 || imageInsets.right != 0) {
return YES;
}
return NO;
}
- (BOOL)isNOTEmptyForTitlePositionAdjustment:(UIOffset)titlePositionAdjustment {
if (titlePositionAdjustment.horizontal != 0 || titlePositionAdjustment.vertical != 0) {
return YES;
}
return NO;
}
- (BOOL)isNOTEmptyForSize:(UIOffset)titlePositionAdjustment {
if (titlePositionAdjustment.horizontal != 0 || titlePositionAdjustment.vertical != 0) {
return YES;
}
return NO;
}
#pragma mark -
#pragma mark - KVO Method
// KVO监听执行
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if(context != CYLTabImageViewDefaultOffsetContext) {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
return;
}
if(context == CYLTabImageViewDefaultOffsetContext) {
CGFloat tabImageViewDefaultOffset = [change[NSKeyValueChangeNewKey] floatValue];
[self offsetTabBarTabImageViewToFit:tabImageViewDefaultOffset];
}
}
- (void)offsetTabBarTabImageViewToFit:(CGFloat)tabImageViewDefaultOffset {
if (self.shouldCustomizeImageInsets) {
return;
}
NSArray *tabBarItems = self.tabBar.items;
[tabBarItems enumerateObjectsUsingBlock:^(UITabBarItem * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
UIEdgeInsets imageInset = UIEdgeInsetsMake(tabImageViewDefaultOffset, 0, -tabImageViewDefaultOffset, 0);
obj.imageInsets = imageInset;
if (!self.shouldCustomizeTitlePositionAdjustment) {
obj.titlePositionAdjustment = UIOffsetMake(0, MAXFLOAT);
}
}];
}
#pragma mark - delegate
- (void)updateSelectionStatusIfNeededForTabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController {
[self updateSelectionStatusIfNeededForTabBarController:tabBarController shouldSelectViewController:viewController shouldSelect:YES];
}
- (void)updateSelectionStatusIfNeededForTabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController shouldSelect:(BOOL)shouldSelect {
[[viewController.tabBarItem cyl_tabButton] cyl_setShouldNotSelect:!shouldSelect];
if (!shouldSelect) {
return;
}
UIButton *plusButton = CYLExternPlusButton;
if (!viewController) {
viewController = self.selectedViewController;
}
BOOL isCurrentViewController = [self isEqualViewController:viewController compairedViewController:CYLPlusChildViewController];
BOOL shouldConfigureSelectionStatus = (!isCurrentViewController);
plusButton.selected = !shouldConfigureSelectionStatus;
if (!shouldConfigureSelectionStatus) {
[self.tabBar cyl_stopAnimationOfAllLottieView];
}
}
- (BOOL)isEqualViewController:(UIViewController *)viewController compairedViewController:(UIViewController *)compairedViewController {
if ([viewController isEqual:compairedViewController]) {
return YES;
}
if ([[viewController cyl_getViewControllerInsteadOfNavigationController] isEqual:[compairedViewController cyl_getViewControllerInsteadOfNavigationController]]) {
return YES;
}
return NO;
}
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController {
[self updateSelectionStatusIfNeededForTabBarController:tabBarController shouldSelectViewController:viewController];
return YES;
}
- (void)tabBarController:(UITabBarController *)tabBarController didSelectControl:(UIControl *)control {
}
- (BOOL)isLottieEnabled {
NSInteger lottieURLCount = self.lottieURLs.count;
BOOL isLottieEnabled = lottieURLCount > 0 ;
return isLottieEnabled;
}
- (void)didSelectControl:(UIControl *)control {
SEL actin = @selector(tabBarController:didSelectControl:);
BOOL shouldSelectViewController = YES;
@try {
shouldSelectViewController = (!control.cyl_shouldNotSelect) && (!control.hidden) ;
} @catch (NSException *exception) {
NSLog(@"🔴类名与方法名:%@(在第%@行),描述:%@", @(__PRETTY_FUNCTION__), @(__LINE__), exception.reason);
}
BOOL isSelected = control.cyl_isSelected;
if (shouldSelectViewController) {
[self.tabBar.cyl_visibleControls enumerateObjectsUsingBlock:^(UIControl * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
obj.selected = NO;
}];
control.selected = YES;
UIControl *tabButton = control;
BOOL isChildViewControllerPlusButton = [control cyl_isChildViewControllerPlusButton];
BOOL isLottieEnabled = [self isLottieEnabled];
if (!isSelected && isLottieEnabled && !isChildViewControllerPlusButton) {
[self addLottieImageWithControl:tabButton animation:YES];
}
}
if ([self.delegate respondsToSelector:actin] && shouldSelectViewController) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[self.delegate performSelector:actin withObject:self withObject:control ?: self.selectedViewController.tabBarItem.cyl_tabButton];
#pragma clang diagnostic pop
}
}
- (void)addLottieImageWithControl:(UIControl *)control animation:(BOOL)animation {
[self addLottieImageWithControl:control animation:animation defaultSelected:NO];
}
- (void)addLottieImageWithControl:(UIControl *)control animation:(BOOL)animation defaultSelected:(BOOL)defaultSelected {
NSUInteger index = [self.tabBar.cyl_subTabBarButtonsWithoutPlusButton indexOfObject:control];
if (NSNotFound == index) {
return;
}
if (control.cyl_isPlusButton) {
return;
}
NSURL *lottieURL = self.lottieURLs[index];
NSValue *lottieSizeValue = self.lottieSizes[index];
CGSize lottieSize = [lottieSizeValue CGSizeValue];
[control cyl_addLottieImageWithLottieURL:lottieURL size:lottieSize];
if (animation) {
[self.tabBar cyl_animationLottieImageWithSelectedControl:control lottieURL:lottieURL size:lottieSize defaultSelected:defaultSelected];
}
}
- (id)rootViewController {
CYLTabBarController *tabBarController = nil;
id delegate = ((id)[[UIApplication sharedApplication] delegate]);
UIWindow *window = delegate.window;
UIViewController *rootViewController = [window.rootViewController cyl_getViewControllerInsteadOfNavigationController];;
if ([rootViewController isKindOfClass:[CYLTabBarController class]]) {
tabBarController = (CYLTabBarController *)rootViewController;
}
return tabBarController;
}
/**
* lazy load lottieURLs
*
* @return NSMutableArray
*/
- (NSMutableArray *)lottieURLs {
if (_lottieURLs == nil) {
NSMutableArray *lottieURLs = [[NSMutableArray alloc] init];
_lottieURLs = lottieURLs;
}
return _lottieURLs;
}
/**
* lazy load lottieSizes
*
* @return NSMutableArray
*/
- (NSMutableArray *)lottieSizes {
if (_lottieSizes == nil) {
NSMutableArray *lottieSizes = [[NSMutableArray alloc] init];
_lottieSizes = lottieSizes;
}
return _lottieSizes;
}
@end
@implementation NSObject (CYLTabBarControllerReferenceExtension)
- (void)cyl_setTabBarController:(CYLTabBarController *)tabBarController {
//OBJC_ASSOCIATION_ASSIGN instead of OBJC_ASSOCIATION_RETAIN_NONATOMIC to avoid retain circle
id __weak weakObject = tabBarController;
id (^block)(void) = ^{ return weakObject; };
objc_setAssociatedObject(self, @selector(cyl_tabBarController),
block, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
static inline UIWindow *getMainWindow(){
UIWindow *window = nil;
if ([UIApplication.sharedApplication.delegate respondsToSelector:@selector(window)]) {
//兼容新版项目结构,也就是AppDelegate没有window的情况
window = UIApplication.sharedApplication.delegate.window;
}
if (!window) {
if (@available(iOS 13.0, *))
{
for (UIWindowScene* wScene in [UIApplication sharedApplication].connectedScenes)
{
if (wScene.activationState == UISceneActivationStateForegroundActive)
{
window = wScene.windows.firstObject;
break;
}
}
}
}
return window;
}
//TODO: 更新实现,多实例场景下进行栈操作,弹出最新一个。
- (CYLTabBarController *)cyl_tabBarController {
CYLTabBarController *tabBarController;
id (^block)(void) = objc_getAssociatedObject(self, @selector(cyl_tabBarController));
tabBarController = (block ? block() : nil);
if (tabBarController && [tabBarController isKindOfClass:[CYLTabBarController class]]) {
return tabBarController;
}
if ([self isKindOfClass:[UIViewController class]] && [(UIViewController *)self parentViewController]) {
tabBarController = [[(UIViewController *)self parentViewController] cyl_tabBarController];
if ([tabBarController isKindOfClass:[CYLTabBarController class]]) {
return tabBarController;
}
}
// id delegate = ((id)[[UIApplication sharedApplication] delegate]);
// UIWindow *window = delegate.window;
UIWindow *window = getMainWindow();
UIViewController *rootViewController = [window.rootViewController cyl_getViewControllerInsteadOfNavigationController];;
if ([rootViewController isKindOfClass:[CYLTabBarController class]]) {
tabBarController = (CYLTabBarController *)rootViewController;
}
return tabBarController;
}
@end
================================================
FILE: CYLTabBarController/NSObject+CYLTabBarControllerExtention.h
================================================
//
// CYLTabBarController.h
// CYLTabBarController
//
// v1.21.x Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 10/20/15.
// Copyright © 2018 https://github.com/ChenYilong . All rights reserved.
//
#import
NS_ASSUME_NONNULL_BEGIN
@interface NSObject (CYLTabBarControllerExtention)
@property (nonatomic, assign, getter=cyl_isForceLandscape, setter=cyl_setIsForceLandscape:) BOOL cyl_isForceLandscape;
- (void)cyl_forceUpdateInterfaceOrientation:(UIInterfaceOrientation)orientation;
- (UIResponder *)cyl_sharedAppDelegate;
+ (UIViewController * __nullable)cyl_topmostViewController;
+ (UINavigationController * __nullable)cyl_currentNavigationController;
+ (void)cyl_dismissAll:(void (^ __nullable)(void))completion;
@end
NS_ASSUME_NONNULL_END
================================================
FILE: CYLTabBarController/NSObject+CYLTabBarControllerExtention.m
================================================
//
// CYLTabBarController.h
// CYLTabBarController
//
// v1.21.x Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 10/20/15.
// Copyright © 2018 https://github.com/ChenYilong . All rights reserved.
//
#import "NSObject+CYLTabBarControllerExtention.h"
#import
@implementation NSObject (CYLTabBarControllerExtention)
- (BOOL)cyl_isForceLandscape {
NSNumber *isForceLandscapeObject = objc_getAssociatedObject(self, @selector(cyl_isForceLandscape));
return [isForceLandscapeObject boolValue];
}
- (void)cyl_setIsForceLandscape:(BOOL)isForceLandscape {
NSNumber *isForceLandscapeObject = @(isForceLandscape);
objc_setAssociatedObject(self, @selector(cyl_isForceLandscape), isForceLandscapeObject, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (UIResponder *)cyl_sharedAppDelegate {
id appDelegate = [UIApplication sharedApplication].delegate;
return (UIResponder *)appDelegate;
}
- (void)cyl_forceUpdateInterfaceOrientation:(UIInterfaceOrientation)orientation {
UIResponder *appDelegate = [self cyl_sharedAppDelegate];
BOOL isForceLandscape = (UIInterfaceOrientationLandscapeLeft == orientation) || (UIInterfaceOrientationLandscapeRight == orientation);
appDelegate.cyl_isForceLandscape = isForceLandscape;
if ([appDelegate respondsToSelector:@selector(application:supportedInterfaceOrientationsForWindow:)]) {
[appDelegate application:[UIApplication sharedApplication] supportedInterfaceOrientationsForWindow:UIApplication.sharedApplication.keyWindow];
}
if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) {
NSNumber *num = [[NSNumber alloc]initWithInt:UIInterfaceOrientationPortrait];
[[UIDevice currentDevice] performSelector:@selector(setOrientation:)withObject:(id)num];
[UIViewController attemptRotationToDeviceOrientation];
SEL selector = NSSelectorFromString(@"setOrientation:");
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[UIDevice instanceMethodSignatureForSelector:selector]];
[invocation setSelector:selector];
[invocation setTarget:[UIDevice currentDevice]];
int val = [@(orientation) intValue];
[invocation setArgument:&val atIndex:2];
[invocation invoke];
}
}
+ (UIViewController * __nullable)cyl_topmostViewController {
UIViewController *topViewController = [[[UIApplication sharedApplication] keyWindow] rootViewController];
if (topViewController == nil) {
return nil;
}
while (true) {
if (topViewController.presentedViewController != nil) {
topViewController = topViewController.presentedViewController;
} else if ([topViewController isKindOfClass:[UINavigationController class]]) {
UINavigationController *navi = (UINavigationController *)topViewController;
topViewController = navi.topViewController;
} else if ([topViewController isKindOfClass:[UITabBarController class]]) {
UITabBarController *tab = (UITabBarController *)topViewController;
topViewController = tab.selectedViewController;
} else {
break;
}
}
return topViewController;
}
+ (UINavigationController * __nullable)cyl_currentNavigationController {
return [[UIViewController cyl_topmostViewController] navigationController];
}
+ (void)cyl_dismissAll:(void (^ __nullable)(void))completion {
UIViewController *topViewController = [[[UIApplication sharedApplication] keyWindow] rootViewController];
if (topViewController == nil) {
!completion ?: completion();
return;
}
NSMutableArray *list = [NSMutableArray new];
while (true) {
if (topViewController.presentedViewController != nil) {
topViewController = topViewController.presentedViewController;
[list addObject:topViewController];
} else if ([topViewController isKindOfClass:[UINavigationController class]]) {
UINavigationController *navi = (UINavigationController *)topViewController;
topViewController = navi.topViewController;
} else if ([topViewController isKindOfClass:[UITabBarController class]]) {
UITabBarController *tab = (UITabBarController *)topViewController;
topViewController = tab.selectedViewController;
} else {
break;
}
}
if (list.count == 0) {
if (completion) {
completion();
}
return;
}
for (NSInteger i = list.count - 1; i >=0 ; i--) {
UIViewController *vc = list[i];
if (i == 0) {
if ([vc isKindOfClass:[UINavigationController class]]) {
[(UINavigationController *)vc popToRootViewControllerAnimated:NO];
}
[vc dismissViewControllerAnimated:NO completion:completion];
} else {
if ([vc isKindOfClass:[UINavigationController class]]) {
[(UINavigationController *)vc popToRootViewControllerAnimated:NO];
}
[vc dismissViewControllerAnimated:NO completion:nil];
}
}
}
@end
================================================
FILE: CYLTabBarController/UIBarButtonItem+CYLBadgeExtention.h
================================================
/*
// CYLTabBarController
// CYLTabBarController
//
// Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 03/06/19.
// Copyright © 2019 https://github.com/ChenYilong . All rights reserved.
*/
#import
#import "UIView+CYLBadgeExtention.h"
#import "CYLBadgeProtocol.h"
NS_ASSUME_NONNULL_BEGIN
@interface UIBarButtonItem (CYLBadgeExtention)
- (BOOL)cyl_isShowBadge;
/**
* show badge with red dot style and CYLBadgeAnimationTypeNone by default.
*/
- (void)cyl_showBadge;
/**
* cyl_showBadge
*
* @param value String value, default is `nil`. if value equal @"" means red dot style.
* @param animationType animationType
*/
- (void)cyl_showBadgeValue:(NSString *)value
animationType:(CYLBadgeAnimationType)animationType;
/**
* clear badge(hide badge)
*/
- (void)cyl_clearBadge;
/**
* make bage(if existing) not hiden
*/
- (void)cyl_resumeBadge;
- (BOOL)cyl_isPauseBadge;
@end
NS_ASSUME_NONNULL_END
================================================
FILE: CYLTabBarController/UIBarButtonItem+CYLBadgeExtention.m
================================================
/*
// CYLTabBarController
// CYLTabBarController
//
// Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 03/06/19.
// Copyright © 2019 https://github.com/ChenYilong . All rights reserved.
*/
#import "UIBarButtonItem+CYLBadgeExtention.h"
#import
#define kActualView [self cyl_getActualBadgeSuperView]
@implementation UIBarButtonItem (CYLBadgeExtention)
#pragma mark -- public methods
/**
* show badge with red dot style and CYLBadgeAnimationTypeNone by default.
*/
- (void)cyl_showBadge {
[kActualView cyl_showBadge];
}
- (void)cyl_showBadgeValue:(NSString *)value
animationType:(CYLBadgeAnimationType)animationType {
[kActualView cyl_showBadgeValue:value animationType:animationType];
}
- (void)cyl_clearBadge {
[kActualView cyl_clearBadge];
}
- (void)cyl_resumeBadge {
[kActualView cyl_resumeBadge];
}
- (BOOL)cyl_isPauseBadge {
return [kActualView cyl_isPauseBadge];
}
- (BOOL)cyl_isShowBadge {
return [kActualView cyl_isShowBadge];
}
#pragma mark -- private method
/**
* Because UIBarButtonItem is kind of NSObject, it is not able to directly attach badge.
This method is used to find actual view (non-nil) inside UIBarButtonItem instance.
*
* @return view
*/
- (UIView *)cyl_getActualBadgeSuperView {
return [self valueForKeyPath:@"_view"];//use KVC to hack actual view
}
#pragma mark -- setter/getter
- (UILabel *)cyl_badge {
return kActualView.cyl_badge;
}
- (void)cyl_setBadge:(UILabel *)label {
[kActualView cyl_setBadge:label];
}
- (UIFont *)cyl_badgeFont {
return kActualView.cyl_badgeFont;
}
- (void)cyl_setBadgeFont:(UIFont *)badgeFont {
[kActualView cyl_setBadgeFont:badgeFont];
}
- (UIColor *)cyl_badgeBackgroundColor {
return [kActualView cyl_badgeBackgroundColor];
}
- (void)cyl_setBadgeBackgroundColor:(UIColor *)badgeBackgroundColor {
[kActualView cyl_setBadgeBackgroundColor:badgeBackgroundColor];
}
- (UIColor *)cyl_badgeTextColor {
return [kActualView cyl_badgeTextColor];
}
- (void)cyl_setBadgeTextColor:(UIColor *)badgeTextColor {
[kActualView cyl_setBadgeTextColor:badgeTextColor];
}
- (CYLBadgeAnimationType)cyl_badgeAnimationType {
return [kActualView cyl_badgeAnimationType];
}
- (void)cyl_setBadgeAnimationType:(CYLBadgeAnimationType)animationType {
[kActualView cyl_setBadgeAnimationType:animationType];
}
- (CGRect)cyl_badgeFrame {
return [kActualView cyl_badgeFrame];
}
- (void)cyl_setBadgeFrame:(CGRect)badgeFrame {
[kActualView cyl_setBadgeFrame:badgeFrame];
}
- (CGPoint)cyl_badgeCenterOffset {
return [kActualView cyl_badgeCenterOffset];
}
- (void)cyl_setBadgeCenterOffset:(CGPoint)badgeCenterOffset {
[kActualView cyl_setBadgeCenterOffset:badgeCenterOffset];
}
- (NSInteger)cyl_badgeMaximumBadgeNumber {
return [kActualView cyl_badgeMaximumBadgeNumber];
}
- (void)cyl_setBadgeMaximumBadgeNumber:(NSInteger)badgeMaximumBadgeNumber {
[kActualView cyl_setBadgeMaximumBadgeNumber:badgeMaximumBadgeNumber];
}
- (CGFloat)cyl_badgeMargin {
return [kActualView cyl_badgeMargin];
}
- (void)cyl_setBadgeMargin:(CGFloat)badgeMargin {
[kActualView cyl_setBadgeMargin:badgeMargin];
}
- (CGFloat)cyl_badgeRadius {
return [kActualView cyl_badgeRadius];
}
- (void)cyl_setBadgeRadius:(CGFloat)badgeRadius {
[kActualView cyl_setBadgeRadius:badgeRadius];
}
- (CGFloat)cyl_badgeCornerRadius {
return [kActualView cyl_badgeCornerRadius];
}
- (void)cyl_setBadgeCornerRadius:(CGFloat)cyl_badgeCornerRadius {
[kActualView cyl_setBadgeCornerRadius:cyl_badgeCornerRadius];
}
@end
================================================
FILE: CYLTabBarController/UIColor+CYLTabBarControllerExtention.h
================================================
//
// UIColor+CYLTabBarControllerExtention.h
// CYLTabBarController
//
// v1.21.x Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 16/2/26.
// Copyright © 2019年 https://github.com/ChenYilong .All rights reserved.
//
#import
#import "CYLConstants.h"
NS_ASSUME_NONNULL_BEGIN
@interface UIColor (CYLTabBarControllerExtention)
@property (class, nonatomic, readonly) UIColor *cyl_systemRedColor;
@property (class, nonatomic, readonly) UIColor *cyl_systemGreenColor;
@property (class, nonatomic, readonly) UIColor *cyl_systemBlueColor;
@property (class, nonatomic, readonly) UIColor *cyl_systemOrangeColor;
@property (class, nonatomic, readonly) UIColor *cyl_systemYellowColor;
@property (class, nonatomic, readonly) UIColor *cyl_systemPinkColor;
@property (class, nonatomic, readonly) UIColor *cyl_systemPurpleColor;
@property (class, nonatomic, readonly) UIColor *cyl_systemTealColor;
@property (class, nonatomic, readonly) UIColor *cyl_systemIndigoColor;
/* Shades of gray. systemGray is the base gray color.
*/
@property (class, nonatomic, readonly) UIColor *cyl_systemGrayColor;
@property (class, nonatomic, readonly) UIColor *cyl_systemGray2Color;
@property (class, nonatomic, readonly) UIColor *cyl_systemGray3Color;
@property (class, nonatomic, readonly) UIColor *cyl_systemGray4Color;
@property (class, nonatomic, readonly) UIColor *cyl_systemGray5Color;
@property (class, nonatomic, readonly) UIColor *cyl_systemGray6Color;
#pragma mark Foreground colors
/* Foreground colors for static text and related elements.
*/
@property (class, nonatomic, readonly) UIColor *cyl_labelColor;
@property (class, nonatomic, readonly) UIColor *cyl_secondaryLabelColor;
@property (class, nonatomic, readonly) UIColor *cyl_tertiaryLabelColor ;
@property (class, nonatomic, readonly) UIColor *cyl_quaternaryLabelColor;
/* Foreground color for standard system links.
*/
@property (class, nonatomic, readonly) UIColor *cyl_linkColor;
/* Foreground color for placeholder text in controls or text fields or text views.
*/
@property (class, nonatomic, readonly) UIColor *cyl_placeholderTextColor;
/* Foreground colors for separators (thin border or divider lines).
* `separatorColor` may be partially transparent, so it can go on top of any content.
* `opaqueSeparatorColor` is intended to look similar, but is guaranteed to be opaque, so it will
* completely cover anything behind it. Depending on the situation, you may need one or the other.
*/
@property (class, nonatomic, readonly) UIColor *cyl_separatorColor;
@property (class, nonatomic, readonly) UIColor *cyl_opaqueSeparatorColor;
#pragma mark Background colors
/* We provide two design systems (also known as "stacks") for structuring an iOS app's backgrounds.
*
* Each stack has three "levels" of background colors. The first color is intended to be the
* main background, farthest back. Secondary and tertiary colors are layered on top
* of the main background, when appropriate.
*
* Inside of a discrete piece of UI, choose a stack, then use colors from that stack.
* We do not recommend mixing and matching background colors between stacks.
* The foreground colors above are designed to work in both stacks.
*
* 1. systemBackground
* Use this stack for views with standard table views, and designs which have a white
* primary background in light mode.
*/
@property (class, nonatomic, readonly) UIColor *cyl_systemBackgroundColor;
@property (class, nonatomic, readonly) UIColor *cyl_secondarySystemBackgroundColor;
@property (class, nonatomic, readonly) UIColor *cyl_tertiarySystemBackgroundColor;
/* 2. systemGroupedBackground
* Use this stack for views with grouped content, such as grouped tables and
* platter-based designs. These are like grouped table views, but you may use these
* colors in places where a table view wouldn't make sense.
*/
@property (class, nonatomic, readonly) UIColor *cyl_systemGroupedBackgroundColor;
@property (class, nonatomic, readonly) UIColor *cyl_secondarySystemGroupedBackgroundColor;
@property (class, nonatomic, readonly) UIColor *cyl_tertiarySystemGroupedBackgroundColor;
#pragma mark Fill colors
/* Fill colors for UI elements.
* These are meant to be used over the background colors, since their alpha component is less than 1.
*
* systemFillColor is appropriate for filling thin and small shapes.
* Example: The track of a slider.
*/
@property (class, nonatomic, readonly) UIColor *cyl_systemFillColor;
/* secondarySystemFillColor is appropriate for filling medium-size shapes.
* Example: The background of a switch.
*/
@property (class, nonatomic, readonly) UIColor *cyl_secondarySystemFillColor;
/* tertiarySystemFillColor is appropriate for filling large shapes.
* Examples: Input fields, search bars, buttons.
*/
@property (class, nonatomic, readonly) UIColor *cyl_tertiarySystemFillColor;
/* quaternarySystemFillColor is appropriate for filling large areas containing complex content.
* Example: Expanded table cells.
*/
@property (class, nonatomic, readonly) UIColor *cyl_quaternarySystemFillColor;
#pragma mark Other colors
/* lightTextColor is always light, and darkTextColor is always dark, regardless of the current UIUserInterfaceStyle.
* When possible, we recommend using `labelColor` and its variants, instead.
*/
@property(class, nonatomic, readonly) UIColor *cyl_lightTextColor; // for a dark background
@property(class, nonatomic, readonly) UIColor *cyl_darkTextColor; // for a light background
@end
#pragma mark - Deprecated API
@interface UIColor (CYLTabBarControllerDeprecated)
@property (class, nonatomic, readonly) UIColor *cyl_systemBrownColor CYL_DEPRECATED("Deprecated in 1.27.5.");
@end
NS_ASSUME_NONNULL_END
================================================
FILE: CYLTabBarController/UIColor+CYLTabBarControllerExtention.m
================================================
//
// UIColor+CYLTabBarControllerExtention.h
// CYLTabBarController
//
// v1.21.x Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 16/2/26.
// Copyright © 2019年 https://github.com/ChenYilong .All rights reserved.
//
#import "UIColor+CYLTabBarControllerExtention.h"
@implementation UIColor (CYLTabBarControllerExtention)
+ (UIColor *)cyl_systemRedColor {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
#if __has_include()
return [UIColor systemRedColor];
#else
#endif
}
#endif
return [UIColor
colorWithRed:1.0
green:0.23137254901960785
blue:0.18823529411764706
alpha:1.0
];
}
+ (UIColor *)cyl_systemGreenColor {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
#if __has_include()
return [UIColor systemGreenColor];
#else
#endif
}
#endif
return [UIColor
colorWithRed:0.20392156862745098
green:0.7803921568627451
blue:0.34901960784313724
alpha:1.0
];
}
+ (UIColor *)cyl_systemBlueColor {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
#if __has_include()
return [UIColor systemBlueColor];
#else
#endif
}
#endif
return [UIColor
colorWithRed:0.0
green:0.47843137254901963
blue:1.0
alpha:1.0
];
}
+ (UIColor *)cyl_systemOrangeColor {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
#if __has_include()
return [UIColor systemOrangeColor];
#else
#endif
}
#endif
return [UIColor
colorWithRed:1.0
green:0.5843137254901961
blue:0.0
alpha:1.0
];
}
+ (UIColor *)cyl_systemYellowColor {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
#if __has_include()
return [UIColor systemYellowColor];
#else
#endif
}
#endif
return [UIColor
colorWithRed:1.0
green:0.8
blue:0.0
alpha:1.0
];
}
+ (UIColor *)cyl_systemPinkColor {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
#if __has_include()
return [UIColor systemPinkColor];
#else
#endif
}
#endif
return [UIColor
colorWithRed:1.0
green:0.17647058823529413
blue:0.3333333333333333
alpha:1.0
];
}
+ (UIColor *)cyl_systemPurpleColor {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
#if __has_include()
return [UIColor systemPurpleColor];
#else
#endif
}
#endif
return [UIColor
colorWithRed:0.6862745098039216
green:0.3215686274509804
blue:0.8705882352941177
alpha:1.0
];
}
+ (UIColor *)cyl_systemTealColor {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
#if __has_include()
return [UIColor systemTealColor];
#else
#endif
}
#endif
return [UIColor
colorWithRed:0.35294117647058826
green:0.7843137254901961
blue:0.9803921568627451
alpha:1.0
];
}
+ (UIColor *)cyl_systemIndigoColor {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
#if __has_include()
return [UIColor systemIndigoColor];
#else
#endif
}
#endif
return [UIColor
colorWithRed:0.34509803921568627
green:0.33725490196078434
blue:0.8392156862745098
alpha:1.0
];
}
+ (UIColor *)cyl_systemGrayColor {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
#if __has_include()
return [UIColor systemGrayColor];
#else
#endif
}
#endif
return [UIColor
colorWithRed:0.5568627450980392
green:0.5568627450980392
blue:0.5764705882352941
alpha:1.0
];
}
+ (UIColor *)cyl_systemGray2Color {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
#if __has_include()
return [UIColor systemGray2Color];
#else
#endif
}
#endif
return [UIColor
colorWithRed:0.6823529411764706
green:0.6823529411764706
blue:0.6980392156862745
alpha:1.0
];
}
+ (UIColor *)cyl_systemGray3Color {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
#if __has_include()
return [UIColor systemGray3Color];
#else
#endif
}
#endif
return [UIColor
colorWithRed:0.7803921568627451
green:0.7803921568627451
blue:0.8
alpha:1.0
];
}
+ (UIColor *)cyl_systemGray4Color {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
#if __has_include()
return [UIColor systemGray4Color];
#else
#endif
}
#endif
return [UIColor
colorWithRed:0.8196078431372549
green:0.8196078431372549
blue:0.8392156862745098
alpha:1.0
];
}
+ (UIColor *)cyl_systemGray5Color {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
#if __has_include()
return [UIColor systemGray5Color];
#else
#endif
}
#endif
return [UIColor
colorWithRed:0.8980392156862745
green:0.8980392156862745
blue:0.9176470588235294
alpha:1.0
];
}
+ (UIColor *)cyl_systemGray6Color {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
#if __has_include()
return [UIColor systemGray6Color];
#else
#endif
}
#endif
return [UIColor
colorWithRed:0.9490196078431372
green:0.9490196078431372
blue:0.9686274509803922
alpha:1.0
];
}
#pragma mark Foreground colors
+ (UIColor *)cyl_labelColor {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
#if __has_include()
return [UIColor labelColor];
#else
#endif
}
#endif
return [UIColor
colorWithRed:0.0
green:0.0
blue:0.0
alpha:1.0
];
}
+ (UIColor *)cyl_secondaryLabelColor {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
#if __has_include()
return [UIColor secondaryLabelColor];
#else
#endif
}
#endif
return [UIColor
colorWithRed:0.23529411764705882
green:0.23529411764705882
blue:0.2627450980392157
alpha:0.6
];
}
+ (UIColor *)cyl_tertiaryLabelColor {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
#endif
if (@available(iOS 13.0, *)) {
#if __has_include()
return [UIColor tertiaryLabelColor];
#else
#endif
}
return [UIColor
colorWithRed:0.23529411764705882
green:0.23529411764705882
blue:0.2627450980392157
alpha:0.3
];
}
+ (UIColor *)cyl_quaternaryLabelColor {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
#if __has_include()
return [UIColor quaternaryLabelColor];
#else
#endif
}
#endif
return [UIColor
colorWithRed:0.23529411764705882
green:0.23529411764705882
blue:0.2627450980392157
alpha:0.18
];
}
/* Foreground color for standard system links.
*/
+ (UIColor *)cyl_linkColor {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
#if __has_include()
return [UIColor linkColor];
#else
#endif
}
#endif
return [UIColor
colorWithRed:0.0
green:0.47843137254901963
blue:1.0
alpha:1.0
];
}
+ (UIColor *)cyl_placeholderTextColor {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
#if __has_include()
return [UIColor placeholderTextColor];
#else
#endif
}
#endif
return [UIColor
colorWithRed:0.23529411764705882
green:0.23529411764705882
blue:0.2627450980392157
alpha:0.3
];
}
+ (UIColor *)cyl_separatorColor {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
#if __has_include()
return [UIColor separatorColor];
#else
#endif
}
#endif
return [UIColor
colorWithRed:0.23529411764705882
green:0.23529411764705882
blue:0.2627450980392157
alpha:0.29
];
}
+ (UIColor *)cyl_opaqueSeparatorColor {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
#if __has_include()
return [UIColor opaqueSeparatorColor];
#else
#endif
}
#endif
return [UIColor
colorWithRed:0.7764705882352941
green:0.7764705882352941
blue:0.7843137254901961
alpha:1.0
];
}
#pragma mark Background colors
+ (UIColor *)cyl_systemBackgroundColor {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
#if __has_include()
return [UIColor systemBackgroundColor];
#else
#endif
}
#endif
return [UIColor
colorWithRed:1.0
green:1.0
blue:1.0
alpha:1.0
];
}
+ (UIColor *)cyl_secondarySystemBackgroundColor {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
#if __has_include()
return [UIColor secondarySystemBackgroundColor];
#else
#endif
}
#endif
return [UIColor
colorWithRed:0.9490196078431372
green:0.9490196078431372
blue:0.9686274509803922
alpha:1.0
];
}
+ (UIColor *)cyl_tertiarySystemBackgroundColor {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
#if __has_include()
return [UIColor tertiarySystemBackgroundColor];
#else
#endif
}
#endif
return [UIColor
colorWithRed:1.0
green:1.0
blue:1.0
alpha:1.0
];
}
+ (UIColor *)cyl_systemGroupedBackgroundColor {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
#if __has_include()
return [UIColor systemGroupedBackgroundColor];
#else
#endif
}
#endif
return [UIColor
colorWithRed:0.9490196078431372
green:0.9490196078431372
blue:0.9686274509803922
alpha:1.0
];
}
+ (UIColor *)cyl_secondarySystemGroupedBackgroundColor {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
#if __has_include()
return [UIColor secondarySystemGroupedBackgroundColor];
#else
#endif
}
#endif
return [UIColor
colorWithRed:1.0
green:1.0
blue:1.0
alpha:1.0
];
}
+ (UIColor *)cyl_tertiarySystemGroupedBackgroundColor {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
#if __has_include()
return [UIColor tertiarySystemGroupedBackgroundColor];
#else
#endif
}
#endif
return [UIColor
colorWithRed:0.9490196078431372
green:0.9490196078431372
blue:0.9686274509803922
alpha:1.0
];
}
#pragma mark Fill colors
+ (UIColor *)cyl_systemFillColor {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
#if __has_include()
return [UIColor systemFillColor];
#else
#endif
}
#endif
return [UIColor
colorWithRed:0.47058823529411764
green:0.47058823529411764
blue:0.5019607843137255
alpha:0.2
];
}
+ (UIColor *)cyl_secondarySystemFillColor {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
#if __has_include()
return [UIColor secondarySystemFillColor];
#else
#endif
}
#endif
return [UIColor
colorWithRed:0.47058823529411764
green:0.47058823529411764
blue:0.5019607843137255
alpha:0.16
];
}
+ (UIColor *)cyl_tertiarySystemFillColor {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
#if __has_include()
return [UIColor tertiarySystemFillColor];
#else
#endif
}
#endif
return [UIColor
colorWithRed:0.4627450980392157
green:0.4627450980392157
blue:0.5019607843137255
alpha:0.12
];
}
+ (UIColor *)cyl_quaternarySystemFillColor {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
#if __has_include()
return [UIColor quaternarySystemFillColor];
#else
#endif
}
#endif
return [UIColor
colorWithRed:0.4549019607843137
green:0.4549019607843137
blue:0.5019607843137255
alpha:0.08
];
}
#pragma mark Other colors
+ (UIColor *)cyl_lightTextColor {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
#if __has_include()
return [UIColor lightTextColor];
#else
#endif
}
#endif
return [UIColor
colorWithRed:1.0
green:1.0
blue:1.0
alpha:0.6
];
}
+ (UIColor *)cyl_darkTextColor {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
#if __has_include()
return [UIColor darkTextColor];
#else
#endif
}
#endif
return [UIColor
colorWithRed:0.0
green:0.0
blue:0.0
alpha:1.0
];
}
#pragma mark - Deprecated API
//Apple remove this API in iOS13 beta 2
+ (UIColor *)cyl_systemBrownColor {
return nil;
}
@end
================================================
FILE: CYLTabBarController/UIControl+CYLTabBarControllerExtention.h
================================================
//
// CYLTabBarController.m
// CYLTabBarController
//
// v1.21.x Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 10/20/15.
// Copyright © 2018 https://github.com/ChenYilong . All rights reserved.
//
#import
NS_ASSUME_NONNULL_BEGIN
@class LOTAnimationView;
@interface UIControl (CYLTabBarControllerExtention)
- (LOTAnimationView *)cyl_lottieAnimationView;
- (BOOL)cyl_isChildViewControllerPlusButton;
/*!
* 调用该方法前已经添加了系统的角标,调用该方法后,系统的角标并未被移除,只是被隐藏,调用 `-cyl_removeTabBadgePoint` 后会重新展示。
*/
- (void)cyl_showTabBadgePoint;
- (void)cyl_removeTabBadgePoint;
- (BOOL)cyl_isShowTabBadgePoint;
- (BOOL)cyl_isSelected;
@property (nonatomic, strong, setter=cyl_setTabBadgePointView:, getter=cyl_tabBadgePointView) UIView *cyl_tabBadgePointView;
@property (nonatomic, assign, setter=cyl_setTabBadgePointViewOffset:, getter=cyl_tabBadgePointViewOffset) UIOffset cyl_tabBadgePointViewOffset;
/*!
* PlusButton without plusViewController equals NSNotFound
*/
@property (nonatomic, assign, getter=cyl_tabBarChildViewControllerIndex, setter=cyl_setTabBarChildViewControllerIndex:) NSInteger cyl_tabBarChildViewControllerIndex;
/*!
* PlusButton has its own visible index,
* in this case PlusButton is same as TabBarItem
*/
@property (nonatomic, assign, getter=cyl_tabBarItemVisibleIndex, setter=cyl_setTabBarItemVisibleIndex:) NSInteger cyl_tabBarItemVisibleIndex;
@property (nonatomic, assign, getter=cyl_shouldNotSelect, setter=cyl_setShouldNotSelect:) BOOL cyl_shouldNotSelect;
- (void)cyl_addLottieImageWithLottieURL:(NSURL *)lottieURL
size:(CGSize)size;
- (void)cyl_replaceTabImageViewWithNewView:(UIView *)newView
show:(BOOL)show;
- (void)cyl_replaceTabImageViewWithNewView:(UIView *)newView
offset:(UIOffset)offset
show:(BOOL)show
completion:(void(^)(BOOL isReplaced, UIControl *tabBarButton, UIView *newView))completion;
- (void)cyl_replaceTabButtonWithNewView:(UIView *)newView
show:(BOOL)show;
- (void)cyl_replaceTabButtonWithNewView:(UIView *)newView
offset:(UIOffset)offset
show:(BOOL)theShow
completion:(void(^)(BOOL isReplaced, UIControl *tabBarButton, UIView *newView))completion;
@end
NS_ASSUME_NONNULL_END
================================================
FILE: CYLTabBarController/UIControl+CYLTabBarControllerExtention.m
================================================
//
// CYLTabBarController.m
// CYLTabBarController
//
// v1.21.x Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 10/20/15.
// Copyright © 2018 https://github.com/ChenYilong . All rights reserved.
//
#import "UIControl+CYLTabBarControllerExtention.h"
#import
#import "UIView+CYLTabBarControllerExtention.h"
#import "CYLConstants.h"
#import "CYLTabBarController.h"
#if __has_include()
#import
#else
#endif
@implementation UIControl (CYLTabBarControllerExtention)
- (BOOL)cyl_isChildViewControllerPlusButton {
BOOL isChildViewControllerPlusButton = ([self cyl_isPlusButton] && CYLPlusChildViewController.cyl_plusViewControllerEverAdded);
return isChildViewControllerPlusButton;
}
- (BOOL)cyl_shouldNotSelect {
NSNumber *shouldNotSelectObject = objc_getAssociatedObject(self, @selector(cyl_shouldNotSelect));
return [shouldNotSelectObject boolValue];
}
- (void)cyl_setShouldNotSelect:(BOOL)shouldNotSelect {
NSNumber *shouldNotSelectObject = @(shouldNotSelect);
objc_setAssociatedObject(self, @selector(cyl_shouldNotSelect), shouldNotSelectObject, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSInteger)cyl_tabBarItemVisibleIndex {
if (!self.cyl_isTabButton && !self.cyl_isPlusButton ) {
return NSNotFound;
}
NSNumber *tabBarItemVisibleIndexObject = objc_getAssociatedObject(self, @selector(cyl_tabBarItemVisibleIndex));
return [tabBarItemVisibleIndexObject integerValue];
}
- (void)cyl_setTabBarItemVisibleIndex:(NSInteger)tabBarItemVisibleIndex {
NSNumber *tabBarItemVisibleIndexObject = [NSNumber numberWithInteger:tabBarItemVisibleIndex];
objc_setAssociatedObject(self, @selector(cyl_tabBarItemVisibleIndex), tabBarItemVisibleIndexObject, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSInteger)cyl_tabBarChildViewControllerIndex {
if (!self.cyl_isTabButton && !self.cyl_isPlusButton ) {
return NSNotFound;
}
NSNumber *tabBarChildViewControllerIndexObject = objc_getAssociatedObject(self, @selector(cyl_tabBarChildViewControllerIndex));
return [tabBarChildViewControllerIndexObject integerValue];
}
- (void)cyl_setTabBarChildViewControllerIndex:(NSInteger)tabBarChildViewControllerIndex {
NSNumber *tabBarChildViewControllerIndexObject = [NSNumber numberWithInteger:tabBarChildViewControllerIndex];
objc_setAssociatedObject(self, @selector(cyl_tabBarChildViewControllerIndex), tabBarChildViewControllerIndexObject, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (void)cyl_showTabBadgePoint {
[self cyl_setShowTabBadgePointIfNeeded:YES];
}
- (void)cyl_removeTabBadgePoint {
[self cyl_setShowTabBadgePointIfNeeded:NO];
}
- (BOOL)cyl_isShowTabBadgePoint {
return !self.cyl_tabBadgePointView.hidden;
}
- (BOOL)cyl_isSelected {
NSUInteger tabBarSelectedIndex = self.cyl_tabBarController.selectedIndex;
NSUInteger tabBarChildViewControllerIndex = self.cyl_tabBarChildViewControllerIndex;
BOOL isSelected = (tabBarSelectedIndex == tabBarChildViewControllerIndex) && self.selected;
if (self.cyl_tabBarController.tabBar.cyl_hasPlusChildViewController) {
isSelected = isSelected && CYLPlusChildViewController.cyl_plusViewControllerEverAdded;
}
return isSelected;
}
- (void)cyl_setShowTabBadgePointIfNeeded:(BOOL)showTabBadgePoint {
@try {
[self cyl_setShowTabBadgePoint:showTabBadgePoint];
} @catch (NSException *exception) {
NSLog(@"CYLPlusChildViewController do not support set TabBarItem red point");
}
}
- (void)cyl_setShowTabBadgePoint:(BOOL)showTabBadgePoint {
if (showTabBadgePoint && self.cyl_tabBadgePointView.superview == nil) {
[self addSubview:self.cyl_tabBadgePointView];
[self bringSubviewToFront:self.cyl_tabBadgePointView];
self.cyl_tabBadgePointView.layer.zPosition = MAXFLOAT;
// X constraint
[self addConstraint:
[NSLayoutConstraint constraintWithItem:self.cyl_tabBadgePointView
attribute:NSLayoutAttributeCenterX
relatedBy:0
toItem:self.cyl_tabImageView
attribute:NSLayoutAttributeRight
multiplier:1
constant:self.cyl_tabBadgePointViewOffset.horizontal]];
//Y constraint
[self addConstraint:
[NSLayoutConstraint constraintWithItem:self.cyl_tabBadgePointView
attribute:NSLayoutAttributeCenterY
relatedBy:0
toItem:self.cyl_tabImageView
attribute:NSLayoutAttributeTop
multiplier:1
constant:self.cyl_tabBadgePointViewOffset.vertical]];
}
self.cyl_tabBadgePointView.hidden = showTabBadgePoint == NO;
self.cyl_tabBadgeView.hidden = showTabBadgePoint == YES;
}
- (void)cyl_setTabBadgePointView:(UIView *)tabBadgePointView {
UIView *tempView = objc_getAssociatedObject(self, @selector(cyl_tabBadgePointView));
if (tempView) {
[tempView removeFromSuperview];
}
if (tabBadgePointView.superview) {
[tabBadgePointView removeFromSuperview];
}
tabBadgePointView.hidden = YES;
objc_setAssociatedObject(self, @selector(cyl_tabBadgePointView), tabBadgePointView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (UIView *)cyl_tabBadgePointView {
UIView *tabBadgePointView = objc_getAssociatedObject(self, @selector(cyl_tabBadgePointView));
if (tabBadgePointView == nil) {
tabBadgePointView = self.cyl_defaultTabBadgePointView;
objc_setAssociatedObject(self, @selector(cyl_tabBadgePointView), tabBadgePointView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return tabBadgePointView;
}
- (void)cyl_setTabBadgePointViewOffset:(UIOffset)tabBadgePointViewOffset {
objc_setAssociatedObject(self, @selector(cyl_tabBadgePointViewOffset), [NSValue valueWithUIOffset:tabBadgePointViewOffset], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
//offset如果都是正数,则往右下偏移
- (UIOffset)cyl_tabBadgePointViewOffset {
id tabBadgePointViewOffsetObject = objc_getAssociatedObject(self, @selector(cyl_tabBadgePointViewOffset));
UIOffset tabBadgePointViewOffset = [tabBadgePointViewOffsetObject UIOffsetValue];
return tabBadgePointViewOffset;
}
- (LOTAnimationView *)cyl_lottieAnimationView {
for (UILabel *subview in self.subviews) {
if ([subview cyl_isLottieAnimationView]) {
return (LOTAnimationView *)subview;
}
}
return nil;
}
- (void)cyl_replaceTabImageViewWithNewView:(UIView *)newView
show:(BOOL)show {
[self cyl_replaceTabImageViewWithNewView:newView offset:UIOffsetZero show:show completion:^(BOOL isReplaced, UIControl *tabBarButton, UIView *newView) {
}];
}
- (void)cyl_replaceTabImageViewWithNewView:(UIView *)newView
offset:(UIOffset)offset
show:(BOOL)theShow
completion:(void(^)(BOOL isReplaced, UIControl *tabBarButton, UIView *newView))completion {
[self cyl_replaceTabImageViewOrTabButton:NO newView:newView offset:offset show:theShow completion:completion];
}
- (void)cyl_replaceTabButtonWithNewView:(UIView *)newView
offset:(UIOffset)offset
show:(BOOL)theShow
completion:(void(^)(BOOL isReplaced, UIControl *tabBarButton, UIView *newView))completion {
[self cyl_replaceTabImageViewOrTabButton:YES newView:newView offset:offset show:theShow completion:completion];
}
- (void)cyl_replaceTabButtonWithNewView:(UIView *)newView
show:(BOOL)show {
[self cyl_replaceTabButtonWithNewView:newView offset:UIOffsetZero show:show completion:^(BOOL isReplaced, UIControl *tabBarButton, UIView *newView) {
}];
}
- (void)cyl_replaceTabImageViewOrTabButton:(BOOL)isTabButton
newView:(UIView *)newView
offset:(UIOffset)offset
show:(BOOL)theShow
completion:(void(^)(BOOL isReplaced, UIControl *tabBarButton, UIView *newView))completion {
UIControl *tabBarButton = self;
UIImageView *swappableImageView = tabBarButton.cyl_tabImageView;
UIView *replacedView = swappableImageView;
if (isTabButton) {
replacedView = tabBarButton;
}
if (!replacedView) {
return;
}
if (newView.frame.size.width == 0 || newView.frame.size.height == 0 || newView.frame.size.width > tabBarButton.frame.size.width || newView.frame.size.height > tabBarButton.frame.size.height) {
UIImage *image = swappableImageView.image;
newView.frame = ({
CGRect frame = newView.frame;
frame.size = CGSizeMake(image.size.width, image.size.height);
frame;
});
}
BOOL newViewCreated = (newView.superview);
BOOL newViewAddedToTabButton = [self.subviews containsObject:newView];
BOOL isNewViewAddedToTabButton = newViewCreated && newViewAddedToTabButton;
if (newView.superview && !newViewAddedToTabButton) {
[newView removeFromSuperview];
}
if (isNewViewAddedToTabButton && theShow) {
!completion?:completion(YES, self, newView);
return;
}
BOOL show = (newView && theShow);
swappableImageView.hidden = (show);
if (isTabButton) {
tabBarButton.cyl_tabLabel.hidden = show;
}
BOOL shouldShowNewView = show && !newView.superview;
BOOL shouldRemoveNewView = newView.superview;
if (shouldShowNewView) {
[tabBarButton addSubview:newView];
[tabBarButton bringSubviewToFront:newView];
CGSize newViewSize = newView.frame.size;
if (@available(iOS 9.0, *)) {
[NSLayoutConstraint activateConstraints:@[
[newView.centerXAnchor constraintEqualToAnchor:swappableImageView.centerXAnchor constant:offset.horizontal],
[newView.centerYAnchor constraintEqualToAnchor:replacedView.centerYAnchor constant:offset.vertical],
[newView.widthAnchor constraintEqualToConstant:newViewSize.width],
[newView.heightAnchor constraintEqualToConstant:newViewSize.height],
]
];
} else {
[self addConstraints:@[
[NSLayoutConstraint constraintWithItem:newView
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:swappableImageView
attribute:NSLayoutAttributeCenterX
multiplier:1.0
constant:offset.horizontal],
[NSLayoutConstraint constraintWithItem:newView
attribute:NSLayoutAttributeCenterY
relatedBy:NSLayoutRelationEqual
toItem:replacedView
attribute:NSLayoutAttributeCenterY
multiplier:1.0
constant:offset.vertical],
[NSLayoutConstraint constraintWithItem:newView
attribute:NSLayoutAttributeCenterY
relatedBy:NSLayoutRelationEqual
toItem:replacedView
attribute:NSLayoutAttributeCenterY
multiplier:1.0
constant:offset.vertical],
[NSLayoutConstraint constraintWithItem:newView
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1.0
constant:newViewSize.width],
[NSLayoutConstraint constraintWithItem:newView
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1.0
constant:newViewSize.height]
]];
}
!completion?:completion(YES, self, newView);
return;
}
if (shouldRemoveNewView) {
[newView removeFromSuperview];
newView = nil;
!completion?:completion(NO, self, nil);
return;
}
}
- (void)cyl_addLottieImageWithLottieURL:(NSURL *)lottieURL
size:(CGSize)size {
#if __has_include()
if (self.cyl_lottieAnimationView) {
return;
}
UIControl *tabButton = self;
LOTAnimationView *lottieView = [[LOTAnimationView alloc] initWithContentsOfURL:lottieURL];
lottieView.frame = CGRectMake(0, 0, size.width, size.height);
lottieView.userInteractionEnabled = NO;
lottieView.contentMode = UIViewContentModeScaleAspectFill;
lottieView.translatesAutoresizingMaskIntoConstraints = NO;
[lottieView setClipsToBounds:NO];
[tabButton cyl_replaceTabImageViewWithNewView:lottieView show:YES];
#else
#endif
}
#pragma mark - private method
- (UIView *)cyl_defaultTabBadgePointView {
UIView *defaultRedTabBadgePointView = [UIView cyl_tabBadgePointViewWithClolor:[UIColor redColor] radius:4.5];
return defaultRedTabBadgePointView;
}
@end
================================================
FILE: CYLTabBarController/UIImage+CYLTabBarControllerExtention.h
================================================
//
// UIImage+CYLTabBarControllerExtention.h
// CYLTabBarController
//
// Created by chenyilong on 18/4/2019.
// Copyright © 2019 微博@iOS程序犭袁. All rights reserved.
//
#import
NS_ASSUME_NONNULL_BEGIN
@interface UIImage (CYLTabBarControllerExtention)
+ (UIImage *)cyl_imageWithColor:(UIColor *)color size:(CGSize)size;
@end
NS_ASSUME_NONNULL_END
================================================
FILE: CYLTabBarController/UIImage+CYLTabBarControllerExtention.m
================================================
//
// UIImage+CYLTabBarControllerExtention.m
// CYLTabBarController
//
// Created by chenyilong on 18/4/2019.
// Copyright © 2019 微博@iOS程序犭袁. All rights reserved.
//
#import "UIImage+CYLTabBarControllerExtention.h"
@implementation UIImage (CYLTabBarControllerExtention)
+ (UIImage *)cyl_imageWithColor:(UIColor *)color size:(CGSize)size {
if (!color || size.width <= 0 || size.height <= 0) return nil;
CGRect rect = CGRectMake(0.0f, 0.0f, size.width, size.height);
UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, color.CGColor);
CGContextFillRect(context, rect);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
}
+ (UIImage *)cyl_assetImageName:(NSString *)assetImageName
userInterfaceStyle:(NSInteger)userInterfaceStyle {
UIImage *image = [UIImage imageNamed:@"image"];
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
#if __has_include()
UITraitCollection *trait;
// UIUserInterfaceStyle currentUserInterfaceStyle = [UITraitCollection currentTraitCollection].userInterfaceStyle;
// if (currentUserInterfaceStyle == UIUserInterfaceStyleUnspecified) {
// currentUserInterfaceStyle == userInterfaceStyle;
// }
trait = [UITraitCollection traitCollectionWithUserInterfaceStyle:userInterfaceStyle];
image = [image.imageAsset imageWithTraitCollection:trait];
//TODO:
return image;
#else
#endif
}
#endif
return image;
}
+ (UIImage *)cyl_lightOrDarkModeImageWithLightImage:(UIImage *)lightImage
darkImage:(UIImage *)darkImage {
return [self cyl_lightOrDarkModeImageWithOwner:nil lightImage:lightImage darkImage:darkImage];
}
+ (UIImage *)cyl_lightOrDarkModeImageWithOwner:(id)owner
lightImageName:(NSString *)lightImageName
darkImageName:(NSString *)darkImageName {
UIImage *lightImage = [UIImage imageNamed:lightImageName];
UIImage *darkImage= [UIImage imageNamed:darkImageName];
UIImage *lightOrDarkImage = [UIImage cyl_lightOrDarkModeImageWithOwner:owner lightImage:lightImage darkImage:darkImage];
return lightOrDarkImage;
}
+ (UIImage *)cyl_lightOrDarkModeImageWithOwner:(id)owner
lightImage:(UIImage *)lightImage
darkImage:(UIImage *)darkImage {
BOOL isDarkImage = NO;
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
#if __has_include()
//TODO:
UITraitCollection *traitCollection = owner.traitCollection ?: [UITraitCollection currentTraitCollection];
UIUserInterfaceStyle userInterfaceStyle = traitCollection.userInterfaceStyle;
isDarkImage = (userInterfaceStyle == UIUserInterfaceStyleDark);
#else
#endif
}
#endif
UIImage *image = (isDarkImage ? darkImage : lightImage);
return image;
}
@end
================================================
FILE: CYLTabBarController/UITabBarItem+CYLBadgeExtention.h
================================================
/*
// CYLTabBarController
// CYLTabBarController
//
// Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 03/06/19.
// Copyright © 2019 https://github.com/ChenYilong . All rights reserved.
*/
#import
#import "UIView+CYLBadgeExtention.h"
#import "CYLBadgeProtocol.h"
NS_ASSUME_NONNULL_BEGIN
@interface UITabBarItem (CYLBadgeExtention)
- (BOOL)cyl_isShowBadge;
/**
* show badge with red dot style and CYLBadgeAnimationTypeNone by default.
*/
- (void)cyl_showBadge;
/**
*
* @param value String value, default is `nil`. if value equal @"" means red dot style.
* @param animationType animationType
* @attention
- 调用该方法前已经添加了系统的角标,调用该方法后,系统的角标并未被移除,只是被隐藏,调用 `-cyl_removeTabBadgePoint` 后会重新展示。
- 不支持 CYLPlusChildViewController 对应的 TabBarItem 角标设置,调用会被忽略。
*/
- (void)cyl_showBadgeValue:(NSString *)value
animationType:(CYLBadgeAnimationType)animationType;
/**
* clear badge(hide badge)
*/
- (void)cyl_clearBadge;
/**
* make bage(if existing) not hiden
*/
- (void)cyl_resumeBadge;
- (BOOL)cyl_isPauseBadge;
@end
NS_ASSUME_NONNULL_END
================================================
FILE: CYLTabBarController/UITabBarItem+CYLBadgeExtention.m
================================================
/*
// CYLTabBarController
// CYLTabBarController
//
// Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 03/06/19.
// Copyright © 2019 https://github.com/ChenYilong . All rights reserved.
*/
#import "UITabBarItem+CYLBadgeExtention.h"
#import "CYLTabBarController.h"
#import
#define kActualView [self cyl_getActualBadgeSuperView]
@implementation UITabBarItem (CYLBadgeExtention)
+ (void)load {
[self cyl_swizzleSetBadgeValue];
}
+ (void)cyl_swizzleSetBadgeValue {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
cyl_ClassMethodSwizzle([self class], @selector(setBadgeValue:), @selector(cyl_setBadgeValue:));
});
}
- (void)cyl_setBadgeValue:(NSString *)badgeValue {
[self.cyl_tabButton cyl_removeTabBadgePoint];
[self cyl_clearBadge];
[self cyl_setBadgeValue:badgeValue];
}
#pragma mark -- public methods
/**
* show badge with red dot style and CYLBadgeAnimationTypeNone by default.
*/
- (void)cyl_showBadge {
[kActualView cyl_showBadgeValue:@"" animationType:CYLBadgeAnimationTypeNone];
}
- (void)cyl_showBadgeValue:(NSString *)value animationType:(CYLBadgeAnimationType)animationType {
[kActualView cyl_showBadgeValue:value animationType:animationType];
self.cyl_tabButton.cyl_tabBadgeView.hidden = YES;
}
- (BOOL)cyl_isShowBadge {
return [kActualView cyl_isShowBadge];
}
- (BOOL)cyl_isPauseBadge {
return [kActualView cyl_isPauseBadge];
}
/**
* clear badge
*/
- (void)cyl_clearBadge {
[kActualView cyl_clearBadge];
self.cyl_tabButton.cyl_tabBadgeView.hidden = NO;
}
- (void)cyl_resumeBadge {
[kActualView cyl_resumeBadge];
self.cyl_tabButton.cyl_tabBadgeView.hidden = YES;
}
#pragma mark -- private method
/**
* Because UIBarButtonItem is kind of NSObject, it is not able to directly attach badge.
This method is used to find actual view (non-nil) inside UIBarButtonItem instance.
*
* @return view
*/
- (UIView *)cyl_getActualBadgeSuperView {
UIControl *tabButton = [self cyl_tabButton];
// badge label will be added onto imageView
UIImageView *tabImageView = [tabButton cyl_tabImageView];
UIView *lottieAnimationView = (UIView *)tabButton.cyl_lottieAnimationView ;
UIView *actualBadgeSuperView = tabImageView;
do {
if (tabImageView && !tabImageView.cyl_isInvisiable) {
actualBadgeSuperView = tabImageView;
break;
}
if (lottieAnimationView && !lottieAnimationView.cyl_isInvisiable) {
actualBadgeSuperView = lottieAnimationView;
break;
}
} while (NO);
[lottieAnimationView setClipsToBounds:NO];
return actualBadgeSuperView;
}
#pragma mark -- setter/getter
- (UILabel *)cyl_badge {
return kActualView.cyl_badge;
}
- (void)cyl_setBadge:(UILabel *)label {
[kActualView cyl_setBadge:label];
}
- (UIFont *)cyl_badgeFont {
return kActualView.cyl_badgeFont;
}
- (void)cyl_setBadgeFont:(UIFont *)badgeFont {
[kActualView cyl_setBadgeFont:badgeFont];
}
- (UIColor *)cyl_badgeBackgroundColor {
return [kActualView cyl_badgeBackgroundColor];
}
- (void)cyl_setBadgeBackgroundColor:(UIColor *)badgeBackgroundColor {
[kActualView cyl_setBadgeBackgroundColor:badgeBackgroundColor];
}
- (UIColor *)cyl_badgeTextColor {
return [kActualView cyl_badgeTextColor];
}
- (void)cyl_setBadgeTextColor:(UIColor *)badgeTextColor {
[kActualView cyl_setBadgeTextColor:badgeTextColor];
}
- (CYLBadgeAnimationType)cyl_badgeAnimationType {
return [kActualView cyl_badgeAnimationType];
}
- (void)cyl_setBadgeAnimationType:(CYLBadgeAnimationType)animationType {
[kActualView cyl_setBadgeAnimationType:animationType];
}
- (CGRect)cyl_badgeFrame {
return [kActualView cyl_badgeFrame];
}
- (void)cyl_setBadgeFrame:(CGRect)badgeFrame {
[kActualView cyl_setBadgeFrame:badgeFrame];
}
- (CGPoint)cyl_badgeCenterOffset {
return [kActualView cyl_badgeCenterOffset];
}
- (void)cyl_setBadgeCenterOffset:(CGPoint)badgeCenterOffset {
[kActualView cyl_setBadgeCenterOffset:badgeCenterOffset];
}
- (NSInteger)cyl_badgeMaximumBadgeNumber {
return [kActualView cyl_badgeMaximumBadgeNumber];
}
- (void)cyl_setBadgeMaximumBadgeNumber:(NSInteger)badgeMaximumBadgeNumber {
[kActualView cyl_setBadgeMaximumBadgeNumber:badgeMaximumBadgeNumber];
}
- (CGFloat)cyl_badgeMargin {
return [kActualView cyl_badgeMargin];
}
- (void)cyl_setBadgeMargin:(CGFloat)badgeMargin {
[kActualView cyl_setBadgeMargin:badgeMargin];
}
- (CGFloat)cyl_badgeRadius {
return [kActualView cyl_badgeRadius];
}
- (void)cyl_setBadgeRadius:(CGFloat)badgeRadius {
[kActualView cyl_setBadgeRadius:badgeRadius];
}
- (CGFloat)cyl_badgeCornerRadius {
return [kActualView cyl_badgeCornerRadius];
}
- (void)cyl_setBadgeCornerRadius:(CGFloat)cyl_badgeCornerRadius {
[kActualView cyl_setBadgeCornerRadius:cyl_badgeCornerRadius];
}
#pragma mark - private method
BOOL cyl_ClassMethodSwizzle(Class aClass, SEL originalSelector, SEL swizzleSelector) {
Method originalMethod = class_getInstanceMethod(aClass, originalSelector);
Method swizzleMethod = class_getInstanceMethod(aClass, swizzleSelector);
BOOL didAddMethod =
class_addMethod(aClass,
originalSelector,
method_getImplementation(swizzleMethod),
method_getTypeEncoding(swizzleMethod));
if (didAddMethod) {
class_replaceMethod(aClass,
swizzleSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, swizzleMethod);
}
return YES;
}
@end
================================================
FILE: CYLTabBarController/UITabBarItem+CYLTabBarControllerExtention.h
================================================
//
// CYLTabBarController.m
// CYLTabBarController
//
// v1.21.x Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 10/20/15.
// Copyright © 2018 https://github.com/ChenYilong . All rights reserved.
//
#import
NS_ASSUME_NONNULL_BEGIN
@interface UITabBarItem (CYLTabBarControllerExtention)
@property (nonatomic, readonly) UIControl *cyl_tabButton;
@end
NS_ASSUME_NONNULL_END
================================================
FILE: CYLTabBarController/UITabBarItem+CYLTabBarControllerExtention.m
================================================
//
// CYLTabBarController.m
// CYLTabBarController
//
// v1.21.x Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 10/20/15.
// Copyright © 2018 https://github.com/ChenYilong . All rights reserved.
//
#import "UITabBarItem+CYLTabBarControllerExtention.h"
#import "UIControl+CYLTabBarControllerExtention.h"
@implementation UITabBarItem (CYLTabBarControllerExtention)
- (UIControl *)cyl_tabButton {
UIControl *control = [self valueForKeyPath:@"_view"];
return control;
}
@end
================================================
FILE: CYLTabBarController/UIView+CYLBadgeExtention.h
================================================
/*
// CYLTabBarController
// CYLTabBarController
//
// Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 03/06/19.
// Copyright © 2019 https://github.com/ChenYilong . All rights reserved.
*/
#import
#import "CYLBadgeProtocol.h"
NS_ASSUME_NONNULL_BEGIN
#pragma mark -- badge apis
@interface UIView (CYLBadgeExtention)
- (BOOL)cyl_isShowBadge;
/**
* show badge with red dot style and CYLBadgeAnimationTypeNone by default.
*/
- (void)cyl_showBadge;
/**
* cyl_showBadge
*
* @param value String value, default is `nil`. if value equal @"" means red dot style.
* @param animationType animationType
*/
- (void)cyl_showBadgeValue:(NSString *)value
animationType:(CYLBadgeAnimationType)animationType;
;
// wBadgeStyle default is CYLBadgeStyleNumber ;
// CYLBadgeAnimationType defualt is CYLBadgeAnimationTypeNone
- (void)cyl_showBadgeValue:(NSString *)value;
/**
* clear badge(hide badge)
*/
- (void)cyl_clearBadge;
/**
* make bage(if existing) not hiden
*/
- (void)cyl_resumeBadge;
- (BOOL)cyl_isPauseBadge;
- (BOOL)cyl_isInvisiable;
- (BOOL)cyl_canNotResponseEvent;
@end
NS_ASSUME_NONNULL_END
================================================
FILE: CYLTabBarController/UIView+CYLBadgeExtention.m
================================================
/*
// CYLTabBarController
// CYLTabBarController
//
// Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 03/06/19.
// Copyright © 2019 https://github.com/ChenYilong . All rights reserved.
*/
#import "UIView+CYLBadgeExtention.h"
#import
#import "CAAnimation+CYLBadgeExtention.h"
#define kCYLBadgeDefaultFont ([UIFont boldSystemFontOfSize:9])
#define kCYLBadgeDefaultMaximumBadgeNumber 99
#define kCYLBadgeDefaultMargin (8.0)
static const CGFloat kCYLBadgeDefaultRedDotRadius = 4.f;
@implementation UIView (CYLBadgeExtention)
#pragma mark -- public methods
/**
* show badge with red dot style and CYLBadgeAnimationTypeNone by default.
*/
- (void)cyl_showBadge {
[self cyl_showBadgeValue:@"" animationType:CYLBadgeAnimationTypeNone];
}
- (void)cyl_showBadgeValue:(NSString *)value animationType:(CYLBadgeAnimationType)animationType {
[[[self cyl_badge] subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];
self.cyl_badgeAnimationType = animationType;
[self cyl_showBadgeWithValue:value];
if (animationType != CYLBadgeAnimationTypeNone) {
[self cyl_beginAnimation];
}
}
- (void)cyl_showBadgeValue:(NSString *)value {
[self cyl_showBadgeValue:value animationType:CYLBadgeAnimationTypeNone];
}
#pragma mark -- private methods
- (void)cyl_showBadgeWithValue:(NSString *)value {
if (!value) {
return;
}
NSCharacterSet *numberSet = [NSCharacterSet decimalDigitCharacterSet];
NSString *trimmedString = [value stringByTrimmingCharactersInSet:numberSet];
BOOL isNumber = NO;
if ((trimmedString.length == 0) && (value.length > 0)) {
isNumber = YES;
}
if (isNumber) {
[self cyl_showNumberBadgeWithValue:[value integerValue]];
return;
}
if ([value isEqualToString:@""]) {
[self cyl_showRedDotBadge];
return;
}
if ([value isEqualToString:@"new"] || [value isEqualToString:@"NEW"] ) {
[self cyl_showNewBadge:value];
return;
}
[self cyl_showTextBadge:value];
}
/**
* clear badge
*/
- (void)cyl_clearBadge {
self.cyl_badge.hidden = YES;
}
- (BOOL)cyl_isShowBadge {
return (self.cyl_badge && !self.cyl_badge.hidden );
}
/**
* make bage(if existing) not hiden
*/
- (void)cyl_resumeBadge {
if (self.cyl_isPauseBadge) {
self.cyl_badge.hidden = NO;
}
}
- (BOOL)cyl_isPauseBadge {
return (self.cyl_badge && self.cyl_badge.hidden == YES);
}
#pragma mark -- private methods
- (void)cyl_addMargin {
CGRect frame = self.cyl_badge.frame;
frame.size.width += self.cyl_badgeMargin;
frame.size.height += self.cyl_badgeMargin;
if(CGRectGetWidth(frame) < CGRectGetHeight(frame)) {
frame.size.width = CGRectGetHeight(frame);
}
self.cyl_badge.frame = frame;
}
- (void)cyl_showRedDotBadge {
[self cyl_badgeInit];
//if badge has been displayed and, in addition, is was not red dot style, we must update UI.
if (self.cyl_badge.tag != CYLBadgeStyleRedDot) {
self.cyl_badge.text = @"";
self.cyl_badge.tag = CYLBadgeStyleRedDot;
[self cyl_resetRedDotBadgeFrame];
self.cyl_badge.layer.cornerRadius = CGRectGetWidth(self.cyl_badge.frame) / 2;
}
self.cyl_badge.hidden = NO;
}
- (void)cyl_showNewBadge:(NSString *)value {
CGSize size = [value sizeWithAttributes:
@{NSFontAttributeName:
self.cyl_badgeFont}];
float labelHeight = ceilf(size.height)+ self.cyl_badgeMargin;
[self cyl_setBadgeCornerRadius:labelHeight/3];
[self cyl_showTextBadge:value];
}
- (void)cyl_showTextBadge:(NSString *)value {
if (value == 0 || !value ||value.length == 0) {
self.cyl_badge.hidden = YES;
return;
}
[self cyl_badgeInit];
self.cyl_badge.tag = CYLBadgeStyleOther;
self.cyl_badge.text = value;
self.cyl_badge.font = self.cyl_badgeFont;
[self cyl_adjustLabelWidth:self.cyl_badge];
[self cyl_addMargin];
self.cyl_badge.center = CGPointMake(CGRectGetWidth(self.frame) + 2 + self.cyl_badgeCenterOffset.x, self.cyl_badgeCenterOffset.y);
//FIXME: to delete
self.cyl_badge.layer.cornerRadius = (self.cyl_badgeCornerRadius !=0 ) ? self.cyl_badgeCornerRadius : CGRectGetHeight(self.cyl_badge.frame) / 2;
self.cyl_badge.hidden = NO;
}
- (void)cyl_showNumberBadgeWithValue:(NSInteger)value {
if (value <= 0) {
self.cyl_badge.hidden = YES;
return;
}
[self cyl_badgeInit];
self.cyl_badge.hidden = (value == 0);
self.cyl_badge.tag = CYLBadgeStyleNumber;
NSString *text = (value > self.cyl_badgeMaximumBadgeNumber ?
[NSString stringWithFormat:@"%@+", @(self.cyl_badgeMaximumBadgeNumber)] :
[NSString stringWithFormat:@"%@", @(value)]);
[self cyl_showTextBadge:text];
}
//lazy loading
- (void)cyl_badgeInit {
if (self.cyl_badgeBackgroundColor == nil) {
self.cyl_badgeBackgroundColor = [UIColor redColor];
}
if (self.cyl_badgeTextColor == nil) {
self.cyl_badgeTextColor = [UIColor whiteColor];
}
if (!self.cyl_badge) {
self.cyl_badge = [[UILabel alloc] init];
[self cyl_resetRedDotBadgeFrame];
self.cyl_badge.textAlignment = NSTextAlignmentCenter;
self.cyl_badge.backgroundColor = self.cyl_badgeBackgroundColor;
self.cyl_badge.textColor = self.cyl_badgeTextColor;
self.cyl_badge.text = @"";
self.cyl_badge.layer.cornerRadius = CGRectGetWidth(self.cyl_badge.frame) / 2;
self.cyl_badge.layer.masksToBounds = YES;//very important
self.cyl_badge.hidden = YES;
self.cyl_badge.layer.zPosition = MAXFLOAT;
[self addSubview:self.cyl_badge];
[self bringSubviewToFront:self.cyl_badge];
}
}
- (void)cyl_resetRedDotBadgeFrame {
CGFloat redotWidth = kCYLBadgeDefaultRedDotRadius *2;
if (self.cyl_badgeRadius) {
redotWidth = self.cyl_badgeRadius * 2;
}
CGRect frame = CGRectMake(CGRectGetWidth(self.frame), -redotWidth, redotWidth, redotWidth);
self.cyl_badge.frame = frame;
self.cyl_badge.center = CGPointMake(CGRectGetWidth(self.frame) + 2 + self.cyl_badgeCenterOffset.x, self.cyl_badgeCenterOffset.y);
}
#pragma mark -- other private methods
- (void)cyl_adjustLabelWidth:(UILabel *)label {
CGSize labelsize = [self cyl_getLabelSize:label];
CGRect frame = label.frame;
frame.size = CGSizeMake(ceilf(labelsize.width), ceilf(labelsize.height));
[label setFrame:frame];
}
- (CGSize)cyl_getLabelSize:(UILabel *)label {
[label setNumberOfLines:0];
NSString *s = label.text;
UIFont *font = label.font;
CGSize size = CGSizeMake(CGRectGetWidth([UIScreen mainScreen].bounds) ,CGFLOAT_MAX);
CGSize labelsize;
if (![s respondsToSelector:@selector(boundingRectWithSize:options:attributes:context:)]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
labelsize = [s sizeWithFont:font constrainedToSize:size lineBreakMode:NSLineBreakByWordWrapping];
#pragma clang diagnostic pop
} else {
NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
[style setLineBreakMode:NSLineBreakByWordWrapping];
labelsize = [s boundingRectWithSize:size
options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
attributes:@{ NSFontAttributeName:font, NSParagraphStyleAttributeName : style}
context:nil].size;
}
return labelsize;
}
#pragma mark -- animation
//if u want to add badge animation type, follow steps bellow:
//1. go to definition of CYLBadgeAnimationType and add new type
//2. go to category of CAAnimation+CYLBadgeExtention to add new animation interface
//3. call that new interface here
- (void)cyl_beginAnimation {
switch(self.cyl_badgeAnimationType) {
case CYLBadgeAnimationTypeBreathe:
[self.cyl_badge.layer addAnimation:[CAAnimation cyl_opacityForever_Animation:1.4]
forKey:CYLBadgeBreatheAnimationKey];
break;
case CYLBadgeAnimationTypeShake:
[self.cyl_badge.layer addAnimation:[CAAnimation cyl_shake_AnimationRepeatTimes:CGFLOAT_MAX
durTimes:1
forObj:self.cyl_badge.layer]
forKey:CYLBadgeShakeAnimationKey];
break;
case CYLBadgeAnimationTypeScale:
[self.cyl_badge.layer addAnimation:[CAAnimation cyl_scaleFrom:1.4
toScale:0.6
durTimes:1
rep:MAXFLOAT]
forKey:CYLBadgeScaleAnimationKey];
break;
case CYLBadgeAnimationTypeBounce:
[self.cyl_badge.layer addAnimation:[CAAnimation cyl_bounce_AnimationRepeatTimes:CGFLOAT_MAX
durTimes:1
forObj:self.cyl_badge.layer]
forKey:CYLBadgeBounceAnimationKey];
break;
case CYLBadgeAnimationTypeNone:
default:
break;
}
}
- (void)cyl_removeAnimation {
if (self.cyl_badge) {
[self.cyl_badge.layer removeAllAnimations];
}
}
#pragma mark -- setter/getter
- (UILabel *)cyl_badge {
return objc_getAssociatedObject(self, @selector(cyl_badge));
}
- (void)cyl_setBadge:(UILabel *)label {
objc_setAssociatedObject(self, @selector(cyl_badge), label, OBJC_ASSOCIATION_RETAIN);
}
- (UIFont *)cyl_badgeFont {
id font = objc_getAssociatedObject(self, @selector(cyl_badgeFont));
return font ?: kCYLBadgeDefaultFont;
}
- (void)cyl_setBadgeFont:(UIFont *)badgeFont {
objc_setAssociatedObject(self, @selector(cyl_badgeFont), badgeFont, OBJC_ASSOCIATION_RETAIN);
if (!self.cyl_badge) {
[self cyl_badgeInit];
}
self.cyl_badge.font = badgeFont;
}
- (UIColor *)cyl_badgeBackgroundColor {
return objc_getAssociatedObject(self, @selector(cyl_badgeBackgroundColor));
}
- (void)cyl_setBadgeBackgroundColor:(UIColor *)badgeBackgroundColor {
objc_setAssociatedObject(self, @selector(cyl_badgeBackgroundColor), badgeBackgroundColor, OBJC_ASSOCIATION_RETAIN);
if (!self.cyl_badge) {
[self cyl_badgeInit];
}
self.cyl_badge.backgroundColor = badgeBackgroundColor;
}
- (UIColor *)cyl_badgeTextColor {
return objc_getAssociatedObject(self, @selector(cyl_badgeTextColor));
}
- (void)cyl_setBadgeTextColor:(UIColor *)badgeTextColor {
objc_setAssociatedObject(self, @selector(cyl_badgeTextColor), badgeTextColor, OBJC_ASSOCIATION_RETAIN);
if (!self.cyl_badge) {
[self cyl_badgeInit];
}
self.cyl_badge.textColor = badgeTextColor;
}
- (CYLBadgeAnimationType)cyl_badgeAnimationType {
id obj = objc_getAssociatedObject(self, @selector(cyl_badgeAnimationType));
if(obj != nil && [obj isKindOfClass:[NSNumber class]]) {
return [obj integerValue];
}
return CYLBadgeAnimationTypeNone;
}
- (void)cyl_setBadgeAnimationType:(CYLBadgeAnimationType)animationType {
NSNumber *numObj = @(animationType);
objc_setAssociatedObject(self, @selector(cyl_badgeAnimationType), numObj, OBJC_ASSOCIATION_RETAIN);
if (!self.cyl_badge) {
[self cyl_badgeInit];
}
[self cyl_removeAnimation];
[self cyl_beginAnimation];
}
- (CGRect)cyl_badgeFrame {
id obj = objc_getAssociatedObject(self, @selector(cyl_badgeFrame));
if (obj != nil && [obj isKindOfClass:[NSDictionary class]] && [obj count] == 4) {
CGFloat x = [obj[@"x"] floatValue];
CGFloat y = [obj[@"y"] floatValue];
CGFloat width = [obj[@"width"] floatValue];
CGFloat height = [obj[@"height"] floatValue];
return CGRectMake(x, y, width, height);
}
return CGRectZero;
}
- (void)cyl_setBadgeFrame:(CGRect)badgeFrame {
NSDictionary *frameInfo = @{@"x" : @(badgeFrame.origin.x), @"y" : @(badgeFrame.origin.y),
@"width" : @(badgeFrame.size.width), @"height" : @(badgeFrame.size.height)};
objc_setAssociatedObject(self, @selector(cyl_badgeFrame), frameInfo, OBJC_ASSOCIATION_RETAIN);
if (!self.cyl_badge) {
[self cyl_badgeInit];
}
self.cyl_badge.frame = badgeFrame;
}
- (CGFloat)cyl_badgeCornerRadius {
NSNumber *badgeCornerRadiusObject = objc_getAssociatedObject(self, @selector(cyl_badgeCornerRadius));
return [badgeCornerRadiusObject floatValue];
}
- (void)cyl_setBadgeCornerRadius:(CGFloat)badgeCornerRadius {
NSNumber *badgeCornerRadiusObject = @(badgeCornerRadius);
objc_setAssociatedObject(self, @selector(cyl_badgeCornerRadius), badgeCornerRadiusObject, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (CGPoint)cyl_badgeCenterOffset {
id obj = objc_getAssociatedObject(self, @selector(cyl_badgeCenterOffset));
if (obj != nil && [obj isKindOfClass:[NSDictionary class]] && [obj count] == 2) {
CGFloat x = [obj[@"x"] floatValue];
CGFloat y = [obj[@"y"] floatValue];
return CGPointMake(x, y);
}
return CGPointZero;
}
- (void)cyl_setBadgeCenterOffset:(CGPoint)badgeCenterOff {
NSDictionary *cenerInfo = @{@"x" : @(badgeCenterOff.x), @"y" : @(badgeCenterOff.y)};
objc_setAssociatedObject(self, @selector(cyl_badgeCenterOffset), cenerInfo, OBJC_ASSOCIATION_RETAIN);
if (!self.cyl_badge) {
[self cyl_badgeInit];
}
self.cyl_badge.center = CGPointMake(CGRectGetWidth(self.frame) + 2 + badgeCenterOff.x, badgeCenterOff.y);
}
//badgeRadiusKey
- (void)cyl_setBadgeRadius:(CGFloat)badgeRadius {
objc_setAssociatedObject(self, @selector(cyl_badgeRadius), [NSNumber numberWithFloat:badgeRadius], OBJC_ASSOCIATION_RETAIN);
if (!self.cyl_badge) {
[self cyl_badgeInit];
}
}
- (CGFloat)cyl_badgeRadius {
return [objc_getAssociatedObject(self, @selector(cyl_badgeRadius)) floatValue];
}
- (void)cyl_setBadgeMargin:(CGFloat)badgeMargin {
objc_setAssociatedObject(self, @selector(cyl_badgeMargin), [NSNumber numberWithFloat:badgeMargin], OBJC_ASSOCIATION_RETAIN);
if (!self.cyl_badge) {
[self cyl_badgeInit];
}
}
- (CGFloat)cyl_badgeMargin {
id margin = objc_getAssociatedObject(self, @selector(cyl_badgeMargin));
return margin == nil ? kCYLBadgeDefaultMargin : [margin floatValue];
}
- (NSInteger)cyl_badgeMaximumBadgeNumber {
id obj = objc_getAssociatedObject(self, @selector(cyl_badgeMaximumBadgeNumber));
if(obj != nil && [obj isKindOfClass:[NSNumber class]]) {
return [obj integerValue];
}
return kCYLBadgeDefaultMaximumBadgeNumber;
}
- (void)cyl_setBadgeMaximumBadgeNumber:(NSInteger)badgeMaximumBadgeNumber {
NSNumber *numObj = @(badgeMaximumBadgeNumber);
objc_setAssociatedObject(self, @selector(cyl_badgeMaximumBadgeNumber), numObj, OBJC_ASSOCIATION_RETAIN);
if (!self.cyl_badge) {
[self cyl_badgeInit];
}
}
- (BOOL)cyl_isInvisiable {
UIView *obj = self;
CGFloat width = obj.frame.size.width;
CGFloat height = obj.frame.size.height;
BOOL isSizeZero = (width == 0 || height == 0);
BOOL isInvisible = (obj.hidden == YES) || (obj.alpha <= 0.01f) || (!obj.superview) || isSizeZero;
return isInvisible;
}
- (BOOL)cyl_canNotResponseEvent {
return self.cyl_isInvisiable || (self.userInteractionEnabled == NO);
}
@end
================================================
FILE: CYLTabBarController/UIView+CYLTabBarControllerExtention.h
================================================
//
// CYLTabBarController.m
// CYLTabBarController
//
// v1.21.x Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 10/20/15.
// Copyright © 2018 https://github.com/ChenYilong . All rights reserved.
//
#import
#import
#import "CYLConstants.h"
NS_ASSUME_NONNULL_BEGIN
@interface UIView (CYLTabBarControllerExtention)
- (BOOL)cyl_isPlusButton;
- (BOOL)cyl_isTabButton;
- (BOOL)cyl_isTabImageView;
- (BOOL)cyl_isTabLabel;
- (BOOL)cyl_isTabBadgeView;
- (BOOL)cyl_isTabBackgroundView;
- (UIView *)cyl_tabBadgeView;
- (UIImageView *)cyl_tabImageView;
- (UILabel *)cyl_tabLabel;
- (UIImageView *)cyl_tabShadowImageView;
- (UIVisualEffectView *)cyl_tabEffectView;
- (BOOL)cyl_isLottieAnimationView;
- (UIView *)cyl_tabBackgroundView;
+ (UIView *)cyl_tabBadgePointViewWithClolor:(UIColor *)color radius:(CGFloat)radius;
- (NSArray *)cyl_allSubviews;
@end
@interface UIView (CYLTabBarControllerExtentionDeprecated)
- (UIView *)cyl_tabBadgeBackgroundView CYL_DEPRECATED("Deprecated in 1.6.0. Use `+[CYLPlusButton cyl_tabBackgroundView]` instead.");
- (UIView *)cyl_tabBadgeBackgroundSeparator CYL_DEPRECATED("Deprecated in 1.6.0. Use `+[CYLPlusButton cyl_tabShadowImageView]` instead.");
@end
NS_ASSUME_NONNULL_END
================================================
FILE: CYLTabBarController/UIView+CYLTabBarControllerExtention.m
================================================
//
// CYLTabBarController.m
// CYLTabBarController
//
// v1.21.x Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 10/20/15.
// Copyright © 2018 https://github.com/ChenYilong . All rights reserved.
//
#import
#import "UIView+CYLTabBarControllerExtention.h"
#import "CYLPlusButton.h"
#if __has_include()
#import
#else
#endif
@implementation UIView (CYLTabBarControllerExtention)
- (BOOL)cyl_isPlusButton {
return [self isKindOfClass:[CYLExternPlusButton class]];
}
- (BOOL)cyl_isTabButton {
BOOL isKindOfButton = [self cyl_isKindOfClass:[UIControl class]];
return isKindOfButton;
}
- (BOOL)cyl_isTabImageView {
BOOL isKindOfImageView = [self cyl_isKindOfClass:[UIImageView class]];
if (!isKindOfImageView) {
return NO;
}
NSString *subString = [NSString stringWithFormat:@"%@cat%@ew", @"Indi" , @"orVi"];
BOOL isBackgroundImage = [self cyl_classStringHasSuffix:subString];
BOOL isTabImageView = !isBackgroundImage;
return isTabImageView;
}
- (BOOL)cyl_isTabLabel {
BOOL isKindOfLabel = [self cyl_isKindOfClass:[UILabel class]];
return isKindOfLabel;
}
- (BOOL)cyl_isTabBadgeView {
BOOL isKindOfClass = [self isKindOfClass:[UIView class]];
BOOL isClass = [self isMemberOfClass:[UIView class]];
BOOL isKind = isKindOfClass && !isClass;
if (!isKind) {
return NO;
}
NSString *tabBarClassString = [NSString stringWithFormat:@"%@IB%@", @"_U" , @"adg"];
BOOL isTabBadgeView = [self cyl_classStringHasPrefix:tabBarClassString];;
return isTabBadgeView;
}
- (BOOL)cyl_isTabBackgroundView {
BOOL isKindOfClass = [self isKindOfClass:[UIView class]];
BOOL isClass = [self isMemberOfClass:[UIView class]];
BOOL isKind = isKindOfClass && !isClass;
if (!isKind) {
return NO;
}
NSString *tabBackgroundViewString = [NSString stringWithFormat:@"%@IB%@", @"_U" , @"arBac"];
BOOL isTabBackgroundView = [self cyl_classStringHasPrefix:tabBackgroundViewString] && [self cyl_classStringHasSuffix:@"nd"];
return isTabBackgroundView;
}
- (UIImageView *)cyl_tabImageView {
for (UIImageView *subview in self.cyl_allSubviews) {
if ([subview cyl_isTabImageView]) {
return (UIImageView *)subview;
}
}
return nil;
}
- (NSArray *)cyl_allSubviews {
__block NSArray* allSubviews = [NSArray arrayWithObject:self];
[self.subviews enumerateObjectsUsingBlock:^(UIView* view, NSUInteger idx, BOOL*stop) {
allSubviews = [allSubviews arrayByAddingObjectsFromArray:[view cyl_allSubviews]];
}];
return allSubviews;
}
- (UIView *)cyl_tabBadgeView {
for (UIView *subview in self.cyl_allSubviews) {
if ([subview cyl_isTabBadgeView]) {
return (UIView *)subview;
}
}
return nil;
}
- (UILabel *)cyl_tabLabel {
for (UILabel *subview in self.cyl_allSubviews) {
if ([subview cyl_isTabLabel]) {
return (UILabel *)subview;
}
}
return nil;
}
//UIVisualEffectView
- (BOOL)cyl_isTabEffectView {
BOOL isClass = [self isMemberOfClass:[UIVisualEffectView class]];
return isClass;
}
//_UIVisualEffectContentView
- (BOOL)cyl_isTabEffectContentView {
BOOL isKindOfClass = [self isKindOfClass:[UIView class]];
BOOL isClass = [self isMemberOfClass:[UIView class]];
BOOL isKind = isKindOfClass && !isClass;
if (!isKind) {
return NO;
}
NSString *tabBackgroundViewString = [NSString stringWithFormat:@"%@IVisualE%@", @"_U" , @"ffectC"];
BOOL isTabBackgroundView = [self cyl_classStringHasPrefix:tabBackgroundViewString] && [self cyl_classStringHasSuffix:@"entView"];
return isTabBackgroundView;
}
//UIVisualEffectView
- (UIVisualEffectView *)cyl_tabEffectView {
for (UIView *subview in self.subviews) {
if ([subview cyl_isTabEffectView]) {
return (UIVisualEffectView *)subview;
}
}
return nil;
}
- (UIView *)cyl_tabBadgeBackgroundView {
return [self cyl_tabBackgroundView];
}
- (UIImageView *)cyl_tabShadowImageView {
if (@available(iOS 10.0, *)) {
//iOS10及以上这样获取ShadowImageView:
UIView *subview = [self cyl_tabBackgroundView];
if (!subview) {
return nil;
}
NSArray<__kindof UIView *> *backgroundSubviews = subview.subviews;
//iOS13系统backgroundSubviews.count > 1可行,12及以下就不可行了
if (backgroundSubviews.count >= 1) {
for (UIView *subview in backgroundSubviews) {
if (CGRectGetHeight(subview.bounds) <= 1.0 ) {
return (UIImageView *)subview;
}
}
}
} else {
//iOS9这样获取ShadowImageView:
for (UIView *subview in self.subviews) {
if (CGRectGetHeight(subview.bounds) <= 1.0 ) {
return (UIImageView *)subview;
}
}
}
return nil;
}
- (UIView *)cyl_tabBackgroundView {
for (UIImageView *subview in self.subviews) {
if ([subview cyl_isTabBackgroundView]) {
return (UIImageView *)subview;
}
}
return nil;
}
- (BOOL)cyl_isLottieAnimationView {
BOOL isKindOfClass = [self isKindOfClass:[UIView class]];
BOOL isClass = [self isMemberOfClass:[UIView class]];
BOOL isKind = isKindOfClass && !isClass;
if (!isKind) {
return NO;
}
Class classType = NSClassFromString(@"LOTAnimationView");
BOOL isLottieAnimationView = ([self isKindOfClass:classType] || [self isMemberOfClass:classType]);
return isLottieAnimationView;
}
- (UIView *)cyl_tabBadgeBackgroundSeparator {
return [self cyl_tabShadowImageView];
}
- (BOOL)cyl_isKindOfClass:(Class)class {
BOOL isKindOfClass = [self isKindOfClass:class];
BOOL isClass = [self isMemberOfClass:class];
BOOL isKind = isKindOfClass && !isClass;
if (!isKind) {
return NO;
}
BOOL isTabBarClass = [self cyl_isTabBarClass];
return isTabBarClass;
}
- (BOOL)cyl_isTabBarClass {
NSString *tabBarClassString = [NSString stringWithFormat:@"U%@a%@ar", @"IT" , @"bB"];
BOOL isTabBarClass = [self cyl_classStringHasPrefix:tabBarClassString];
return isTabBarClass;
}
- (BOOL)cyl_classStringHasPrefix:(NSString *)prefix {
NSString *classString = NSStringFromClass([self class]);
return [classString hasPrefix:prefix];
}
- (BOOL)cyl_classStringHasSuffix:(NSString *)suffix {
NSString *classString = NSStringFromClass([self class]);
return [classString hasSuffix:suffix];
}
+ (UIView *)cyl_tabBadgePointViewWithClolor:(UIColor *)color radius:(CGFloat)radius {
UIView *defaultTabBadgePointView = [[UIView alloc] init];
[defaultTabBadgePointView setTranslatesAutoresizingMaskIntoConstraints:NO];
defaultTabBadgePointView.backgroundColor = color;
defaultTabBadgePointView.layer.cornerRadius = radius;
defaultTabBadgePointView.layer.masksToBounds = YES;
defaultTabBadgePointView.hidden = YES;
// Width constraint
[defaultTabBadgePointView addConstraint:[NSLayoutConstraint constraintWithItem:defaultTabBadgePointView
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute: NSLayoutAttributeNotAnAttribute
multiplier:1
constant:radius * 2]];
// Height constraint
[defaultTabBadgePointView addConstraint:[NSLayoutConstraint constraintWithItem:defaultTabBadgePointView
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute: NSLayoutAttributeNotAnAttribute
multiplier:1
constant:radius * 2]];
return defaultTabBadgePointView;
}
@end
================================================
FILE: CYLTabBarController/UIViewController+CYLNavigationControllerExtention.h
================================================
/*
// CYLTabBarController
// CYLTabBarController
//
// Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 03/06/19.
// Copyright © 2019 https://github.com/ChenYilong . All rights reserved.
*/
#import
NS_ASSUME_NONNULL_BEGIN
@interface UIViewController (CYLNavigationControllerExtention)
@property (nonatomic, assign, getter=cyl_disablePopGestureRecognizer, setter=cyl_setDisablePopGestureRecognizer:) BOOL cyl_disablePopGestureRecognizer;
@property (nonatomic, assign, getter=cyl_hideNavigationBarSeparator, setter=cyl_setHideNavigationBarSeparator:) BOOL cyl_hideNavigationBarSeparator;
@property (nonatomic, assign, getter=cyl_navigationBarHidden, setter=cyl_setNavigationBarHidden:) BOOL cyl_navigationBarHidden;
/*!
* 使用方法:用在viewWillDisappear/dealloc
* 作用:在左滑动的过渡的时间段内禁用interactivePopGestureRecognizer
*/
- (void)cyl_disableInteractivePopGestureRecognizer;
/*!
* use in viewDidDisappear
* 作用:在左滑动的结束后启用interactivePopGestureRecognizer
*/
- (void)cyl_enableInteractivePopGestureRecognizer;
/*!
* use in viewDidAppear
* 当新的视图控制器加载完成后再启用
*/
- (void)cyl_resetInteractivePopGestureRecognizer;
/*!
* use in viewWillAppear
*/
- (void)cyl_hideNavigationBarSeparatorIfNeeded;
- (BOOL)cyl_shouldNavigationBarVisible;
//use in viewWillDisappear
- (void)cyl_setNavigationBarVisibleIfNeeded:(BOOL)animated;
//use in viewWillAppear
- (void)cyl_setNavigationBarHiddenIfNeeded:(BOOL)animated;
- (void)cyl_viewWillAppearNavigationSetting:(BOOL)animated;
- (void)cyl_viewWillDisappearNavigationSetting:(BOOL)animated;
- (void)cyl_viewDidDisappearNavigationSetting:(BOOL)animated;
- (void)cyl_viewDidAppearNavigationSetting:(BOOL)animated;
- (void)cyl_deallocNavigationSetting;
@end
NS_ASSUME_NONNULL_END
================================================
FILE: CYLTabBarController/UIViewController+CYLNavigationControllerExtention.m
================================================
/*
// CYLTabBarController
// CYLTabBarController
//
// Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 03/06/19.
// Copyright © 2019 https://github.com/ChenYilong . All rights reserved.
*/
#import "UIViewController+CYLNavigationControllerExtention.h"
#import
@implementation UIViewController (CYLNavigationControllerExtention)
- (BOOL)cyl_disablePopGestureRecognizer {
NSNumber *disablePopGestureRecognizerObject = objc_getAssociatedObject(self, @selector(cyl_disablePopGestureRecognizer));
return [disablePopGestureRecognizerObject boolValue];
}
- (void)cyl_setDisablePopGestureRecognizer:(BOOL)disablePopGestureRecognizer {
NSNumber *disablePopGestureRecognizerObject = [NSNumber numberWithBool:disablePopGestureRecognizer];
objc_setAssociatedObject(self, @selector(cyl_disablePopGestureRecognizer), disablePopGestureRecognizerObject, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (BOOL)cyl_hideNavigationBarSeparator {
NSNumber *hideNavigationBarSeparatorObject = objc_getAssociatedObject(self, @selector(cyl_hideNavigationBarSeparator));
return [hideNavigationBarSeparatorObject boolValue];
}
- (void)cyl_setHideNavigationBarSeparator:(BOOL)hideNavigationBarSeparator {
NSNumber *hideNavigationBarSeparatorObject = [NSNumber numberWithBool:hideNavigationBarSeparator];
objc_setAssociatedObject(self, @selector(cyl_hideNavigationBarSeparator), hideNavigationBarSeparatorObject, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (BOOL)cyl_navigationBarHidden {
NSNumber *navigationBarHiddenObject = objc_getAssociatedObject(self, @selector(cyl_navigationBarHidden));
return [navigationBarHiddenObject boolValue];
}
- (void)cyl_setNavigationBarHidden:(BOOL)navigationBarHidden {
NSNumber *navigationBarHiddenObject = [NSNumber numberWithBool:navigationBarHidden];
objc_setAssociatedObject(self, @selector(cyl_navigationBarHidden), navigationBarHiddenObject, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
//viewWillDisappear
//dealloc
// 在左滑动的过渡的时间段内禁用interactivePopGestureRecognizer
- (void)cyl_disableInteractivePopGestureRecognizer {
if (![self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
return;
}
self.navigationController.interactivePopGestureRecognizer.delegate = nil;
}
//viewDidDisappear
// 在左滑动的结束后启用interactivePopGestureRecognizer
- (void)cyl_enableInteractivePopGestureRecognizer {
if (![self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
return;
}
self.navigationController.interactivePopGestureRecognizer.delegate = (id )self;
self.navigationController.interactivePopGestureRecognizer.enabled = YES;
}
//viewDidAppear
// 当新的视图控制器加载完成后再启用
- (void)cyl_resetInteractivePopGestureRecognizer {
if (![self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
return;
}
BOOL isSingleViewControllerInNavigationController = ([self.navigationController.viewControllers count] == 1);
BOOL needDisableInteractivePopGestureRecognizer = (self.cyl_disablePopGestureRecognizer) || isSingleViewControllerInNavigationController;
if (needDisableInteractivePopGestureRecognizer) {
self.navigationController.interactivePopGestureRecognizer.enabled = NO;
} else {
self.navigationController.interactivePopGestureRecognizer.enabled = YES;
}
}
//viewWillAppear
- (void)cyl_hideNavigationBarSeparatorIfNeeded {
if (self.cyl_hideNavigationBarSeparator) {
self.navigationController.navigationBar.shadowImage = [UIImage new];
self.navigationController.navigationBar.translucent = NO;
}
}
//在viewwilldisappear使用
- (BOOL)cyl_shouldNavigationBarVisible {
BOOL shouldSetNo = YES;
BOOL isPop = YES;
if (!self.navigationController) {
return shouldSetNo;
}
//push的时候会先将vc添加到viewControllers,再调用viewWillDisappear
//pop的时候会先将vc从viewControllers移除,再调用viewWillDisappear
NSInteger selfIndex = -1;
if (self.navigationController.viewControllers.count > 0) {
NSArray *vcList = self.navigationController.viewControllers;
for (NSInteger i = 0; i < vcList.count; i++) {
UIViewController *vc = vcList[i];
if (vc == self) {
selfIndex = i;
if (selfIndex == vcList.count - 1) {
//这种情况是navigationController push第一个vc或者present,不需要特殊处理,直接return
return YES;
}
isPop = NO;
break;
}
}
if (isPop) {
UIViewController *preVc = (UIViewController *)self.navigationController.viewControllers.lastObject;
if (self.cyl_navigationBarHidden == preVc.cyl_navigationBarHidden) {
shouldSetNo = NO;
}
} else {
if (selfIndex + 1 < self.navigationController.viewControllers.count) {
UIViewController *nextVc = (UIViewController *)self.navigationController.viewControllers[selfIndex + 1];
if (self.cyl_navigationBarHidden == nextVc.cyl_navigationBarHidden) {
shouldSetNo = NO;
}
}
}
}
return shouldSetNo;
}
//viewWillDisappear
- (void)cyl_setNavigationBarVisibleIfNeeded:(BOOL)animated {
if (self.cyl_navigationBarHidden && [self cyl_shouldNavigationBarVisible]) {
[self.navigationController setNavigationBarHidden:!self.cyl_navigationBarHidden animated:animated];
}
}
//viewWillAppear
- (void)cyl_setNavigationBarHiddenIfNeeded:(BOOL)animated {
if (self.cyl_navigationBarHidden) {
[self.navigationController setNavigationBarHidden:self.cyl_navigationBarHidden animated:animated];
}
}
- (void)cyl_viewWillAppearNavigationSetting:(BOOL)animated {
[self cyl_hideNavigationBarSeparatorIfNeeded];
[self cyl_setNavigationBarHiddenIfNeeded:animated];
}
- (void)cyl_viewWillDisappearNavigationSetting:(BOOL)animated {
[self cyl_disableInteractivePopGestureRecognizer];
[self cyl_setNavigationBarVisibleIfNeeded:animated];
}
- (void)cyl_viewDidDisappearNavigationSetting:(BOOL)animated {
[self cyl_enableInteractivePopGestureRecognizer];
}
- (void)cyl_viewDidAppearNavigationSetting:(BOOL)animated {
[self cyl_resetInteractivePopGestureRecognizer];
}
- (void)cyl_deallocNavigationSetting {
[self cyl_disableInteractivePopGestureRecognizer];
}
@end
================================================
FILE: CYLTabBarController/UIViewController+CYLTabBarControllerExtention.h
================================================
//
// UIViewController+CYLTabBarControllerExtention.h
// CYLTabBarController
//
// v1.21.x Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 16/2/26.
// Copyright © 2018年 https://github.com/ChenYilong .All rights reserved.
//
#import
#import "CYLBadgeProtocol.h"
#import "CYLConstants.h"
NS_ASSUME_NONNULL_BEGIN
typedef void (^CYLPopSelectTabBarChildViewControllerCompletion)(__kindof UIViewController *selectedTabBarChildViewController);
typedef void (^CYLPushOrPopCompletionHandler)(BOOL shouldPop,
__kindof UIViewController *viewControllerPopTo,
BOOL shouldPopSelectTabBarChildViewController,
NSUInteger index
);
typedef void (^CYLPushOrPopCallback)(NSArray<__kindof UIViewController *> *viewControllers, CYLPushOrPopCompletionHandler completionHandler);
@interface UIViewController (CYLTabBarControllerExtention)
@property (nonatomic, readonly, getter=cyl_isEmbedInTabBarController) BOOL cyl_embedInTabBarController;
@property (nonatomic, readonly, getter=cyl_tabIndex) NSInteger cyl_tabIndex;
@property (nonatomic, readonly) UIControl *cyl_tabButton;
@property (nonatomic, copy, setter=cyl_setContext:, getter=cyl_context) NSString *cyl_context;
@property (nonatomic, assign, setter=cyl_setPlusViewControllerEverAdded:, getter=cyl_plusViewControllerEverAdded) BOOL cyl_plusViewControllerEverAdded;
- (BOOL)cyl_isShowBadge;
/**
* show badge with red dot style and CYLBadgeAnimationTypeNone by default.
*/
- (void)cyl_showBadge;
/**
*
* @param value String value, default is `nil`. if value equal @"" means red dot style.
* @param animationType animationType
* @attention
- 调用该方法前已经添加了系统的角标,调用该方法后,系统的角标并未被移除,只是被隐藏,调用 `-cyl_removeTabBadgePoint` 后会重新展示。
- 不支持 CYLPlusChildViewController 对应的 TabBarItem 角标设置,调用会被忽略。
*/
- (void)cyl_showBadgeValue:(NSString *)value
animationType:(CYLBadgeAnimationType)animationType;
/**
* clear badge(hide badge)
*/
- (void)cyl_clearBadge;
/**
* make bage(if existing) not hiden
*/
- (void)cyl_resumeBadge;
- (BOOL)cyl_isPauseBadge;
/*!
* Pop 到当前 `NavigationController` 的栈底,并改变 `TabBarController` 的 `selectedViewController` 属性,并将被选择的控制器作为返回值返回。
@param index 需要选择的控制器在 `TabBar` 中的 index。
@return 最终被选择的控制器。
@attention 注意:方法中的参数和返回值都是 `UIViewController` 的子类,但并非 `UINavigationController` 的子类,该方法无 pop 动画。
*/
- (UIViewController *)cyl_popSelectTabBarChildViewControllerAtIndex:(NSUInteger)index;
/*!
* Pop 到当前 `NavigationController` 的栈底,并改变 `TabBarController` 的 `selectedViewController` 属性,并将被选择的控制器作为返回值返回。
@param index 需要选择的控制器在 `TabBar` 中的 index。
@param animated 动画
@return 最终被选择的控制器。
@attention 注意:方法中的参数和返回值都是 `UIViewController` 的子类,但并非 `UINavigationController` 的子类。
*/
- (UIViewController *)cyl_popSelectTabBarChildViewControllerAtIndex:(NSUInteger)index animated:(BOOL)animated;
/*!
* Pop 到当前 `NavigationController` 的栈底,并改变 `TabBarController` 的 `selectedViewController` 属性,并将被选择的控制器在 `Block` 回调中返回。
@param index 需要选择的控制器在 `TabBar` 中的 index。
@attention 注意:方法中的参数和返回值都是 `UIViewController` 的子类,但并非 `UINavigationController` 的子类。
*/
- (void)cyl_popSelectTabBarChildViewControllerAtIndex:(NSUInteger)index
completion:(CYLPopSelectTabBarChildViewControllerCompletion)completion;
/*!
* Pop 到当前 `NavigationController` 的栈底,并改变 `TabBarController` 的 `selectedViewController` 属性,并将被选择的控制器作为返回值返回。
@param classType 需要选择的控制器所属的类。
@return 最终被选择的控制器。
@attention 注意:
- 方法中的参数和返回值都是 `UIViewController` 的子类,但并非 `UINavigationController` 的子类。
- 如果 TabBarViewController 的 viewControllers 中包含多个相同的 `classType` 类型,会返回最左端的一个。
*/
- (UIViewController *)cyl_popSelectTabBarChildViewControllerForClassType:(Class)classType;
/*!
* Pop 到当前 `NavigationController` 的栈底,并改变 `TabBarController` 的 `selectedViewController` 属性,并将被选择的控制器在 `Block` 回调中返回。
@param classType 需要选择的控制器所属的类。
@attention 注意:
- 方法中的参数和返回值都是 `UIViewController` 的子类,但并非 `UINavigationController` 的子类。
- 如果 TabBarViewController 的 viewControllers 中包含多个相同的 `classType` 类型,会返回最左端的一个。
*/
- (void)cyl_popSelectTabBarChildViewControllerForClassType:(Class)classType
completion:(CYLPopSelectTabBarChildViewControllerCompletion)completion;
/*!
*@brief 如果当前的 `NavigationViewController` 栈中包含有准备 Push 到的目标控制器,可以选择 Pop 而非 Push。
*@param viewController Pop 或 Push 到的“目标控制器”,由 completionHandler 的参数控制 Pop 和 Push 的细节。
*@param animated Pop 或 Push 时是否带动画
*@param callback 回调,如果传 nil,将进行 Push。callback 包含以下几个参数:
* param : viewControllers 表示与“目标控制器”相同类型的控制器;
* param : completionHandler 包含以下几个参数:
* param : shouldPop 是否 Pop
* param : viewControllerPopTo Pop 回的控制器
* param : shouldPopSelectTabBarChildViewController 在进行 Push 行为之前,是否 Pop 到当前 `NavigationController` 的栈底。
可能的值如下:
NO 如果上一个参数为 NO,下一个参数 index 将被忽略。
YES 会根据 index 参数改变 `TabBarController` 的 `selectedViewController` 属性。
注意:该属性在 Pop 行为时不起作用。
* param : index Pop 改变 `TabBarController` 的 `selectedViewController` 属性。
注意:该属性在 Pop 行为时不起作用。
*/
- (void)cyl_pushOrPopToViewController:(UIViewController *)viewController
animated:(BOOL)animated
callback:(CYLPushOrPopCallback)callback;
/*!
* 如果正要 Push 的页面与当前栈顶的页面类型相同则取消 Push
* 这样做防止主界面卡顿时,导致一个 ViewController 被 Push 多次
*/
- (void)cyl_pushViewController:(UIViewController *)viewController animated:(BOOL)animated;
- (UIViewController *)cyl_getViewControllerInsteadOfNavigationController;
- (void)cyl_handleNavigationBackAction;
- (void)cyl_handleNavigationBackActionWithAnimated:(BOOL)animated;
@end
@interface UIViewController (CYLTabBarControllerExtentionDeprecated)
- (void)cyl_showTabBadgePoint CYL_DEPRECATED("Deprecated in 1.19.0. Use `-[UIViewController cyl_showBadgeValue:animationType:]` instead.");
- (void)cyl_removeTabBadgePoint CYL_DEPRECATED("Deprecated in 1.19.0. Use `-[UIViewController cyl_clearBadge]` instead.");
- (BOOL)cyl_isShowTabBadgePoint CYL_DEPRECATED("Deprecated in 1.19.0. Use `-[UIViewController cyl_isShowBadge]` instead.");
@property (nonatomic, strong, setter=cyl_setTabBadgePointView:, getter=cyl_tabBadgePointView) UIView *cyl_tabBadgePointView CYL_DEPRECATED("Deprecated in 1.19.0. Use method in instead.");
@property (nonatomic, assign, setter=cyl_setTabBadgePointViewOffset:, getter=cyl_tabBadgePointViewOffset) UIOffset cyl_tabBadgePointViewOffset CYL_DEPRECATED("Deprecated in 1.19.0. Use method in instead.");
@end
NS_ASSUME_NONNULL_END
================================================
FILE: CYLTabBarController/UIViewController+CYLTabBarControllerExtention.m
================================================
//
// UIViewController+CYLTabBarControllerExtention.m
// CYLTabBarController
//
// v1.21.x Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 16/2/26.
// Copyright © 2018年 https://github.com/ChenYilong .All rights reserved.
//
#import "UIViewController+CYLTabBarControllerExtention.h"
#import "CYLTabBarController.h"
#import
#define kActualView [self cyl_getActualBadgeSuperView]
@implementation UIViewController (CYLTabBarControllerExtention)
#pragma mark -
#pragma mark - public Methods
- (UIViewController *)cyl_popSelectTabBarChildViewControllerAtIndex:(NSUInteger)index {
return [self cyl_popSelectTabBarChildViewControllerAtIndex:index animated:NO];
}
- (UIViewController *)cyl_popSelectTabBarChildViewControllerAtIndex:(NSUInteger)index animated:(BOOL)animated {
UIViewController *viewController = [self cyl_getViewControllerInsteadOfNavigationController];
[viewController checkTabBarChildControllerValidityAtIndex:index];
CYLTabBarController *tabBarController = [viewController cyl_tabBarController];
tabBarController.selectedIndex = index;
[viewController.navigationController popToRootViewControllerAnimated:animated];
UIViewController *selectedTabBarChildViewController = tabBarController.selectedViewController;
return [selectedTabBarChildViewController cyl_getViewControllerInsteadOfNavigationController];
}
- (void)cyl_popSelectTabBarChildViewControllerAtIndex:(NSUInteger)index
completion:(CYLPopSelectTabBarChildViewControllerCompletion)completion {
UIViewController *selectedTabBarChildViewController = [self cyl_popSelectTabBarChildViewControllerAtIndex:index];
dispatch_async(dispatch_get_main_queue(), ^{
!completion ?: completion(selectedTabBarChildViewController);
});
}
- (UIViewController *)cyl_popSelectTabBarChildViewControllerForClassType:(Class)classType {
CYLTabBarController *tabBarController = [[self cyl_getViewControllerInsteadOfNavigationController] cyl_tabBarController];
NSArray *viewControllers = tabBarController.viewControllers;
NSInteger atIndex = [self cyl_indexForClassType:classType inViewControllers:viewControllers];
return [self cyl_popSelectTabBarChildViewControllerAtIndex:atIndex];
}
- (void)cyl_popSelectTabBarChildViewControllerForClassType:(Class)classType
completion:(CYLPopSelectTabBarChildViewControllerCompletion)completion {
UIViewController *selectedTabBarChildViewController = [self cyl_popSelectTabBarChildViewControllerForClassType:classType];
dispatch_async(dispatch_get_main_queue(), ^{
!completion ?: completion(selectedTabBarChildViewController);
});
}
- (void)cyl_pushOrPopToViewController:(UIViewController *)viewController
animated:(BOOL)animated
callback:(CYLPushOrPopCallback)callback {
if (!callback) {
[self.navigationController pushViewController:viewController animated:animated];
return;
}
void (^popSelectTabBarChildViewControllerCallback)(BOOL shouldPopSelectTabBarChildViewController, NSUInteger index) = ^(BOOL shouldPopSelectTabBarChildViewController, NSUInteger index) {
if (shouldPopSelectTabBarChildViewController) {
[self cyl_popSelectTabBarChildViewControllerAtIndex:index completion:^(__kindof UIViewController *selectedTabBarChildViewController) {
[selectedTabBarChildViewController.navigationController pushViewController:viewController animated:animated];
}];
} else {
[self.navigationController pushViewController:viewController animated:animated];
}
};
NSArray<__kindof UIViewController *> *otherSameClassTypeViewControllersInCurrentNavigationControllerStack = [self cyl_getOtherSameClassTypeViewControllersInCurrentNavigationControllerStack:viewController];
CYLPushOrPopCompletionHandler completionHandler = ^(BOOL shouldPop,
__kindof UIViewController *viewControllerPopTo,
BOOL shouldPopSelectTabBarChildViewController,
NSUInteger index
) {
if (!otherSameClassTypeViewControllersInCurrentNavigationControllerStack || otherSameClassTypeViewControllersInCurrentNavigationControllerStack.count == 0) {
shouldPop = NO;
}
dispatch_async(dispatch_get_main_queue(),^{
if (shouldPop) {
[self.navigationController popToViewController:viewControllerPopTo animated:animated];
return;
}
popSelectTabBarChildViewControllerCallback(shouldPopSelectTabBarChildViewController, index);
});
};
callback(otherSameClassTypeViewControllersInCurrentNavigationControllerStack, completionHandler);
}
- (void)cyl_pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
UIViewController *fromViewController = [self cyl_getViewControllerInsteadOfNavigationController];
NSArray *childViewControllers = fromViewController.navigationController.childViewControllers;
if (childViewControllers.count > 0) {
if ([[childViewControllers lastObject] isKindOfClass:[viewController class]]) {
return;
}
}
[fromViewController.navigationController pushViewController:viewController animated:animated];
}
- (UIViewController *)cyl_getViewControllerInsteadOfNavigationController {
BOOL isNavigationController = [[self class] isSubclassOfClass:[UINavigationController class]];
if (isNavigationController && ((UINavigationController *)self).viewControllers.count > 0) {
return ((UINavigationController *)self).viewControllers[0];
}
return self;
}
#pragma mark - public method
- (BOOL)cyl_isPlusChildViewController {
if (!CYLPlusChildViewController) {
return NO;
}
return (self == CYLPlusChildViewController);
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- (void)cyl_showTabBadgePoint {
if (self.cyl_isPlusChildViewController) {
return;
}
[self cyl_showBadge];
}
- (void)cyl_removeTabBadgePoint {
if (self.cyl_isPlusChildViewController) {
return;
}
[self cyl_clearBadge];
}
- (BOOL)cyl_isShowTabBadgePoint {
if (self.cyl_isPlusChildViewController) {
return NO;
}
return [self cyl_isShowBadge];;
}
#pragma clang diagnostic pop
- (void)cyl_setTabBadgePointView:(UIView *)tabBadgePointView {
if (self.cyl_isPlusChildViewController) {
return;
}
[self.cyl_tabButton cyl_setTabBadgePointView:tabBadgePointView];
}
- (UIView *)cyl_tabBadgePointView {
if (self.cyl_isPlusChildViewController) {
return nil;
}
return [self.cyl_tabButton cyl_tabBadgePointView];;
}
- (void)cyl_setTabBadgePointViewOffset:(UIOffset)tabBadgePointViewOffset {
if (self.cyl_isPlusChildViewController) {
return;
}
return [self.cyl_tabButton cyl_setTabBadgePointViewOffset:tabBadgePointViewOffset];
}
//offset如果都是整数,则往右下偏移
- (UIOffset)cyl_tabBadgePointViewOffset {
if (self.cyl_isPlusChildViewController) {
return UIOffsetZero;
}
return [self.cyl_tabButton cyl_tabBadgePointViewOffset];
}
- (BOOL)cyl_isEmbedInTabBarController {
if (self.cyl_tabBarController == nil) {
return NO;
}
if (self.cyl_isPlusChildViewController) {
return NO;
}
BOOL isEmbedInTabBarController = NO;
UIViewController *viewControllerInsteadIOfNavigationController = [self cyl_getViewControllerInsteadOfNavigationController];
for (NSInteger i = 0; i < self.cyl_tabBarController.viewControllers.count; i++) {
UIViewController * vc = self.cyl_tabBarController.viewControllers[i];
if ([vc cyl_getViewControllerInsteadOfNavigationController] == viewControllerInsteadIOfNavigationController) {
isEmbedInTabBarController = YES;
[self cyl_setTabIndex:i];
break;
}
}
return isEmbedInTabBarController;
}
- (void)cyl_setTabIndex:(NSInteger)tabIndex {
objc_setAssociatedObject(self, @selector(cyl_tabIndex), @(tabIndex), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSInteger)cyl_tabIndex {
if (!self.cyl_isEmbedInTabBarController) {
return NSNotFound;
}
id tabIndexObject = objc_getAssociatedObject(self, @selector(cyl_tabIndex));
NSInteger tabIndex = [tabIndexObject integerValue];
return tabIndex;
}
- (UIControl *)cyl_tabButton {
if (!self.cyl_isEmbedInTabBarController) {
return nil;
}
UITabBarItem *tabBarItem;
UIControl *control;
@try {
tabBarItem = self.cyl_tabBarController.tabBar.items[self.cyl_tabIndex];
control = [tabBarItem cyl_tabButton];
} @catch (NSException *exception) {}
return control;
}
- (NSString *)cyl_context {
return objc_getAssociatedObject(self, @selector(cyl_context));
}
- (void)cyl_setContext:(NSString *)cyl_context {
objc_setAssociatedObject(self, @selector(cyl_context), cyl_context, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (BOOL)cyl_plusViewControllerEverAdded {
NSNumber *cyl_plusViewControllerEverAddedObject = objc_getAssociatedObject(self, @selector(cyl_plusViewControllerEverAdded));
return [cyl_plusViewControllerEverAddedObject boolValue];
}
- (void)cyl_setPlusViewControllerEverAdded:(BOOL)cyl_plusViewControllerEverAdded {
NSNumber *cyl_plusViewControllerEverAddedObject = [NSNumber numberWithBool:cyl_plusViewControllerEverAdded];
objc_setAssociatedObject(self, @selector(cyl_plusViewControllerEverAdded), cyl_plusViewControllerEverAddedObject, OBJC_ASSOCIATION_ASSIGN);
}
#pragma mark -
#pragma mark - Private Methods
- (NSArray<__kindof UIViewController *> *)cyl_getOtherSameClassTypeViewControllersInCurrentNavigationControllerStack:(UIViewController *)viewController {
NSArray *currentNavigationControllerStack = [self.navigationController childViewControllers];
if (currentNavigationControllerStack.count < 2) {
return nil;
}
NSMutableArray *mutableArray = [currentNavigationControllerStack mutableCopy];
[mutableArray removeObject:self];
currentNavigationControllerStack = [mutableArray copy];
__block NSMutableArray *mutableOtherViewControllersInNavigationControllerStack = [NSMutableArray arrayWithCapacity:currentNavigationControllerStack.count];
[currentNavigationControllerStack enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
UIViewController *otherViewController = obj;
if ([otherViewController isKindOfClass:[viewController class]]) {
[mutableOtherViewControllersInNavigationControllerStack addObject:otherViewController];
}
}];
return [mutableOtherViewControllersInNavigationControllerStack copy];
}
- (void)checkTabBarChildControllerValidityAtIndex:(NSUInteger)index {
CYLTabBarController *tabBarController = [[self cyl_getViewControllerInsteadOfNavigationController] cyl_tabBarController];
@try {
UIViewController *viewController;
viewController = tabBarController.viewControllers[index];
UIButton *plusButton = CYLExternPlusButton;
BOOL shouldConfigureSelectionStatus = (CYLPlusChildViewController) && ((index != CYLPlusButtonIndex) && (viewController != CYLPlusChildViewController));
if (shouldConfigureSelectionStatus) {
plusButton.selected = NO;
}
} @catch (NSException *exception) {
NSString *formatString = @"\n\n\
------ BEGIN NSException Log ---------------------------------------------------------------------\n \
class name: %@ \n \
------line: %@ \n \
----reason: The Class Type or the index or its NavigationController you pass in method `-cyl_popSelectTabBarChildViewControllerAtIndex` or `-cyl_popSelectTabBarChildViewControllerForClassType` is not the item of CYLTabBarViewController \n \
------ END ---------------------------------------------------------------------------------------\n\n";
NSString *reason = [NSString stringWithFormat:formatString,
@(__PRETTY_FUNCTION__),
@(__LINE__)];
NSLog(@"🔴类名与方法名:%@(在第%@行),描述:%@", @(__PRETTY_FUNCTION__), @(__LINE__), reason);
}
}
- (NSInteger)cyl_indexForClassType:(Class)classType inViewControllers:(NSArray *)viewControllers {
__block NSInteger atIndex = NSNotFound;
[viewControllers enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
UIViewController *obj_ = [obj cyl_getViewControllerInsteadOfNavigationController];
if ([obj_ isKindOfClass:classType]) {
atIndex = idx;
*stop = YES;
return;
}
}];
return atIndex;
}
- (void)cyl_handleNavigationBackAction {
[self cyl_handleNavigationBackActionWithAnimated:YES];
}
- (void)cyl_handleNavigationBackActionWithAnimated:(BOOL)animated {
if (!self.presentationController) {
[self.navigationController popViewControllerAnimated:animated];
return;
}
if (self.navigationController.viewControllers.count > 1) {
[self.navigationController popViewControllerAnimated:animated];
} else {
[self dismissViewControllerAnimated:animated completion:nil];
}
}
#pragma mark -- public methods
/**
* show badge with red dot style and CYLBadgeAnimationTypeNone by default.
*/
- (void)cyl_showBadge {
[kActualView cyl_showBadge];
}
- (void)cyl_showBadgeValue:(NSString *)value
animationType:(CYLBadgeAnimationType)animationType {
[kActualView cyl_showBadgeValue:value animationType:animationType];
}
- (void)cyl_clearBadge {
[kActualView cyl_clearBadge];
}
- (void)cyl_resumeBadge {
[kActualView cyl_resumeBadge];
}
- (BOOL)cyl_isShowBadge {
return [kActualView cyl_isShowBadge];
}
- (BOOL)cyl_isPauseBadge {
return [kActualView cyl_isPauseBadge];
}
#pragma mark -- private method
/**
* Because UIBarButtonItem is kind of NSObject, it is not able to directly attach badge.
This method is used to find actual view (non-nil) inside UIBarButtonItem instance.
*
* @return view
*/
- (UITabBarItem *)cyl_getActualBadgeSuperView {
UIViewController *viewController = self.cyl_getViewControllerInsteadOfNavigationController;
UITabBarItem *viewControllerItem = viewController.tabBarItem;
UIControl *viewControllerControl = viewControllerItem.cyl_tabButton;
UITabBarItem *navigationViewControllerItem = viewController.navigationController.tabBarItem;
if (viewControllerControl) {
return viewControllerItem;
}
return navigationViewControllerItem;
}
#pragma mark -- setter/getter
- (UILabel *)cyl_badge {
return kActualView.cyl_badge;
}
- (void)cyl_setBadge:(UILabel *)label {
[kActualView cyl_setBadge:label];
}
- (UIFont *)cyl_badgeFont {
return kActualView.cyl_badgeFont;
}
- (void)cyl_setBadgeFont:(UIFont *)badgeFont {
[kActualView cyl_setBadgeFont:badgeFont];
}
- (UIColor *)cyl_badgeBackgroundColor {
return [kActualView cyl_badgeBackgroundColor];
}
- (void)cyl_setBadgeBackgroundColor:(UIColor *)badgeBackgroundColor {
[kActualView cyl_setBadgeBackgroundColor:badgeBackgroundColor];
}
- (UIColor *)cyl_badgeTextColor {
return [kActualView cyl_badgeTextColor];
}
- (void)cyl_setBadgeTextColor:(UIColor *)badgeTextColor {
[kActualView cyl_setBadgeTextColor:badgeTextColor];
}
- (CYLBadgeAnimationType)cyl_badgeAnimationType {
return [kActualView cyl_badgeAnimationType];
}
- (void)cyl_setBadgeAnimationType:(CYLBadgeAnimationType)animationType {
[kActualView cyl_setBadgeAnimationType:animationType];
}
- (CGRect)cyl_badgeFrame {
return [kActualView cyl_badgeFrame];
}
- (void)cyl_setBadgeFrame:(CGRect)badgeFrame {
[kActualView cyl_setBadgeFrame:badgeFrame];
}
- (CGPoint)cyl_badgeCenterOffset {
return [kActualView cyl_badgeCenterOffset];
}
- (void)cyl_setBadgeCenterOffset:(CGPoint)badgeCenterOffset {
[kActualView cyl_setBadgeCenterOffset:badgeCenterOffset];
}
- (NSInteger)cyl_badgeMaximumBadgeNumber {
return [kActualView cyl_badgeMaximumBadgeNumber];
}
- (void)cyl_setBadgeMaximumBadgeNumber:(NSInteger)badgeMaximumBadgeNumber {
[kActualView cyl_setBadgeMaximumBadgeNumber:badgeMaximumBadgeNumber];
}
- (CGFloat)cyl_badgeMargin {
return [kActualView cyl_badgeMargin];
}
- (void)cyl_setBadgeMargin:(CGFloat)badgeMargin {
[kActualView cyl_setBadgeMargin:badgeMargin];
}
- (CGFloat)cyl_badgeRadius {
return [kActualView cyl_badgeRadius];
}
- (void)cyl_setBadgeRadius:(CGFloat)badgeRadius {
[kActualView cyl_setBadgeRadius:badgeRadius];
}
- (CGFloat)cyl_badgeCornerRadius {
return [kActualView cyl_badgeCornerRadius];
}
- (void)cyl_setBadgeCornerRadius:(CGFloat)cyl_badgeCornerRadius {
[kActualView cyl_setBadgeCornerRadius:cyl_badgeCornerRadius];
}
@end
================================================
FILE: CYLTabBarController.podspec
================================================
Pod::Spec.new do |s|
s.name = "CYLTabBarController"
s.version = "1.29.2"
s.summary = "Highly customizable tabBar and tabBarController for iOS"
s.description = "[EN]It is an iOS UI module library for adding animation to iOS tabbar items and icons with Lottie. [CN]【中国特色 TabBar】一行代码实现 Lottie 动画TabBar,支持中间带+号的TabBar样式,自带红点角标,支持动态刷新。【iOS12 & iPhone XS MAX supported】"
s.homepage = "https://github.com/ChenYilong/CYLTabBarController"
s.license = { :type => 'MIT', :file => 'LICENSE' }
s.author = { "ChenYilong" => "luohanchenyilong@163.com" }
s.social_media_url = 'http://weibo.com/luohanchenyilong/'
s.platform = :ios, '8.0'
s.source = { :git => "https://github.com/ChenYilong/CYLTabBarController.git", :tag => s.version.to_s }
s.requires_arc = true
s.default_subspec = 'Core'
s.subspec 'Core' do |core|
core.source_files = 'CYLTabBarController', 'CYLTabBarController/**/*.{h,m}'
core.public_header_files = 'CYLTabBarController/**/*.h'
end
s.subspec 'Lottie' do |lottie|
lottie.dependency 'CYLTabBarController/Core'
lottie.dependency "lottie-ios" , '~> 2.5.3'
end
end
================================================
FILE: CYLTabBarController.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
56676081F69A826056C45ADD /* Pods_CYLTabBarController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7EA6761185EC902A2428DDB4 /* Pods_CYLTabBarController.framework */; };
9A1559C81CB6D4D300CAB1AF /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A1559C61CB6D4D300CAB1AF /* AppDelegate.m */; };
9A1559DB1CB6D56500CAB1AF /* CYLHomeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A1559CC1CB6D56500CAB1AF /* CYLHomeViewController.m */; };
9A1559DC1CB6D56500CAB1AF /* CYLMessageViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A1559CF1CB6D56500CAB1AF /* CYLMessageViewController.m */; };
9A1559DD1CB6D56500CAB1AF /* CYLMineViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A1559D21CB6D56500CAB1AF /* CYLMineViewController.m */; };
9A1559DE1CB6D56500CAB1AF /* CYLDetailsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A1559D51CB6D56500CAB1AF /* CYLDetailsViewController.m */; };
9A1559DF1CB6D56500CAB1AF /* CYLSameCityViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A1559D71CB6D56500CAB1AF /* CYLSameCityViewController.m */; };
9A1559E41CB6EB1F00CAB1AF /* CYLPlusButtonSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A1559E31CB6EB1F00CAB1AF /* CYLPlusButtonSubclass.m */; };
9A3865F62266FA3C008EE46F /* tab_message_animate.json in Resources */ = {isa = PBXBuildFile; fileRef = 9A3865F22266FA3C008EE46F /* tab_message_animate.json */; };
9A3865F72266FA3C008EE46F /* tab_home_animate.json in Resources */ = {isa = PBXBuildFile; fileRef = 9A3865F32266FA3C008EE46F /* tab_home_animate.json */; };
9A3865F82266FA3C008EE46F /* tab_search_animate.json in Resources */ = {isa = PBXBuildFile; fileRef = 9A3865F42266FA3C008EE46F /* tab_search_animate.json */; };
9A3865F92266FA3C008EE46F /* tab_me_animate.json in Resources */ = {isa = PBXBuildFile; fileRef = 9A3865F52266FA3C008EE46F /* tab_me_animate.json */; };
9A7C59902181C39000EDB266 /* MainTabBarController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A7C598E2181C39000EDB266 /* MainTabBarController.m */; };
9A98017D2461249F00E65289 /* green_lottie_tab_mine.json in Resources */ = {isa = PBXBuildFile; fileRef = 9A9801792461249F00E65289 /* green_lottie_tab_mine.json */; };
9A98017E2461249F00E65289 /* green_lottie_tab_discover.json in Resources */ = {isa = PBXBuildFile; fileRef = 9A98017A2461249F00E65289 /* green_lottie_tab_discover.json */; };
9A98017F2461249F00E65289 /* green_lottie_tab_news.json in Resources */ = {isa = PBXBuildFile; fileRef = 9A98017B2461249F00E65289 /* green_lottie_tab_news.json */; };
9A9801802461249F00E65289 /* green_lottie_tab_home.json in Resources */ = {isa = PBXBuildFile; fileRef = 9A98017C2461249F00E65289 /* green_lottie_tab_home.json */; };
9AC0181B1FE90AA1001EC2D6 /* CYLPlusDemoChildViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9AC0181A1FE90AA1001EC2D6 /* CYLPlusDemoChildViewController.m */; };
9AD7F5B022B7D4B6004BF0A0 /* gray_tabbar_me_animation.json in Resources */ = {isa = PBXBuildFile; fileRef = 9AD7F5AD22B7D4B6004BF0A0 /* gray_tabbar_me_animation.json */; };
9AD7F5B122B7D4B6004BF0A0 /* gray_tabbar_home_animation.json in Resources */ = {isa = PBXBuildFile; fileRef = 9AD7F5AE22B7D4B6004BF0A0 /* gray_tabbar_home_animation.json */; };
9AD7F5B222B7D4B6004BF0A0 /* gray_tabbar_message_animation.json in Resources */ = {isa = PBXBuildFile; fileRef = 9AD7F5AF22B7D4B6004BF0A0 /* gray_tabbar_message_animation.json */; };
9AD7F5BA22B7D695004BF0A0 /* img_tab_message_0.png in Resources */ = {isa = PBXBuildFile; fileRef = 9AD7F5B322B7D694004BF0A0 /* img_tab_message_0.png */; };
9AD7F5BB22B7D695004BF0A0 /* img_tab_me_1.png in Resources */ = {isa = PBXBuildFile; fileRef = 9AD7F5B422B7D694004BF0A0 /* img_tab_me_1.png */; };
9AD7F5BC22B7D695004BF0A0 /* img_tab_home_1.png in Resources */ = {isa = PBXBuildFile; fileRef = 9AD7F5B522B7D694004BF0A0 /* img_tab_home_1.png */; };
9AD7F5BD22B7D695004BF0A0 /* img_tab_home_2.png in Resources */ = {isa = PBXBuildFile; fileRef = 9AD7F5B622B7D695004BF0A0 /* img_tab_home_2.png */; };
9AD7F5BE22B7D695004BF0A0 /* img_tab_home_0.png in Resources */ = {isa = PBXBuildFile; fileRef = 9AD7F5B722B7D695004BF0A0 /* img_tab_home_0.png */; };
9AD7F5BF22B7D695004BF0A0 /* img_tab_message_1.png in Resources */ = {isa = PBXBuildFile; fileRef = 9AD7F5B822B7D695004BF0A0 /* img_tab_message_1.png */; };
9AD7F5C022B7D695004BF0A0 /* img_tab_me_0.png in Resources */ = {isa = PBXBuildFile; fileRef = 9AD7F5B922B7D695004BF0A0 /* img_tab_me_0.png */; };
9AE0BD3122303BA800302A35 /* CYLMainRootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9AE0BD3022303BA800302A35 /* CYLMainRootViewController.m */; };
9AE942E71BDC933E00354519 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9AE942CB1BDC933E00354519 /* LaunchScreen.xib */; };
9AE942E81BDC933E00354519 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9AE942CD1BDC933E00354519 /* Main.storyboard */; };
9AE942EF1BDC933E00354519 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9AE942E31BDC933E00354519 /* Images.xcassets */; };
9AE942F11BDC933E00354519 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 9AE942E51BDC933E00354519 /* main.m */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
7EA6761185EC902A2428DDB4 /* Pods_CYLTabBarController.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_CYLTabBarController.framework; sourceTree = BUILT_PRODUCTS_DIR; };
89D5086598A9EFD751C286DB /* Pods-CYLTabBarController.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CYLTabBarController.debug.xcconfig"; path = "Target Support Files/Pods-CYLTabBarController/Pods-CYLTabBarController.debug.xcconfig"; sourceTree = ""; };
8A12E1E008D40054CA1B0110 /* Pods-CYLTabBarController.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CYLTabBarController.release.xcconfig"; path = "Target Support Files/Pods-CYLTabBarController/Pods-CYLTabBarController.release.xcconfig"; sourceTree = ""; };
9A1559C61CB6D4D300CAB1AF /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
9A1559C71CB6D4D300CAB1AF /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
9A1559CB1CB6D56500CAB1AF /* CYLHomeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CYLHomeViewController.h; sourceTree = ""; };
9A1559CC1CB6D56500CAB1AF /* CYLHomeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CYLHomeViewController.m; sourceTree = ""; };
9A1559CE1CB6D56500CAB1AF /* CYLMessageViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CYLMessageViewController.h; sourceTree = ""; };
9A1559CF1CB6D56500CAB1AF /* CYLMessageViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CYLMessageViewController.m; sourceTree = ""; };
9A1559D11CB6D56500CAB1AF /* CYLMineViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CYLMineViewController.h; sourceTree = ""; };
9A1559D21CB6D56500CAB1AF /* CYLMineViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CYLMineViewController.m; sourceTree = ""; };
9A1559D41CB6D56500CAB1AF /* CYLDetailsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CYLDetailsViewController.h; sourceTree = ""; };
9A1559D51CB6D56500CAB1AF /* CYLDetailsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CYLDetailsViewController.m; sourceTree = ""; };
9A1559D61CB6D56500CAB1AF /* CYLSameCityViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CYLSameCityViewController.h; sourceTree = ""; };
9A1559D71CB6D56500CAB1AF /* CYLSameCityViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CYLSameCityViewController.m; sourceTree = ""; };
9A1559E21CB6EB1F00CAB1AF /* CYLPlusButtonSubclass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CYLPlusButtonSubclass.h; sourceTree = ""; };
9A1559E31CB6EB1F00CAB1AF /* CYLPlusButtonSubclass.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CYLPlusButtonSubclass.m; sourceTree = ""; };
9A3865F22266FA3C008EE46F /* tab_message_animate.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = tab_message_animate.json; sourceTree = ""; };
9A3865F32266FA3C008EE46F /* tab_home_animate.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = tab_home_animate.json; sourceTree = ""; };
9A3865F42266FA3C008EE46F /* tab_search_animate.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = tab_search_animate.json; sourceTree = ""; };
9A3865F52266FA3C008EE46F /* tab_me_animate.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = tab_me_animate.json; sourceTree = ""; };
9A579C98225F6E3A00F3C8F0 /* Location.gpx */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = Location.gpx; path = ../../../../../Location.gpx; sourceTree = ""; };
9A7C598E2181C39000EDB266 /* MainTabBarController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MainTabBarController.m; sourceTree = ""; };
9A7C598F2181C39000EDB266 /* MainTabBarController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MainTabBarController.h; sourceTree = ""; };
9A9801792461249F00E65289 /* green_lottie_tab_mine.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = green_lottie_tab_mine.json; sourceTree = ""; };
9A98017A2461249F00E65289 /* green_lottie_tab_discover.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = green_lottie_tab_discover.json; sourceTree = ""; };
9A98017B2461249F00E65289 /* green_lottie_tab_news.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = green_lottie_tab_news.json; sourceTree = ""; };
9A98017C2461249F00E65289 /* green_lottie_tab_home.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = green_lottie_tab_home.json; sourceTree = ""; };
9AC018191FE90AA1001EC2D6 /* CYLPlusDemoChildViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CYLPlusDemoChildViewController.h; sourceTree = ""; };
9AC0181A1FE90AA1001EC2D6 /* CYLPlusDemoChildViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CYLPlusDemoChildViewController.m; sourceTree = ""; };
9AD7F5AD22B7D4B6004BF0A0 /* gray_tabbar_me_animation.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = gray_tabbar_me_animation.json; sourceTree = ""; };
9AD7F5AE22B7D4B6004BF0A0 /* gray_tabbar_home_animation.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = gray_tabbar_home_animation.json; sourceTree = ""; };
9AD7F5AF22B7D4B6004BF0A0 /* gray_tabbar_message_animation.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = gray_tabbar_message_animation.json; sourceTree = ""; };
9AD7F5B322B7D694004BF0A0 /* img_tab_message_0.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = img_tab_message_0.png; sourceTree = ""; };
9AD7F5B422B7D694004BF0A0 /* img_tab_me_1.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = img_tab_me_1.png; sourceTree = ""; };
9AD7F5B522B7D694004BF0A0 /* img_tab_home_1.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = img_tab_home_1.png; sourceTree = ""; };
9AD7F5B622B7D695004BF0A0 /* img_tab_home_2.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = img_tab_home_2.png; sourceTree = ""; };
9AD7F5B722B7D695004BF0A0 /* img_tab_home_0.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = img_tab_home_0.png; sourceTree = ""; };
9AD7F5B822B7D695004BF0A0 /* img_tab_message_1.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = img_tab_message_1.png; sourceTree = ""; };
9AD7F5B922B7D695004BF0A0 /* img_tab_me_0.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = img_tab_me_0.png; sourceTree = ""; };
9AE0BD2F22303BA800302A35 /* CYLMainRootViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CYLMainRootViewController.h; sourceTree = ""; };
9AE0BD3022303BA800302A35 /* CYLMainRootViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CYLMainRootViewController.m; sourceTree = ""; };
9AE942741BDC91B800354519 /* CYLTabBarController.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CYLTabBarController.app; sourceTree = BUILT_PRODUCTS_DIR; };
9AE942921BDC91B900354519 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
9AE942931BDC91B900354519 /* CYLTabBarControllerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CYLTabBarControllerTests.m; sourceTree = ""; };
9AE942CC1BDC933E00354519 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; };
9AE942CE1BDC933E00354519 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
9AE942E31BDC933E00354519 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
9AE942E41BDC933E00354519 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
9AE942E51BDC933E00354519 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
9AE942711BDC91B800354519 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
56676081F69A826056C45ADD /* Pods_CYLTabBarController.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
36A0A7E83F2E6D2B770F8CDA /* Pods */ = {
isa = PBXGroup;
children = (
89D5086598A9EFD751C286DB /* Pods-CYLTabBarController.debug.xcconfig */,
8A12E1E008D40054CA1B0110 /* Pods-CYLTabBarController.release.xcconfig */,
);
path = Pods;
sourceTree = "";
};
7D5EF7117AB467CA9F870F71 /* Frameworks */ = {
isa = PBXGroup;
children = (
7EA6761185EC902A2428DDB4 /* Pods_CYLTabBarController.framework */,
);
name = Frameworks;
sourceTree = "";
};
9A1559C91CB6D56500CAB1AF /* Module */ = {
isa = PBXGroup;
children = (
9AC018181FE90A70001EC2D6 /* Other */,
9A1559CA1CB6D56500CAB1AF /* Home */,
9A1559CD1CB6D56500CAB1AF /* Message */,
9A1559D01CB6D56500CAB1AF /* Mine */,
9A1559D31CB6D56500CAB1AF /* SameCity */,
);
path = Module;
sourceTree = "";
};
9A1559CA1CB6D56500CAB1AF /* Home */ = {
isa = PBXGroup;
children = (
9A1559CB1CB6D56500CAB1AF /* CYLHomeViewController.h */,
9A1559CC1CB6D56500CAB1AF /* CYLHomeViewController.m */,
);
path = Home;
sourceTree = "";
};
9A1559CD1CB6D56500CAB1AF /* Message */ = {
isa = PBXGroup;
children = (
9A1559CE1CB6D56500CAB1AF /* CYLMessageViewController.h */,
9A1559CF1CB6D56500CAB1AF /* CYLMessageViewController.m */,
);
path = Message;
sourceTree = "";
};
9A1559D01CB6D56500CAB1AF /* Mine */ = {
isa = PBXGroup;
children = (
9A1559D11CB6D56500CAB1AF /* CYLMineViewController.h */,
9A1559D21CB6D56500CAB1AF /* CYLMineViewController.m */,
);
path = Mine;
sourceTree = "";
};
9A1559D31CB6D56500CAB1AF /* SameCity */ = {
isa = PBXGroup;
children = (
9A1559D41CB6D56500CAB1AF /* CYLDetailsViewController.h */,
9A1559D51CB6D56500CAB1AF /* CYLDetailsViewController.m */,
9A1559D61CB6D56500CAB1AF /* CYLSameCityViewController.h */,
9A1559D71CB6D56500CAB1AF /* CYLSameCityViewController.m */,
9A579C98225F6E3A00F3C8F0 /* Location.gpx */,
);
path = SameCity;
sourceTree = "";
};
9A1559E11CB6EB1F00CAB1AF /* View */ = {
isa = PBXGroup;
children = (
9A1559E21CB6EB1F00CAB1AF /* CYLPlusButtonSubclass.h */,
9A1559E31CB6EB1F00CAB1AF /* CYLPlusButtonSubclass.m */,
);
path = View;
sourceTree = "";
};
9A3865CF22663549008EE46F /* Other */ = {
isa = PBXGroup;
children = (
9A3865D5226635A1008EE46F /* LottieResources */,
);
path = Other;
sourceTree = "";
};
9A3865D5226635A1008EE46F /* LottieResources */ = {
isa = PBXGroup;
children = (
9AD7F5B722B7D695004BF0A0 /* img_tab_home_0.png */,
9AD7F5B522B7D694004BF0A0 /* img_tab_home_1.png */,
9AD7F5B622B7D695004BF0A0 /* img_tab_home_2.png */,
9AD7F5B922B7D695004BF0A0 /* img_tab_me_0.png */,
9AD7F5B422B7D694004BF0A0 /* img_tab_me_1.png */,
9AD7F5B322B7D694004BF0A0 /* img_tab_message_0.png */,
9AD7F5B822B7D695004BF0A0 /* img_tab_message_1.png */,
9AD7F5AE22B7D4B6004BF0A0 /* gray_tabbar_home_animation.json */,
9AD7F5AD22B7D4B6004BF0A0 /* gray_tabbar_me_animation.json */,
9AD7F5AF22B7D4B6004BF0A0 /* gray_tabbar_message_animation.json */,
9A3865F32266FA3C008EE46F /* tab_home_animate.json */,
9A3865F52266FA3C008EE46F /* tab_me_animate.json */,
9A3865F22266FA3C008EE46F /* tab_message_animate.json */,
9A3865F42266FA3C008EE46F /* tab_search_animate.json */,
9A98017A2461249F00E65289 /* green_lottie_tab_discover.json */,
9A98017C2461249F00E65289 /* green_lottie_tab_home.json */,
9A9801792461249F00E65289 /* green_lottie_tab_mine.json */,
9A98017B2461249F00E65289 /* green_lottie_tab_news.json */,
);
path = LottieResources;
sourceTree = "";
};
9AC018181FE90A70001EC2D6 /* Other */ = {
isa = PBXGroup;
children = (
9AC018191FE90AA1001EC2D6 /* CYLPlusDemoChildViewController.h */,
9AC0181A1FE90AA1001EC2D6 /* CYLPlusDemoChildViewController.m */,
);
path = Other;
sourceTree = "";
};
9AE9426B1BDC91B800354519 = {
isa = PBXGroup;
children = (
9AE942C81BDC933E00354519 /* Example */,
9AE942901BDC91B900354519 /* CYLTabBarControllerTests */,
9AE942751BDC91B800354519 /* Products */,
36A0A7E83F2E6D2B770F8CDA /* Pods */,
7D5EF7117AB467CA9F870F71 /* Frameworks */,
);
sourceTree = "";
};
9AE942751BDC91B800354519 /* Products */ = {
isa = PBXGroup;
children = (
9AE942741BDC91B800354519 /* CYLTabBarController.app */,
);
name = Products;
sourceTree = "";
};
9AE942901BDC91B900354519 /* CYLTabBarControllerTests */ = {
isa = PBXGroup;
children = (
9AE942931BDC91B900354519 /* CYLTabBarControllerTests.m */,
9AE942911BDC91B900354519 /* Supporting Files */,
);
path = CYLTabBarControllerTests;
sourceTree = "";
};
9AE942911BDC91B900354519 /* Supporting Files */ = {
isa = PBXGroup;
children = (
9AE942921BDC91B900354519 /* Info.plist */,
);
name = "Supporting Files";
sourceTree = "";
};
9AE942C81BDC933E00354519 /* Example */ = {
isa = PBXGroup;
children = (
9A1559C71CB6D4D300CAB1AF /* AppDelegate.h */,
9A1559C61CB6D4D300CAB1AF /* AppDelegate.m */,
9A7C598F2181C39000EDB266 /* MainTabBarController.h */,
9A7C598E2181C39000EDB266 /* MainTabBarController.m */,
9AE0BD2F22303BA800302A35 /* CYLMainRootViewController.h */,
9AE0BD3022303BA800302A35 /* CYLMainRootViewController.m */,
9AE942CF1BDC933E00354519 /* Classes */,
9AE942CB1BDC933E00354519 /* LaunchScreen.xib */,
9AE942CD1BDC933E00354519 /* Main.storyboard */,
9AE942E31BDC933E00354519 /* Images.xcassets */,
9AE942E41BDC933E00354519 /* Info.plist */,
9AE942E51BDC933E00354519 /* main.m */,
);
path = Example;
sourceTree = "";
};
9AE942CF1BDC933E00354519 /* Classes */ = {
isa = PBXGroup;
children = (
9A3865CF22663549008EE46F /* Other */,
9A1559E11CB6EB1F00CAB1AF /* View */,
9A1559C91CB6D56500CAB1AF /* Module */,
);
path = Classes;
sourceTree = "";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
9AE942731BDC91B800354519 /* CYLTabBarController */ = {
isa = PBXNativeTarget;
buildConfigurationList = 9AE942971BDC91B900354519 /* Build configuration list for PBXNativeTarget "CYLTabBarController" */;
buildPhases = (
5B2F02C6CEFA9E652D86AB7B /* [CP] Check Pods Manifest.lock */,
9AE942701BDC91B800354519 /* Sources */,
9AE942711BDC91B800354519 /* Frameworks */,
9AE942721BDC91B800354519 /* Resources */,
21663BD34D0451A2C1920020 /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = CYLTabBarController;
productName = CYLTabBarController;
productReference = 9AE942741BDC91B800354519 /* CYLTabBarController.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
9AE9426C1BDC91B800354519 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1100;
ORGANIZATIONNAME = "微博@iOS程序犭袁";
TargetAttributes = {
9AE942731BDC91B800354519 = {
CreatedOnToolsVersion = 6.3;
ProvisioningStyle = Manual;
};
};
};
buildConfigurationList = 9AE9426F1BDC91B800354519 /* Build configuration list for PBXProject "CYLTabBarController" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 9AE9426B1BDC91B800354519;
productRefGroup = 9AE942751BDC91B800354519 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
9AE942731BDC91B800354519 /* CYLTabBarController */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
9AE942721BDC91B800354519 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
9A9801802461249F00E65289 /* green_lottie_tab_home.json in Resources */,
9AE942EF1BDC933E00354519 /* Images.xcassets in Resources */,
9A98017F2461249F00E65289 /* green_lottie_tab_news.json in Resources */,
9AD7F5BE22B7D695004BF0A0 /* img_tab_home_0.png in Resources */,
9AE942E71BDC933E00354519 /* LaunchScreen.xib in Resources */,
9AD7F5B122B7D4B6004BF0A0 /* gray_tabbar_home_animation.json in Resources */,
9A3865F82266FA3C008EE46F /* tab_search_animate.json in Resources */,
9A98017D2461249F00E65289 /* green_lottie_tab_mine.json in Resources */,
9AD7F5BA22B7D695004BF0A0 /* img_tab_message_0.png in Resources */,
9AD7F5B022B7D4B6004BF0A0 /* gray_tabbar_me_animation.json in Resources */,
9AD7F5B222B7D4B6004BF0A0 /* gray_tabbar_message_animation.json in Resources */,
9A98017E2461249F00E65289 /* green_lottie_tab_discover.json in Resources */,
9AD7F5C022B7D695004BF0A0 /* img_tab_me_0.png in Resources */,
9AE942E81BDC933E00354519 /* Main.storyboard in Resources */,
9A3865F92266FA3C008EE46F /* tab_me_animate.json in Resources */,
9A3865F72266FA3C008EE46F /* tab_home_animate.json in Resources */,
9AD7F5BC22B7D695004BF0A0 /* img_tab_home_1.png in Resources */,
9AD7F5BD22B7D695004BF0A0 /* img_tab_home_2.png in Resources */,
9A3865F62266FA3C008EE46F /* tab_message_animate.json in Resources */,
9AD7F5BB22B7D695004BF0A0 /* img_tab_me_1.png in Resources */,
9AD7F5BF22B7D695004BF0A0 /* img_tab_message_1.png in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
21663BD34D0451A2C1920020 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-CYLTabBarController/Pods-CYLTabBarController-frameworks.sh",
"${BUILT_PRODUCTS_DIR}/CYLTabBarController/CYLTabBarController.framework",
"${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework",
"${BUILT_PRODUCTS_DIR}/lottie-ios/Lottie.framework",
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CYLTabBarController.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MJRefresh.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Lottie.framework",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-CYLTabBarController/Pods-CYLTabBarController-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
5B2F02C6CEFA9E652D86AB7B /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-CYLTabBarController-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
9AE942701BDC91B800354519 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
9A1559DC1CB6D56500CAB1AF /* CYLMessageViewController.m in Sources */,
9AE0BD3122303BA800302A35 /* CYLMainRootViewController.m in Sources */,
9A1559DE1CB6D56500CAB1AF /* CYLDetailsViewController.m in Sources */,
9A1559E41CB6EB1F00CAB1AF /* CYLPlusButtonSubclass.m in Sources */,
9A1559DF1CB6D56500CAB1AF /* CYLSameCityViewController.m in Sources */,
9A1559DB1CB6D56500CAB1AF /* CYLHomeViewController.m in Sources */,
9A1559C81CB6D4D300CAB1AF /* AppDelegate.m in Sources */,
9A7C59902181C39000EDB266 /* MainTabBarController.m in Sources */,
9A1559DD1CB6D56500CAB1AF /* CYLMineViewController.m in Sources */,
9AE942F11BDC933E00354519 /* main.m in Sources */,
9AC0181B1FE90AA1001EC2D6 /* CYLPlusDemoChildViewController.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
9AE942CB1BDC933E00354519 /* LaunchScreen.xib */ = {
isa = PBXVariantGroup;
children = (
9AE942CC1BDC933E00354519 /* Base */,
);
name = LaunchScreen.xib;
sourceTree = "";
};
9AE942CD1BDC933E00354519 /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
9AE942CE1BDC933E00354519 /* Base */,
);
name = Main.storyboard;
sourceTree = "";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
9AE942951BDC91B900354519 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
9AE942961BDC91B900354519 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
9AE942981BDC91B900354519 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 89D5086598A9EFD751C286DB /* Pods-CYLTabBarController.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
CODE_SIGN_ENTITLEMENTS = "";
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = "$(SRCROOT)/Example/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "CYL.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
PROVISIONING_PROFILE_SPECIFIER = "";
SUPPORTS_UIKITFORMAC = NO;
TARGETED_DEVICE_FAMILY = 1;
};
name = Debug;
};
9AE942991BDC91B900354519 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 8A12E1E008D40054CA1B0110 /* Pods-CYLTabBarController.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
CODE_SIGN_ENTITLEMENTS = "";
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = "$(SRCROOT)/Example/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "CYL.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
PROVISIONING_PROFILE_SPECIFIER = "";
SUPPORTS_UIKITFORMAC = NO;
TARGETED_DEVICE_FAMILY = 1;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
9AE9426F1BDC91B800354519 /* Build configuration list for PBXProject "CYLTabBarController" */ = {
isa = XCConfigurationList;
buildConfigurations = (
9AE942951BDC91B900354519 /* Debug */,
9AE942961BDC91B900354519 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
9AE942971BDC91B900354519 /* Build configuration list for PBXNativeTarget "CYLTabBarController" */ = {
isa = XCConfigurationList;
buildConfigurations = (
9AE942981BDC91B900354519 /* Debug */,
9AE942991BDC91B900354519 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 9AE9426C1BDC91B800354519 /* Project object */;
}
================================================
FILE: CYLTabBarController.xcodeproj/xcshareddata/xcschemes/CYLTabBarController.xcscheme
================================================
================================================
FILE: CYLTabBarControllerTests/CYLTabBarControllerTests.m
================================================
//
// CYLTabBarControllerTests.m
// CYLTabBarControllerTests
//
// v1.21.x Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 15/10/25.
// Copyright (c) 2018年 https://github.com/ChenYilong .All rights reserved.
//
#import
#import
@interface CYLTabBarControllerTests : XCTestCase
@end
@implementation CYLTabBarControllerTests
- (void)setUp {
[super setUp];
// Put setup code here. This method is called before the invocation of each test method in the class.
}
- (void)tearDown {
// Put teardown code here. This method is called after the invocation of each test method in the class.
[super tearDown];
}
- (void)testExample {
// This is an example of a functional test case.
XCTAssert(YES, @"Pass");
}
- (void)testPerformanceExample {
// This is an example of a performance test case.
[self measureBlock:^{
// Put the code you want to measure the time of here.
}];
}
@end
================================================
FILE: CYLTabBarControllerTests/Info.plist
================================================
CFBundleDevelopmentRegion
en
CFBundleExecutable
$(EXECUTABLE_NAME)
CFBundleIdentifier
$(PRODUCT_BUNDLE_IDENTIFIER)
CFBundleInfoDictionaryVersion
6.0
CFBundleName
$(PRODUCT_NAME)
CFBundlePackageType
BNDL
CFBundleShortVersionString
1.0
CFBundleSignature
????
CFBundleVersion
1
================================================
FILE: Example/AppDelegate.h
================================================
//
// AppDelegate.h
// CYLTabBarControllerDemo
//
// v1.21.x Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 10/20/15.
// Copyright © 2018 https://github.com/ChenYilong . All rights reserved.
//
#import
@interface AppDelegate : UIResponder
@property (strong, nonatomic) UIWindow *window;
@end
================================================
FILE: Example/AppDelegate.m
================================================
//
// AppDelegate.m
// CYLTabBarController
//
// v1.21.x Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 10/20/15.
// Copyright © 2018 https://github.com/ChenYilong . All rights reserved.
//
#import "AppDelegate.h"
#import "CYLPlusButtonSubclass.h"
#import "CYLMainRootViewController.h"
@interface AppDelegate ()
@property (nonatomic, strong) NSMutableData *data;
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[UIApplication sharedApplication].statusBarHidden = NO;
// 设置主窗口,并设置根控制器
self.window = [[UIWindow alloc] init];
self.window.frame = [UIScreen mainScreen].bounds;
[self.window makeKeyAndVisible];
CYLMainRootViewController *rootViewController = [[CYLMainRootViewController alloc] init];
[self.window setRootViewController:rootViewController];
[self setUpNavigationBarAppearance];
return YES;
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wmethod-signatures"
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
//设置强制旋转屏幕
if (self.cyl_isForceLandscape) {
//只支持横屏
return UIInterfaceOrientationMaskLandscape;
} else {
//只支持竖屏
return UIInterfaceOrientationMaskPortrait;
}
}
#pragma clang diagnostic pop
/**
* 设置navigationBar样式
*/
- (void)setUpNavigationBarAppearance {
UINavigationBar *navigationBarAppearance = [UINavigationBar appearance];
UIColor *backgroundColor = [UIColor cyl_systemBackgroundColor];
NSDictionary *textAttributes = nil;
UIColor *labelColor = [UIColor cyl_labelColor];
if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) {
textAttributes = @{
NSFontAttributeName : [UIFont boldSystemFontOfSize:18],
NSForegroundColorAttributeName : labelColor,
};
} else {
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_7_0
textAttributes = @{
UITextAttributeFont : [UIFont boldSystemFontOfSize:18],
UITextAttributeTextColor : labelColor,
UITextAttributeTextShadowColor : [UIColor clearColor],
UITextAttributeTextShadowOffset : [NSValue valueWithUIOffset:UIOffsetZero],
};
#endif
}
[navigationBarAppearance setBarTintColor:backgroundColor];
[navigationBarAppearance setTitleTextAttributes:textAttributes];
}
@end
================================================
FILE: Example/Base.lproj/LaunchScreen.xib
================================================
================================================
FILE: Example/Base.lproj/Main.storyboard
================================================
================================================
FILE: Example/CYLMainRootViewController.h
================================================
//
// CYLMainRootViewController.h
// CYLTabBarController
//
// Created by chenyilong on 7/3/2019.
// Copyright © 2019 微博@iOS程序犭袁. All rights reserved.
//
#import
#if __has_include()
#import
#else
#import "CYLTabBarController.h"
#endif
NS_ASSUME_NONNULL_BEGIN
@interface CYLMainRootViewController : UINavigationController
- (CYLTabBarController *)createNewTabBarWithContext:(NSString *)context;
@end
NS_ASSUME_NONNULL_END
================================================
FILE: Example/CYLMainRootViewController.m
================================================
//
// CYLMainRootViewController.m
// CYLTabBarController
//
// Created by chenyilong on 7/3/2019.
// Copyright © 2019 微博@iOS程序犭袁. All rights reserved.
//
#import "CYLMainRootViewController.h"
#import "MainTabBarController.h"
#import "CYLPlusButtonSubclass.h"
@interface CYLMainRootViewController ()
@end
@implementation CYLMainRootViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationBarHidden = YES;
self.view.backgroundColor = [UIColor whiteColor];
[self createNewTabBar];
}
- (CYLTabBarController *)createNewTabBar {
[CYLPlusButtonSubclass registerPlusButton];
return [self createNewTabBarWithContext:nil];
}
- (CYLTabBarController *)createNewTabBarWithContext:(NSString *)context {
MainTabBarController *tabBarController = [[MainTabBarController alloc] initWithContext:context];
self.viewControllers = @[tabBarController];
return tabBarController;
}
@end
================================================
FILE: Example/Classes/Module/Home/CYLHomeViewController.h
================================================
//
// CYLHomeViewController.h
// CYLTabBarController
//
// v1.21.x Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 10/20/15.
// Copyright © 2018 https://github.com/ChenYilong . All rights reserved.
//
#import
#if __has_include()
#import
#else
#import "CYLTabBarController.h"
#endif
@interface CYLHomeViewController : CYLBaseTableViewController
- (void)refresh;
@end
================================================
FILE: Example/Classes/Module/Home/CYLHomeViewController.m
================================================
//
// CYLHomeViewController.m
// CYLTabBarController
//
// v1.21.x Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 10/20/15.
// Copyright © 2018 https://github.com/ChenYilong . All rights reserved.
//
#import "CYLHomeViewController.h"
//#import "CYLTabBarControllerConfig.h"
//#import "CYLPlusButtonSubclass.h"
#import "MainTabBarController.h"
#import "CYLMainRootViewController.h"
#import
@implementation CYLHomeViewController
#pragma mark - View lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
self.navigationItem.title = @"首页(3)"; //✅sets navigation bar title.The right way to set the title of the navigation
self.tabBarItem.title = @"首页"; //❌sets tab bar title. Even the `tabBarItem.title` changed, this will be ignored in tabbar.
//self.title = @"首页1"; //❌sets both of these. Do not do this‼️‼️This may cause something strange like this : http://i68.tinypic.com/282l3x4.jpg .
// [self.navigationController.tabBarItem setBadgeValue:@"3"];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"refresh TabBar" style:UIBarButtonItemStylePlain target:self action:@selector(refreshTabBar:)];
__weak __typeof(self) weakSelf = self;
self.tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{
//Call this Block When enter the refresh status automatically
NSUInteger delaySeconds = 1;
dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delaySeconds * NSEC_PER_SEC));
dispatch_after(when, dispatch_get_main_queue(), ^{
[weakSelf.tableView.mj_header endRefreshing];
});
}];
}
- (void)refresh {
[self.tableView.mj_header beginRefreshing];
NSUInteger delaySeconds = 1;
dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delaySeconds * NSEC_PER_SEC));
dispatch_after(when, dispatch_get_main_queue(), ^{
[self.tableView.mj_header endRefreshing];
});
}
- (void)refreshTabBar:(id)sender {
[self createNewTabBardynamically];
}
- (void)createNewTabBardynamically {
id delegate = ((id)[[UIApplication sharedApplication] delegate]);
UIWindow *window = delegate.window;
CYLMainRootViewController *rootController = (CYLMainRootViewController *)window.rootViewController;
[rootController createNewTabBarWithContext:NSStringFromClass([self class])];
}
#pragma mark - Methods
- (void)configureCell:(UITableViewCell *)cell forIndexPath:(NSIndexPath *)indexPath {
[[cell textLabel] setText:[NSString stringWithFormat:@"%@ CYLTabBarController %@", self.tabBarItem.title, @(indexPath.row)]];
}
#pragma mark - Table view
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString * CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
[self configureCell:cell forIndexPath:indexPath];
return cell;
}
#pragma mark - UINavigationControllerDelegate
- (void)navigationController:(UINavigationController *)navigationController
didShowViewController:(UIViewController *)viewController
animated:(BOOL)animate {
if ([navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
if ([navigationController.viewControllers count] == 1) {
navigationController.interactivePopGestureRecognizer.enabled = NO;
} else {
navigationController.interactivePopGestureRecognizer.enabled = YES;
}
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 30;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSNumber *badgeNumber = @(indexPath.row);
self.navigationItem.title = [NSString stringWithFormat:@"首页(%@)", badgeNumber]; //sets navigation bar title.
// [self.navigationController.tabBarItem setBadgeValue:[NSString stringWithFormat:@"%@", badgeNumber]];
// CYLTabBarControllerConfig *tabBarControllerConfig = [[CYLTabBarControllerConfig alloc] init];
// CYLTabBarController *tabBarController = tabBarControllerConfig.tabBarController;
// tabBarController.delegate = self;
//
[self cyl_showBadgeValue:[NSString stringWithFormat:@"%@", @(indexPath.row)] animationType:CYLBadgeAnimationTypeScale];
[self pushToNewViewController];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[self pushToNewViewController];
}
- (void)pushToNewViewController {
CYLBaseViewController *viewController = [CYLBaseViewController new];
viewController.view.backgroundColor = [UIColor orangeColor];
[viewController cyl_setNavigationBarHidden:YES];
[self.navigationController pushViewController:viewController animated:YES];
}
@end
================================================
FILE: Example/Classes/Module/Message/CYLMessageViewController.h
================================================
//
// CYLMessageViewController.h
// CYLTabBarController
//
// v1.21.x Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 10/20/15.
// Copyright © 2018 https://github.com/ChenYilong . All rights reserved.
//
#import
#if __has_include()
#import
#else
#import "CYLTabBarController.h"
#endif
@interface CYLMessageViewController : CYLBaseTableViewController
- (void)refresh;
@end
================================================
FILE: Example/Classes/Module/Message/CYLMessageViewController.m
================================================
//
// CYLMessageViewController.m
// CYLTabBarController
//
// v1.21.x Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 10/20/15.
// Copyright © 2018 https://github.com/ChenYilong . All rights reserved.
//
#import "CYLMessageViewController.h"
#import "CYLMainRootViewController.h"
#import
@implementation CYLMessageViewController
#pragma mark - View lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
self.navigationItem.title = @"消息"; //✅sets navigation bar title.The right way to set the title of the navigation
self.tabBarItem.title = @"消息"; //❌sets tab bar title. Even the `tabBarItem.title` changed, this will be ignored in tabbar.
//self.title = @"消息1"; //❌sets both of these. Do not do this‼️‼️ This may cause something strange like this : http://i68.tinypic.com/282l3x4.jpg .
__weak __typeof(self) weakSelf = self;
self.tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{
//Call this Block When enter the refresh status automatically
NSUInteger delaySeconds = 1;
dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delaySeconds * NSEC_PER_SEC));
dispatch_after(when, dispatch_get_main_queue(), ^{
[weakSelf.tableView.mj_header endRefreshing];
});
}];
}
- (void)refresh {
[self.tableView.mj_header beginRefreshing];
NSUInteger delaySeconds = 1;
dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delaySeconds * NSEC_PER_SEC));
dispatch_after(when, dispatch_get_main_queue(), ^{
[self.tableView.mj_header endRefreshing];
});
}
#pragma mark - Methods
- (void)viewDidAppear:(BOOL)animated {
[self.navigationItem.leftBarButtonItem cyl_showBadge];
}
- (void)configureCell:(UITableViewCell *)cell forIndexPath:(NSIndexPath *)indexPath {
[[cell textLabel] setText:[NSString stringWithFormat:@"%@ CYLTabBarController %@", self.tabBarItem.title, @(indexPath.row)]];
}
#pragma mark - Table view
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString * CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
[self configureCell:cell forIndexPath:indexPath];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
// NSNumber *badgeNumber = @(indexPath.row);
// self.navigationItem.title = [NSString stringWithFormat:@"首页(%@)", badgeNumber]; //sets navigation bar title.
// [self.navigationController.tabBarItem setBadgeValue:[NSString stringWithFormat:@"%@", badgeNumber]];
// CYLTabBarControllerConfig *tabBarControllerConfig = [[CYLTabBarControllerConfig alloc] init];
// CYLTabBarController *tabBarController = tabBarControllerConfig.tabBarController;
// tabBarController.delegate = self;
//
// [self cyl_showBadgeValue:[NSString stringWithFormat:@"%@", @(indexPath.row)] animationType:CYLBadgeAnimationTypeScale];
// [self pushToNewViewController];
CYLTabBarController *tabBarController = [[CYLMainRootViewController new] createNewTabBarWithContext:NSStringFromClass([self class])];
[self.navigationController pushViewController:tabBarController animated:YES];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 15;
}
@end
================================================
FILE: Example/Classes/Module/Mine/CYLMineViewController.h
================================================
//
// CYLMineViewController.h
// CYLTabBarController
//
// v1.21.x Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 10/20/15.
// Copyright © 2018 https://github.com/ChenYilong . All rights reserved.
//
#import
#if __has_include()
#import
#else
#import "CYLTabBarController.h"
#endif
@interface CYLMineViewController : CYLBaseTableViewController
- (void)testPush;
- (void)refresh;
@end
================================================
FILE: Example/Classes/Module/Mine/CYLMineViewController.m
================================================
//
// CYLMineViewController.m
// CYLTabBarController
//
// v1.21.x Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 10/20/15.
// Copyright © 2018 https://github.com/ChenYilong . All rights reserved.
//
#import "CYLMineViewController.h"
#import "CYLDetailsViewController.h"
#import
@implementation CYLMineViewController
#pragma mark - View lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
self.navigationItem.title = @"我的"; //✅sets navigation bar title.The right way to set the title of the navigation
self.tabBarItem.title = @"我的"; //❌sets tab bar title. Even the `tabBarItem.title` changed, this will be ignored in tabbar.
//self.title = @"我的1"; //❌sets both of these. Do not do this‼️‼️ This may cause something strange like this : http://i68.tinypic.com/282l3x4.jpg .
// [self.navigationController.tabBarItem setBadgeValue:@"3"];
__weak __typeof(self) weakSelf = self;
self.tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{
//Call this Block When enter the refresh status automatically
NSUInteger delaySeconds = 1;
dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delaySeconds * NSEC_PER_SEC));
dispatch_after(when, dispatch_get_main_queue(), ^{
[weakSelf.tableView.mj_header endRefreshing];
});
}];
}
- (void)refresh {
[self.tableView.mj_header beginRefreshing];
NSUInteger delaySeconds = 1;
dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delaySeconds * NSEC_PER_SEC));
dispatch_after(when, dispatch_get_main_queue(), ^{
[self.tableView.mj_header endRefreshing];
});
}
#pragma mark - Methods
- (void)configureCell:(UITableViewCell *)cell forIndexPath:(NSIndexPath *)indexPath {
[[cell textLabel] setText:[NSString stringWithFormat:@"%@ CYLTabBarController %@", self.tabBarItem.title, @(indexPath.row)]];
}
#pragma mark - Table view
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString * CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
[self configureCell:cell forIndexPath:indexPath];
return cell;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 30;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
[self cyl_showBadgeValue:[NSString stringWithFormat:@"%@", @(indexPath.row)] animationType:CYLBadgeAnimationTypeNone];
[self testPush];
}
- (void)testPush {
UIViewController *viewController = [[UIViewController alloc] init];
viewController.view.backgroundColor = [UIColor redColor];
[self.navigationController pushViewController:viewController animated:YES];
}
@end
================================================
FILE: Example/Classes/Module/Other/CYLPlusDemoChildViewController.h
================================================
//
// CYLPlusDemoChildViewController.h
// CYLTabBarController
//
// Created by chenyilong on 19/12/2017.
// Copyright © 2017 微博@iOS程序犭袁. All rights reserved.
//
#import
@interface CYLPlusDemoChildViewController : UIViewController
@end
================================================
FILE: Example/Classes/Module/Other/CYLPlusDemoChildViewController.m
================================================
//
// CYLPlusDemoChildViewController.m
// CYLTabBarController
//
// Created by chenyilong on 19/12/2017.
// Copyright © 2017 微博@iOS程序犭袁. All rights reserved.
//
#import "CYLPlusDemoChildViewController.h"
@interface CYLPlusDemoChildViewController ()
@end
@implementation CYLPlusDemoChildViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)dealloc {
NSLog(@"🔴类名与方法名:%@(在第%@行),描述:%@", @(__PRETTY_FUNCTION__), @(__LINE__), @"");
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
@end
================================================
FILE: Example/Classes/Module/SameCity/CYLDetailsViewController.h
================================================
//
// CYLDetailsViewController.h
// CYLTabBarController
//
// v1.21.x Created by Robert Dimitrov on 11/8/14.
// Copyright (c) 2014 Robert Dimitrov. All rights reserved.
//
#import
#if __has_include()
#import
#else
#import "CYLTabBarController.h"
#endif
@interface CYLDetailsViewController : CYLBaseViewController
@end
================================================
FILE: Example/Classes/Module/SameCity/CYLDetailsViewController.m
================================================
//
// CYLDetailsViewController.m
// CYLTabBarController
//
// v1.21.x Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 10/20/15.
// Copyright © 2018 https://github.com/ChenYilong . All rights reserved.
//
#import "CYLDetailsViewController.h"
#import "CYLMineViewController.h"
#import "CYLSameCityViewController.h"
#import "CYLHomeViewController.h"
@interface CYLDetailsViewController ()
@end
@implementation CYLDetailsViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"详情页";
self.view.backgroundColor = [UIColor orangeColor];
UILabel *label = [[UILabel alloc] init];
label.text = @"点击屏幕可跳转到“我的”,执行testPush";
label.frame = CGRectMake(20, 150, CGRectGetWidth(self.view.frame) - 2 * 20, 20);
label.autoresizingMask = UIViewAutoresizingFlexibleWidth;
label.textAlignment = NSTextAlignmentCenter;
[self.view addSubview:label];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[[self cyl_sharedAppDelegate] cyl_forceUpdateInterfaceOrientation:UIInterfaceOrientationLandscapeLeft];
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
[[self cyl_sharedAppDelegate] cyl_forceUpdateInterfaceOrientation:UIInterfaceOrientationPortrait];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
// [self cyl_popSelectTabBarChildViewControllerAtIndex:4 completion:^(__kindof UIViewController *selectedTabBarChildViewController) {
[self cyl_popSelectTabBarChildViewControllerForClassType:[CYLMineViewController class] completion:^(__kindof UIViewController *selectedTabBarChildViewController) {
CYLMineViewController *mineViewController = selectedTabBarChildViewController;
@try {
[mineViewController testPush];
} @catch (NSException *exception) {
NSLog(@"🔴类名与方法名:%@(在第%@行),描述:%@", @(__PRETTY_FUNCTION__), @(__LINE__), exception.reason);
}
}];
}
@end
================================================
FILE: Example/Classes/Module/SameCity/CYLSameCityViewController.h
================================================
//
// CYLSameCityViewController.h
// CYLTabBarController
//
// v1.21.x Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 10/20/15.
// Copyright © 2018 https://github.com/ChenYilong . All rights reserved.
//
#import
#if __has_include()
#import
#else
#import "CYLTabBarController.h"
#endif
@interface CYLSameCityViewController : CYLBaseTableViewController
- (void)refresh;
@end
================================================
FILE: Example/Classes/Module/SameCity/CYLSameCityViewController.m
================================================
//
// CYLSameCityViewController.m
// CYLTabBarController
//
// v1.21.x Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 10/20/15.
// Copyright © 2018 https://github.com/ChenYilong . All rights reserved.
//
#import "CYLSameCityViewController.h"
#import "CYLDetailsViewController.h"
#import
@implementation CYLSameCityViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
self.navigationItem.title = @"同城"; //✅sets navigation bar title.The right way to set the title of the navigation
self.tabBarItem.title = @"同城"; //❌sets tab bar title. Even the `tabBarItem.title` changed, this will be ignored in tabbar.
//self.title = @"同城1"; //❌sets both of these. Do not do this‼️‼️ This may cause something strange like this : http://i68.tinypic.com/282l3x4.jpg .
__weak __typeof(self) weakSelf = self;
self.tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{
//Call this Block When enter the refresh status automatically
NSUInteger delaySeconds = 1;
dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delaySeconds * NSEC_PER_SEC));
dispatch_after(when, dispatch_get_main_queue(), ^{
[weakSelf.tableView.mj_header endRefreshing];
});
}];
}
- (void)refresh {
[self.tableView.mj_header beginRefreshing];
NSUInteger delaySeconds = 1;
dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delaySeconds * NSEC_PER_SEC));
dispatch_after(when, dispatch_get_main_queue(), ^{
[self.tableView.mj_header endRefreshing];
});
}
#pragma mark - Methods
- (void)configureCell:(UITableViewCell *)cell forIndexPath:(NSIndexPath *)indexPath {
[[cell textLabel] setText:[NSString stringWithFormat:@"%@ CYLTabBarController %@", self.tabBarItem.title, @(indexPath.row)]];
}
#pragma mark - Table view
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString * CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
[self configureCell:cell forIndexPath:indexPath];
return cell;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 15;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
UIViewController *viewController = [[CYLDetailsViewController alloc] init];
// viewController.hidesBottomBarWhenPushed = YES; // This property needs to be set before pushing viewController to the navigationController's stack. Meanwhile as it is all base on CYLBaseNavigationController, there is no need to do this.
[viewController cyl_setNavigationBarHidden:YES];
[self.navigationController pushViewController:viewController animated:YES];
}
@end
================================================
FILE: Example/Classes/Other/LottieResources/gray_tabbar_home_animation.json
================================================
{"v":"5.5.2","fr":25,"ip":0,"op":25,"w":52,"h":52,"nm":"tab1-easy","ddd":0,"assets":[{"id":"image_0","w":188,"h":188,"u":"","p":"img_tab_home_0.png","e":0},{"id":"image_1","w":16,"h":14,"u":"","p":"img_tab_home_1.png","e":0},{"id":"image_2","w":50,"h":48,"u":"","p":"img_tab_home_2.png","e":0}],"layers":[{"ddd":0,"ind":1,"ty":2,"nm":"1黑_1_1.png","cl":"png","refId":"image_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[25.2,26,0],"ix":2},"a":{"a":0,"k":[94,94,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":0,"s":[25,25,100]},{"t":3,"s":[0,0,100]}],"ix":6}},"ao":0,"ip":0,"op":3,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":2,"nm":"Fill 9.png","cl":"png","refId":"image_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":4,"s":[200]},{"t":8,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":4,"s":[25.2,26,0],"to":[0,-0.833,0],"ti":[0,0.833,0]},{"t":8,"s":[25.2,21,0]}],"ix":2},"a":{"a":0,"k":[8,7,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":4,"s":[0,0,100]},{"t":8,"s":[100,100,100]}],"ix":6,"x":"var $bm_rt;\nvar freq, decay, n, n, t, amp, w;\nfreq = 4;\ndecay = 8;\n$bm_rt = n = 0;\nif (numKeys > 0) {\n $bm_rt = n = nearestKey(time).index;\n if (key(n).time > time)\n n--;\n}\nif (n > 0) {\n t = $bm_sub(time, key(n).time);\n amp = velocityAtTime($bm_sub(key(n).time, 0.001));\n w = $bm_mul($bm_mul(freq, Math.PI), 2);\n $bm_rt = $bm_sum(value, $bm_mul(amp, $bm_div($bm_div(Math.sin($bm_mul(t, w)), Math.exp($bm_mul(decay, t))), w)));\n} else\n $bm_rt = value;"}},"ao":0,"ip":4,"op":128,"st":3,"bm":0},{"ddd":0,"ind":3,"ty":2,"nm":"分组 11.png","cl":"png","refId":"image_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[26,26,0],"ix":2},"a":{"a":0,"k":[25,24,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":3,"s":[0,0,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":4,"s":[25,25,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":5,"s":[50,50,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":6,"s":[75,75,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":7,"s":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":8,"s":[116.517,116.517,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":9,"s":[113.923,113.923,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":10,"s":[101.517,101.517,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":11,"s":[92.663,92.663,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":12,"s":[92.877,92.877,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":13,"s":[98.535,98.535,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":14,"s":[103.173,103.173,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":15,"s":[103.581,103.581,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":16,"s":[101.056,101.056,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":17,"s":[98.674,98.674,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":18,"s":[98.229,98.229,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":19,"s":[99.327,99.327,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":20,"s":[100.529,100.529,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":21,"s":[100.862,100.862,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":22,"s":[100.399,100.399,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":23,"s":[99.803,99.803,100]},{"t":24,"s":[99.587,99.587,100]}],"ix":6}},"ao":0,"ip":3,"op":128,"st":3,"bm":0}],"markers":[]}
================================================
FILE: Example/Classes/Other/LottieResources/gray_tabbar_me_animation.json
================================================
{"v":"5.5.2","fr":25,"ip":0,"op":25,"w":52,"h":52,"nm":"tab3-easy","ddd":0,"assets":[{"id":"image_0","w":40,"h":44,"u":"","p":"img_tab_me_0.png","e":0},{"id":"image_1","w":40,"h":44,"u":"","p":"img_tab_me_1.png","e":0},{"id":"comp_0","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"“未标题-4”轮廓","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[26,23.75,0],"ix":2},"a":{"a":0,"k":[400.568,400.679,0],"ix":1},"s":{"a":0,"k":[200,200,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[1.352,0],[0,0],[0,1.351],[0,0]],"o":[[0,0],[-1.351,0],[0,0],[0,1.351]],"v":[[0,1.223],[0,1.223],[-2.446,-1.223],[2.446,-1.223]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.165000002992,0.165000002992,0.226999993418,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[400.568,400.679],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":4,"op":125,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":2,"nm":"分组 12.png","cl":"png","refId":"image_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[26,26,0],"ix":2},"a":{"a":0,"k":[20,22,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":0,"s":[100,100,100]},{"t":3,"s":[0,0,100]}],"ix":6}},"ao":0,"ip":0,"op":125,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":0,"nm":"“未标题-4”轮廓 合成 1","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[26,26,0],"ix":2},"a":{"a":0,"k":[26,26,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":4,"s":[0,0,100]},{"t":9,"s":[100,100,100]}],"ix":6,"x":"var $bm_rt;\nvar freq, decay, n, n, t, amp, w;\nfreq = 4;\ndecay = 8;\n$bm_rt = n = 0;\nif (numKeys > 0) {\n $bm_rt = n = nearestKey(time).index;\n if (key(n).time > time)\n n--;\n}\nif (n > 0) {\n t = $bm_sub(time, key(n).time);\n amp = velocityAtTime($bm_sub(key(n).time, 0.001));\n w = $bm_mul($bm_mul(freq, Math.PI), 2);\n $bm_rt = $bm_sum(value, $bm_mul(amp, $bm_div($bm_div(Math.sin($bm_mul(t, w)), Math.exp($bm_mul(decay, t))), w)));\n} else\n $bm_rt = value;"}},"ao":0,"w":52,"h":52,"ip":0,"op":125,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":2,"nm":"分组 15.png","cl":"png","refId":"image_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[26,26,0],"ix":2},"a":{"a":0,"k":[20,22,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":3,"s":[0,0,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":4,"s":[25,25,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":5,"s":[50,50,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":6,"s":[75,75,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":7,"s":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":8,"s":[116.517,116.517,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":9,"s":[113.923,113.923,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":10,"s":[101.517,101.517,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":11,"s":[92.663,92.663,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":12,"s":[92.877,92.877,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":13,"s":[98.535,98.535,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":14,"s":[103.173,103.173,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":15,"s":[103.581,103.581,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":16,"s":[101.056,101.056,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":17,"s":[98.674,98.674,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":18,"s":[98.229,98.229,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":19,"s":[99.327,99.327,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":20,"s":[100.529,100.529,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":21,"s":[100.862,100.862,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":22,"s":[100.399,100.399,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":23,"s":[99.803,99.803,100]},{"t":24,"s":[99.587,99.587,100]}],"ix":6}},"ao":0,"ip":0,"op":125,"st":0,"bm":0}],"markers":[]}
================================================
FILE: Example/Classes/Other/LottieResources/gray_tabbar_message_animation.json
================================================
{"v":"5.5.2","fr":25,"ip":0,"op":25,"w":52,"h":52,"nm":"tab2-easy","ddd":0,"assets":[{"id":"image_0","w":160,"h":160,"u":"","p":"img_tab_message_0.png","e":0},{"id":"image_1","w":40,"h":40,"u":"","p":"img_tab_message_1.png","e":0}],"layers":[{"ddd":0,"ind":1,"ty":2,"nm":"3黑_5_1.png","cl":"png","refId":"image_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[26,26,0],"ix":2},"a":{"a":0,"k":[80,80,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":0,"s":[25,25,100]},{"t":3,"s":[0,0,100]}],"ix":6}},"ao":0,"ip":0,"op":3,"st":-21,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"“描边”轮廓 - 组 3","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":4,"s":[0]},{"t":7,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[25.75,21.938,0],"ix":2},"a":{"a":0,"k":[313.023,463,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":4,"s":[0,0,100]},{"t":8,"s":[100,100,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[305.529,463],[320.517,463]],"c":false},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.165000002992,0.165000002992,0.226999993418,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 3","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\nvar freq, decay, n, n, t, amp, w;\nfreq = 3;\ndecay = 5;\n$bm_rt = n = 0;\nif (numKeys > 0) {\n $bm_rt = n = nearestKey(time).index;\n if (key(n).time > time)\n n--;\n}\nif (n > 0) {\n t = $bm_sub(time, key(n).time);\n amp = velocityAtTime($bm_sub(key(n).time, 0.001));\n w = $bm_mul($bm_mul(freq, Math.PI), 2);\n $bm_rt = $bm_sum(value, $bm_mul(amp, $bm_div($bm_div(Math.sin($bm_mul(t, w)), Math.exp($bm_mul(decay, t))), w)));\n} else\n $bm_rt = value;"},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":5,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":14,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":15,"s":[95.304]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":16,"s":[93.827]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":17,"s":[95.826]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":18,"s":[99.033]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":19,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":22,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":23,"s":[99.569]},{"t":24,"s":[99.166]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"修剪路径 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":4,"op":129,"st":4,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"“描边”轮廓 - 组 1","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":4,"s":[0]},{"t":8,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[22.85,30.562,0],"ix":2},"a":{"a":0,"k":[310.124,476.562,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":4,"s":[0,0,100]},{"t":8,"s":[100,100,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[305.574,476.562],[314.674,476.562]],"c":false},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.165000002992,0.165000002992,0.226999993418,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":5,"s":[0]},{"t":10,"s":[100]}],"ix":2,"x":"var $bm_rt;\nvar freq, decay, n, n, t, amp, w;\nfreq = 3;\ndecay = 6;\n$bm_rt = n = 0;\nif (numKeys > 0) {\n $bm_rt = n = nearestKey(time).index;\n if (key(n).time > time)\n n--;\n}\nif (n > 0) {\n t = $bm_sub(time, key(n).time);\n amp = velocityAtTime($bm_sub(key(n).time, 0.001));\n w = $bm_mul($bm_mul(freq, Math.PI), 2);\n $bm_rt = $bm_sum(value, $bm_mul(amp, $bm_div($bm_div(Math.sin($bm_mul(t, w)), Math.exp($bm_mul(decay, t))), w)));\n} else\n $bm_rt = value;"},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"修剪路径 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":4,"op":129,"st":4,"bm":0},{"ddd":0,"ind":4,"ty":2,"nm":"消息.png","cl":"png","refId":"image_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[26,26,0],"ix":2},"a":{"a":0,"k":[20,20,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":3,"s":[0,0,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":4,"s":[25,25,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":5,"s":[50,50,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":6,"s":[75,75,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":7,"s":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":8,"s":[116.517,116.517,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":9,"s":[113.923,113.923,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":10,"s":[101.517,101.517,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":11,"s":[92.663,92.663,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":12,"s":[92.877,92.877,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":13,"s":[98.535,98.535,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":14,"s":[103.173,103.173,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":15,"s":[103.581,103.581,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":16,"s":[101.056,101.056,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":17,"s":[98.674,98.674,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":18,"s":[98.229,98.229,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":19,"s":[99.327,99.327,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":20,"s":[100.529,100.529,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":21,"s":[100.862,100.862,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":22,"s":[100.399,100.399,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":23,"s":[99.803,99.803,100]},{"t":24,"s":[99.587,99.587,100]}],"ix":6}},"ao":0,"ip":3,"op":128,"st":3,"bm":0}],"markers":[]}
================================================
FILE: Example/Classes/Other/LottieResources/green_lottie_tab_discover.json
================================================
{"v":"5.1.16","fr":30,"ip":0,"op":30,"w":60,"h":60,"nm":"Tab_Discovery_Active","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Icon_Discovery_Active_Line_Circle_Small","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[30,30,0],"ix":2},"a":{"a":0,"k":[30,30,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[4.418,0],[0,4.418],[-4.418,0],[0,-4.418]],"o":[[-4.418,0],[0,-4.418],[4.418,0],[0,4.418]],"v":[[0,8],[-8,0],[0,-8],[8,0]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.325,0.843,0.416,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":2,"lj":2,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[30,30],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"内圈","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"n":["0p4_1_0p6_0"],"t":0,"s":[0],"e":[99]},{"t":20}],"ix":2},"o":{"a":0,"k":180,"ix":3},"m":1,"ix":2,"nm":"修剪路径 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":30,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Icon_Discovery_Active_Line_Circle_Big","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[30,30,0],"ix":2},"a":{"a":0,"k":[30,30,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,-2.107],[1.432,-2.755],[3.5,-1.907],[3.46,0],[0,11.046],[-11.046,0],[-1.872,-0.58]],"o":[[0.604,1.907],[0,3.321],[-1.839,3.54],[-2.839,1.545],[-11.046,0],[0,-11.045],[2.063,0],[0,0]],"v":[[19.07,-6.044],[20,0],[17.759,9.208],[9.553,17.576],[0,20],[-20,0],[0,-20],[5.924,-19.108]],"c":false},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.325,0.843,0.416,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":2,"lj":2,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[30,30],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"外圈","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.875],"y":[1]},"o":{"x":[0.6],"y":[0]},"n":["0p875_1_0p6_0"],"t":20,"s":[0],"e":[100]},{"t":29}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"修剪路径 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":30,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Icon_Discovery_Active_Triangle","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0.048]},"n":["0p2_1_0p167_0p048"],"t":10,"s":[0],"e":[100]},{"t":14}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"n":["0p2_1_0p4_0"],"t":10,"s":[-45],"e":[0]},{"t":24}],"ix":10},"p":{"a":0,"k":[30,30,0],"ix":2},"a":{"a":0,"k":[30,30,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[7.779,-7.778],[0.708,7.778],[-7.779,-0.707]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.325,0.843,0.416,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[37.778,22.222],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"三角","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":30,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Icon_Discovery_Active_Main","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.61],"y":[1]},"o":{"x":[0.24],"y":[0]},"n":["0p61_1_0p24_0"],"t":20,"s":[0],"e":[100]},{"t":26}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[30,30,0],"ix":2},"a":{"a":0,"k":[30,30,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-3.313,0],[0,3.313],[3.313,0],[0,-3.313]],"o":[[3.313,0],[0,-3.313],[-3.313,0],[0,3.313]],"v":[[0,6],[6,0],[0,-6],[-6,0]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.682,0.878,0.69,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[32,32],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"内圆","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":30,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Icon_Discovery_Normal","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.8],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"n":["0p8_1_0p167_0p167"],"t":0,"s":[100],"e":[6]},{"t":10}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[30,30,0],"ix":2},"a":{"a":0,"k":[30,30,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.418,0],[0,4.418],[4.418,0],[0,-4.418]],"o":[[4.418,0],[0,-4.418],[-4.418,0],[0,4.418]],"v":[[0,8],[8,0],[0,-8],[-8,0]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.498,0.498,0.498,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":2,"lj":2,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[30,30],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[7.779,-7.778],[0.708,7.778],[-7.779,-0.707]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.498,0.498,0.498,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[37.778,22.222],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 3","np":2,"cix":2,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[2.063,0],[0,-11.045],[-11.046,0],[-2.839,1.545],[-1.839,3.54],[0,3.321],[0.604,1.907]],"o":[[-1.872,-0.58],[-11.046,0],[0,11.046],[3.46,0],[3.5,-1.907],[1.432,-2.755],[0,-2.107],[0,0]],"v":[[5.924,-19.108],[0,-20],[-20,0],[0,20],[9.553,17.576],[17.759,9.208],[20,0],[19.07,-6.044]],"c":false},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.498,0.498,0.498,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":2,"lj":2,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[30,30],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 4","np":2,"cix":2,"ix":3,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":30,"st":0,"bm":0}],"markers":[]}
================================================
FILE: Example/Classes/Other/LottieResources/green_lottie_tab_home.json
================================================
{"v":"5.1.16","fr":30,"ip":0,"op":30,"w":60,"h":60,"nm":"Tab_Shop_Active","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Icon_Shop_Active_Line_A","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[30,30,0],"ix":2},"a":{"a":0,"k":[30,30,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-3.313,0],[-1.075,1.617],[-2.087,0],[-1.075,1.617],[-2.087,0],[-1.075,1.617],[-2.087,0],[0,3.313],[0,0],[0.845,0],[0,0],[0.284,-0.796]],"o":[[0,3.313],[2.087,0],[1.075,1.617],[2.087,0],[1.075,1.617],[2.087,0],[1.075,1.617],[3.313,0],[0,0],[-0.285,-0.796],[0,0],[-0.846,0],[0,0]],"v":[[-21,-4],[-15,2],[-10,-0.682],[-5,2],[0,-0.682],[5,2],[10,-0.682],[15,2],[21,-4],[16.474,-16.673],[14.591,-18],[-14.59,-18],[-16.474,-16.673]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.325,0.843,0.416,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":2,"lj":2,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.61],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"n":["0p61_1_0p167_0p167"],"t":16,"s":[6],"e":[0]},{"t":18}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"n":["0p4_1_0p6_0"],"t":0,"s":[6],"e":[100]},{"i":{"x":[0.8],"y":[1]},"o":{"x":[0.6],"y":[0]},"n":["0p8_1_0p6_0"],"t":16,"s":[100],"e":[100]},{"t":35}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":3,"nm":"修剪路径 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"tr","p":{"a":0,"k":[30,30],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"Line","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":30,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Icon_Shop_Active_Line_B","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[30,30,0],"ix":2},"a":{"a":0,"k":[30,30,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-1.104,0],[0,0],[0,1.104],[0,0]],"o":[[0,0],[0,1.104],[0,0],[1.104,0],[0,0],[0,0]],"v":[[-16,0],[-16,16],[-14,18],[14,18],[16,16],[16,10]],"c":false},"ix":2},"nm":"路径 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.325,0.843,0.416,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":2,"lj":2,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tm","s":{"a":0,"k":6,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.977],"y":[0.791]},"o":{"x":[0.964],"y":[0]},"n":["0p977_0p791_0p964_0"],"t":16,"s":[6],"e":[100]},{"i":{"x":[0.8],"y":[1]},"o":{"x":[1],"y":[0]},"n":["0p8_1_1_0"],"t":29,"s":[100],"e":[100]},{"t":35}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":3,"nm":"修剪路径 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"tr","p":{"a":0,"k":[30,30],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"Line","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":30,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Icon_Shop_Active_Main","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.61],"y":[1]},"o":{"x":[0.24],"y":[0]},"n":["0p61_1_0p24_0"],"t":20,"s":[0],"e":[100]},{"t":26}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[30,30,0],"ix":2},"a":{"a":0,"k":[30,30,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0.145,-0.39],[0,0],[-3.314,0],[-1.075,1.616],[-2.087,0],[-1.075,1.616],[-2.087,0],[0,3.314],[0,0],[0.416,0]],"o":[[-0.416,0],[0,0],[0,3.314],[2.087,0],[1.075,1.616],[2.087,0],[1.075,1.616],[3.314,0],[0,0],[-0.147,-0.39],[0,0]],"v":[[-12.307,-7],[-13.243,-6.351],[-16,1],[-10,7],[-5,4.318],[0,7],[5,4.318],[10,7],[16,1],[13.244,-6.351],[12.307,-7]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.682,0.878,0.69,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[35,25],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"Main","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":30,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Icon_Shop_Normal","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.8],"y":[1]},"o":{"x":[0.6],"y":[0]},"n":["0p8_1_0p6_0"],"t":0,"s":[100],"e":[6]},{"t":10}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[30,30,0],"ix":2},"a":{"a":0,"k":[30,30,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,3.313],[0,0],[-0.846,0],[0,0],[-0.285,-0.796],[0,0],[3.313,0],[1.075,1.617],[2.087,0],[1.075,1.617],[2.087,0],[1.075,1.617],[2.087,0]],"o":[[0,0],[0.284,-0.796],[0,0],[0.845,0],[0,0],[0,3.313],[-2.087,0],[-1.075,1.617],[-2.087,0],[-1.075,1.617],[-2.087,0],[-1.075,1.617],[-3.313,0]],"v":[[-21,-4],[-16.474,-16.673],[-14.59,-18],[14.591,-18],[16.474,-16.673],[21,-4],[15,2],[10,-0.682],[5,2],[0,-0.682],[-5,2],[-10,-0.682],[-15,2]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[1.104,0],[0,0],[0,1.104],[0,0]],"o":[[0,0],[0,1.104],[0,0],[-1.104,0],[0,0],[0,0]],"v":[[16,10],[16,16],[14,18],[-14,18],[-16,16],[-16,2]],"c":false},"ix":2},"nm":"路径 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"合并路径 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"st","c":{"a":0,"k":[0.498,0.498,0.498,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":2,"lj":2,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[30,30],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"Line","np":4,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":30,"st":0,"bm":0}],"markers":[]}
================================================
FILE: Example/Classes/Other/LottieResources/green_lottie_tab_mine.json
================================================
{"v":"5.1.16","fr":30,"ip":0,"op":30,"w":60,"h":60,"nm":"Tab_Mine_Active","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Icon_Mine_Active_Line","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[30,30,0],"ix":2},"a":{"a":0,"k":[30,30,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,1.407],[5.523,0],[0,-5.523],[-5.523,0],[0,-9.942],[0,0],[-3.893,3.302]],"o":[[0.524,-1.215],[0,-5.523],[-5.523,0],[0,5.523],[9.942,0],[0,0],[0,-5.505],[0,0]],"v":[[9.185,-5.039],[10,-9],[0,-19],[-10,-9],[0,1],[18,19],[-18,19],[-11.636,5.266]],"c":false},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.325,0.843,0.416,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":2,"lj":2,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[30,29],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.955],"y":[1]},"o":{"x":[1],"y":[0]},"n":["0p955_1_1_0"],"t":0,"s":[0],"e":[38]},{"i":{"x":[0.964],"y":[1]},"o":{"x":[1],"y":[0]},"n":["0p964_1_1_0"],"t":16,"s":[38],"e":[100]},{"t":26}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"修剪路径 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":30,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Icon_Mine_Active_Main","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.76],"y":[1]},"o":{"x":[0.24],"y":[0]},"n":["0p76_1_0p24_0"],"t":20,"s":[0],"e":[100]},{"t":26}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[30,30,0],"ix":2},"a":{"a":0,"k":[30,30,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-8.284],[0,0],[-8.284,0]],"o":[[0,0],[0,-8.284],[8.284,0]],"v":[[15,16.5],[-15,16.5],[0,1.5]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[3.866,0],[0,3.866],[-3.866,0],[0,-3.866]],"o":[[-3.866,0],[0,-3.866],[3.866,0],[0,3.866]],"v":[[0,-2.5],[-7,-9.5],[0,-16.5],[7,-9.5]],"c":true},"ix":2},"nm":"路径 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"合并路径 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0.682,0.878,0.69,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[33,32.5],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 2","np":4,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":30,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Icon_Mine_Normal","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.8],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"n":["0p8_1_0p167_0p167"],"t":0,"s":[100],"e":[6]},{"t":10}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[30,30,0],"ix":2},"a":{"a":0,"k":[30,30,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,1.407],[5.523,0],[0,-5.523],[-5.523,0],[0,-9.942],[0,0],[-3.893,3.302]],"o":[[0.524,-1.215],[0,-5.523],[-5.523,0],[0,5.523],[9.942,0],[0,0],[0,-5.505],[0,0]],"v":[[9.185,-5.039],[10,-9],[0,-19],[-10,-9],[0,1],[18,19],[-18,19],[-11.636,5.266]],"c":false},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.498,0.498,0.498,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":2,"lj":2,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[30,29],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":30,"st":0,"bm":0}],"markers":[]}
================================================
FILE: Example/Classes/Other/LottieResources/green_lottie_tab_news.json
================================================
{"v":"5.1.16","fr":30,"ip":0,"op":30,"w":60,"h":60,"nm":"Tab_Knowledge_Active","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Icon_Knowledge_Active_Line_A","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[30,30,0],"ix":2},"a":{"a":0,"k":[30,30,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,-2.2],[2.019,-1.142]],"o":[[0,0],[0,0],[0,0],[0,0],[1.974,0.669],[0,2.231],[0,0]],"v":[[-1.74,7],[-21.74,-1],[-1.74,-9],[18.26,-1],[18.346,-1],[21.74,3.737],[18.26,9]],"c":false},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.325,0.843,0.416,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":2,"lj":2,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[31.74,21],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 2","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.357],"y":[1]},"o":{"x":[0.644],"y":[0]},"n":["0p357_1_0p644_0"],"t":0,"s":[0],"e":[100]},{"t":16}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"修剪路径 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":30,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Icon_Knowledge_Active_Line_B","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[30,30,0],"ix":2},"a":{"a":0,"k":[30,30,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[20,-4],[0,4],[-20,-4]],"c":false},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.325,0.843,0.416,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":2,"lj":2,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[30,34],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"n":["0p2_1_0p4_0"],"t":16,"s":[0],"e":[100]},{"t":28}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"修剪路径 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":30,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Icon_Knowledge_Active_Line_C","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[30,30,0],"ix":2},"a":{"a":0,"k":[30,30,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,-2.199],[2.019,-1.142],[0,0],[0,0]],"o":[[1.974,0.669],[0,2.232],[0,0],[0,0],[0,0]],"v":[[18.346,-9],[21.74,-4.264],[18.26,1],[-1.74,9],[-21.74,1]],"c":false},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.325,0.843,0.416,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":2,"lj":2,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[31.74,39],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 3","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"n":["0p2_1_0p4_0"],"t":20,"s":[0],"e":[100]},{"t":28}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"修剪路径 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":30,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Icon_Knowledge_Active_Main","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.76],"y":[1]},"o":{"x":[0.24],"y":[0]},"n":["0p76_1_0p24_0"],"t":20,"s":[0],"e":[100]},{"t":26}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[30,30,0],"ix":2},"a":{"a":0,"k":[30,30,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-17,-8.001],[-5,-3.501],[-5,16.501],[17,7.501],[17,-10.499],[2.5,-16.501]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.682,0.878,0.69,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[35,31.5],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 4","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":30,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Icon_Knowledge_Normal","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.8],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"n":["0p8_1_0p167_0p167"],"t":0,"s":[100],"e":[6]},{"t":10}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[30,30,0],"ix":2},"a":{"a":0,"k":[30,30,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[20,-4],[0,4],[-20,-4]],"c":false},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.498,0.498,0.498,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":2,"lj":2,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[30,34],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,-2.2],[2.019,-1.142]],"o":[[0,0],[0,0],[0,0],[0,0],[1.974,0.669],[0,2.231],[0,0]],"v":[[-1.74,7],[-21.74,-1],[-1.74,-9],[18.26,-1],[18.346,-1],[21.74,3.737],[18.26,9]],"c":false},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.498,0.498,0.498,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":2,"lj":2,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[31.74,21],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 2","np":2,"cix":2,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,2.232],[1.974,0.669]],"o":[[0,0],[0,0],[2.019,-1.142],[0,-2.199],[0,0]],"v":[[-21.74,1],[-1.74,9],[18.26,1],[21.74,-4.264],[18.346,-9]],"c":false},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.498,0.498,0.498,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":2,"lj":2,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[31.74,39],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 3","np":2,"cix":2,"ix":3,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":30,"st":0,"bm":0}],"markers":[]}
================================================
FILE: Example/Classes/Other/LottieResources/tab_home_animate.json
================================================
{"v":"4.7.0","fr":24,"ip":0,"op":19,"w":66,"h":66,"nm":"主页到刷新(66x66)大变 8","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"形状图层 10","ks":{"o":{"a":0,"k":100},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":5,"s":[-180],"e":[-154]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":6,"s":[-154],"e":[-63]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":7,"s":[-63],"e":[15]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":8,"s":[15],"e":[49]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":9,"s":[49],"e":[81]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":10,"s":[81],"e":[116]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":11,"s":[116],"e":[147]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":12,"s":[147],"e":[180]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":13,"s":[180],"e":[215]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":14,"s":[215],"e":[258]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":15,"s":[258],"e":[286]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":16,"s":[286],"e":[321]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":17,"s":[321],"e":[359]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":18,"s":[359],"e":[361]},{"t":19}]},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":5,"s":[33.097,31.625,0],"e":[39.582,25.888,0],"to":[-0.01841666735709,-5.55231285095215,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":6,"s":[39.582,25.888,0],"e":[52,33,0],"to":[0,0,0],"ti":[0,-13.3487205505371,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":8,"s":[52,33,0],"e":[33,52,0],"to":[0,10.4934120178223,0],"ti":[10.493408203125,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":10,"s":[33,52,0],"e":[14,33,0],"to":[-10.4934158325195,0,0],"ti":[0,10.4934158325195,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":13,"s":[14,33,0],"e":[33,14,0],"to":[0,-10.4934196472168,0],"ti":[-10.4934158325195,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":15.5,"s":[33,14,0],"e":[33,14,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":15.501,"s":[33,14,0],"e":[52,33,0],"to":[10.4934120178223,0,0],"ti":[0,-10.4934196472168,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":18,"s":[52,33,0],"e":[52,33,0],"to":[0,0,0],"ti":[0,-8.51000690460205,0]},{"t":19}]},"a":{"a":0,"k":[-0.103,-6.545,0]},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":5,"s":[264,164,100],"e":[196.667,134.095,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":6,"s":[196.667,134.095,100],"e":[101,75.286,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":8,"s":[101,75.286,100],"e":[100,100,100]},{"t":19}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":5,"s":[{"i":[[-0.104,0.151],[0,0],[0.683,0.469],[0.303,0],[0,0],[0,-0.828],[-0.172,-0.25],[0,0],[-0.683,0.469]],"o":[[0,0],[0.469,-0.683],[-0.25,-0.172],[0,0],[-0.829,0],[0,0.303],[0,0],[0.469,0.683],[0.151,-0.104]],"v":[[1.775,5.87],[8.57,-4.016],[8.184,-6.101],[7.334,-6.365],[-6.256,-6.365],[-7.756,-4.865],[-7.492,-4.016],[-0.697,5.87],[1.389,6.256]],"c":true}],"e":[{"i":[[-0.104,0.151],[0,0],[0.683,0.469],[0.303,0],[0,0],[0,-0.828],[-0.172,-0.25],[0,0],[-0.683,0.469]],"o":[[0,0],[0.469,-0.683],[-0.25,-0.172],[0,0],[-0.829,0],[0,0.303],[0,0],[0.469,0.683],[0.151,-0.104]],"v":[[1.775,5.87],[8.57,-4.016],[8.184,-6.101],[7.334,-6.365],[-6.256,-6.365],[-7.756,-4.865],[-7.492,-4.016],[-0.697,5.87],[1.389,6.256]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":8,"s":[{"i":[[-0.104,0.151],[0,0],[0.683,0.469],[0.303,0],[0,0],[0,-0.828],[-0.172,-0.25],[0,0],[-0.683,0.469]],"o":[[0,0],[0.469,-0.683],[-0.25,-0.172],[0,0],[-0.829,0],[0,0.303],[0,0],[0.469,0.683],[0.151,-0.104]],"v":[[1.775,5.87],[8.57,-4.016],[8.184,-6.101],[7.334,-6.365],[-6.256,-6.365],[-7.756,-4.865],[-7.492,-4.016],[-0.697,5.87],[1.389,6.256]],"c":true}],"e":[{"i":[[-0.104,0.151],[0,0],[0.683,0.469],[0.303,0],[0,0],[0,-0.828],[-0.172,-0.25],[0,0],[-0.683,0.469]],"o":[[0,0],[0.469,-0.683],[-0.25,-0.172],[0,0],[-0.829,0],[0,0.303],[0,0],[0.469,0.683],[0.151,-0.104]],"v":[[1.775,5.87],[8.57,-4.016],[8.184,-6.101],[7.334,-6.365],[-6.256,-6.365],[-7.756,-4.865],[-7.492,-4.016],[-0.697,5.87],[1.389,6.256]],"c":true}]},{"t":19}]},"nm":"路径 1","mn":"ADBE Vector Shape - Group"},{"ty":"fl","c":{"a":0,"k":[0.133,0.133,0.133,1]},"o":{"a":0,"k":100},"r":1,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[-0.642,-0.18],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"矩形 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":6,"op":96,"st":4,"bm":0,"sr":1},{"ddd":0,"ind":2,"ty":4,"nm":"形状图层 7","ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[33,33,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":4,"s":[{"i":[[0,0],[0,-13.349],[10.493,0],[0,10.493],[-10.493,0],[0,0],[0,-10.493]],"o":[[-0.097,-29.375],[0,10.493],[-10.493,0],[0,-10.493],[0,0],[10.493,0],[0,0]],"v":[[3.756,22.586],[22.658,3.586],[3.658,22.586],[-15.342,3.586],[3.658,-15.414],[3.658,-15.414],[22.658,3.586]],"c":false}],"e":[{"i":[[0,0],[0,-13.349],[10.493,0],[0,10.493],[-10.493,0],[0,0],[0,-10.493]],"o":[[0,-34.687],[0,10.493],[-10.493,0],[0,-10.493],[0,0],[10.493,0],[0,0]],"v":[[3.756,22.586],[22.658,3.586],[3.658,22.586],[-15.342,3.586],[3.658,-15.414],[3.658,-15.414],[22.658,3.586]],"c":false}]},{"t":19}]},"nm":"路径 1","mn":"ADBE Vector Shape - Group"},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":4,"s":[0],"e":[6.2]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":6,"s":[6.2],"e":[41]},{"t":19}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":4,"s":[0],"e":[20]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":7,"s":[20],"e":[26.667]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":8,"s":[26.667],"e":[44.836]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":10,"s":[44.836],"e":[64.091]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":13,"s":[64.091],"e":[80.455]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":15,"s":[80.455],"e":[86.97]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":16,"s":[86.97],"e":[100]},{"t":18}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"修剪路径 1","mn":"ADBE Vector Filter - Trim"},{"ty":"st","c":{"a":0,"k":[0.133,0.133,0.133,1]},"o":{"a":0,"k":100},"w":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":4,"s":[38],"e":[37]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":5,"s":[37],"e":[14]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":8,"s":[14],"e":[8]},{"t":19}]},"lc":2,"lj":1,"ml":4,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke"},{"ty":"tr","p":{"a":0,"k":[-3.658,-3.586],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"矩形 1","np":4,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":6,"op":95,"st":4,"bm":0,"sr":1},{"ddd":0,"ind":3,"ty":4,"nm":"“图层 6”轮廓 3","td":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[32.438,33.875,0]},"a":{"a":0,"k":[42,39,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-2.232,0],[0,0],[0,2.235],[0,0],[0,0]],"o":[[0,0],[0,2.24],[0,0],[2.24,0],[0,0],[0,0],[0,0]],"v":[[-19.231,-14.445],[-19.231,10.398],[-15.188,14.445],[15.187,14.445],[19.231,10.398],[19.231,-14.445],[-0.46,-30.57]],"c":true}},"nm":"路径 1","mn":"ADBE Vector Shape - Group"},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0.062,0.062],[0,0],[0.197,0.099],[0.633,-0.781],[0,0],[0.02,-0.029],[0,0],[-0.78,-0.781],[0,0],[-0.831,0.721],[0,0],[0,0],[-0.692,0.855],[0,0],[0.839,0.713]],"o":[[-0.052,-0.068],[0,0],[-0.16,-0.16],[-0.822,-0.519],[0,0],[-0.022,0.027],[0,0],[-0.836,0.725],[0,0],[0.78,0.779],[0,0],[0,0],[0.836,0.71],[0,0],[0.697,-0.862],[0,0]],"v":[[1.442,-30.764],[1.271,-30.959],[1.303,-30.927],[0.764,-31.315],[-1.784,-30.893],[-1.726,-30.964],[-1.789,-30.881],[-22.231,-13.124],[-22.323,-10.404],[-22.356,-10.437],[-19.437,-10.33],[-0.191,-27.049],[19.222,-10.562],[21.995,-10.818],[21.938,-10.746],[21.671,-13.584]],"c":true}},"nm":"路径 2","mn":"ADBE Vector Shape - Group"},{"ty":"fl","c":{"a":0,"k":[0.133,0.133,0.133,1]},"o":{"a":0,"k":100},"r":1,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[42.897,46.78],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":6,"st":-18,"bm":0,"sr":1},{"ddd":0,"ind":4,"ty":4,"nm":"形状图层 9","tt":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":-1,"s":[33,93.013,0],"e":[33,46.763,0],"to":[0,-7.70833349227905,0],"ti":[0,7.70833349227905,0]},{"t":5}]},"a":{"a":0,"k":[0.47,24.873,0]},"s":{"a":0,"k":[186,186,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[37.657,37.657]},"p":{"a":0,"k":[0,0]},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse"},{"ty":"fl","c":{"a":0,"k":[0.133,0.133,0.133,1]},"o":{"a":0,"k":100},"r":1,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[0.47,24.873],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[104.142,104.142],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"椭圆 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":6,"st":0,"bm":0,"sr":1},{"ddd":0,"ind":5,"ty":4,"nm":"“图层 2”轮廓","ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[32.438,33.875,0]},"a":{"a":0,"k":[42,39,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0.062,0.062],[0,0],[0.197,0.099],[0.633,-0.781],[0,0],[0.02,-0.029],[0,0],[-0.78,-0.781],[0,0],[-0.831,0.721],[0,0],[0,0],[-0.692,0.855],[0,0],[0.839,0.713]],"o":[[-0.052,-0.068],[0,0],[-0.16,-0.16],[-0.822,-0.519],[0,0],[-0.022,0.027],[0,0],[-0.836,0.725],[0,0],[0.78,0.779],[0,0],[0,0],[0.836,0.71],[0,0],[0.697,-0.862],[0,0]],"v":[[1.676,-10.042],[1.505,-10.238],[1.537,-10.206],[0.998,-10.594],[-1.55,-10.171],[-1.492,-10.242],[-1.555,-10.16],[-21.997,7.598],[-22.089,10.318],[-22.122,10.285],[-19.203,10.391],[0.043,-6.327],[19.456,10.16],[22.229,9.904],[22.172,9.975],[21.905,7.137]],"c":true}},"nm":"路径 1","mn":"ADBE Vector Shape - Group"},{"ty":"fl","c":{"a":0,"k":[0.133,0.133,0.133,1]},"o":{"a":0,"k":100},"r":1,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[42.664,26.059],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":5,"st":-18,"bm":0,"sr":1},{"ddd":0,"ind":6,"ty":4,"nm":"“图层 3_复制”轮廓 3","ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[33.125,46.911,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[-1.164,0],[0,-1.167],[0,0],[0,0],[0,0],[3.375,0],[0,-3.378],[0,0]],"o":[[0,0],[0,0],[0,0],[0,-1.167],[1.164,0],[0,0],[0,0],[0,0],[0,-3.39],[-3.368,0],[0,0],[0,0]],"v":[[-40.577,-43.207],[-40.577,-47.299],[-44.805,-47.298],[-44.805,-55.122],[-42.694,-57.239],[-40.583,-55.122],[-40.583,-43.207],[-36.583,-43.207],[-36.583,-55.122],[-42.694,-61.239],[-48.805,-55.122],[-48.805,-43.207]],"c":true}},"nm":"路径 1","mn":"ADBE Vector Shape - Group"},{"ty":"fl","c":{"a":0,"k":[0.133,0.133,0.133,1]},"o":{"a":0,"k":100},"r":1,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[42.694,52.388],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":5,"st":-18,"bm":0,"sr":1},{"ddd":0,"ind":7,"ty":4,"nm":"“图层 6”轮廓","ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[32.438,33.875,0]},"a":{"a":0,"k":[42,39,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[-2.232,0],[0,0],[0,2.235],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,2.24],[0,0],[2.24,0],[0,0],[0,0]],"v":[[15.311,-14.445],[15.311,10.512],[-15.356,10.512],[-15.356,-14.445],[-19.231,-14.445],[-19.231,10.398],[-15.188,14.445],[15.187,14.445],[19.231,10.398],[19.231,-14.445]],"c":true}},"nm":"路径 1","mn":"ADBE Vector Shape - Group"},{"ty":"fl","c":{"a":0,"k":[0.133,0.133,0.133,1]},"o":{"a":0,"k":100},"r":1,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[42.897,46.78],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":5,"st":-18,"bm":0,"sr":1}]}
================================================
FILE: Example/Classes/Other/LottieResources/tab_me_animate.json
================================================
{"v":"4.6.3","fr":24,"ip":0,"op":10,"w":66,"h":66,"nm":"个人(66x66)","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"空 15","ks":{"o":{"a":0,"k":0},"r":{"a":0,"k":0},"p":{"a":0,"k":[33.625,32.5,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":-1,"s":[100,100,100],"e":[92,92,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":3,"s":[92,92,100],"e":[103,103,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":7,"s":[103,103,100],"e":[100,100,100]},{"t":9}]}},"ao":0,"ip":0,"op":10,"st":-45,"bm":0,"sr":1},{"ddd":0,"ind":2,"ty":4,"nm":"形状图层 2","parent":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":2,"s":[4.365,16.432,0],"e":[-2.135,16.432,0],"to":[-1.08333337306976,0,0],"ti":[0.83333331346512,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":6,"s":[-2.135,16.432,0],"e":[-0.635,16.432,0],"to":[-0.83333331346512,0,0],"ti":[-0.25,0,0]},{"t":9}]},"a":{"a":0,"k":[0.271,16.432,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[4,4]},"p":{"a":0,"k":[0,0]},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse"},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[0.271,16.432],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"椭圆 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":3,"op":10,"st":-45,"bm":0,"sr":1},{"ddd":0,"ind":3,"ty":4,"nm":"“图层 2”轮廓 2","parent":4,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":-23},"p":{"a":0,"k":[42.5,35.5,0]},"a":{"a":0,"k":[42.5,35.5,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":-1,"s":[{"i":[[0,-6.627],[6.627,0],[0,11.188],[0,0]],"o":[[0,6.627],[-0.062,0.062],[0,-10.881],[6.627,0]],"v":[[12,0],[0,12],[9.875,-0.125],[0,-12]],"c":true}],"e":[{"i":[[0,-6.627],[6.627,0],[0,6.627],[-6.627,0]],"o":[[0,6.627],[-6.627,0],[0,-6.627],[6.627,0]],"v":[[12,0],[0,12],[-12,0],[0,-12]],"c":true}]},{"t":6}]},"nm":"路径 1","mn":"ADBE Vector Shape - Group"},{"ty":"tr","p":{"a":0,"k":[42.5,35.5],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group"},{"ty":"fl","c":{"a":0,"k":[0.1333333,0.1333333,0.1333333,1]},"o":{"a":0,"k":100},"r":1,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill"}],"ip":0,"op":10,"st":-45,"bm":0,"sr":1},{"ddd":0,"ind":4,"ty":4,"nm":"“图层 2”轮廓","parent":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":-1,"s":[-0.5,-9.531,0],"e":[-1.25,-7.031,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":2,"s":[-1.25,-7.031,0],"e":[-1,-9.531,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":6,"s":[-1,-9.531,0],"e":[-0.5,-9.531,0],"to":[0,0,0],"ti":[0,0,0]},{"t":9}]},"a":{"a":0,"k":[42,36,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-6.627],[6.627,0],[0,6.627],[-6.627,0]],"o":[[0,6.627],[-6.627,0],[0,-6.627],[6.627,0]],"v":[[12,0],[0,12],[-12,0],[0,-12]],"c":true}},"nm":"路径 1","mn":"ADBE Vector Shape - Group"},{"ty":"st","c":{"a":0,"k":[0.1333333,0.1333333,0.1333333,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":4},"lc":1,"lj":1,"ml":10,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke"},{"ty":"tr","p":{"a":0,"k":[42,36],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":10,"st":-45,"bm":0,"sr":1},{"ddd":0,"ind":5,"ty":4,"nm":"“图层 2_复制”轮廓 2","parent":1,"td":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[0,0,0]},"a":{"a":0,"k":[42.5,45.5,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-3.342,0],[-2.607,1.537],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[2.657,1.623],[3.245,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-8.728,-8.702],[0.395,-6.144],[9.286,-8.562],[16.02,-1.548],[18.062,6.286],[16.938,8.702],[-18.062,8.245],[-17.688,1.494],[-10.938,-7.215]],"c":true}},"nm":"路径 1","mn":"ADBE Vector Shape - Group"},{"ty":"fl","c":{"a":0,"k":[0.1333333,0.1333333,0.1333333,1]},"o":{"a":0,"k":100},"r":1,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[41.604,59.672],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":10,"st":-45,"bm":0,"sr":1},{"ddd":0,"ind":6,"ty":4,"nm":"形状图层 3","parent":1,"tt":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[-0.232,14.395,0]},"a":{"a":0,"k":[-0.982,14.395,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[{"i":[[0,0],[0.706,-6.542],[0,0],[0,0],[0,0]],"o":[[0,0],[1.288,5.372],[0,0],[0,0],[0,0]],"v":[[4.06,-11.103],[8.032,-1.062],[3.935,10.187],[25.345,17.404],[25.345,-7.886]],"c":true}],"e":[{"i":[[0,0],[6.002,-6.583],[0,0],[0,0],[0,0]],"o":[[0,0],[-2.013,4.244],[0,0],[0,0],[0,0]],"v":[[3.476,-11.312],[0.296,2.272],[-12.774,9.728],[24.42,15.708],[24.42,-9.582]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":1.93,"s":[{"i":[[0,0],[6.002,-6.583],[0,0],[0,0],[0,0]],"o":[[0,0],[-2.013,4.244],[0,0],[0,0],[0,0]],"v":[[3.476,-11.312],[0.296,2.272],[-12.774,9.728],[24.42,15.708],[24.42,-9.582]],"c":true}],"e":[{"i":[[0,0],[9.172,-7.75],[0,0],[0,0],[0,0]],"o":[[0,0],[-9.565,8.082],[0,0],[0,0],[0,0]],"v":[[11.143,-12.395],[-7.19,-2.27],[-22.357,30.395],[24.046,16.04],[24.046,-9.25]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":4.071,"s":[{"i":[[0,0],[9.172,-7.75],[0,0],[0,0],[0,0]],"o":[[0,0],[-9.565,8.082],[0,0],[0,0],[0,0]],"v":[[11.143,-12.395],[-7.19,-2.27],[-22.357,30.395],[24.046,16.04],[24.046,-9.25]],"c":true}],"e":[{"i":[[0,0],[9.006,-7.688],[0,0],[0,0],[0,0]],"o":[[0,0],[-9.994,7.312],[0,0],[0,0],[0,0]],"v":[[5.768,-11.958],[-10.649,-2.458],[-27.294,19.52],[26.59,20.341],[26.59,-4.949]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":6,"s":[{"i":[[0,0],[9.006,-7.688],[0,0],[0,0],[0,0]],"o":[[0,0],[-9.994,7.312],[0,0],[0,0],[0,0]],"v":[[5.768,-11.958],[-10.649,-2.458],[-27.294,19.52],[26.59,20.341],[26.59,-4.949]],"c":true}],"e":[{"i":[[0,0],[4.161,-8.25],[0,0],[0,0],[0,0]],"o":[[0,0],[-4.161,8.25],[0,0],[0,0],[0,0]],"v":[[-8.357,-11.27],[-18.357,-1.395],[-18.732,12.145],[29.131,14.109],[29.131,-11.181]],"c":true}]},{"t":8}]},"nm":"路径 1","mn":"ADBE Vector Shape - Group"},{"ty":"fl","c":{"a":0,"k":[0.1333333,0.1333333,0.1333333,1]},"o":{"a":0,"k":100},"r":1,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[-0.982,14.395],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"矩形 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":10,"st":-45,"bm":0,"sr":1},{"ddd":0,"ind":7,"ty":4,"nm":"“图层 3”轮廓","parent":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[0,0,0]},"a":{"a":0,"k":[42.5,45.5,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[5.28,3.24],[0,0],[0.391,0],[0,-1.104],[-0.582,-0.349],[0,0],[-0.147,-0.095],[-0.121,-0.084],[-0.131,-0.097],[-0.11,-0.088],[-0.124,-0.104],[-0.104,-0.093],[-0.113,-0.108],[-0.1,-0.1],[-0.103,-0.111],[-0.095,-0.106],[-0.096,-0.119],[-0.085,-0.108],[-0.09,-0.124],[-0.078,-0.111],[-0.081,-0.127],[-0.069,-0.117],[-0.072,-0.132],[-0.06,-0.118],[-0.065,-0.137],[-0.053,-0.121],[-0.055,-0.138],[-0.045,-0.124],[-0.046,-0.145],[-0.035,-0.123],[-0.037,-0.155],[-0.025,-0.12],[-0.028,-0.168],[-0.016,-0.112],[-0.017,-0.197],[-0.006,-0.086],[0,-0.286],[0,0],[-4.411,2.612],[0,0],[0,0.718],[1.105,0],[0.29,-0.164],[0,0],[0.05,-0.031],[0.018,-0.013],[0.135,-0.087],[0.157,-0.107],[0.16,-0.116],[0.15,-0.115],[0.153,-0.125],[0.14,-0.122],[0.146,-0.135],[0.131,-0.128],[0.137,-0.143],[0.121,-0.134],[0.128,-0.151],[0.113,-0.14],[0.117,-0.157],[0.102,-0.147],[0.108,-0.165],[0.093,-0.151],[0.098,-0.174],[0.08,-0.153],[0.087,-0.181],[0.07,-0.158],[0.075,-0.19],[0.059,-0.161],[0.065,-0.199],[0.046,-0.16],[0.051,-0.208],[0.035,-0.16],[0.038,-0.222],[0.023,-0.153],[0.025,-0.254],[0.009,-0.129],[0,-0.391],[0,0],[-1.105,0],[0,0],[-0.174,1.085],[0,1.375]],"o":[[0,0],[-0.309,-0.195],[-1.105,0],[0,0.73],[0,0],[0.151,0.093],[0.123,0.081],[0.135,0.095],[0.115,0.085],[0.128,0.1],[0.108,0.091],[0.119,0.105],[0.104,0.097],[0.108,0.108],[0.099,0.104],[0.102,0.115],[0.089,0.106],[0.095,0.122],[0.08,0.109],[0.084,0.125],[0.073,0.114],[0.078,0.13],[0.065,0.117],[0.069,0.135],[0.056,0.12],[0.058,0.138],[0.048,0.124],[0.051,0.144],[0.039,0.122],[0.043,0.155],[0.029,0.118],[0.036,0.165],[0.019,0.11],[0.027,0.195],[0.008,0.085],[0.019,0.284],[0,0],[0,-4.669],[0,0],[0.567,-0.353],[0,-1.104],[-0.356,0],[0,0],[-0.051,0.029],[-0.017,0.012],[-0.137,0.083],[-0.16,0.102],[-0.164,0.112],[-0.153,0.111],[-0.157,0.121],[-0.144,0.118],[-0.15,0.13],[-0.135,0.125],[-0.142,0.139],[-0.125,0.132],[-0.133,0.147],[-0.116,0.138],[-0.122,0.154],[-0.108,0.145],[-0.114,0.163],[-0.096,0.149],[-0.104,0.172],[-0.085,0.152],[-0.094,0.179],[-0.075,0.157],[-0.082,0.187],[-0.064,0.159],[-0.071,0.196],[-0.051,0.158],[-0.059,0.207],[-0.04,0.159],[-0.046,0.22],[-0.026,0.152],[-0.035,0.251],[-0.012,0.128],[-0.027,0.385],[0,1.375],[0.162,1.079],[0,0],[1.113,0],[0,0],[0,-6.185]],"v":[[11.254,-9.225],[11.253,-9.223],[10.188,-9.531],[8.188,-7.531],[9.165,-5.822],[9.162,-5.816],[9.602,-5.529],[9.972,-5.285],[10.366,-4.993],[10.708,-4.738],[11.08,-4.428],[11.403,-4.156],[11.746,-3.833],[12.055,-3.54],[12.367,-3.21],[12.661,-2.896],[12.954,-2.544],[13.22,-2.225],[13.492,-1.852],[13.733,-1.525],[13.976,-1.145],[14.195,-0.799],[14.415,-0.404],[14.608,-0.053],[14.802,0.357],[14.971,0.715],[15.135,1.132],[15.28,1.503],[15.419,1.939],[15.536,2.305],[15.65,2.773],[15.737,3.127],[15.825,3.628],[15.883,3.958],[15.944,4.548],[15.971,4.803],[16,5.656],[-16,5.656],[-8.939,-5.951],[-8.944,-5.956],[-8,-7.656],[-10,-9.656],[-10.97,-9.378],[-10.977,-9.391],[-11.125,-9.298],[-11.183,-9.268],[-11.586,-9.007],[-12.065,-8.697],[-12.549,-8.35],[-13.006,-8.014],[-13.467,-7.641],[-13.898,-7.283],[-14.337,-6.882],[-14.74,-6.505],[-15.154,-6.078],[-15.529,-5.684],[-15.915,-5.232],[-16.264,-4.818],[-16.617,-4.348],[-16.939,-3.913],[-17.265,-3.419],[-17.555,-2.971],[-17.852,-2.449],[-18.106,-1.994],[-18.37,-1.451],[-18.594,-0.982],[-18.822,-0.417],[-19.013,0.06],[-19.208,0.657],[-19.361,1.13],[-19.518,1.754],[-19.637,2.229],[-19.756,2.894],[-19.837,3.35],[-19.918,4.111],[-19.958,4.493],[-20,5.656],[-19.82,7.691],[-17.503,9.656],[17.503,9.656],[19.821,7.691],[20,5.656]],"c":true}},"nm":"路径 1","mn":"ADBE Vector Shape - Group"},{"ty":"fl","c":{"a":0,"k":[0.1333333,0.1333333,0.1333333,1]},"o":{"a":0,"k":100},"r":1,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[41.833,60.333],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":10,"st":-45,"bm":0,"sr":1}]}
================================================
FILE: Example/Classes/Other/LottieResources/tab_message_animate.json
================================================
{"v":"4.6.3","fr":24,"ip":0,"op":10,"w":66,"h":66,"nm":"信息(66x66)","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"空 12","ks":{"o":{"a":0,"k":0},"r":{"a":0,"k":0},"p":{"a":0,"k":[34.562,29.5,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":-1,"s":[100,100,100],"e":[92,92,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":2,"s":[92,92,100],"e":[103,103,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":7,"s":[103,103,100],"e":[100,100,100]},{"t":9}]}},"ao":0,"ip":0,"op":10,"st":-2,"bm":0,"sr":1},{"ddd":0,"ind":2,"ty":4,"nm":"“图层 3”轮廓","parent":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":5,"s":[-11,1,0],"e":[-13.5,1,0],"to":[-0.41666665673256,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":6,"s":[-13.5,1,0],"e":[-11,1,0],"to":[0,0,0],"ti":[-0.41666665673256,0,0]},{"t":9}]},"a":{"a":0,"k":[39.5,49.5,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-1.381],[1.381,0],[0,1.381],[-1.381,0]],"o":[[0,1.381],[-1.381,0],[0,-1.381],[1.381,0]],"v":[[2.5,0],[0,2.5],[-2.5,0],[0,-2.5]],"c":true}},"nm":"路径 1","mn":"ADBE Vector Shape - Group"},{"ty":"fl","c":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":5,"s":[0.1333333,0.1333333,0.1333333,1],"e":[1,1,1,1]},{"t":6}]},"o":{"a":0,"k":100},"r":1,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[39.5,49.5],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":10,"st":-22,"bm":0,"sr":1},{"ddd":0,"ind":3,"ty":4,"nm":"“图层 4”轮廓","parent":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":4,"s":[-1,1,0],"e":[-3.5,1,0],"to":[-0.41666665673256,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":5,"s":[-3.5,1,0],"e":[-1,1,0],"to":[0,0,0],"ti":[-0.41666665673256,0,0]},{"t":8}]},"a":{"a":0,"k":[49.5,49.5,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-1.381],[1.381,0],[0,1.381],[-1.381,0]],"o":[[0,1.381],[-1.381,0],[0,-1.381],[1.381,0]],"v":[[2.5,0],[0,2.5],[-2.5,0],[0,-2.5]],"c":true}},"nm":"路径 1","mn":"ADBE Vector Shape - Group"},{"ty":"fl","c":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":4,"s":[0.1333333,0.1333333,0.1333333,1],"e":[1,1,1,1]},{"t":5}]},"o":{"a":0,"k":100},"r":1,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[49.5,49.5],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":10,"st":-22,"bm":0,"sr":1},{"ddd":0,"ind":4,"ty":4,"nm":"“图层 2”轮廓","parent":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":3,"s":[9,1,0],"e":[6.5,1,0],"to":[-0.41666665673256,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":4,"s":[6.5,1,0],"e":[9,1,0],"to":[0,0,0],"ti":[-0.41666665673256,0,0]},{"t":7}]},"a":{"a":0,"k":[59.5,49.5,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-1.381],[1.381,0],[0,1.381],[-1.381,0]],"o":[[0,1.381],[-1.381,0],[0,-1.381],[1.381,0]],"v":[[2.5,0],[0,2.5],[-2.5,0],[0,-2.5]],"c":true}},"nm":"路径 1","mn":"ADBE Vector Shape - Group"},{"ty":"fl","c":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":3,"s":[0.1333333,0.1333333,0.1333333,1],"e":[1,1,1,1]},{"t":4}]},"o":{"a":0,"k":100},"r":1,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[59.5,49.5],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":10,"st":-22,"bm":0,"sr":1},{"ddd":0,"ind":5,"ty":4,"nm":"形状图层 11","parent":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[-0.557,5.651,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[68.493,68.493,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[{"i":[[1.5,0.125],[-0.372,-18.05],[20.636,-0.031],[22.326,18.969],[-0.41,-1.161],[-2.972,-0.113],[-1.927,0],[-1,-0.375],[-3.316,-3.56],[0.372,2.99],[-4.168,-0.022],[0,2.25],[0.25,2.625]],"o":[[2.533,7.509],[0.277,13.408],[-8.721,0.013],[-3.815,-3.242],[0.322,0.912],[3.956,0.151],[3.375,0],[1,0.375],[-0.539,-2.676],[4.358,0.083],[2.528,0.013],[0,-2.25],[-0.625,-1.875]],"v":[[29.821,-28.983],[31.223,-4.158],[10.489,14.531],[-6.669,15.193],[-34.5,13.75],[-28.121,15.509],[-23.577,15.503],[-9.703,15.736],[8.495,29.114],[8.602,15.878],[29.132,15.74],[33.75,10.125],[33.375,-26.375]],"c":true}],"e":[{"i":[[1.5,0.125],[-0.077,-18.053],[9.089,-9.543],[22.326,18.969],[-0.41,-1.161],[-2.972,-0.113],[-1.927,0],[-1,-0.375],[-3.316,-3.56],[0.372,2.99],[-4.168,-0.022],[0,2.25],[0.25,2.625]],"o":[[2.533,7.509],[0.051,11.834],[-6.015,6.315],[-3.815,-3.242],[0.322,0.912],[3.956,0.151],[3.375,0],[1,0.375],[-0.539,-2.676],[4.358,0.083],[2.528,0.013],[0,-2.25],[-0.625,-1.875]],"v":[[29.821,-28.983],[30.598,-3.783],[8.239,14.531],[-6.669,15.193],[-34.5,13.75],[-28.121,15.509],[-23.577,15.503],[-9.703,15.736],[8.495,29.114],[8.602,15.878],[29.132,15.74],[33.75,10.125],[33.375,-26.375]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":1,"s":[{"i":[[1.5,0.125],[-0.077,-18.053],[9.089,-9.543],[22.326,18.969],[-0.41,-1.161],[-2.972,-0.113],[-1.927,0],[-1,-0.375],[-3.316,-3.56],[0.372,2.99],[-4.168,-0.022],[0,2.25],[0.25,2.625]],"o":[[2.533,7.509],[0.051,11.834],[-6.015,6.315],[-3.815,-3.242],[0.322,0.912],[3.956,0.151],[3.375,0],[1,0.375],[-0.539,-2.676],[4.358,0.083],[2.528,0.013],[0,-2.25],[-0.625,-1.875]],"v":[[29.821,-28.983],[30.598,-3.783],[8.239,14.531],[-6.669,15.193],[-34.5,13.75],[-28.121,15.509],[-23.577,15.503],[-9.703,15.736],[8.495,29.114],[8.602,15.878],[29.132,15.74],[33.75,10.125],[33.375,-26.375]],"c":true}],"e":[{"i":[[1.5,0.125],[-0.077,-18.053],[4.786,-8.116],[8.767,8.974],[-0.41,-1.161],[-2.972,-0.113],[-1.927,0],[-1,-0.375],[-3.316,-3.56],[-2.577,2.273],[-4.168,-0.022],[0,2.25],[0.25,2.625]],"o":[[2.533,7.509],[0.051,11.834],[-4.43,7.512],[-3.498,-3.581],[0.322,0.912],[3.956,0.151],[3.375,0],[1,0.375],[-0.539,-2.676],[4.358,0.083],[2.528,0.013],[0,-2.25],[-0.625,-1.875]],"v":[[29.821,-28.983],[31.112,-7.124],[2.969,14.017],[-7.312,15.579],[-34.5,13.75],[-28.121,15.509],[-23.577,15.503],[-15.23,15.993],[7.852,29.242],[8.216,15.878],[29.132,15.74],[33.75,10.125],[33.375,-26.375]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":2,"s":[{"i":[[1.5,0.125],[-0.077,-18.053],[4.786,-8.116],[8.767,8.974],[-0.41,-1.161],[-2.972,-0.113],[-1.927,0],[-1,-0.375],[-3.316,-3.56],[-2.577,2.273],[-4.168,-0.022],[0,2.25],[0.25,2.625]],"o":[[2.533,7.509],[0.051,11.834],[-4.43,7.512],[-3.498,-3.581],[0.322,0.912],[3.956,0.151],[3.375,0],[1,0.375],[-0.539,-2.676],[4.358,0.083],[2.528,0.013],[0,-2.25],[-0.625,-1.875]],"v":[[29.821,-28.983],[31.112,-7.124],[2.969,14.017],[-7.312,15.579],[-34.5,13.75],[-28.121,15.509],[-23.577,15.503],[-15.23,15.993],[7.852,29.242],[8.216,15.878],[29.132,15.74],[33.75,10.125],[33.375,-26.375]],"c":true}],"e":[{"i":[[1.5,0.125],[6.538,-12.759],[6.759,-6.414],[8.767,8.974],[-0.41,-1.161],[-2.972,-0.113],[-1.927,0],[-1,-0.375],[-3.316,-3.56],[-2.577,2.273],[-4.168,-0.022],[0,2.25],[0.25,2.625]],"o":[[-1.304,0.068],[-6.163,12.027],[-6.326,6.003],[-3.498,-3.581],[0.322,0.912],[3.956,0.151],[3.375,0],[1,0.375],[-0.539,-2.676],[4.358,0.083],[2.528,0.013],[0,-2.25],[-0.625,-1.875]],"v":[[29.821,-28.983],[27.145,-6.727],[5.085,9.652],[-9.956,15.711],[-34.5,13.75],[-28.121,15.509],[-23.577,15.503],[-15.23,15.993],[5.075,29.639],[4.91,15.878],[29.132,15.74],[33.75,10.125],[33.375,-26.375]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":3,"s":[{"i":[[1.5,0.125],[6.538,-12.759],[6.759,-6.414],[8.767,8.974],[-0.41,-1.161],[-2.972,-0.113],[-1.927,0],[-1,-0.375],[-3.316,-3.56],[-2.577,2.273],[-4.168,-0.022],[0,2.25],[0.25,2.625]],"o":[[-1.304,0.068],[-6.163,12.027],[-6.326,6.003],[-3.498,-3.581],[0.322,0.912],[3.956,0.151],[3.375,0],[1,0.375],[-0.539,-2.676],[4.358,0.083],[2.528,0.013],[0,-2.25],[-0.625,-1.875]],"v":[[29.821,-28.983],[27.145,-6.727],[5.085,9.652],[-9.956,15.711],[-34.5,13.75],[-28.121,15.509],[-23.577,15.503],[-15.23,15.993],[5.075,29.639],[4.91,15.878],[29.132,15.74],[33.75,10.125],[33.375,-26.375]],"c":true}],"e":[{"i":[[1.5,0.125],[2.789,-3.235],[6.759,-6.414],[5.685,-9.097],[-0.41,-1.161],[-2.972,-0.113],[-1.927,0],[-1,-0.375],[-3.316,-3.56],[-2.577,2.273],[-4.168,-0.022],[0,2.25],[0.25,2.625]],"o":[[-3,0.25],[-2.449,2.84],[-6.326,6.003],[-2.653,4.246],[0.322,0.912],[3.956,0.151],[3.375,0],[1,0.375],[-0.539,-2.676],[4.358,0.083],[2.528,0.013],[0,-2.25],[-0.625,-1.875]],"v":[[27.625,-29.5],[20.3,-25.714],[9.348,-9.205],[-16.673,11.449],[-34.5,13.75],[-28.121,15.509],[-23.577,15.503],[-15.23,15.993],[5.075,29.639],[4.91,15.878],[29.132,15.74],[33.75,10.125],[33.375,-26.375]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":4,"s":[{"i":[[1.5,0.125],[2.789,-3.235],[6.759,-6.414],[5.685,-9.097],[-0.41,-1.161],[-2.972,-0.113],[-1.927,0],[-1,-0.375],[-3.316,-3.56],[-2.577,2.273],[-4.168,-0.022],[0,2.25],[0.25,2.625]],"o":[[-3,0.25],[-2.449,2.84],[-6.326,6.003],[-2.653,4.246],[0.322,0.912],[3.956,0.151],[3.375,0],[1,0.375],[-0.539,-2.676],[4.358,0.083],[2.528,0.013],[0,-2.25],[-0.625,-1.875]],"v":[[27.625,-29.5],[20.3,-25.714],[9.348,-9.205],[-16.673,11.449],[-34.5,13.75],[-28.121,15.509],[-23.577,15.503],[-15.23,15.993],[5.075,29.639],[4.91,15.878],[29.132,15.74],[33.75,10.125],[33.375,-26.375]],"c":true}],"e":[{"i":[[1.5,0.125],[3.75,0],[1.913,-4.424],[6.378,-2.468],[-0.41,-1.161],[-2.972,-0.113],[-1.927,0],[-1,-0.375],[-1.704,-3.936],[-2.577,2.273],[-4.168,-0.022],[0,2.25],[0.25,2.625]],"o":[[-3,0.25],[-3.75,0],[-0.955,2.207],[-4.669,1.807],[0.322,0.912],[3.956,0.151],[3.375,0],[1,0.375],[3.043,-2.078],[4.358,0.083],[2.528,0.013],[0,-2.25],[-0.625,-1.875]],"v":[[27.625,-29.5],[-5.447,-29.5],[-13.749,-11.476],[-30.43,7.915],[-34.5,13.75],[-28.121,15.509],[-23.577,15.503],[-15.23,15.993],[-7.294,28.755],[4.91,15.878],[29.132,15.74],[33.75,10.125],[33.375,-26.375]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":5,"s":[{"i":[[1.5,0.125],[3.75,0],[1.913,-4.424],[6.378,-2.468],[-0.41,-1.161],[-2.972,-0.113],[-1.927,0],[-1,-0.375],[-1.704,-3.936],[-2.577,2.273],[-4.168,-0.022],[0,2.25],[0.25,2.625]],"o":[[-3,0.25],[-3.75,0],[-0.955,2.207],[-4.669,1.807],[0.322,0.912],[3.956,0.151],[3.375,0],[1,0.375],[3.043,-2.078],[4.358,0.083],[2.528,0.013],[0,-2.25],[-0.625,-1.875]],"v":[[27.625,-29.5],[-5.447,-29.5],[-13.749,-11.476],[-30.43,7.915],[-34.5,13.75],[-28.121,15.509],[-23.577,15.503],[-15.23,15.993],[-7.294,28.755],[4.91,15.878],[29.132,15.74],[33.75,10.125],[33.375,-26.375]],"c":true}],"e":[{"i":[[1.5,0.125],[3.75,0],[2.125,-1.125],[0.25,-5],[-0.41,-1.161],[-2.972,-0.113],[-1.927,0],[-1,-0.375],[1.422,-3.689],[-2.577,2.273],[-4.168,-0.022],[0,2.25],[0.25,2.625]],"o":[[-3,0.25],[-3.75,0],[-2.125,1.125],[-0.25,5],[0.322,0.912],[3.956,0.151],[3.375,0],[1,0.375],[3.043,-2.078],[4.358,0.083],[2.528,0.013],[0,-2.25],[-0.625,-1.875]],"v":[[27.625,-29.5],[-11,-29.5],[-32.875,-28.875],[-34.625,-8.25],[-34.5,13.75],[-28.121,15.509],[-23.577,15.503],[-15.23,15.993],[-19.016,28.632],[4.91,15.878],[29.132,15.74],[33.75,10.125],[33.375,-26.375]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":6,"s":[{"i":[[1.5,0.125],[3.75,0],[2.125,-1.125],[0.25,-5],[-0.41,-1.161],[-2.972,-0.113],[-1.927,0],[-1,-0.375],[1.422,-3.689],[-2.577,2.273],[-4.168,-0.022],[0,2.25],[0.25,2.625]],"o":[[-3,0.25],[-3.75,0],[-2.125,1.125],[-0.25,5],[0.322,0.912],[3.956,0.151],[3.375,0],[1,0.375],[3.043,-2.078],[4.358,0.083],[2.528,0.013],[0,-2.25],[-0.625,-1.875]],"v":[[27.625,-29.5],[-11,-29.5],[-32.875,-28.875],[-34.625,-8.25],[-34.5,13.75],[-28.121,15.509],[-23.577,15.503],[-15.23,15.993],[-19.016,28.632],[4.91,15.878],[29.132,15.74],[33.75,10.125],[33.375,-26.375]],"c":true}],"e":[{"i":[[1.5,0.125],[3.75,0],[2.125,-1.125],[0.25,-5],[-0.41,-1.161],[-2.972,-0.113],[-1.927,0],[-1,-0.375],[0.002,-2.808],[-2.577,2.273],[-4.168,-0.022],[0,2.25],[0.25,2.625]],"o":[[-3,0.25],[-3.75,0],[-2.125,1.125],[-0.25,5],[0.322,0.912],[3.956,0.151],[3.375,0],[1,0.375],[3.043,-2.078],[4.358,0.083],[2.528,0.013],[0,-2.25],[-0.625,-1.875]],"v":[[27.625,-29.5],[-11,-29.5],[-32.875,-28.875],[-34.625,-8.25],[-34.5,13.75],[-28.121,15.509],[-23.577,15.503],[-15.23,15.993],[-17.93,28.632],[4.91,15.878],[29.132,15.74],[33.75,10.125],[33.375,-26.375]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":7,"s":[{"i":[[1.5,0.125],[3.75,0],[2.125,-1.125],[0.25,-5],[-0.41,-1.161],[-2.972,-0.113],[-1.927,0],[-1,-0.375],[0.002,-2.808],[-2.577,2.273],[-4.168,-0.022],[0,2.25],[0.25,2.625]],"o":[[-3,0.25],[-3.75,0],[-2.125,1.125],[-0.25,5],[0.322,0.912],[3.956,0.151],[3.375,0],[1,0.375],[3.043,-2.078],[4.358,0.083],[2.528,0.013],[0,-2.25],[-0.625,-1.875]],"v":[[27.625,-29.5],[-11,-29.5],[-32.875,-28.875],[-34.625,-8.25],[-34.5,13.75],[-28.121,15.509],[-23.577,15.503],[-15.23,15.993],[-17.93,28.632],[4.91,15.878],[29.132,15.74],[33.75,10.125],[33.375,-26.375]],"c":true}],"e":[{"i":[[1.5,0.125],[3.75,0],[2.125,-1.125],[0.25,-5],[-0.41,-1.161],[-2.972,-0.113],[-1.927,0],[-1,-0.375],[0.002,-2.808],[-2.577,2.273],[-4.168,-0.022],[0,2.25],[0.25,2.625]],"o":[[-3,0.25],[-3.75,0],[-2.125,1.125],[-0.25,5],[0.322,0.912],[3.956,0.151],[3.375,0],[1,0.375],[3.043,-2.078],[4.358,0.083],[2.528,0.013],[0,-2.25],[-0.625,-1.875]],"v":[[27.625,-29.5],[-11,-29.5],[-32.875,-28.875],[-34.625,-8.25],[-34.5,13.75],[-28.121,15.509],[-23.577,15.503],[-16.057,15.875],[-16.04,28.868],[4.91,15.878],[29.132,15.74],[33.75,10.125],[33.375,-26.375]],"c":true}]},{"t":9}]},"nm":"路径 1","mn":"ADBE Vector Shape - Group"},{"ty":"fl","c":{"a":0,"k":[0.1333333,0.1333333,0.1333333,1]},"o":{"a":0,"k":100},"r":1,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"形状 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":10,"st":0,"bm":0,"sr":1},{"ddd":0,"ind":6,"ty":4,"nm":"“图层 1”轮廓 2","parent":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[-2,0.5,0]},"a":{"a":0,"k":[48.5,49,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,-2.758],[0,0],[0,0],[1.229,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[-2.758,0],[0,0],[0,0],[-1.003,-0.711],[0,0],[0,0],[0,0]],"v":[[20.496,-17.098],[20.5,-17.094],[20.491,7.902],[9.502,7.902],[4.5,12.904],[4.5,14.227],[-2.891,8.989],[-6.303,7.902],[-20.5,7.898],[-20.49,-17.098]],"c":true}],"e":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,-2.758],[0,0],[0,0],[1.229,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[-2.758,0],[0,0],[0,0],[-1.003,-0.711],[0,0],[0,0],[0,0]],"v":[[20.496,-17.098],[20.5,-17.094],[20.491,7.902],[4.502,7.902],[-0.5,12.904],[-0.5,14.227],[-7.891,8.989],[-11.303,7.902],[-20.5,7.898],[-20.49,-17.098]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":4,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,-2.758],[0,0],[0,0],[1.229,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[-2.758,0],[0,0],[0,0],[-1.003,-0.711],[0,0],[0,0],[0,0]],"v":[[20.496,-17.098],[20.5,-17.094],[20.491,7.902],[4.502,7.902],[-0.5,12.904],[-0.5,14.227],[-7.891,8.989],[-11.303,7.902],[-20.5,7.898],[-20.49,-17.098]],"c":true}],"e":[{"i":[[0,0],[0,0],[0,0],[0,0],[2.188,-1.593],[0,0],[0,0],[1.229,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[-2.758,0],[0,0],[0,0],[-1.003,-0.711],[0,0],[0,0],[0,0]],"v":[[20.496,-17.098],[20.5,-17.094],[20.491,7.902],[4.502,7.902],[-5.312,12.927],[-7.938,14.203],[-7.891,8.989],[-11.303,7.902],[-20.5,7.898],[-20.49,-17.098]],"c":true}]},{"t":6}]},"nm":"路径 2","mn":"ADBE Vector Shape - Group"},{"ty":"mm","mm":1,"nm":"合并路径 1","mn":"ADBE Vector Filter - Merge"},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[49.5,54.098],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":10,"st":-22,"bm":0,"sr":1},{"ddd":0,"ind":7,"ty":4,"nm":"“图层 1”轮廓","parent":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[-2,0.5,0]},"a":{"a":0,"k":[48.5,49,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[{"i":[[2.211,0],[0,0],[0,-2.215],[0,0],[-2.212,0],[0,0],[-0.321,-0.228],[0,0],[-0.241,0],[0,0.744],[0,0],[-0.551,0],[0,0],[0,2.215],[0,0]],"o":[[0,0],[-2.214,0],[0,0],[0,2.211],[0,0],[0.394,0],[0,0],[0.3,0.207],[0.499,0],[0,0],[0,-0.551],[0,0],[2.214,0],[0,0],[0,-2.211]],"v":[[20.496,-21.098],[-20.49,-21.098],[-24.5,-17.089],[-24.5,7.898],[-20.495,11.902],[-6.303,11.902],[-5.204,12.251],[6.849,20.795],[7.67,21.098],[8.5,19.935],[8.5,12.904],[9.502,11.902],[20.491,11.902],[24.5,7.892],[24.5,-17.094]],"c":true}],"e":[{"i":[[2.211,0],[0,0],[0,-2.215],[0,0],[-2.212,0],[0,0],[-0.321,-0.228],[0,0],[-0.241,0],[0,0.744],[0,0],[-0.551,0],[0,0],[0,2.215],[0,0]],"o":[[0,0],[-2.214,0],[0,0],[0,2.211],[0,0],[0.394,0],[0,0],[0.3,0.207],[0.499,0],[0,0],[0,-0.551],[0,0],[2.214,0],[0,0],[0,-2.211]],"v":[[20.496,-21.098],[-20.49,-21.098],[-24.5,-17.089],[-24.5,7.898],[-20.495,11.902],[-11.303,11.902],[-10.204,12.251],[3.255,20.795],[4.076,21.098],[4.906,19.935],[3.5,12.904],[4.502,11.902],[20.491,11.902],[24.5,7.892],[24.5,-17.094]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":4,"s":[{"i":[[2.211,0],[0,0],[0,-2.215],[0,0],[-2.212,0],[0,0],[-0.321,-0.228],[0,0],[-0.241,0],[0,0.744],[0,0],[-0.551,0],[0,0],[0,2.215],[0,0]],"o":[[0,0],[-2.214,0],[0,0],[0,2.211],[0,0],[0.394,0],[0,0],[0.3,0.207],[0.499,0],[0,0],[0,-0.551],[0,0],[2.214,0],[0,0],[0,-2.211]],"v":[[20.496,-21.098],[-20.49,-21.098],[-24.5,-17.089],[-24.5,7.898],[-20.495,11.902],[-11.303,11.902],[-10.204,12.251],[3.255,20.795],[4.076,21.098],[4.906,19.935],[3.5,12.904],[4.502,11.902],[20.491,11.902],[24.5,7.892],[24.5,-17.094]],"c":true}],"e":[{"i":[[2.211,0],[0,0],[0,-2.215],[0,0],[-2.212,0],[0,0],[-0.321,-0.228],[0,0],[-0.241,0],[-0.664,0.422],[0,0],[-0.551,0],[0,0],[0,2.215],[0,0]],"o":[[0,0],[-2.214,0],[0,0],[0,2.211],[0,0],[0.394,0],[0,0],[-0.263,0.687],[0.604,0.196],[0,0],[0.563,-0.314],[0,0],[2.214,0],[0,0],[0,-2.211]],"v":[[20.496,-21.098],[-20.49,-21.098],[-24.5,-17.089],[-24.5,7.898],[-20.495,11.902],[-11.303,11.902],[-10.579,12.626],[-13.674,19.589],[-13.541,20.768],[-11.523,20.104],[2.938,12.841],[4.502,11.902],[20.491,11.902],[24.5,7.891],[24.5,-17.094]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":6,"s":[{"i":[[2.211,0],[0,0],[0,-2.215],[0,0],[-2.212,0],[0,0],[-0.321,-0.228],[0,0],[-0.241,0],[-0.664,0.422],[0,0],[-0.551,0],[0,0],[0,2.215],[0,0]],"o":[[0,0],[-2.214,0],[0,0],[0,2.211],[0,0],[0.394,0],[0,0],[-0.263,0.687],[0.604,0.196],[0,0],[0.563,-0.314],[0,0],[2.214,0],[0,0],[0,-2.211]],"v":[[20.496,-21.098],[-20.49,-21.098],[-24.5,-17.089],[-24.5,7.898],[-20.495,11.902],[-11.303,11.902],[-10.579,12.626],[-13.674,19.589],[-13.541,20.768],[-11.523,20.104],[2.938,12.841],[4.502,11.902],[20.491,11.902],[24.5,7.891],[24.5,-17.094]],"c":true}],"e":[{"i":[[2.211,0],[0,0],[0,-2.215],[0,0],[-2.212,0],[0,0],[-0.321,-0.228],[0,0],[-0.241,0],[-0.664,0.422],[0,0],[-0.551,0],[0,0],[0,2.215],[0,0]],"o":[[0,0],[-2.214,0],[0,0],[0,2.211],[0,0],[1.116,-0.027],[0,0],[-0.013,0.646],[0.604,0.196],[0,0],[0.563,-0.314],[0,0],[2.214,0],[0,0],[0,-2.211]],"v":[[20.496,-21.098],[-20.49,-21.098],[-24.5,-17.089],[-24.5,7.898],[-20.495,11.902],[-12.74,11.928],[-11.516,12.631],[-11.424,19.568],[-11.041,20.747],[-9.023,20.083],[2.938,12.841],[5.377,11.928],[20.491,11.902],[24.5,7.891],[24.5,-17.094]],"c":true}]},{"t":9}]},"nm":"路径 1","mn":"ADBE Vector Shape - Group"},{"ind":1,"ty":"sh","ix":2,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,-2.758],[0,0],[0,0],[1.229,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[-2.758,0],[0,0],[0,0],[-1.003,-0.711],[0,0],[0,0],[0,0]],"v":[[20.496,-17.098],[20.5,-17.094],[20.491,7.902],[9.502,7.902],[4.5,12.904],[4.5,14.227],[-2.891,8.989],[-6.303,7.902],[-20.5,7.898],[-20.49,-17.098]],"c":true}],"e":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,-2.758],[0,0],[0,0],[1.229,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[-2.758,0],[0,0],[0,0],[-1.003,-0.711],[0,0],[0,0],[0,0]],"v":[[20.496,-17.098],[20.5,-17.094],[20.491,7.902],[4.502,7.902],[-0.5,12.904],[-0.5,14.227],[-7.891,8.989],[-11.303,7.902],[-20.5,7.898],[-20.49,-17.098]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":4,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,-2.758],[0,0],[0,0],[1.229,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[-2.758,0],[0,0],[0,0],[-1.003,-0.711],[0,0],[0,0],[0,0]],"v":[[20.496,-17.098],[20.5,-17.094],[20.491,7.902],[4.502,7.902],[-0.5,12.904],[-0.5,14.227],[-7.891,8.989],[-11.303,7.902],[-20.5,7.898],[-20.49,-17.098]],"c":true}],"e":[{"i":[[0,0],[0,0],[0,0],[0,0],[2.188,-1.593],[0,0],[0,0],[1.229,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[-2.758,0],[0,0],[0,0],[-1.003,-0.711],[0,0],[0,0],[0,0]],"v":[[20.496,-17.098],[20.5,-17.094],[20.491,7.902],[4.502,7.902],[-5.312,12.927],[-7.938,14.203],[-7.891,8.989],[-11.303,7.902],[-20.5,7.898],[-20.49,-17.098]],"c":true}]},{"t":6}]},"nm":"路径 2","mn":"ADBE Vector Shape - Group"},{"ty":"mm","mm":1,"nm":"合并路径 1","mn":"ADBE Vector Filter - Merge"},{"ty":"fl","c":{"a":0,"k":[0.133,0.133,0.133,1]},"o":{"a":0,"k":100},"r":1,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[49.5,54.098],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 1","np":4,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":10,"st":-22,"bm":0,"sr":1}]}
================================================
FILE: Example/Classes/Other/LottieResources/tab_search_animate.json
================================================
{"v":"4.6.3","fr":24,"ip":0,"op":10,"w":66,"h":66,"nm":"地球(66x66)","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"空 12","ks":{"o":{"a":0,"k":0},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":3,"s":[0],"e":[-5]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":6,"s":[-5],"e":[0]},{"t":9}]},"p":{"a":0,"k":[32.375,31.5,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":-1,"s":[100,100,100],"e":[92,92,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":3,"s":[92,92,100],"e":[103,103,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":7,"s":[103,103,100],"e":[100,100,100]},{"t":9}]}},"ao":0,"ip":0,"op":10,"st":-1,"bm":0,"sr":1},{"ddd":0,"ind":2,"ty":4,"nm":"形状图层 5","parent":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.999,"y":1},"o":{"x":0.59,"y":0},"n":"0p999_1_0p59_0","t":2,"s":[-8.614,-7.245,0],"e":[6.347,-10.364,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.999,"y":1},"o":{"x":0.001,"y":0},"n":"0p999_1_0p001_0","t":7,"s":[6.347,-10.364,0],"e":[5.09,-10.1,0],"to":[0,0,0],"ti":[0,0,0]},{"t":9}]},"a":{"a":0,"k":[-11.598,-6.663,0]},"s":{"a":0,"k":[88.312,88.312,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[4.278,4.278]},"p":{"a":0,"k":[0,0]},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse"},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[-11.598,-6.663],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"椭圆 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":2,"op":10,"st":-22,"bm":0,"sr":1},{"ddd":0,"ind":3,"ty":4,"nm":"形状图层 4","parent":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.999,"y":1},"o":{"x":0.59,"y":0},"n":"0p999_1_0p59_0","t":2,"s":[-1.892,15.666,0],"e":[13.881,11.86,0],"to":[2.83333325386047,0.03125,0],"ti":[-3.80208325386047,1.21875,0]},{"i":{"x":0.999,"y":1},"o":{"x":0.001,"y":0},"n":"0p999_1_0p001_0","t":7,"s":[13.881,11.86,0],"e":[12.374,12.249,0],"to":[-0.04859279468656,0.04732451215386,0],"ti":[0,0,0]},{"t":9}]},"a":{"a":0,"k":[-14.376,-0.626,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[1.998,1.998]},"p":{"a":0,"k":[0,0]},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse"},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[-14.376,-0.626],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"椭圆 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":2,"op":10,"st":-22,"bm":0,"sr":1},{"ddd":0,"ind":4,"ty":4,"nm":"形状图层 3","parent":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.999,"y":1},"o":{"x":0.59,"y":0},"n":"0p999_1_0p59_0","t":2,"s":[-11.642,-0.709,0],"e":[3.756,-2.89,0],"to":[2.83333325386047,0.03125,0],"ti":[-3.67708325386047,0.59375,0]},{"i":{"x":0.999,"y":1},"o":{"x":0.001,"y":0},"n":"0p999_1_0p001_0","t":7,"s":[3.756,-2.89,0],"e":[2.249,-2.626,0],"to":[0.00749717839062,0.02958649583161,0],"ti":[0,0,0]},{"t":9}]},"a":{"a":0,"k":[-14.376,-0.626,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[1.998,1.998]},"p":{"a":0,"k":[0,0]},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse"},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[-14.376,-0.626],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"椭圆 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":2,"op":10,"st":-22,"bm":0,"sr":1},{"ddd":0,"ind":5,"ty":4,"nm":"“图层 4”轮廓","parent":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.999,"y":1},"o":{"x":0.59,"y":0},"n":"0p999_1_0p59_0","t":0,"s":[6.789,-8.273,0],"e":[17.539,-11.273,0],"to":[1.79166662693024,-0.5,0],"ti":[-1.79166662693024,0.5,0]},{"t":5}]},"a":{"a":0,"k":[57.289,40.227,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-1.002],[1.002,0],[0,1.002],[-1.002,0]],"o":[[0,1.002],[-1.002,0],[0,-1.002],[1.002,0]],"v":[[1.814,0],[0,1.814],[-1.814,0],[0,-1.814]],"c":true}},"nm":"路径 1","mn":"ADBE Vector Shape - Group"},{"ty":"st","c":{"a":0,"k":[0.133,0.133,0.133,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":1,"ml":10,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke"},{"ty":"tr","p":{"a":0,"k":[57.289,40.227],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":4,"st":-4,"bm":0,"sr":1},{"ddd":0,"ind":6,"ty":4,"nm":"“图层 3”轮廓","parent":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.999,"y":1},"o":{"x":0.59,"y":0},"n":"0p999_1_0p59_0","t":0,"s":[2.078,-11.188,0],"e":[12.828,-14.188,0],"to":[1.79166662693024,-0.5,0],"ti":[-1.79166662693024,0.5,0]},{"t":5}]},"a":{"a":0,"k":[52.578,37.312,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-0.652],[0.653,0],[0,0.652],[-0.652,0]],"o":[[0,0.652],[-0.652,0],[0,-0.652],[0.653,0]],"v":[[1.182,0],[-0.001,1.182],[-1.182,0],[-0.001,-1.182]],"c":true}},"nm":"路径 1","mn":"ADBE Vector Shape - Group"},{"ty":"st","c":{"a":0,"k":[0.133,0.133,0.133,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":1,"lj":1,"ml":10,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke"},{"ty":"tr","p":{"a":0,"k":[52.578,37.312],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":4,"st":-4,"bm":0,"sr":1},{"ddd":0,"ind":7,"ty":4,"nm":"“图层 2”轮廓","parent":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.999,"y":1},"o":{"x":0.59,"y":0},"n":"0p999_1_0p59_0","t":0,"s":[8.992,13.133,0],"e":[19.742,10.133,0],"to":[1.79166662693024,-0.5,0],"ti":[-1.79166662693024,0.5,0]},{"t":5}]},"a":{"a":0,"k":[59.492,61.633,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-0.764],[0.764,0],[0,0.764],[-0.763,0]],"o":[[0,0.764],[-0.763,0],[0,-0.764],[0.764,0]],"v":[[1.383,0],[0,1.383],[-1.383,0],[0,-1.383]],"c":true}},"nm":"路径 1","mn":"ADBE Vector Shape - Group"},{"ty":"fl","c":{"a":0,"k":[0.133,0.133,0.133,1]},"o":{"a":0,"k":100},"r":1,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[59.492,61.633],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":4,"st":-4,"bm":0,"sr":1},{"ddd":0,"ind":8,"ty":4,"nm":"“图层 12”轮廓 2","parent":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[0.86,1.5,0]},"a":{"a":0,"k":[51.36,50,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-12.151],[0,0],[-1.188,-0.039],[0,0.992],[0,0],[-9.941,0],[-2.039,-7.705],[-1.149,0.688],[0.205,0.564],[9.757,0]],"o":[[0,0.454],[0.076,0.742],[1.188,0.04],[0,0],[0,-9.941],[8.345,0],[0.324,0.797],[1.16,-0.694],[-2.881,-8.795],[-12.151,0]],"v":[[-22.499,0],[-22.458,1.008],[-20.499,2.601],[-18.499,1.008],[-18.499,0],[-0.499,-18],[16.904,-4.617],[19.595,-3.969],[20.413,-6.853],[-0.499,-22]],"c":true}},"nm":"路径 1","mn":"ADBE Vector Shape - Group"},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0.34,-0.373],[0,0],[0,0],[-0.5,-0.308],[-0.792,-0.413],[-2.472,-0.314],[-7.605,1.617],[-4.728,2.867],[-0.892,1.121],[0,0],[0.496,0.292],[0.95,0.337],[0,0.946],[-1.16,0],[-0.187,-0.055],[0,0],[-0.411,-1.933],[16.522,-3.513],[1.225,5.763],[-2.031,1.988],[-0.007,-0.007],[-0.529,0],[0,-1.16]],"o":[[0.005,0.005],[-0.682,0.667],[-0.323,0.484],[0,0],[1.271,0.662],[5.485,0.695],[7.605,-1.617],[2.131,-1.292],[0.556,-0.7],[0.299,-0.497],[0,0],[-0.86,-0.262],[0,-1.16],[0.205,0],[0,0],[2.957,0.994],[1.225,5.763],[-16.522,3.513],[-0.387,-1.82],[0,0],[0.369,-0.323],[1.16,0],[0,0.545]],"v":[[-24.456,3.38],[-24.449,3.388],[-25.304,4.423],[-25.029,5.901],[-24.853,5.995],[-19.154,7.506],[1.242,6.123],[20.436,-0.911],[25.028,-4.609],[25.15,-4.767],[24.795,-6.211],[23.347,-6.917],[21.86,-8.926],[23.96,-11.026],[24.551,-10.941],[24.558,-10.962],[29.818,-6.545],[2.119,10.251],[-30.015,6.176],[-27.4,0.373],[-27.39,0.383],[-26.008,-0.135],[-23.908,1.965]],"c":true}},"nm":"路径 2","mn":"ADBE Vector Shape - Group"},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0,0],[-1.605,-0.064],[-6.923,0],[-0.71,9.291],[-1.234,0.731],[0,-0.239],[12.15,0],[3.188,8.221]],"o":[[1.439,0.209],[3.011,5.73],[9.473,0],[1.455,-0.67],[0.007,0.237],[0,12.15],[-9.347,0],[0,0]],"v":[[-21.056,7.994],[-16.48,8.405],[-0.536,18.043],[17.411,1.434],[21.453,-0.67],[21.464,0.043],[-0.536,22.043],[-21.056,7.994]],"c":true}},"nm":"路径 3","mn":"ADBE Vector Shape - Group"},{"ty":"mm","mm":1,"nm":"合并路径 1","mn":"ADBE Vector Filter - Merge"},{"ty":"fl","c":{"a":0,"k":[0.1333333,0.1333333,0.1333333,1]},"o":{"a":0,"k":100},"r":1,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[51.499,50],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 1","np":5,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":10,"st":-4,"bm":0,"sr":1},{"ddd":0,"ind":10,"ty":4,"nm":"形状图层 1","parent":1,"td":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[0,0,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.999,"y":1},"o":{"x":0.59,"y":0},"n":"0p999_1_0p59_0","t":0,"s":[{"i":[[-0.875,-14.375],[-6.812,-2.25],[3.387,6.235],[0.184,2.986],[0,0.419],[-11.046,0]],"o":[[0.875,14.375],[-7.594,0],[-1.352,-2.49],[-0.025,-0.413],[0,-11.046],[-5,1.75]],"v":[[-17.014,0.88],[-2.077,20.442],[-19.663,9.975],[-22.039,1.69],[-22.077,0.442],[-2.077,-19.558]],"c":true}],"e":[{"i":[[-0.275,-15.238],[11.036,0],[3.718,6.848],[0.202,3.279],[0,0.46],[-12.131,0]],"o":[[0.24,13.315],[-8.34,0],[-1.485,-2.735],[-0.027,-0.454],[0,-12.131],[10.159,0]],"v":[[21.71,0.052],[-0.254,22.016],[-19.568,10.521],[-22.177,1.422],[-22.219,0.052],[-0.254,-21.913]],"c":true}]},{"t":8}]},"nm":"路径 1","mn":"ADBE Vector Shape - Group"},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[0.494,1.198],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"椭圆 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":10,"st":-4,"bm":0,"sr":1},{"ddd":0,"ind":11,"ty":4,"nm":"“图层 5”轮廓","parent":1,"tt":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[0,0,0]},"a":{"a":0,"k":[50.5,48.5,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.025,0.646],[-12.143,0.424],[-3.186,-8.688],[1.136,-0.734],[14.314,-2.001],[1.642,0.454],[0.229,0.358]],"o":[[-0.424,-12.143],[9.751,-0.341],[0.225,0.557],[-0.552,0.358],[-10.341,1.242],[-1.641,-0.454],[-0.282,-0.437]],"v":[[-21.462,9.572],[-0.243,-13.182],[21.184,1.225],[20.751,4.729],[-2.356,12.282],[-18.656,12.839],[-21.046,11.275]],"c":true}},"nm":"路径 1","mn":"ADBE Vector Shape - Group"},{"ty":"fl","c":{"a":0,"k":[0.133,0.133,0.133,1]},"o":{"a":0,"k":100},"r":1,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[50.468,41.209],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":10,"st":-4,"bm":0,"sr":1},{"ddd":0,"ind":12,"ty":4,"nm":"形状图层 2","parent":1,"td":1,"ks":{"o":{"a":0,"k":100},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":3,"s":[0],"e":[-3]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":6,"s":[-3],"e":[0]},{"t":9}]},"p":{"a":0,"k":[0,0,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":0,"s":[100,100,100],"e":[96,96,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":3,"s":[96,96,100],"e":[103,103,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":8,"s":[103,103,100],"e":[100,100,100]},{"t":9}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.999,"y":1},"o":{"x":0.59,"y":0},"n":"0p999_1_0p59_0","t":0,"s":[{"i":[[-0.875,-14.375],[-6.812,-2.25],[3.387,6.235],[0.184,2.986],[0,0.419],[-11.046,0]],"o":[[0.875,14.375],[-7.594,0],[-1.352,-2.49],[-0.025,-0.413],[0,-11.046],[-5,1.75]],"v":[[-14.931,0.489],[0.006,20.052],[-17.58,9.585],[-19.956,1.3],[-19.994,0.052],[0.006,-19.948]],"c":true}],"e":[{"i":[[-0.25,-13.875],[10.049,0],[3.387,6.235],[0.184,2.986],[0,0.419],[-11.046,0]],"o":[[0.218,12.124],[-7.594,0],[-1.352,-2.49],[-0.025,-0.413],[0,-11.046],[9.25,0]],"v":[[19.756,0.052],[-0.244,20.052],[-17.83,9.585],[-20.206,1.3],[-20.244,0.052],[-0.244,-19.948]],"c":true}]},{"t":8}]},"nm":"路径 1","mn":"ADBE Vector Shape - Group"},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[0.494,1.198],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"椭圆 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":10,"st":-4,"bm":0,"sr":1},{"ddd":0,"ind":13,"ty":4,"nm":"“图层 6”轮廓","parent":1,"tt":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[0,0,0]},"a":{"a":0,"k":[50.5,48.5,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[19.341,-1.949],[-6.923,0],[-0.71,9.291]],"o":[[3.011,5.73],[9.473,0],[-7.758,2.355]],"v":[[-16.945,-1.334],[-1.001,8.305],[16.945,-8.305]],"c":true}},"nm":"路径 1","mn":"ADBE Vector Shape - Group"},{"ty":"fl","c":{"a":0,"k":[0.133,0.133,0.133,1]},"o":{"a":0,"k":100},"r":1,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[52.479,61.7],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":10,"st":-4,"bm":0,"sr":1}]}
================================================
FILE: Example/Classes/View/CYLPlusButtonSubclass.h
================================================
//
// CYLPlusButtonSubclass.h
// CYLTabBarControllerDemo
//
// v1.21.x Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 15/10/24.
// Copyright (c) 2018年 https://github.com/ChenYilong . All rights reserved.
//
#import "CYLPlusButton.h"
@interface CYLPlusButtonSubclass : CYLPlusButton
@end
================================================
FILE: Example/Classes/View/CYLPlusButtonSubclass.m
================================================
//
// CYLPlusButtonSubclass.m
// CYLTabBarControllerDemo
//
// v1.21.x Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 15/10/24.
// Copyright (c) 2018年 https://github.com/ChenYilong . All rights reserved.
//
#import "CYLPlusButtonSubclass.h"
#import "CYLMineViewController.h"
@interface CYLPlusButtonSubclass () {
CGFloat _buttonImageHeight;
}
@end
@implementation CYLPlusButtonSubclass
#pragma mark -
#pragma mark - Life Cycle
+ (void)load {
//请在 `-[AppDelegate application:didFinishLaunchingWithOptions:]` 中进行注册,否则iOS10系统下存在Crash风险。
//[super registerPlusButton];
}
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
self.titleLabel.textAlignment = NSTextAlignmentCenter;
self.adjustsImageWhenHighlighted = NO;
}
return self;
}
//上下结构的 button
//- (void)layoutSubviews {
// [super layoutSubviews];
//
// // 控件大小,间距大小
// // 注意:一定要根据项目中的图片去调整下面的0.7和0.9,Demo之所以这么设置,因为demo中的 plusButton 的 icon 不是正方形。
// CGFloat const imageViewEdgeWidth = self.bounds.size.width * 0.7;
// CGFloat const imageViewEdgeHeight = imageViewEdgeWidth * 0.9;
//
// CGFloat const centerOfView = self.bounds.size.width * 0.5;
// CGFloat const labelLineHeight = self.titleLabel.font.lineHeight;
// CGFloat const verticalMargin = (self.bounds.size.height - labelLineHeight - imageViewEdgeHeight) * 0.5;
//
// // imageView 和 titleLabel 中心的 Y 值
// CGFloat const centerOfImageView = verticalMargin + imageViewEdgeHeight * 0.5;
// CGFloat const centerOfTitleLabel = imageViewEdgeHeight + verticalMargin * 2 + labelLineHeight * 0.5 + 5;
//
// //imageView position 位置
// self.imageView.bounds = CGRectMake(0, 0, imageViewEdgeWidth, imageViewEdgeHeight);
// self.imageView.center = CGPointMake(centerOfView, centerOfImageView);
//
// //title position 位置
// self.titleLabel.bounds = CGRectMake(0, 0, self.bounds.size.width, labelLineHeight);
// self.titleLabel.center = CGPointMake(centerOfView, centerOfTitleLabel);
//}
#pragma mark -
#pragma mark - CYLPlusButtonSubclassing Methods
/*
*
Create a custom UIButton with title and add it to the center of our tab bar
*
*/
+ (id)plusButton {
CYLPlusButtonSubclass *button = [[CYLPlusButtonSubclass alloc] init];
UIImage *normalButtonImage = [UIImage imageNamed:@"icon_tabbar_plus"];
UIImage *hlightButtonImage = [UIImage imageNamed:@"icon_tabbar_plus"];
[button setImage:normalButtonImage forState:UIControlStateNormal];
[button setImage:[hlightButtonImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateHighlighted];
[button setImage:[hlightButtonImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateSelected];
[button setTintColor: [UIColor colorWithRed:0/255.0f green:255/255.0f blue:189/255.0f alpha:1]];
// UIImage *normalButtonBackImage = [UIImage imageNamed:@"videoback"];
// [button setBackgroundImage:normalButtonBackImage forState:UIControlStateNormal];
// [button setBackgroundImage:normalButtonBackImage forState:UIControlStateSelected];
button.imageEdgeInsets = UIEdgeInsetsMake(5, 0, -5, 0);
button.titleLabel.font = [UIFont systemFontOfSize:9.5];
[button sizeToFit]; // or set frame in this way `button.frame = CGRectMake(0.0, 0.0, 250, 100);`
button.frame = CGRectMake(0.0, 0.0, 55, 59);
// if you use `+plusChildViewController` , do not addTarget to plusButton.
[button addTarget:button action:@selector(clickPublish) forControlEvents:UIControlEventTouchUpInside];
return button;
}
/*
*
Create a custom UIButton without title and add it to the center of our tab bar
*
*/
//+ (id)plusButton
//{
//
// UIImage *buttonImage = [UIImage imageNamed:@"hood.png"];
// UIImage *highlightImage = [UIImage imageNamed:@"hood-selected.png"];
//
// CYLPlusButtonSubclass* button = [CYLPlusButtonSubclass buttonWithType:UIButtonTypeCustom];
//
// button.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleTopMargin;
// button.frame = CGRectMake(0.0, 0.0, buttonImage.size.width, buttonImage.size.height);
// [button setBackgroundImage:buttonImage forState:UIControlStateNormal];
// [button setBackgroundImage:highlightImage forState:UIControlStateHighlighted];
// [button addTarget:button action:@selector(clickPublish) forControlEvents:UIControlEventTouchUpInside];
//
// return button;
//}
#pragma mark -
#pragma mark - Event Response
- (void)clickPublish {
CYLTabBarController *tabBarController = [self cyl_tabBarController];
UIViewController *viewController = tabBarController.selectedViewController;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:nil
delegate:nil
cancelButtonTitle:@"取消"
destructiveButtonTitle:nil
otherButtonTitles:@"拍照", @"从相册选取", @"淘宝一键转卖", nil];
[actionSheet showInView:viewController.view];
#pragma clang diagnostic pop
}
#pragma mark - UIActionSheetDelegate
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex {
NSLog(@"buttonIndex = %@", @(buttonIndex));
}
#pragma clang diagnostic pop
#pragma mark - CYLPlusButtonSubclassing
+ (UIViewController *)plusChildViewController {
UIViewController *plusChildViewController = [[UIViewController alloc] init];
plusChildViewController.view.backgroundColor = [UIColor redColor];
plusChildViewController.navigationItem.title = @"PlusChildViewController";
UIViewController *plusChildNavigationController = [[UINavigationController alloc]
initWithRootViewController:plusChildViewController];
return plusChildNavigationController;
}
+ (NSUInteger)indexOfPlusButtonInTabBar {
return 2;
}
+ (BOOL)shouldSelectPlusChildViewController {
BOOL isSelected = CYLExternPlusButton.selected;
if (isSelected) {
// HDLLogDebug("🔴类名与方法名:%@(在第%@行),描述:%@", @(__PRETTY_FUNCTION__), @(__LINE__), @"PlusButton is selected");
} else {
// HDLLogDebug("🔴类名与方法名:%@(在第%@行),描述:%@", @(__PRETTY_FUNCTION__), @(__LINE__), @"PlusButton is not selected");
}
return YES;
}
+ (CGFloat)multiplierOfTabBarHeight:(CGFloat)tabBarHeight {
return 0.3;
}
+ (CGFloat)constantOfPlusButtonCenterYOffsetForTabBarHeight:(CGFloat)tabBarHeight {
return (CYL_IS_IPHONE_X ? - 6 : 4);
}
//+ (NSString *)tabBarContext {
// return NSStringFromClass([self class]);
//}
@end
================================================
FILE: Example/Images.xcassets/AppIcon.appiconset/Contents.json
================================================
{
"images" : [
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "3x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-Small.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-Small@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-Small@3x.png",
"scale" : "3x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-40@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-40@3x.png",
"scale" : "3x"
},
{
"size" : "57x57",
"idiom" : "iphone",
"filename" : "Icon.png",
"scale" : "1x"
},
{
"size" : "57x57",
"idiom" : "iphone",
"filename" : "Icon@2x.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-60@2x.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-60@3x.png",
"scale" : "3x"
},
{
"idiom" : "ipad",
"size" : "20x20",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "20x20",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-Small.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-Small@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-40.png",
"scale" : "1x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-40@2x.png",
"scale" : "2x"
},
{
"size" : "50x50",
"idiom" : "ipad",
"filename" : "Icon-Small-50.png",
"scale" : "1x"
},
{
"size" : "50x50",
"idiom" : "ipad",
"filename" : "Icon-Small-50@2x.png",
"scale" : "2x"
},
{
"size" : "72x72",
"idiom" : "ipad",
"filename" : "Icon-72.png",
"scale" : "1x"
},
{
"size" : "72x72",
"idiom" : "ipad",
"filename" : "Icon-72@2x.png",
"scale" : "2x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-76.png",
"scale" : "1x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-76@2x.png",
"scale" : "2x"
},
{
"size" : "83.5x83.5",
"idiom" : "ipad",
"filename" : "Icon-83.5@2x.png",
"scale" : "2x"
},
{
"idiom" : "ios-marketing",
"size" : "1024x1024",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Example/Images.xcassets/Contents.json
================================================
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: Example/Images.xcassets/LaunchImage.launchimage/Contents.json
================================================
{
"images" : [
{
"filename" : "default-portrait-1792h@3x.png",
"subtype" : "1792h",
"minimum-system-version" : "12.0",
"extent" : "full-screen",
"orientation" : "portrait",
"scale" : "2x",
"idiom" : "iphone"
},
{
"orientation" : "landscape",
"minimum-system-version" : "12.0",
"subtype" : "1792h",
"filename" : "default-landscape-1792h@3x.png",
"idiom" : "iphone",
"extent" : "full-screen",
"scale" : "2x"
},
{
"scale" : "3x",
"idiom" : "iphone",
"subtype" : "2688h",
"extent" : "full-screen",
"filename" : "default-portrait-2688h@3x.png",
"minimum-system-version" : "12.0",
"orientation" : "portrait"
},
{
"extent" : "full-screen",
"orientation" : "landscape",
"filename" : "default-landscape-2688h@3x.png",
"scale" : "3x",
"subtype" : "2688h",
"idiom" : "iphone",
"minimum-system-version" : "12.0"
},
{
"orientation" : "portrait",
"idiom" : "iphone",
"extent" : "full-screen",
"filename" : "default-portrait-2436h@3x.png",
"minimum-system-version" : "11.0",
"subtype" : "2436h",
"scale" : "3x"
},
{
"scale" : "3x",
"subtype" : "2436h",
"orientation" : "landscape",
"extent" : "full-screen",
"idiom" : "iphone",
"filename" : "default-landscape-2436h@3x.png",
"minimum-system-version" : "11.0"
},
{
"extent" : "full-screen",
"scale" : "1x",
"filename" : "default.png",
"idiom" : "iphone",
"orientation" : "portrait"
},
{
"orientation" : "portrait",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"filename" : "default@2x.png",
"idiom" : "iphone",
"scale" : "2x"
},
{
"subtype" : "retina4",
"idiom" : "iphone",
"scale" : "2x",
"orientation" : "portrait",
"extent" : "full-screen",
"filename" : "default-568h@2x.png"
},
{
"orientation" : "portrait",
"scale" : "2x",
"subtype" : "retina4",
"idiom" : "iphone",
"minimum-system-version" : "7.0",
"filename" : "default-568h@2x.png",
"extent" : "full-screen"
},
{
"idiom" : "iphone",
"filename" : "default@2x.png",
"scale" : "2x",
"extent" : "full-screen",
"orientation" : "portrait"
},
{
"extent" : "to-status-bar",
"idiom" : "ipad",
"scale" : "1x",
"orientation" : "portrait",
"filename" : "default~ipad.png"
},
{
"filename" : "default~ipad@2x.png",
"orientation" : "portrait",
"extent" : "to-status-bar",
"scale" : "2x",
"idiom" : "ipad"
},
{
"idiom" : "ipad",
"orientation" : "landscape",
"extent" : "to-status-bar",
"filename" : "default~ipad~landscape.png",
"scale" : "1x"
},
{
"scale" : "2x",
"extent" : "to-status-bar",
"orientation" : "landscape",
"filename" : "default~ipad~landscape@2x.png",
"idiom" : "ipad"
},
{
"orientation" : "portrait",
"filename" : "default~ipad~nostatusbar.png",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "1x",
"idiom" : "ipad"
},
{
"filename" : "default~ipad~nostatusbar.png",
"idiom" : "ipad",
"extent" : "full-screen",
"scale" : "1x",
"orientation" : "portrait"
},
{
"minimum-system-version" : "7.0",
"filename" : "default~ipad~nostatusbar@2x.png",
"scale" : "2x",
"extent" : "full-screen",
"orientation" : "portrait",
"idiom" : "ipad"
},
{
"idiom" : "ipad",
"extent" : "full-screen",
"scale" : "2x",
"orientation" : "portrait",
"filename" : "default~ipad~nostatusbar@2x.png"
},
{
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"filename" : "default~ipad~landscape~nostatusbar.png",
"scale" : "1x",
"orientation" : "landscape",
"idiom" : "ipad"
},
{
"idiom" : "ipad",
"orientation" : "landscape",
"extent" : "full-screen",
"filename" : "default~ipad~landscape~nostatusbar.png",
"scale" : "1x"
},
{
"extent" : "full-screen",
"orientation" : "landscape",
"idiom" : "ipad",
"filename" : "default~ipad~landscape~nostatusbar@2x.png",
"minimum-system-version" : "7.0",
"scale" : "2x"
},
{
"filename" : "default~ipad~landscape~nostatusbar@2x.png",
"idiom" : "ipad",
"scale" : "2x",
"extent" : "full-screen",
"orientation" : "landscape"
},
{
"subtype" : "736h",
"filename" : "default-portrait-736h@3x.png",
"orientation" : "portrait",
"idiom" : "iphone",
"scale" : "3x",
"minimum-system-version" : "8.0",
"extent" : "full-screen"
},
{
"extent" : "full-screen",
"scale" : "3x",
"idiom" : "iphone",
"subtype" : "736h",
"minimum-system-version" : "8.0",
"orientation" : "landscape",
"filename" : "default-landscape-736h@3x.png"
},
{
"orientation" : "portrait",
"scale" : "2x",
"minimum-system-version" : "8.0",
"extent" : "full-screen",
"filename" : "default-667h@2x.png",
"subtype" : "667h",
"idiom" : "iphone"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: Example/Images.xcassets/NavBar/Contents.json
================================================
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Example/Images.xcassets/NavBar/home_bar_scan.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "home_bar_scan@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x",
"filename" : "home_bar_scan@3x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Example/Images.xcassets/NavBar/home_title_slogan.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "home_title_slogan@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x",
"filename" : "home_title_slogan@3x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Example/Images.xcassets/NavBar/icon_search.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "icon_search@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x",
"filename" : "icon_search@3x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Example/Images.xcassets/TabBarIcon/Contents.json
================================================
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Example/Images.xcassets/TabBarIcon/TabBar_Bg_Shadow.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "TabBar_Bg_Shadow@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Example/Images.xcassets/TabBarIcon/account/Contents.json
================================================
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Example/Images.xcassets/TabBarIcon/account/account_highlight.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"filename" : "account_highlight.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "account_highlight@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "account_highlight@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Example/Images.xcassets/TabBarIcon/account/account_normal.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"filename" : "account_normal.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "account_normal@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "account_normal@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Example/Images.xcassets/TabBarIcon/fishpond/Contents.json
================================================
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Example/Images.xcassets/TabBarIcon/fishpond/fishpond_highlight.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"filename" : "fishpond_highlight.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "fishpond_highlight@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "fishpond_highlight@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Example/Images.xcassets/TabBarIcon/fishpond/fishpond_normal.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"filename" : "fishpond_normal.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "fishpond_normal@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "fishpond_normal@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Example/Images.xcassets/TabBarIcon/home/Contents.json
================================================
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Example/Images.xcassets/TabBarIcon/home/home_highlight.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"filename" : "home_highlight.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "home_highlight@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "home_highlight@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Example/Images.xcassets/TabBarIcon/home/home_normal.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"filename" : "home_normal.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "home_normal@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "home_normal@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Example/Images.xcassets/TabBarIcon/home_select_cover.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "home_select_cover@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "home_select_cover@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Example/Images.xcassets/TabBarIcon/lottie_placeholder/Contents.json
================================================
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Example/Images.xcassets/TabBarIcon/lottie_placeholder/gray_tabbar_home_animation_lottie_placeholder.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "gray_tabbar_home_animation_lottie_placeholder@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Example/Images.xcassets/TabBarIcon/lottie_placeholder/gray_tabbar_me_animation_lottie_placeholder.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "gray_tabbar_me_animation_lottie_placeholder@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Example/Images.xcassets/TabBarIcon/lottie_placeholder/gray_tabbar_message_animation_lottie_placeholder.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "gray_tabbar_message_animation_lottie_placeholder@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Example/Images.xcassets/TabBarIcon/message/Contents.json
================================================
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Example/Images.xcassets/TabBarIcon/message/message_highlight.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"filename" : "message_highlight.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "message_highlight@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "message_highlight@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Example/Images.xcassets/TabBarIcon/message/message_normal.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"filename" : "message_normal.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "message_normal@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "message_normal@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Example/Images.xcassets/TabBarIcon/post/Contents.json
================================================
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Example/Images.xcassets/TabBarIcon/post/post_highlight.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "post_highlight@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "post_highlight@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Example/Images.xcassets/TabBarIcon/post/post_normal.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "post_normal@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "post_normal@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Example/Images.xcassets/TabBarIcon/tabbarBg.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "tabbarBg@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "tabbarBg@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Example/Images.xcassets/TabBarIcon/tabbar_background.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "tabbar_background@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Example/Images.xcassets/TabBarIcon/tapbar_top_line.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "tapbar_top_line@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
},
"properties" : {
"template-rendering-intent" : "original"
}
}
================================================
FILE: Example/Images.xcassets/TabBarIcon/videoback.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "videoback@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "videoback@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Example/Images.xcassets/home-float-icon.imageset/Contents.json
================================================
{
"images" : [
{
"filename" : "home-float-icon.jpg",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "home-float-icon@2x.jpg",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "home-float-icon@3x.jpg",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: Example/Images.xcassets/icon_tabbar_plus.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "icon_tabbar_plus@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "icon_tabbar_plus@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: Example/Images.xcassets/navigationbar_background_tall.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "navigationbar_background_tall@2x.png"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Example/Info.plist
================================================