├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── TXScrollLabelView.podspec
├── TXScrollLabelView
├── TXScrollLabelView.h
├── TXScrollLabelView.m
├── UIView+TXFrame.h
└── UIView+TXFrame.m
└── TXScrollLabelViewDemo
├── TXScrollLabelViewDemo.xcodeproj
├── project.pbxproj
├── project.xcworkspace
│ └── contents.xcworkspacedata
└── xcshareddata
│ └── xcschemes
│ └── TXScrollLabelViewDemo.xcscheme
├── TXScrollLabelViewDemo
├── AppDelegate.h
├── AppDelegate.m
├── Assets.xcassets
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── Base.lproj
│ └── LaunchScreen.storyboard
├── Info.plist
├── Main.storyboard
├── NSString+AttributedString.h
├── NSString+AttributedString.m
├── ViewController.h
├── ViewController.m
└── main.m
├── TXScrollLabelViewDemoTests
├── Info.plist
└── TXScrollLabelViewDemoTests.m
└── TXScrollLabelViewDemoUITests
├── Info.plist
└── TXScrollLabelViewDemoUITests.m
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## Build generated
6 | build/
7 | DerivedData/
8 |
9 | ## Various settings
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata/
19 |
20 | ## Other
21 | *.moved-aside
22 | *.xcuserstate
23 |
24 | ## Obj-C/Swift specific
25 | *.hmap
26 | *.ipa
27 | *.dSYM.zip
28 | *.dSYM
29 |
30 | # CocoaPods
31 | #
32 | # We recommend against adding the Pods directory to your .gitignore. However
33 | # you should judge for yourself, the pros and cons are mentioned at:
34 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
35 | #
36 | # Pods/
37 |
38 | # Carthage
39 | #
40 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
41 | # Carthage/Checkouts
42 |
43 | Carthage/Build
44 |
45 | # fastlane
46 | #
47 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
48 | # screenshots whenever they are needed.
49 | # For more information about the recommended setup visit:
50 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md
51 |
52 | fastlane/report.xml
53 | fastlane/screenshots
54 |
55 | #Code Injection
56 | #
57 | # After new code Injection tools there's a generated folder /iOSInjectionProject
58 | # https://github.com/johnno1962/injectionforxcode
59 |
60 | iOSInjectionProject/
61 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: objective-c
2 | os: osx
3 | osx_image: xcode8.3
4 |
5 | env:
6 | global:
7 | - XCODE_PROJ=TXScrollLabelViewDemo/TXScrollLabelViewDemo.xcodeproj
8 | matrix:
9 | - SCHEME="TXScrollLabelViewDemo"
10 |
11 | before_install:
12 | - gem install xcpretty --no-rdoc --no-ri --no-document --quiet
13 |
14 | script:
15 | - set -o pipefail
16 | - xcodebuild -project "$XCODE_PROJ" -scheme "$SCHEME" -configuration Debug clean build CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO | xcpretty -c
17 | - xcodebuild -project "$XCODE_PROJ" -scheme "$SCHEME" -configuration Release clean build CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO | xcpretty -c
18 |
19 | after_success:
20 | - bash <(curl -s https://codecov.io/bash)
21 | - sleep 10
22 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 tingxins
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | `TXScrollLabelView` is an iOS lightweight library that can displays adverts or boardcast e.g. with an custom view.
20 |
21 | > [中文介绍](http://www.jianshu.com/p/8f1f1b1ee814)
22 |
23 | 
24 |
25 | ## Support what kinds of scrollType
26 |
27 | - **TXScrollLabelViewTypeLeftRight** : scrolling from right to left, and cycle all contents(`scrollTitle`) in a single line.
28 |
29 |
30 | - **TXScrollLabelViewTypeUpDown**: scrolling from bottom to top, and cycle all contents.
31 |
32 |
33 | - **TXScrollLabelViewTypeFlipRepeat**: scrolling from bottom to top, and cycle the first line of your contents.
34 |
35 |
36 | - **TXScrollLabelViewTypeFlipNoRepeat**: scrolling from bottom to top, and cycle all contents with a line once times.
37 |
38 | And `scrollVelocity` property now supports all above enum of `TXScrollLabelViewType`, just enjoy it!
39 |
40 | ## Installation
41 |
42 | There are three ways to use TXScrollLabelView in your project:
43 |
44 | * Using CocoaPods
45 |
46 | * Manual
47 |
48 | * Using Carthage
49 |
50 | ### CocoaPods
51 |
52 | CocoaPods is a dependency manager for Objective-C, which automates and simplifies the process of using 3rd-party libraries in your projects.
53 |
54 | **Podfile**
55 |
56 | platform :ios, '7.0'
57 | pod 'TXScrollLabelView'
58 |
59 | ### Manual
60 |
61 | Download repo's zip, and just drag **ALL** files in the TXScrollLabelView folder to your projects. Import header file when you are using:
62 |
63 | #import "TXScrollLabelView.h"
64 |
65 | ### Carthage
66 |
67 | [Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks.
68 |
69 | You can install Carthage with [Homebrew](http://brew.sh/) using the following command:
70 |
71 | $ brew update
72 | $ brew install carthage
73 |
74 | To integrate **TXScrollLableView** into your Xcode project using Carthage, specify it in your Cartfile:
75 |
76 | github "tingxins/TXScrollLableView"
77 |
78 | Run carthage to build the frameworks and drag the framework into your Xcode project.
79 |
80 | ## Usage
81 |
82 | Now, TXScrollLabelView supports both **array & string**. just enjoy it. 👀
83 |
84 | ### Example
85 |
86 | **Objective-C :**
87 |
88 | /** Step1: 滚动文字 */
89 | NSString *scrollTitle = @"xxxxxx";
90 |
91 | /** Step2: 创建 ScrollLabelView */
92 | TXScrollLabelView *scrollLabelView = [TXScrollLabelView scrollWithTitle:scrollTitle type:TXScrollLabelViewTypeFlipNoRepeat velocity:velocity options:UIViewAnimationOptionCurveEaseInOut];
93 |
94 | /** Step3: 设置代理进行回调(Optional) */
95 | scrollLabelView.scrollLabelViewDelegate = self;
96 |
97 | /** Step4: 布局(Required) */
98 | scrollLabelView.frame = CGRectMake(50, 100, 300, 30);
99 | [self.view addSubview:scrollLabelView];
100 |
101 | /** Step5: 开始滚动(Start scrolling!) */
102 | [scrollLabelView beginScrolling];
103 |
104 |
105 | You can running **TXScrollLabelViewDemo** for more details.
106 |
107 | **Swift :** Producting.([**Swift-version**](https://github.com/tingxins/ScrollLabelView))
108 |
109 | ### Delegate Method
110 |
111 | Tap Gesture callback.
112 |
113 | ```
114 |
115 | - (void)scrollLabelView:(TXScrollLabelView *)scrollLabelView didClickWithText:(NSString *)text atIndex:(NSInteger)index;
116 |
117 | ```
118 |
119 | ## Communication
120 |
121 | Absolutely,you can contribute to this project all the time if you want to.
122 |
123 | - If you **need help or ask general question**, just [**@tingxins**](http://weibo.com/tingxins) in `Weibo` or `Twitter`, ofcourse, you can access to my [**blog**](https://tingxins.com).
124 |
125 | - If you **found a bug**, just open an issue.
126 |
127 | - If you **have a feature request**, just open an issue.
128 |
129 | - If you **want to contribute**, fork this repository, and then submit a pull request.
130 |
131 | ## License
132 |
133 | `TXScrollLabelView` is available under the MIT license. See the LICENSE file for more info.
134 |
135 | ## Ad
136 |
137 | Welcome to my Official Account of WeChat.
138 |
139 | 
140 |
141 |
--------------------------------------------------------------------------------
/TXScrollLabelView.podspec:
--------------------------------------------------------------------------------
1 |
2 | Pod::Spec.new do |s|
3 | s.name = "TXScrollLabelView"
4 | s.version = "1.3.2"
5 | s.summary = "TXScrollLabelView (Objective-C), the best way to show & display informations such as Adverts / Boardcast / OnSale e.g. with a customView."
6 | s.homepage = "https://github.com/tingxins/TXScrollLabelView"
7 | s.license = { :type => "MIT", :file => "LICENSE" }
8 | s.author = { "tingxins" => "tingxins@sina.com" }
9 | s.platform = :ios, "7.0"
10 | s.source = { :git => "https://github.com/tingxins/TXScrollLabelView.git", :tag => 'v1.3.2' }
11 | s.source_files = 'TXScrollLabelView/**/*.{h,m}'
12 | s.requires_arc = true
13 | end
14 |
--------------------------------------------------------------------------------
/TXScrollLabelView/TXScrollLabelView.h:
--------------------------------------------------------------------------------
1 | //
2 | // TXScrollLabelView.h
3 | //
4 | // Created by tingxins on 2/23/16.
5 | // Copyright © 2016 tingxins. All rights reserved.
6 | // 如果在使用 TXScrollLabelView 的过程中出现bug,请及时联系,我会尽快进行修复。如果有更好的点子,直接 Open an issue 或者 submit a pr。
7 | /**
8 | Blog : https://tingxins.com
9 | 简书 :http://www.jianshu.com/u/5141561e4d59
10 | GitHub : https://github.com/tingxins
11 | Weibo : http://weibo.com/tingxins
12 | Twitter : http://twitter.com/tingxins
13 | */
14 |
15 | #define TX_DEPRECATED_METHODS(explain) __attribute__((deprecated(explain)))
16 | #define TX_DEPRECATED_MESSAGES(explain) __deprecated_msg(explain)
17 |
18 | #import
19 | #import "UIView+TXFrame.h"
20 |
21 | @class TXScrollLabelView;
22 |
23 | @protocol TXScrollLabelViewDelegate
24 | @optional
25 | - (void)scrollLabelView:(TXScrollLabelView *)scrollLabelView didClickWithText:(NSString *)text atIndex:(NSInteger)index;
26 |
27 | @end
28 |
29 | @interface TXScrollLabelView : UIScrollView
30 |
31 | typedef NS_ENUM(NSInteger, TXScrollLabelViewType) {
32 | TXScrollLabelViewTypeLeftRight = 0, //not supports scrollInset.top\bottom\right
33 | TXScrollLabelViewTypeUpDown, //not supports scrollInset.top\bottom
34 | TXScrollLabelViewTypeFlipRepeat, //not supports scrollInset.top\bottom
35 | TXScrollLabelViewTypeFlipNoRepeat //not supports scrollInset.top\bottom
36 | };
37 |
38 | /*************WILL BE REMOVED IN FUTURE.********************/
39 | #pragma mark - Deprecated property
40 | /** Deprecated, please Use `scrollTitle` */
41 | @property (copy, nonatomic) NSString *tx_scrollTitle TX_DEPRECATED_METHODS("Deprecated, please Use `scrollTitle`");
42 | /** Deprecated, please Use `scrollType` */
43 | @property (assign, nonatomic) TXScrollLabelViewType tx_scrollType TX_DEPRECATED_METHODS("Deprecated, please Use `scrollType`");
44 | /** Deprecated, please Use `scrollVelocity` */
45 | @property (assign, nonatomic) NSTimeInterval tx_scrollVelocity TX_DEPRECATED_METHODS("Deprecated, please Use `scrollVelocity`");
46 | /** Deprecated, please Use `frame` */
47 | @property (assign, nonatomic) CGRect tx_scrollContentSize TX_DEPRECATED_METHODS("Deprecated, please Use `frame`");
48 | /** Deprecated, please Use `scrollTitleColor` */
49 | @property (strong, nonatomic) UIColor *tx_scrollTitleColor TX_DEPRECATED_METHODS("Deprecated, please Use `scrollTitleColor`");
50 | /*************ALL ABOVE.***********************************/
51 |
52 | #pragma mark - On Used Property
53 | @property (weak, nonatomic) id scrollLabelViewDelegate;
54 | /** 滚动文字 */
55 | @property (copy, nonatomic) NSString *scrollTitle;
56 | /** 滚动类型 */
57 | @property (assign, nonatomic) TXScrollLabelViewType scrollType;
58 | /** 滚动速率([0, 10]),单位秒s,建议在初始化方法中设置该属性*/
59 | @property (assign, nonatomic) NSTimeInterval scrollVelocity;
60 | /** 文本颜色 */
61 | @property (strong, nonatomic) UIColor *scrollTitleColor;
62 | /** 滚动内部inset */
63 | @property (assign, nonatomic) UIEdgeInsets scrollInset;
64 | /** 每次循环滚动的间距 */
65 | @property (assign, nonatomic) CGFloat scrollSpace;
66 | /** 文字排版 */
67 | @property (assign, nonatomic) NSTextAlignment textAlignment;
68 | /** 字体大小 */
69 | @property (strong, nonatomic) UIFont *font;
70 | //根据内容自适应宽度 Pending!!
71 | @property (assign, nonatomic) BOOL autoWidth;
72 |
73 | #pragma mark - setupAttributeTitle
74 |
75 | - (void)setupAttributeTitle:(NSAttributedString *)attributeTitle;
76 |
77 | #pragma mark - Instance Methods
78 |
79 | - (instancetype)initWithTitle:(NSString *)scrollTitle
80 | type:(TXScrollLabelViewType)scrollType
81 | velocity:(NSTimeInterval)scrollVelocity
82 | options:(UIViewAnimationOptions)options
83 | inset:(UIEdgeInsets)inset;
84 |
85 | #pragma mark - Factory Methods
86 |
87 | + (instancetype)scrollWithTitle:(NSString *)scrollTitle;
88 |
89 | + (instancetype)scrollWithTitle:(NSString *)scrollTitle
90 | type:(TXScrollLabelViewType)scrollType;
91 |
92 | + (instancetype)scrollWithTitle:(NSString *)scrollTitle
93 | type:(TXScrollLabelViewType)scrollType
94 | velocity:(NSTimeInterval)scrollVelocity;
95 |
96 | + (instancetype)scrollWithTitle:(NSString *)scrollTitle
97 | type:(TXScrollLabelViewType)scrollType
98 | velocity:(NSTimeInterval)scrollVelocity
99 | options:(UIViewAnimationOptions)options;
100 |
101 | /**
102 | 类初始化方法
103 | @param scrollTitle 滚动文本
104 | @param scrollType 滚动类型
105 | @param scrollVelocity 滚动速率
106 | @param options Now, supports the types of TXScrollLabelViewTypeFlipRepeat\NoRepeat only.
107 | @param inset just edgeInset.
108 | */
109 | + (instancetype)scrollWithTitle:(NSString *)scrollTitle
110 | type:(TXScrollLabelViewType)scrollType
111 | velocity:(NSTimeInterval)scrollVelocity
112 | options:(UIViewAnimationOptions)options
113 | inset:(UIEdgeInsets)inset;
114 |
115 | #pragma mark - Operation Methods
116 | /**
117 | * 开始滚动
118 | */
119 | - (void) beginScrolling;
120 | /**
121 | * 停止滚动
122 | */
123 | - (void) endScrolling;
124 |
125 | /**
126 | * 暂停滚动(暂不支持恢复)
127 | */
128 | - (void) pauseScrolling;
129 |
130 | @end
131 |
132 | @interface TXScrollLabelView (TXArray)
133 |
134 | /**
135 | 类初始化方法
136 | @param scrollTexts 滚动文本数组
137 | */
138 | - (instancetype)initWithTextArray:(NSArray *)scrollTexts
139 | type:(TXScrollLabelViewType)scrollType
140 | velocity:(NSTimeInterval)scrollVelocity
141 | options:(UIViewAnimationOptions)options
142 | inset:(UIEdgeInsets)inset;
143 |
144 | + (instancetype)scrollWithTextArray:(NSArray *)scrollTexts
145 | type:(TXScrollLabelViewType)scrollType
146 | velocity:(NSTimeInterval)scrollVelocity
147 | options:(UIViewAnimationOptions)options
148 | inset:(UIEdgeInsets)inset;
149 |
150 | @end
151 |
152 | @interface TXScrollLabelView (TXScrollLabelViewDeprecated)
153 |
154 | + (instancetype)tx_setScrollTitle:(NSString *)scrollTitle TX_DEPRECATED_MESSAGES("Method deprecated. Use `+ scrollWithTitle:`");
155 |
156 | + (instancetype)tx_setScrollTitle:(NSString *)scrollTitle
157 | scrollType:(TXScrollLabelViewType)scrollType TX_DEPRECATED_MESSAGES("Method deprecated. Use `+ scrollWithTitle:type:`");
158 |
159 | + (instancetype)tx_setScrollTitle:(NSString *)scrollTitle
160 | scrollType:(TXScrollLabelViewType)scrollType
161 | scrollVelocity:(NSTimeInterval)scrollVelocity TX_DEPRECATED_MESSAGES("Method deprecated. Use `+ scrollWithTitle:type:velocity:`");
162 |
163 | + (instancetype)tx_setScrollTitle:(NSString *)scrollTitle
164 | scrollType:(TXScrollLabelViewType)scrollType
165 | scrollVelocity:(NSTimeInterval)scrollVelocity
166 | options:(UIViewAnimationOptions)options TX_DEPRECATED_MESSAGES("Method deprecated. Use `+ scrollWithTitle:type:velocity:options:`");
167 |
168 | + (instancetype)tx_setScrollTitle:(NSString *)scrollTitle
169 | scrollType:(TXScrollLabelViewType)scrollType
170 | scrollVelocity:(NSTimeInterval)scrollVelocity
171 | options:(UIViewAnimationOptions)options
172 | inset:(UIEdgeInsets)inset TX_DEPRECATED_MESSAGES("Method deprecated. Use `+ scrollWithTitle:type:velocity:options:inset:`");
173 | @end
174 |
175 | @interface UIView (TXAdditions)
176 |
177 | - (void)addTapGesture:(id)target sel:(SEL)selector;
178 |
179 | @end
180 |
181 |
--------------------------------------------------------------------------------
/TXScrollLabelView/TXScrollLabelView.m:
--------------------------------------------------------------------------------
1 | //
2 | // TXScrollLabelView.m
3 | //
4 | // Created by tingxins on 2/23/16.
5 | // Copyright © 2016 tingxins. All rights reserved.
6 | // 如果在使用 TXScrollLabelView 的过程中出现bug,请及时联系,我会尽快进行修复。如果有更好的点子,直接 Open an issue 或者 submit a pr。
7 | /**
8 | Blog : https://tingxins.com
9 | 简书 :http://www.jianshu.com/u/5141561e4d59
10 | GitHub : https://github.com/tingxins
11 | Weibo : http://weibo.com/tingxins
12 | Twitter : http://twitter.com/tingxins
13 | */
14 |
15 | #define TXScrollLabelFont [UIFont systemFontOfSize:14]
16 | #import "TXScrollLabelView.h"
17 | #import
18 |
19 | static const NSInteger TXScrollDefaultTimeInterval = 2.0;//滚动默认时间
20 |
21 | typedef NS_ENUM(NSInteger, TXScrollLabelType) {
22 | TXScrollLabelTypeUp = 0,
23 | TXScrollLabelTypeDown
24 | };
25 |
26 | #pragma mark - NSTimer+TXTimerTarget
27 |
28 | @interface NSTimer (TXTimerTarget)
29 |
30 | + (NSTimer *)tx_scheduledTimerWithTimeInterval:(NSTimeInterval)interval repeat:(BOOL)yesOrNo block:(void(^)(NSTimer *timer))block;
31 |
32 | @end
33 |
34 |
35 | @implementation NSTimer (TXTimerTarget)
36 |
37 | + (NSTimer *)tx_scheduledTimerWithTimeInterval:(NSTimeInterval)interval repeat:(BOOL)yesOrNo block:(void (^)(NSTimer *))block{
38 | return [self scheduledTimerWithTimeInterval:interval target:self selector:@selector(startTimer:) userInfo:[block copy] repeats:yesOrNo];
39 | }
40 |
41 | + (void)startTimer:(NSTimer *)timer {
42 | void (^block)(NSTimer *timer) = timer.userInfo;
43 | if (block) {
44 | block(timer);
45 | }
46 | }
47 |
48 | @end
49 |
50 | #pragma mark - UILabel+TXLabel
51 |
52 |
53 | @interface TXScrollLabel : UILabel
54 |
55 | @property (assign, nonatomic) UIEdgeInsets contentInset;
56 |
57 | @end
58 |
59 | @implementation TXScrollLabel
60 |
61 | - (instancetype)init {
62 | if (self = [super init]) {
63 | _contentInset = UIEdgeInsetsZero;
64 | }
65 | return self;
66 | }
67 |
68 | - (instancetype)initWithFrame:(CGRect)frame {
69 | if (self = [super initWithFrame:frame]) {
70 | _contentInset = UIEdgeInsetsZero;
71 | }
72 | return self;
73 | }
74 |
75 | - (void)drawTextInRect:(CGRect)rect {
76 | [super drawTextInRect:UIEdgeInsetsInsetRect(rect, _contentInset)];
77 | }
78 |
79 | @end
80 |
81 | @interface TXScrollLabel (TXLabel)
82 |
83 | + (instancetype)tx_label;
84 |
85 | @end
86 |
87 | @implementation TXScrollLabel (TXLabel)
88 |
89 | + (instancetype)tx_label {
90 | TXScrollLabel *label = [[TXScrollLabel alloc]init];
91 | label.numberOfLines = 0;
92 | label.font = TXScrollLabelFont;
93 | label.textColor = [UIColor whiteColor];
94 | label.lineBreakMode = NSLineBreakByWordWrapping;
95 | label.textAlignment = NSTextAlignmentCenter;
96 | return label;
97 | }
98 |
99 | @end
100 |
101 | #pragma mark - TXScrollLabelView
102 |
103 | @interface TXScrollLabelView ()
104 |
105 | @property (assign, nonatomic) UIViewAnimationOptions options;
106 |
107 | @property (weak, nonatomic) TXScrollLabel *upLabel;
108 |
109 | @property (weak, nonatomic) TXScrollLabel *downLabel;
110 | //定时器
111 | @property (strong, nonatomic) NSTimer *scrollTimer;
112 | //文本行分割数组
113 | @property (strong, nonatomic) NSArray *scrollArray;
114 |
115 | @property (strong, nonatomic) NSArray *scrollTexts;
116 | //当前滚动行
117 | @property (assign, nonatomic) NSInteger currentSentence;
118 | //是否第一次开始计时
119 | @property (assign, nonatomic, getter=isFirstTime) BOOL firstTime;
120 | //传入参数是否为数组
121 | @property (assign, nonatomic) BOOL isArray;
122 |
123 | @end
124 |
125 | @implementation TXScrollLabelView
126 |
127 | @synthesize scrollSpace = _scrollSpace;
128 |
129 | @synthesize font = _font;
130 |
131 | #pragma mark - Preference Methods
132 |
133 | - (void)setSomePreference {
134 | /** Default preference. */
135 | self.backgroundColor = [UIColor blackColor];
136 | self.scrollEnabled = NO;
137 | }
138 |
139 | - (void)setSomeSubviews {
140 | TXScrollLabel *upLabel = [TXScrollLabel tx_label];
141 | self.upLabel = upLabel;
142 | [self addSubview:upLabel];
143 |
144 | TXScrollLabel *downLabel = [TXScrollLabel tx_label];
145 | self.downLabel = downLabel;
146 | [self addSubview:downLabel];
147 |
148 | [upLabel addTapGesture:self sel:@selector(didTap:)];
149 | [downLabel addTapGesture:self sel:@selector(didTap:)];
150 | }
151 |
152 | #pragma mark - UITapGestureRecognizer Methods
153 |
154 | - (void)didTap:(UITapGestureRecognizer *)tapGesture {
155 | UILabel *label = (UILabel *)tapGesture.view;
156 |
157 | if (!label || ![label isKindOfClass:[UILabel class]]) return;
158 |
159 | NSInteger index = 0;
160 | if (self.scrollArray.count) index = [self.scrollArray indexOfObject:label.text];
161 |
162 | if ([self.scrollLabelViewDelegate respondsToSelector:@selector(scrollLabelView:didClickWithText:atIndex:)]) {
163 | [self.scrollLabelViewDelegate scrollLabelView:self didClickWithText:label.text atIndex:index];
164 | }
165 | }
166 |
167 | #pragma mark - Instance Methods
168 | /** Terminating app due to uncaught exception 'Warning TXScrollLabelView -[TXScrollLabelView init] unimplemented!', reason: 'unimplemented, use - scrollWithTitle:scrollType:scrollVelocity:options:'*/
169 | - (instancetype)init {
170 | @throw [NSException exceptionWithName:[NSString stringWithFormat:@"Warning %@ %s unimplemented!", self.class, __func__] reason:@"unimplemented, please use - scrollWithTitle:scrollType:scrollVelocity:options:" userInfo:nil];
171 | }
172 |
173 | - (instancetype)initWithFrame:(CGRect)frame {
174 | if (self = [super initWithFrame:frame]) {
175 |
176 | [self setSomePreference];
177 |
178 | [self setSomeSubviews];
179 | }
180 | return self;
181 | }
182 |
183 | - (instancetype)initWithTitle:(NSString *)scrollTitle
184 | type:(TXScrollLabelViewType)scrollType
185 | velocity:(NSTimeInterval)scrollVelocity
186 | options:(UIViewAnimationOptions)options
187 | inset:(UIEdgeInsets)inset {
188 | if (self = [super init]) {
189 | _scrollTitle = scrollTitle;
190 | _scrollType = scrollType;
191 | self.scrollVelocity = scrollVelocity;
192 | _options = options;
193 | _scrollInset = inset;
194 | }
195 | return self;
196 | }
197 |
198 | #pragma mark - Factory Methods
199 |
200 | + (instancetype)scrollWithTitle:(NSString *)scrollTitle {
201 |
202 | return [self scrollWithTitle:scrollTitle
203 | type:TXScrollLabelViewTypeLeftRight];
204 | }
205 |
206 | + (instancetype)scrollWithTitle:(NSString *)scrollTitle
207 | type:(TXScrollLabelViewType)scrollType {
208 |
209 | return [self scrollWithTitle:scrollTitle
210 | type:scrollType
211 | velocity:TXScrollDefaultTimeInterval];
212 | }
213 |
214 | + (instancetype)scrollWithTitle:(NSString *)scrollTitle
215 | type:(TXScrollLabelViewType)scrollType
216 | velocity:(NSTimeInterval)scrollVelocity {
217 |
218 | return [self scrollWithTitle:scrollTitle
219 | type:scrollType
220 | velocity:scrollVelocity
221 | options:UIViewAnimationOptionCurveEaseInOut];
222 | }
223 |
224 | + (instancetype)scrollWithTitle:(NSString *)scrollTitle
225 | type:(TXScrollLabelViewType)scrollType
226 | velocity:(NSTimeInterval)scrollVelocity
227 | options:(UIViewAnimationOptions)options {
228 |
229 | return [self scrollWithTitle:scrollTitle
230 | type:scrollType
231 | velocity:scrollVelocity
232 | options:options
233 | inset:UIEdgeInsetsMake(0, 5, 0, 5)];
234 | }
235 |
236 | + (instancetype)scrollWithTitle:(NSString *)scrollTitle
237 | type:(TXScrollLabelViewType)scrollType
238 | velocity:(NSTimeInterval)scrollVelocity
239 | options:(UIViewAnimationOptions)options
240 | inset:(UIEdgeInsets)inset {
241 |
242 | return [[self alloc] initWithTitle:scrollTitle
243 | type:scrollType
244 | velocity:scrollVelocity
245 | options:options
246 | inset:inset];
247 | }
248 |
249 | #pragma mark - Deprecated Getter & Setter Methods
250 | /*************WILL BE REMOVED IN THE FUTURE.****************************/
251 |
252 | - (void)setTx_scrollTitle:(NSString *)tx_scrollTitle {
253 | self.scrollTitle = tx_scrollTitle;
254 | }
255 |
256 | - (void)setTx_scrollType:(TXScrollLabelViewType)tx_scrollType {
257 | self.scrollType = tx_scrollType;
258 | }
259 |
260 | - (void)setTx_scrollVelocity:(NSTimeInterval)tx_scrollVelocity {
261 | self.scrollVelocity = tx_scrollVelocity;
262 | }
263 |
264 | - (void)setTx_scrollContentSize:(CGRect)tx_scrollContentSize{
265 | _tx_scrollContentSize = tx_scrollContentSize;
266 | self.frame = _tx_scrollContentSize;
267 | }
268 |
269 | - (void)setTx_scrollTitleColor:(UIColor *)tx_scrollTitleColor {
270 | self.scrollTitleColor = tx_scrollTitleColor;
271 | }
272 | /*************ALL ABOVE.*******************************************/
273 |
274 |
275 | #pragma mark - Getter & Setter Methods
276 |
277 | - (void)setScrollTitle:(NSString *)scrollTitle {
278 | _scrollTitle = scrollTitle;
279 | // self.scrollArray = nil;
280 | [self resetScrollLabelView];
281 | }
282 |
283 | - (void)setScrollType:(TXScrollLabelViewType)scrollType {
284 | if (_scrollType == scrollType) return;
285 |
286 | _scrollType = scrollType;
287 | self.scrollVelocity = _scrollVelocity;
288 | [self resetScrollLabelView];
289 | }
290 |
291 | - (void)setScrollVelocity:(NSTimeInterval)scrollVelocity {
292 | CGFloat velocity = scrollVelocity;
293 | if (scrollVelocity < 0.1) {
294 | velocity = 0.1;
295 | }else if (scrollVelocity > 10) {
296 | velocity = 10;
297 | }
298 |
299 | if (_scrollType == TXScrollLabelViewTypeLeftRight || _scrollType == TXScrollLabelViewTypeUpDown) {
300 | _scrollVelocity = velocity / 30.0;
301 | }else {
302 | _scrollVelocity = velocity;
303 | }
304 | }
305 |
306 | - (UIViewAnimationOptions)options {
307 | if (_options) return _options;
308 | return _options = UIViewAnimationOptionCurveEaseInOut;
309 | }
310 |
311 | - (void)setScrollTitleColor:(UIColor *)scrollTitleColor {
312 | _scrollTitleColor = scrollTitleColor;
313 | [self setupTextColor:scrollTitleColor];
314 | }
315 |
316 | - (void)setScrollInset:(UIEdgeInsets)scrollInset {
317 | _scrollInset = scrollInset;
318 | [self setupSubviewsLayout];
319 | }
320 |
321 | - (void)setScrollSpace:(CGFloat)scrollSpace {
322 | _scrollSpace = scrollSpace;
323 | [self setupSubviewsLayout];
324 | }
325 |
326 | - (CGFloat)scrollSpace {
327 | if (_scrollSpace) return _scrollSpace;
328 | return 0.f;
329 | }
330 |
331 | - (NSArray *)scrollArray {
332 | if (_scrollArray) return _scrollArray;
333 | if (_scrollTexts.count) {
334 | return _scrollArray = _scrollTexts;
335 | }
336 | return _scrollArray = [self getSeparatedLinesFromLabel];
337 | }
338 |
339 | - (void)setFrame:(CGRect)frame {
340 | [super setFrame:frame];
341 | [self setupSubviewsLayout];
342 | }
343 |
344 | - (void)setTextAlignment:(NSTextAlignment)textAlignment {
345 | _textAlignment = textAlignment;
346 | self.upLabel.textAlignment = textAlignment;
347 | self.downLabel.textAlignment = textAlignment;
348 | }
349 |
350 | - (void)setFont:(UIFont *)font {
351 | _font = font;
352 | self.upLabel.font = font;
353 | self.downLabel.font = font;
354 | [self setupSubviewsLayout];
355 | }
356 |
357 | - (UIFont *)font {
358 | if (_font) return _font;
359 | return TXScrollLabelFont;
360 | }
361 |
362 | #pragma mark - Custom Methods
363 |
364 | // Component initial
365 | - (void)setupInitial {
366 | switch (_scrollType) {
367 | case TXScrollLabelViewTypeLeftRight:
368 | [self updateTextForScrollViewWithSEL:@selector(updateLeftRightScrollLabelLayoutWithText:labelType:)];
369 | break;
370 |
371 | case TXScrollLabelViewTypeUpDown:
372 | [self updateTextForScrollViewWithSEL:@selector(updateUpDownScrollLabelLayoutWithText:labelType:)];
373 | break;
374 | case TXScrollLabelViewTypeFlipRepeat:
375 | case TXScrollLabelViewTypeFlipNoRepeat:
376 | // TODO
377 | break;
378 |
379 | default:
380 | @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"TXScrollLabelViewType unrecognized in -[TXScrollLabelView setupInitial]" userInfo:nil];
381 | break;
382 | }
383 | }
384 |
385 | /** 重置滚动视图 */
386 | - (void)resetScrollLabelView {
387 | [self endup];//停止滚动
388 | [self setupSubviewsLayout];//重新布局
389 | [self startup];//开始滚动
390 | }
391 |
392 | - (void)setupTextColor:(UIColor *)color {
393 | self.upLabel.textColor = color;
394 | self.downLabel.textColor = color;
395 | }
396 |
397 | - (void)setupTitle:(NSString *)title {
398 | self.upLabel.text = title;
399 | self.downLabel.text = title;
400 | }
401 |
402 | - (void)setupAttributeTitle:(NSAttributedString *)attributeTitle {
403 | _scrollTitle = attributeTitle.string;
404 | [self setupSubviewsLayout];
405 | self.upLabel.attributedText = attributeTitle;
406 | self.downLabel.attributedText = attributeTitle;
407 | }
408 |
409 | #pragma mark - SubviewsLayout Methods
410 |
411 | - (void)setupSubviewsLayout {
412 | switch (_scrollType) {
413 | case TXScrollLabelViewTypeLeftRight:
414 | if (self.isArray) {
415 | [self setupInitial];
416 | }else {
417 | [self setupSubviewsLayout_LeftRight];
418 | }
419 | break;
420 | case TXScrollLabelViewTypeUpDown:
421 | if (self.isArray) {
422 | [self setupInitial];
423 | }else {
424 | [self setupSubviewsLayout_UpDown];
425 | }
426 | break;
427 | case TXScrollLabelViewTypeFlipRepeat: {
428 | [self setupSubviewsLayout_Flip];
429 | [self setupTitle:_scrollTitle];
430 | }
431 | break;
432 | case TXScrollLabelViewTypeFlipNoRepeat:
433 | [self setupSubviewsLayout_Flip];
434 | break;
435 |
436 | default:
437 | break;
438 | }
439 | }
440 |
441 | - (void)setupSubviewsLayout_LeftRight {
442 |
443 | CGFloat labelMaxH = self.tx_height;//最大高度
444 | CGFloat labelMaxW = 0;//无限宽
445 | CGFloat labelH = labelMaxH;//label实际高度
446 | __block CGFloat labelW = 0;//label宽度,有待计算
447 | self.contentOffset = CGPointZero;
448 | [self setupLRUDTypeLayoutWithMaxSize:CGSizeMake(labelMaxW, labelMaxH) width:labelW height:labelH completedHandler:^(CGSize size) {
449 | labelW = MAX(size.width, self.tx_width);
450 | //开始布局
451 | self.upLabel.frame = CGRectMake(_scrollInset.left, 0, labelW, labelH);
452 | //由于 TXScrollLabelViewTypeLeftRight\UpDown 类型 X\Y 值均不一样,此处不再block中处理!
453 | self.downLabel.frame = CGRectMake(CGRectGetMaxX(self.upLabel.frame) + self.scrollSpace, 0, labelW, labelH);
454 | }];
455 | }
456 |
457 | - (void)setupSubviewsLayout_UpDown {
458 | CGFloat labelMaxH = 0;
459 | CGFloat labelMaxW = self.tx_width - _scrollInset.left - _scrollInset.right;
460 | CGFloat labelW = labelMaxW;
461 | __block CGFloat labelH = 0;
462 |
463 | [self setupLRUDTypeLayoutWithMaxSize:CGSizeMake(labelMaxW, labelMaxH) width:labelW height:labelH completedHandler:^(CGSize size) {
464 | labelH = MAX(size.height, self.tx_height);
465 | self.upLabel.frame = CGRectMake(_scrollInset.left, 0, labelW, labelH);
466 | self.downLabel.frame = CGRectMake(_scrollInset.left, CGRectGetMaxY(self.upLabel.frame) + self.scrollSpace, labelW, labelH);
467 | }];
468 | }
469 |
470 | - (void)setupSubviewsLayout_Flip {
471 | CGFloat labelW = self.tx_width - _scrollInset.left - _scrollInset.right;
472 | CGFloat labelX = _scrollInset.left;
473 | self.upLabel.frame = CGRectMake(labelX, 0, labelW, self.tx_height);
474 | self.downLabel.frame = CGRectMake(labelX, CGRectGetMaxY(self.upLabel.frame), labelW, self.tx_height);
475 | }
476 |
477 | - (void)setupLRUDTypeLayoutWithMaxSize:(CGSize)size
478 | width:(CGFloat)width
479 | height:(CGFloat)height
480 | completedHandler:(void(^)(CGSize size))completedHandler {
481 | CGSize scrollLabelS = [_scrollTitle boundingRectWithSize:size
482 | options:NSStringDrawingUsesLineFragmentOrigin
483 | attributes:@{NSFontAttributeName: self.font} context:nil].size;
484 | //回调获取布局数据
485 | completedHandler(scrollLabelS);
486 | if (!self.isArray) {
487 | [self setupTitle:_scrollTitle];
488 | }
489 | }
490 |
491 | - (void)setupLRUDTypeLayoutWithTitle:(NSString *)title
492 | maxSize:(CGSize)size
493 | width:(CGFloat)width
494 | height:(CGFloat)height
495 | completedHandler:(void(^)(CGSize size))completedHandler {
496 | CGSize scrollLabelS = [title boundingRectWithSize:size
497 | options:NSStringDrawingUsesLineFragmentOrigin
498 | attributes:@{NSFontAttributeName: self.font} context:nil].size;
499 | //回调获取布局数据
500 | completedHandler(scrollLabelS);
501 | }
502 |
503 | /**
504 | update the frame of scrollLabel. Just layout
505 |
506 | @param text scrollText
507 | @param type scrollLabel type
508 | */
509 | - (void)updateLeftRightScrollLabelLayoutWithText:(NSString *)text labelType:(TXScrollLabelType)type {
510 | CGFloat labelMaxH = self.tx_height;//最大高度
511 | CGFloat labelMaxW = 0;//无限宽
512 | CGFloat labelH = labelMaxH;//label实际高度
513 | __block CGFloat labelW = 0;//label宽度,有待计算
514 |
515 | [self setupLRUDTypeLayoutWithTitle:text maxSize:CGSizeMake(labelMaxW, labelMaxH) width:labelW height:labelH completedHandler:^(CGSize size) {
516 | labelW = MAX(size.width, self.tx_width);
517 | //开始布局
518 | if (type == TXScrollLabelTypeUp) {
519 | self.upLabel.frame = CGRectMake(_scrollInset.left, 0, labelW, labelH);
520 | }else if (type == TXScrollLabelTypeDown) {
521 | self.downLabel.frame = CGRectMake(CGRectGetMaxX(self.upLabel.frame) + self.scrollSpace, 0, labelW, labelH);
522 | }
523 | }];
524 | }
525 |
526 | /**
527 | The same as "-updateLeftRightScrollLabelLayoutWithText:labelType:"
528 | */
529 | - (void)updateUpDownScrollLabelLayoutWithText:(NSString *)text labelType:(TXScrollLabelType)type {
530 | CGFloat labelMaxH = 0;
531 | CGFloat labelMaxW = self.tx_width - _scrollInset.left - _scrollInset.right;
532 | CGFloat labelW = labelMaxW;
533 | __block CGFloat labelH = 0;
534 |
535 | [self setupLRUDTypeLayoutWithTitle:text maxSize:CGSizeMake(labelMaxW, labelMaxH) width:labelW height:labelH completedHandler:^(CGSize size) {
536 | labelH = MAX(size.height, self.tx_height);
537 | if (type == TXScrollLabelTypeUp) {
538 | self.upLabel.frame = CGRectMake(_scrollInset.left, 0, labelW, labelH);
539 | }else if (type == TXScrollLabelTypeDown) {
540 | self.downLabel.frame = CGRectMake(_scrollInset.left, CGRectGetMaxY(self.upLabel.frame) + self.scrollSpace, labelW, labelH);
541 | }
542 | }];
543 | }
544 |
545 | #pragma mark - Scrolling Operation Methods -- Public
546 |
547 | - (void)beginScrolling {
548 | self.currentSentence = 0;
549 | if (self.isArray) {
550 | [self setupInitial];
551 | }
552 | [self startup];
553 | }
554 |
555 | - (void)endScrolling {
556 | [self endup];
557 | }
558 |
559 | - (void)pauseScrolling {
560 | [self endup];
561 | }
562 |
563 | #pragma mark - Scrolling Operation Methods -- Private
564 |
565 | - (void)endup {
566 | [self.scrollTimer invalidate];
567 | self.scrollTimer = nil;
568 | self.scrollArray = nil;
569 | }
570 |
571 | - (void)startup {
572 | if (!self.scrollTitle.length && !self.scrollArray.count) return;
573 |
574 | [self endup];
575 |
576 | if (_scrollType == TXScrollLabelViewTypeFlipRepeat || _scrollType == TXScrollLabelViewTypeFlipNoRepeat) {
577 | _firstTime = YES;
578 | if (_scrollType == TXScrollLabelViewTypeFlipNoRepeat) {
579 | [self setupTitle:[self.scrollArray firstObject]];//初次显示
580 | }
581 | [self startWithVelocity:1];
582 | }else {
583 | [self startWithVelocity:self.scrollVelocity];
584 | }
585 | }
586 |
587 | //开始计时
588 | - (void)startWithVelocity:(NSTimeInterval)velocity {
589 | // if (!self.scrollTitle.length) return;
590 |
591 | if (!self.scrollTitle.length && self.scrollArray.count) return;
592 |
593 | __weak typeof(self) weakSelf = self;
594 | self.scrollTimer = [NSTimer tx_scheduledTimerWithTimeInterval:velocity repeat:YES block:^(NSTimer *timer) {
595 | TXScrollLabelView *strongSelf = weakSelf;
596 | if (strongSelf) {
597 | [strongSelf updateScrolling];
598 | }
599 | }];
600 | [[NSRunLoop mainRunLoop] addTimer:self.scrollTimer forMode:NSRunLoopCommonModes];
601 | }
602 |
603 | #pragma mark - Scrolling Animation Methods
604 |
605 | - (void)updateScrolling {
606 | switch (self.scrollType) {
607 | case TXScrollLabelViewTypeLeftRight:
608 | [self updateScrollingType_LeftRight];
609 | break;
610 | case TXScrollLabelViewTypeUpDown:
611 | [self updateScrollingType_UpDown];
612 | break;
613 | case TXScrollLabelViewTypeFlipRepeat:
614 | [self updateScrollingType_FlipRepeat];
615 | break;
616 | case TXScrollLabelViewTypeFlipNoRepeat:
617 | [self updateScrollingType_FlipNoRepeat];
618 | break;
619 | default:
620 | break;
621 | }
622 | }
623 |
624 | #pragma mark - ScrollLabelView + Methods
625 |
626 | - (void)updateScrollingType_LeftRight {
627 |
628 | if (self.contentOffset.x >= (_scrollInset.left + self.upLabel.tx_width + self.scrollSpace)) {
629 | /** 更新 Label.text */
630 | if ((self.contentOffset.x > (_scrollInset.left + self.upLabel.tx_width) - self.tx_width) &&
631 | self.isArray) {
632 | [self updateTextForScrollViewWithSEL:@selector(updateLeftRightScrollLabelLayoutWithText:labelType:)];
633 | }
634 | [self endup];
635 | self.contentOffset = CGPointMake(_scrollInset.left + 1, 0);//x增加偏移量,防止卡顿
636 | [self startup];
637 | }else {
638 | self.contentOffset = CGPointMake(self.contentOffset.x + 1, self.contentOffset.y);
639 | }
640 |
641 | }
642 |
643 | - (void)updateScrollingType_UpDown {
644 | if (self.contentOffset.y >= (self.upLabel.tx_height + self.scrollSpace)) {
645 | /** 更新 Label.text */
646 | if ((self.contentOffset.y >= (self.upLabel.tx_height)) &&
647 | self.isArray) {
648 | [self updateTextForScrollViewWithSEL:@selector(updateUpDownScrollLabelLayoutWithText:labelType:)];
649 | }
650 | [self endup];
651 | self.contentOffset = CGPointMake(0, 2);//y增加偏移量,防止卡顿
652 | [self startup];
653 | }else {
654 | self.contentOffset = CGPointMake(self.contentOffset.x, self.contentOffset.y + 1);
655 | }
656 | }
657 |
658 | - (void)updateScrollingType_FlipRepeat {
659 | [self updateRepeatTypeWithOperation:^(NSTimeInterval velocity) {
660 | [self flipAnimationWithDelay:velocity];
661 | }];
662 | }
663 |
664 | - (void)updateScrollingType_FlipNoRepeat {
665 | [self updateRepeatTypeWithOperation:^(NSTimeInterval velocity) {
666 | [self flipNoCleAnimationWithDelay:velocity];
667 | }];
668 | }
669 |
670 | - (void)updateRepeatTypeWithOperation:(void(^)(NSTimeInterval))operation {
671 | NSTimeInterval velocity = self.scrollVelocity;
672 | if (self.isFirstTime) {
673 | _firstTime = NO;
674 | [self endup];
675 | [self startWithVelocity:velocity];
676 | }
677 | operation(velocity);
678 | }
679 |
680 | - (void)flipAnimationWithDelay:(NSTimeInterval)delay {
681 | [UIView transitionWithView:self.upLabel duration:delay * 0.5 options:self.options animations:^{
682 | self.upLabel.tx_bottom = 0;
683 | [UIView transitionWithView:self.upLabel duration:delay * 0.5 options:self.options animations:^{
684 | self.downLabel.tx_y = 0;
685 | } completion:^(BOOL finished) {
686 | self.upLabel.tx_y = self.tx_height;
687 | TXScrollLabel *tempLabel = self.upLabel;
688 | self.upLabel = self.downLabel;
689 | self.downLabel = tempLabel;
690 | }];
691 | } completion:nil];
692 | }
693 |
694 |
695 | /**
696 | Execute flip animation.
697 |
698 | @param delay animation duration.
699 | */
700 | - (void)flipNoCleAnimationWithDelay:(NSTimeInterval)delay {
701 | if (!self.scrollArray.count) return;
702 | /** 更新文本 */
703 | [self updateScrollText];
704 | /** 执行翻滚动画 */
705 | [self flipAnimationWithDelay:delay];
706 | }
707 |
708 | #pragma mark - Params For Array
709 |
710 | void (*setter)(id, SEL, NSString *, TXScrollLabelType);
711 |
712 | - (void)updateTextForScrollViewWithSEL:(SEL)sel {
713 |
714 | if (!self.scrollArray.count) return;
715 |
716 | /** 更新文本 */
717 | [self updateScrollText];
718 | /** 执行 SEL */
719 | setter = (void (*)(id, SEL, NSString *, TXScrollLabelType))[self methodForSelector:sel];
720 | setter(self, sel, self.upLabel.text, TXScrollLabelTypeUp);
721 | setter(self, sel, self.downLabel.text, TXScrollLabelTypeDown);
722 | }
723 |
724 | - (void)updateScrollText {
725 | NSInteger currentSentence = self.currentSentence;
726 | if (currentSentence >= self.scrollArray.count) currentSentence = 0;
727 | self.upLabel.text = self.scrollArray[currentSentence];
728 | currentSentence ++;
729 | if (currentSentence >= self.scrollArray.count) currentSentence = 0;
730 | self.downLabel.text = self.scrollArray[currentSentence];
731 |
732 | self.currentSentence = currentSentence;
733 | }
734 |
735 | #pragma mark - Text-Separator
736 |
737 | -(NSArray *)getSeparatedLinesFromLabel {
738 | if (!_scrollTitle.length) return nil;
739 |
740 | NSString *text = _scrollTitle;
741 | UIFont *font = self.font;
742 | CTFontRef myFont = CTFontCreateWithName((__bridge CFStringRef)([font fontName]), [font pointSize], NULL);
743 | NSMutableAttributedString *attStr = [[NSMutableAttributedString alloc] initWithString:text];
744 | [attStr addAttribute:(NSString *)kCTFontAttributeName value:(__bridge id)myFont range:NSMakeRange(0, attStr.length)];
745 |
746 | CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attStr);
747 | CGMutablePathRef path = CGPathCreateMutable();
748 | CGPathAddRect(path, NULL, CGRectMake(0,0,self.upLabel.tx_width,100000));
749 | CTFrameRef frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, 0), path, NULL);
750 |
751 | NSArray *lines = (__bridge NSArray *)CTFrameGetLines(frame);
752 |
753 | NSMutableArray *linesArray = [[NSMutableArray alloc]init];
754 | for (id line in lines) {
755 | CTLineRef lineRef = (__bridge CTLineRef )line;
756 | CFRange lineRange = CTLineGetStringRange(lineRef);
757 | NSRange range = NSMakeRange(lineRange.location, lineRange.length);
758 | NSString *lineString = [text substringWithRange:range];
759 | [linesArray addObject:lineString];
760 | }
761 |
762 | return (NSArray *)linesArray;
763 | }
764 |
765 | - (void)dealloc {
766 | [self endup];
767 | }
768 |
769 | @end
770 |
771 | @implementation TXScrollLabelView (TXArray)
772 |
773 | #pragma mark - Array Methods
774 |
775 | - (instancetype)initWithTextArray:(NSArray *)scrollTexts
776 | type:(TXScrollLabelViewType)scrollType
777 | velocity:(NSTimeInterval)scrollVelocity
778 | options:(UIViewAnimationOptions)options
779 | inset:(UIEdgeInsets)inset {
780 | if (self = [super init]) {
781 | self.isArray = YES;
782 | _scrollTexts = [scrollTexts copy];
783 | _scrollTitle = [_scrollTexts firstObject];
784 | _scrollType = scrollType;
785 | self.scrollVelocity = scrollVelocity;
786 | _options = options;
787 | _scrollInset = inset;
788 | }
789 | return self;
790 | }
791 |
792 | + (instancetype)scrollWithTextArray:(NSArray *)scrollTexts
793 | type:(TXScrollLabelViewType)scrollType
794 | velocity:(NSTimeInterval)scrollVelocity
795 | options:(UIViewAnimationOptions)options
796 | inset:(UIEdgeInsets)inset {
797 | return [[self alloc] initWithTextArray:scrollTexts
798 | type:scrollType
799 | velocity:scrollVelocity
800 | options:options
801 | inset:inset];
802 | }
803 |
804 | @end
805 |
806 | @implementation TXScrollLabelView (TXScrollLabelViewDeprecated)
807 |
808 | + (instancetype)tx_setScrollTitle:(NSString *)scrollTitle {
809 |
810 | return [self scrollWithTitle:scrollTitle];
811 | }
812 |
813 | + (instancetype)tx_setScrollTitle:(NSString *)scrollTitle
814 | scrollType:(TXScrollLabelViewType)scrollType {
815 |
816 | return [self scrollWithTitle:scrollTitle
817 | type:scrollType];
818 | }
819 |
820 | + (instancetype)tx_setScrollTitle:(NSString *)scrollTitle
821 | scrollType:(TXScrollLabelViewType)scrollType
822 | scrollVelocity:(NSTimeInterval)scrollVelocity {
823 |
824 | return [self scrollWithTitle:scrollTitle
825 | type:scrollType
826 | velocity:scrollVelocity];
827 | }
828 |
829 | + (instancetype)tx_setScrollTitle:(NSString *)scrollTitle
830 | scrollType:(TXScrollLabelViewType)scrollType
831 | scrollVelocity:(NSTimeInterval)scrollVelocity
832 | options:(UIViewAnimationOptions)options {
833 |
834 | return [self scrollWithTitle:scrollTitle
835 | type:scrollType
836 | velocity:scrollVelocity
837 | options:options];
838 | }
839 |
840 | + (instancetype)tx_setScrollTitle:(NSString *)scrollTitle
841 | scrollType:(TXScrollLabelViewType)scrollType
842 | scrollVelocity:(NSTimeInterval)scrollVelocity
843 | options:(UIViewAnimationOptions)options
844 | inset:(UIEdgeInsets)inset {
845 |
846 | return [self scrollWithTitle:scrollTitle
847 | type:scrollType
848 | velocity:scrollVelocity
849 | options:options
850 | inset:inset];
851 | }
852 |
853 | @end
854 |
855 |
856 | @implementation UIView (TXAdditions)
857 |
858 | - (void)addTapGesture:(id)target sel:(SEL)selector {
859 | self.userInteractionEnabled = YES;
860 | UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:target action:selector];
861 | [self addGestureRecognizer:tap];
862 | }
863 |
864 | @end
865 |
--------------------------------------------------------------------------------
/TXScrollLabelView/UIView+TXFrame.h:
--------------------------------------------------------------------------------
1 | //
2 | // UIView+TXFrame.h
3 | // TXSwipeTableViewTest
4 | //
5 | // Created by tingxins on 9/1/16.
6 | // Copyright © 2016 tingxins. All rights reserved.
7 | // Welcome to my blog: https://tingxins.com
8 | //
9 |
10 | #import
11 |
12 | @interface UIView (TXFrame)
13 | /** 设置x值 */
14 | @property (assign, nonatomic) CGFloat tx_x;
15 | /** 设置y值 */
16 | @property (assign, nonatomic) CGFloat tx_y;
17 | /** 设置width */
18 | @property (assign, nonatomic) CGFloat tx_width;
19 | /** 设置height */
20 | @property (assign, nonatomic) CGFloat tx_height;
21 | /** 设置size */
22 | @property (assign, nonatomic) CGSize tx_size;
23 | /** 设置origin */
24 | @property (assign, nonatomic) CGPoint tx_origin;
25 | /** 设置center */
26 | @property (assign, nonatomic) CGPoint tx_center;
27 | /** 设置center.x */
28 | @property (assign, nonatomic) CGFloat tx_centerX;
29 | /** 设置center.y */
30 | @property (assign, nonatomic) CGFloat tx_centerY;
31 | /** 设置bottom */
32 | @property (assign, nonatomic) CGFloat tx_bottom;
33 | @end
34 |
--------------------------------------------------------------------------------
/TXScrollLabelView/UIView+TXFrame.m:
--------------------------------------------------------------------------------
1 | //
2 | // UIView+TXFrame.m
3 | // TXSwipeTableViewTest
4 | //
5 | // Created by tingxins on 9/1/16.
6 | // Copyright © 2016 tingxins. All rights reserved.
7 | //
8 |
9 | #import "UIView+TXFrame.h"
10 |
11 | @implementation UIView (TXFrame)
12 |
13 | - (CGFloat)tx_x {
14 | return self.frame.origin.x;
15 | }
16 |
17 | - (void)setTx_x:(CGFloat)tx_x {
18 | CGRect frame = self.frame;
19 | frame.origin.x = tx_x;
20 | self.frame = frame;
21 | }
22 |
23 | - (CGFloat)tx_y {
24 | return self.frame.origin.y;
25 | }
26 |
27 | - (void)setTx_y:(CGFloat)tx_y {
28 | CGRect frame = self.frame;
29 | frame.origin.y = tx_y;
30 | self.frame = frame;
31 | }
32 |
33 | - (CGFloat)tx_width {
34 | return self.frame.size.width;
35 | }
36 |
37 | - (void)setTx_width:(CGFloat)tx_width {
38 | CGRect frame = self.frame;
39 | frame.size.width = tx_width;
40 | self.frame = frame;
41 | }
42 |
43 | - (CGFloat)tx_height {
44 | return self.frame.size.height;
45 | }
46 |
47 | - (void)setTx_height:(CGFloat)tx_height {
48 | CGRect frame = self.frame;
49 | frame.size.height = tx_height;
50 | self.frame = frame;
51 | }
52 |
53 | - (CGSize)tx_size {
54 | return self.frame.size;
55 | }
56 |
57 | - (void)setTx_size:(CGSize)tx_size {
58 | CGRect frame = self.frame;
59 | frame.size = tx_size;
60 | self.frame = frame;
61 | }
62 |
63 | - (CGPoint)tx_origin {
64 | return self.frame.origin;
65 | }
66 |
67 | - (void)setTx_origin:(CGPoint)tx_origin {
68 | CGRect frame = self.frame;
69 | frame.origin = tx_origin;
70 | self.frame = frame;
71 | }
72 |
73 | - (CGPoint)tx_center {
74 | return self.center;
75 | }
76 |
77 | - (void)setTx_center:(CGPoint)tx_center {
78 | self.center = tx_center;
79 | }
80 |
81 | - (CGFloat)tx_centerX {
82 | return self.center.x;
83 | }
84 |
85 | - (void)setTx_centerX:(CGFloat)tx_centerX {
86 | CGPoint center = self.center;
87 | center.x = tx_centerX;
88 | self.center = center;
89 | }
90 |
91 | - (CGFloat)tx_centerY {
92 | return self.center.y;
93 | }
94 |
95 | - (void)setTx_centerY:(CGFloat)tx_centerY {
96 | CGPoint center = self.center;
97 | center.y = tx_centerY;
98 | self.center = center;
99 | }
100 |
101 | - (CGFloat)tx_bottom {
102 | return CGRectGetMaxY(self.frame);
103 | }
104 |
105 | - (void)setTx_bottom:(CGFloat)tx_bottom {
106 | CGRect frame = self.frame;
107 | frame.origin.y = tx_bottom - frame.size.height;
108 | self.frame = frame;
109 | }
110 |
111 | @end
112 |
--------------------------------------------------------------------------------
/TXScrollLabelViewDemo/TXScrollLabelViewDemo.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 972620CA1DDE2F0600009F23 /* TXScrollLabelView.m in Sources */ = {isa = PBXBuildFile; fileRef = 972620C61DDE2F0600009F23 /* TXScrollLabelView.m */; };
11 | 972620CB1DDE2F0600009F23 /* UIView+TXFrame.m in Sources */ = {isa = PBXBuildFile; fileRef = 972620C91DDE2F0600009F23 /* UIView+TXFrame.m */; };
12 | 97883B5E1EBD7A6800552DFE /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97883B5D1EBD7A6800552DFE /* Main.storyboard */; };
13 | 97886D991DB8E0AF00A0B326 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97886D981DB8E0AF00A0B326 /* main.m */; };
14 | 97886D9C1DB8E0AF00A0B326 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 97886D9B1DB8E0AF00A0B326 /* AppDelegate.m */; };
15 | 97886D9F1DB8E0AF00A0B326 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 97886D9E1DB8E0AF00A0B326 /* ViewController.m */; };
16 | 97886DA41DB8E0AF00A0B326 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97886DA31DB8E0AF00A0B326 /* Assets.xcassets */; };
17 | 97886DA71DB8E0AF00A0B326 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97886DA51DB8E0AF00A0B326 /* LaunchScreen.storyboard */; };
18 | 97886DB21DB8E0AF00A0B326 /* TXScrollLabelViewDemoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 97886DB11DB8E0AF00A0B326 /* TXScrollLabelViewDemoTests.m */; };
19 | 97886DBD1DB8E0AF00A0B326 /* TXScrollLabelViewDemoUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 97886DBC1DB8E0AF00A0B326 /* TXScrollLabelViewDemoUITests.m */; };
20 | AF1B25351DF5803200AB8923 /* NSString+AttributedString.m in Sources */ = {isa = PBXBuildFile; fileRef = AF1B25341DF5803200AB8923 /* NSString+AttributedString.m */; };
21 | /* End PBXBuildFile section */
22 |
23 | /* Begin PBXContainerItemProxy section */
24 | 97886DAE1DB8E0AF00A0B326 /* PBXContainerItemProxy */ = {
25 | isa = PBXContainerItemProxy;
26 | containerPortal = 97886D8C1DB8E0AF00A0B326 /* Project object */;
27 | proxyType = 1;
28 | remoteGlobalIDString = 97886D931DB8E0AF00A0B326;
29 | remoteInfo = TXScrollLabelViewDemo;
30 | };
31 | 97886DB91DB8E0AF00A0B326 /* PBXContainerItemProxy */ = {
32 | isa = PBXContainerItemProxy;
33 | containerPortal = 97886D8C1DB8E0AF00A0B326 /* Project object */;
34 | proxyType = 1;
35 | remoteGlobalIDString = 97886D931DB8E0AF00A0B326;
36 | remoteInfo = TXScrollLabelViewDemo;
37 | };
38 | /* End PBXContainerItemProxy section */
39 |
40 | /* Begin PBXFileReference section */
41 | 972620C61DDE2F0600009F23 /* TXScrollLabelView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TXScrollLabelView.m; sourceTree = ""; };
42 | 972620C71DDE2F0600009F23 /* TXScrollLabelView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TXScrollLabelView.h; sourceTree = ""; };
43 | 972620C81DDE2F0600009F23 /* UIView+TXFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+TXFrame.h"; sourceTree = ""; };
44 | 972620C91DDE2F0600009F23 /* UIView+TXFrame.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+TXFrame.m"; sourceTree = ""; };
45 | 97883B5D1EBD7A6800552DFE /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; };
46 | 97886D941DB8E0AF00A0B326 /* TXScrollLabelViewDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TXScrollLabelViewDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
47 | 97886D981DB8E0AF00A0B326 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
48 | 97886D9A1DB8E0AF00A0B326 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
49 | 97886D9B1DB8E0AF00A0B326 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
50 | 97886D9D1DB8E0AF00A0B326 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; };
51 | 97886D9E1DB8E0AF00A0B326 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; };
52 | 97886DA31DB8E0AF00A0B326 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
53 | 97886DA61DB8E0AF00A0B326 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
54 | 97886DA81DB8E0AF00A0B326 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
55 | 97886DAD1DB8E0AF00A0B326 /* TXScrollLabelViewDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TXScrollLabelViewDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
56 | 97886DB11DB8E0AF00A0B326 /* TXScrollLabelViewDemoTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TXScrollLabelViewDemoTests.m; sourceTree = ""; };
57 | 97886DB31DB8E0AF00A0B326 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
58 | 97886DB81DB8E0AF00A0B326 /* TXScrollLabelViewDemoUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TXScrollLabelViewDemoUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
59 | 97886DBC1DB8E0AF00A0B326 /* TXScrollLabelViewDemoUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TXScrollLabelViewDemoUITests.m; sourceTree = ""; };
60 | 97886DBE1DB8E0AF00A0B326 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
61 | AF1B25331DF5803200AB8923 /* NSString+AttributedString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+AttributedString.h"; sourceTree = ""; };
62 | AF1B25341DF5803200AB8923 /* NSString+AttributedString.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+AttributedString.m"; sourceTree = ""; };
63 | /* End PBXFileReference section */
64 |
65 | /* Begin PBXFrameworksBuildPhase section */
66 | 97886D911DB8E0AF00A0B326 /* Frameworks */ = {
67 | isa = PBXFrameworksBuildPhase;
68 | buildActionMask = 2147483647;
69 | files = (
70 | );
71 | runOnlyForDeploymentPostprocessing = 0;
72 | };
73 | 97886DAA1DB8E0AF00A0B326 /* Frameworks */ = {
74 | isa = PBXFrameworksBuildPhase;
75 | buildActionMask = 2147483647;
76 | files = (
77 | );
78 | runOnlyForDeploymentPostprocessing = 0;
79 | };
80 | 97886DB51DB8E0AF00A0B326 /* Frameworks */ = {
81 | isa = PBXFrameworksBuildPhase;
82 | buildActionMask = 2147483647;
83 | files = (
84 | );
85 | runOnlyForDeploymentPostprocessing = 0;
86 | };
87 | /* End PBXFrameworksBuildPhase section */
88 |
89 | /* Begin PBXGroup section */
90 | 972620C51DDE2F0600009F23 /* TXScrollLabelView */ = {
91 | isa = PBXGroup;
92 | children = (
93 | 972620C71DDE2F0600009F23 /* TXScrollLabelView.h */,
94 | 972620C61DDE2F0600009F23 /* TXScrollLabelView.m */,
95 | 972620C81DDE2F0600009F23 /* UIView+TXFrame.h */,
96 | 972620C91DDE2F0600009F23 /* UIView+TXFrame.m */,
97 | );
98 | name = TXScrollLabelView;
99 | path = ../../TXScrollLabelView;
100 | sourceTree = "";
101 | };
102 | 97886D8B1DB8E0AF00A0B326 = {
103 | isa = PBXGroup;
104 | children = (
105 | 97886D961DB8E0AF00A0B326 /* TXScrollLabelViewDemo */,
106 | 97886DB01DB8E0AF00A0B326 /* TXScrollLabelViewDemoTests */,
107 | 97886DBB1DB8E0AF00A0B326 /* TXScrollLabelViewDemoUITests */,
108 | 97886D951DB8E0AF00A0B326 /* Products */,
109 | );
110 | sourceTree = "";
111 | };
112 | 97886D951DB8E0AF00A0B326 /* Products */ = {
113 | isa = PBXGroup;
114 | children = (
115 | 97886D941DB8E0AF00A0B326 /* TXScrollLabelViewDemo.app */,
116 | 97886DAD1DB8E0AF00A0B326 /* TXScrollLabelViewDemoTests.xctest */,
117 | 97886DB81DB8E0AF00A0B326 /* TXScrollLabelViewDemoUITests.xctest */,
118 | );
119 | name = Products;
120 | sourceTree = "";
121 | };
122 | 97886D961DB8E0AF00A0B326 /* TXScrollLabelViewDemo */ = {
123 | isa = PBXGroup;
124 | children = (
125 | 972620C51DDE2F0600009F23 /* TXScrollLabelView */,
126 | 97886D9A1DB8E0AF00A0B326 /* AppDelegate.h */,
127 | 97886D9B1DB8E0AF00A0B326 /* AppDelegate.m */,
128 | 97886D9D1DB8E0AF00A0B326 /* ViewController.h */,
129 | 97886D9E1DB8E0AF00A0B326 /* ViewController.m */,
130 | AF1B25331DF5803200AB8923 /* NSString+AttributedString.h */,
131 | AF1B25341DF5803200AB8923 /* NSString+AttributedString.m */,
132 | 97886DA31DB8E0AF00A0B326 /* Assets.xcassets */,
133 | 97886DA51DB8E0AF00A0B326 /* LaunchScreen.storyboard */,
134 | 97886DA81DB8E0AF00A0B326 /* Info.plist */,
135 | 97883B5D1EBD7A6800552DFE /* Main.storyboard */,
136 | 97886D971DB8E0AF00A0B326 /* Supporting Files */,
137 | );
138 | path = TXScrollLabelViewDemo;
139 | sourceTree = "";
140 | };
141 | 97886D971DB8E0AF00A0B326 /* Supporting Files */ = {
142 | isa = PBXGroup;
143 | children = (
144 | 97886D981DB8E0AF00A0B326 /* main.m */,
145 | );
146 | name = "Supporting Files";
147 | sourceTree = "";
148 | };
149 | 97886DB01DB8E0AF00A0B326 /* TXScrollLabelViewDemoTests */ = {
150 | isa = PBXGroup;
151 | children = (
152 | 97886DB11DB8E0AF00A0B326 /* TXScrollLabelViewDemoTests.m */,
153 | 97886DB31DB8E0AF00A0B326 /* Info.plist */,
154 | );
155 | path = TXScrollLabelViewDemoTests;
156 | sourceTree = "";
157 | };
158 | 97886DBB1DB8E0AF00A0B326 /* TXScrollLabelViewDemoUITests */ = {
159 | isa = PBXGroup;
160 | children = (
161 | 97886DBC1DB8E0AF00A0B326 /* TXScrollLabelViewDemoUITests.m */,
162 | 97886DBE1DB8E0AF00A0B326 /* Info.plist */,
163 | );
164 | path = TXScrollLabelViewDemoUITests;
165 | sourceTree = "";
166 | };
167 | /* End PBXGroup section */
168 |
169 | /* Begin PBXNativeTarget section */
170 | 97886D931DB8E0AF00A0B326 /* TXScrollLabelViewDemo */ = {
171 | isa = PBXNativeTarget;
172 | buildConfigurationList = 97886DC11DB8E0AF00A0B326 /* Build configuration list for PBXNativeTarget "TXScrollLabelViewDemo" */;
173 | buildPhases = (
174 | 97886D901DB8E0AF00A0B326 /* Sources */,
175 | 97886D911DB8E0AF00A0B326 /* Frameworks */,
176 | 97886D921DB8E0AF00A0B326 /* Resources */,
177 | );
178 | buildRules = (
179 | );
180 | dependencies = (
181 | );
182 | name = TXScrollLabelViewDemo;
183 | productName = TXScrollLabelViewDemo;
184 | productReference = 97886D941DB8E0AF00A0B326 /* TXScrollLabelViewDemo.app */;
185 | productType = "com.apple.product-type.application";
186 | };
187 | 97886DAC1DB8E0AF00A0B326 /* TXScrollLabelViewDemoTests */ = {
188 | isa = PBXNativeTarget;
189 | buildConfigurationList = 97886DC41DB8E0AF00A0B326 /* Build configuration list for PBXNativeTarget "TXScrollLabelViewDemoTests" */;
190 | buildPhases = (
191 | 97886DA91DB8E0AF00A0B326 /* Sources */,
192 | 97886DAA1DB8E0AF00A0B326 /* Frameworks */,
193 | 97886DAB1DB8E0AF00A0B326 /* Resources */,
194 | );
195 | buildRules = (
196 | );
197 | dependencies = (
198 | 97886DAF1DB8E0AF00A0B326 /* PBXTargetDependency */,
199 | );
200 | name = TXScrollLabelViewDemoTests;
201 | productName = TXScrollLabelViewDemoTests;
202 | productReference = 97886DAD1DB8E0AF00A0B326 /* TXScrollLabelViewDemoTests.xctest */;
203 | productType = "com.apple.product-type.bundle.unit-test";
204 | };
205 | 97886DB71DB8E0AF00A0B326 /* TXScrollLabelViewDemoUITests */ = {
206 | isa = PBXNativeTarget;
207 | buildConfigurationList = 97886DC71DB8E0AF00A0B326 /* Build configuration list for PBXNativeTarget "TXScrollLabelViewDemoUITests" */;
208 | buildPhases = (
209 | 97886DB41DB8E0AF00A0B326 /* Sources */,
210 | 97886DB51DB8E0AF00A0B326 /* Frameworks */,
211 | 97886DB61DB8E0AF00A0B326 /* Resources */,
212 | );
213 | buildRules = (
214 | );
215 | dependencies = (
216 | 97886DBA1DB8E0AF00A0B326 /* PBXTargetDependency */,
217 | );
218 | name = TXScrollLabelViewDemoUITests;
219 | productName = TXScrollLabelViewDemoUITests;
220 | productReference = 97886DB81DB8E0AF00A0B326 /* TXScrollLabelViewDemoUITests.xctest */;
221 | productType = "com.apple.product-type.bundle.ui-testing";
222 | };
223 | /* End PBXNativeTarget section */
224 |
225 | /* Begin PBXProject section */
226 | 97886D8C1DB8E0AF00A0B326 /* Project object */ = {
227 | isa = PBXProject;
228 | attributes = {
229 | LastUpgradeCheck = 0810;
230 | ORGANIZATIONNAME = tingxins;
231 | TargetAttributes = {
232 | 97886D931DB8E0AF00A0B326 = {
233 | CreatedOnToolsVersion = 8.0;
234 | DevelopmentTeam = QZ2B7EZFJP;
235 | ProvisioningStyle = Automatic;
236 | };
237 | 97886DAC1DB8E0AF00A0B326 = {
238 | CreatedOnToolsVersion = 8.0;
239 | DevelopmentTeam = X37JS8D42G;
240 | ProvisioningStyle = Automatic;
241 | TestTargetID = 97886D931DB8E0AF00A0B326;
242 | };
243 | 97886DB71DB8E0AF00A0B326 = {
244 | CreatedOnToolsVersion = 8.0;
245 | DevelopmentTeam = X37JS8D42G;
246 | ProvisioningStyle = Automatic;
247 | TestTargetID = 97886D931DB8E0AF00A0B326;
248 | };
249 | };
250 | };
251 | buildConfigurationList = 97886D8F1DB8E0AF00A0B326 /* Build configuration list for PBXProject "TXScrollLabelViewDemo" */;
252 | compatibilityVersion = "Xcode 3.2";
253 | developmentRegion = English;
254 | hasScannedForEncodings = 0;
255 | knownRegions = (
256 | en,
257 | Base,
258 | );
259 | mainGroup = 97886D8B1DB8E0AF00A0B326;
260 | productRefGroup = 97886D951DB8E0AF00A0B326 /* Products */;
261 | projectDirPath = "";
262 | projectRoot = "";
263 | targets = (
264 | 97886D931DB8E0AF00A0B326 /* TXScrollLabelViewDemo */,
265 | 97886DAC1DB8E0AF00A0B326 /* TXScrollLabelViewDemoTests */,
266 | 97886DB71DB8E0AF00A0B326 /* TXScrollLabelViewDemoUITests */,
267 | );
268 | };
269 | /* End PBXProject section */
270 |
271 | /* Begin PBXResourcesBuildPhase section */
272 | 97886D921DB8E0AF00A0B326 /* Resources */ = {
273 | isa = PBXResourcesBuildPhase;
274 | buildActionMask = 2147483647;
275 | files = (
276 | 97883B5E1EBD7A6800552DFE /* Main.storyboard in Resources */,
277 | 97886DA71DB8E0AF00A0B326 /* LaunchScreen.storyboard in Resources */,
278 | 97886DA41DB8E0AF00A0B326 /* Assets.xcassets in Resources */,
279 | );
280 | runOnlyForDeploymentPostprocessing = 0;
281 | };
282 | 97886DAB1DB8E0AF00A0B326 /* Resources */ = {
283 | isa = PBXResourcesBuildPhase;
284 | buildActionMask = 2147483647;
285 | files = (
286 | );
287 | runOnlyForDeploymentPostprocessing = 0;
288 | };
289 | 97886DB61DB8E0AF00A0B326 /* Resources */ = {
290 | isa = PBXResourcesBuildPhase;
291 | buildActionMask = 2147483647;
292 | files = (
293 | );
294 | runOnlyForDeploymentPostprocessing = 0;
295 | };
296 | /* End PBXResourcesBuildPhase section */
297 |
298 | /* Begin PBXSourcesBuildPhase section */
299 | 97886D901DB8E0AF00A0B326 /* Sources */ = {
300 | isa = PBXSourcesBuildPhase;
301 | buildActionMask = 2147483647;
302 | files = (
303 | 972620CB1DDE2F0600009F23 /* UIView+TXFrame.m in Sources */,
304 | 972620CA1DDE2F0600009F23 /* TXScrollLabelView.m in Sources */,
305 | 97886D9F1DB8E0AF00A0B326 /* ViewController.m in Sources */,
306 | 97886D9C1DB8E0AF00A0B326 /* AppDelegate.m in Sources */,
307 | AF1B25351DF5803200AB8923 /* NSString+AttributedString.m in Sources */,
308 | 97886D991DB8E0AF00A0B326 /* main.m in Sources */,
309 | );
310 | runOnlyForDeploymentPostprocessing = 0;
311 | };
312 | 97886DA91DB8E0AF00A0B326 /* Sources */ = {
313 | isa = PBXSourcesBuildPhase;
314 | buildActionMask = 2147483647;
315 | files = (
316 | 97886DB21DB8E0AF00A0B326 /* TXScrollLabelViewDemoTests.m in Sources */,
317 | );
318 | runOnlyForDeploymentPostprocessing = 0;
319 | };
320 | 97886DB41DB8E0AF00A0B326 /* Sources */ = {
321 | isa = PBXSourcesBuildPhase;
322 | buildActionMask = 2147483647;
323 | files = (
324 | 97886DBD1DB8E0AF00A0B326 /* TXScrollLabelViewDemoUITests.m in Sources */,
325 | );
326 | runOnlyForDeploymentPostprocessing = 0;
327 | };
328 | /* End PBXSourcesBuildPhase section */
329 |
330 | /* Begin PBXTargetDependency section */
331 | 97886DAF1DB8E0AF00A0B326 /* PBXTargetDependency */ = {
332 | isa = PBXTargetDependency;
333 | target = 97886D931DB8E0AF00A0B326 /* TXScrollLabelViewDemo */;
334 | targetProxy = 97886DAE1DB8E0AF00A0B326 /* PBXContainerItemProxy */;
335 | };
336 | 97886DBA1DB8E0AF00A0B326 /* PBXTargetDependency */ = {
337 | isa = PBXTargetDependency;
338 | target = 97886D931DB8E0AF00A0B326 /* TXScrollLabelViewDemo */;
339 | targetProxy = 97886DB91DB8E0AF00A0B326 /* PBXContainerItemProxy */;
340 | };
341 | /* End PBXTargetDependency section */
342 |
343 | /* Begin PBXVariantGroup section */
344 | 97886DA51DB8E0AF00A0B326 /* LaunchScreen.storyboard */ = {
345 | isa = PBXVariantGroup;
346 | children = (
347 | 97886DA61DB8E0AF00A0B326 /* Base */,
348 | );
349 | name = LaunchScreen.storyboard;
350 | sourceTree = "";
351 | };
352 | /* End PBXVariantGroup section */
353 |
354 | /* Begin XCBuildConfiguration section */
355 | 97886DBF1DB8E0AF00A0B326 /* Debug */ = {
356 | isa = XCBuildConfiguration;
357 | buildSettings = {
358 | ALWAYS_SEARCH_USER_PATHS = NO;
359 | CLANG_ANALYZER_NONNULL = YES;
360 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
361 | CLANG_CXX_LIBRARY = "libc++";
362 | CLANG_ENABLE_MODULES = YES;
363 | CLANG_ENABLE_OBJC_ARC = YES;
364 | CLANG_WARN_BOOL_CONVERSION = YES;
365 | CLANG_WARN_CONSTANT_CONVERSION = YES;
366 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
367 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
368 | CLANG_WARN_EMPTY_BODY = YES;
369 | CLANG_WARN_ENUM_CONVERSION = YES;
370 | CLANG_WARN_INFINITE_RECURSION = YES;
371 | CLANG_WARN_INT_CONVERSION = YES;
372 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
373 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
374 | CLANG_WARN_SUSPICIOUS_MOVES = YES;
375 | CLANG_WARN_UNREACHABLE_CODE = YES;
376 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
377 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
378 | COPY_PHASE_STRIP = NO;
379 | DEBUG_INFORMATION_FORMAT = dwarf;
380 | ENABLE_STRICT_OBJC_MSGSEND = YES;
381 | ENABLE_TESTABILITY = YES;
382 | GCC_C_LANGUAGE_STANDARD = gnu99;
383 | GCC_DYNAMIC_NO_PIC = NO;
384 | GCC_NO_COMMON_BLOCKS = YES;
385 | GCC_OPTIMIZATION_LEVEL = 0;
386 | GCC_PREPROCESSOR_DEFINITIONS = (
387 | "DEBUG=1",
388 | "$(inherited)",
389 | );
390 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
391 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
392 | GCC_WARN_UNDECLARED_SELECTOR = YES;
393 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
394 | GCC_WARN_UNUSED_FUNCTION = YES;
395 | GCC_WARN_UNUSED_VARIABLE = YES;
396 | IPHONEOS_DEPLOYMENT_TARGET = 10.0;
397 | MTL_ENABLE_DEBUG_INFO = YES;
398 | ONLY_ACTIVE_ARCH = YES;
399 | SDKROOT = iphoneos;
400 | };
401 | name = Debug;
402 | };
403 | 97886DC01DB8E0AF00A0B326 /* Release */ = {
404 | isa = XCBuildConfiguration;
405 | buildSettings = {
406 | ALWAYS_SEARCH_USER_PATHS = NO;
407 | CLANG_ANALYZER_NONNULL = YES;
408 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
409 | CLANG_CXX_LIBRARY = "libc++";
410 | CLANG_ENABLE_MODULES = YES;
411 | CLANG_ENABLE_OBJC_ARC = YES;
412 | CLANG_WARN_BOOL_CONVERSION = YES;
413 | CLANG_WARN_CONSTANT_CONVERSION = YES;
414 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
415 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
416 | CLANG_WARN_EMPTY_BODY = YES;
417 | CLANG_WARN_ENUM_CONVERSION = YES;
418 | CLANG_WARN_INFINITE_RECURSION = YES;
419 | CLANG_WARN_INT_CONVERSION = YES;
420 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
421 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
422 | CLANG_WARN_SUSPICIOUS_MOVES = YES;
423 | CLANG_WARN_UNREACHABLE_CODE = YES;
424 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
425 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
426 | COPY_PHASE_STRIP = NO;
427 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
428 | ENABLE_NS_ASSERTIONS = NO;
429 | ENABLE_STRICT_OBJC_MSGSEND = YES;
430 | GCC_C_LANGUAGE_STANDARD = gnu99;
431 | GCC_NO_COMMON_BLOCKS = YES;
432 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
433 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
434 | GCC_WARN_UNDECLARED_SELECTOR = YES;
435 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
436 | GCC_WARN_UNUSED_FUNCTION = YES;
437 | GCC_WARN_UNUSED_VARIABLE = YES;
438 | IPHONEOS_DEPLOYMENT_TARGET = 10.0;
439 | MTL_ENABLE_DEBUG_INFO = NO;
440 | SDKROOT = iphoneos;
441 | VALIDATE_PRODUCT = YES;
442 | };
443 | name = Release;
444 | };
445 | 97886DC21DB8E0AF00A0B326 /* Debug */ = {
446 | isa = XCBuildConfiguration;
447 | buildSettings = {
448 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
449 | DEVELOPMENT_TEAM = QZ2B7EZFJP;
450 | INFOPLIST_FILE = TXScrollLabelViewDemo/Info.plist;
451 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
452 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
453 | PRODUCT_BUNDLE_IDENTIFIER = com.tingxins.demo.TXScrollLabelViewDemo;
454 | PRODUCT_NAME = "$(TARGET_NAME)";
455 | };
456 | name = Debug;
457 | };
458 | 97886DC31DB8E0AF00A0B326 /* Release */ = {
459 | isa = XCBuildConfiguration;
460 | buildSettings = {
461 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
462 | DEVELOPMENT_TEAM = QZ2B7EZFJP;
463 | INFOPLIST_FILE = TXScrollLabelViewDemo/Info.plist;
464 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
465 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
466 | PRODUCT_BUNDLE_IDENTIFIER = com.tingxins.demo.TXScrollLabelViewDemo;
467 | PRODUCT_NAME = "$(TARGET_NAME)";
468 | };
469 | name = Release;
470 | };
471 | 97886DC51DB8E0AF00A0B326 /* Debug */ = {
472 | isa = XCBuildConfiguration;
473 | buildSettings = {
474 | BUNDLE_LOADER = "$(TEST_HOST)";
475 | DEVELOPMENT_TEAM = X37JS8D42G;
476 | INFOPLIST_FILE = TXScrollLabelViewDemoTests/Info.plist;
477 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
478 | PRODUCT_BUNDLE_IDENTIFIER = com.tingxins.TXScrollLabelViewDemoTests;
479 | PRODUCT_NAME = "$(TARGET_NAME)";
480 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/TXScrollLabelViewDemo.app/TXScrollLabelViewDemo";
481 | };
482 | name = Debug;
483 | };
484 | 97886DC61DB8E0AF00A0B326 /* Release */ = {
485 | isa = XCBuildConfiguration;
486 | buildSettings = {
487 | BUNDLE_LOADER = "$(TEST_HOST)";
488 | DEVELOPMENT_TEAM = X37JS8D42G;
489 | INFOPLIST_FILE = TXScrollLabelViewDemoTests/Info.plist;
490 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
491 | PRODUCT_BUNDLE_IDENTIFIER = com.tingxins.TXScrollLabelViewDemoTests;
492 | PRODUCT_NAME = "$(TARGET_NAME)";
493 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/TXScrollLabelViewDemo.app/TXScrollLabelViewDemo";
494 | };
495 | name = Release;
496 | };
497 | 97886DC81DB8E0AF00A0B326 /* Debug */ = {
498 | isa = XCBuildConfiguration;
499 | buildSettings = {
500 | DEVELOPMENT_TEAM = X37JS8D42G;
501 | INFOPLIST_FILE = TXScrollLabelViewDemoUITests/Info.plist;
502 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
503 | PRODUCT_BUNDLE_IDENTIFIER = com.tingxins.TXScrollLabelViewDemoUITests;
504 | PRODUCT_NAME = "$(TARGET_NAME)";
505 | TEST_TARGET_NAME = TXScrollLabelViewDemo;
506 | };
507 | name = Debug;
508 | };
509 | 97886DC91DB8E0AF00A0B326 /* Release */ = {
510 | isa = XCBuildConfiguration;
511 | buildSettings = {
512 | DEVELOPMENT_TEAM = X37JS8D42G;
513 | INFOPLIST_FILE = TXScrollLabelViewDemoUITests/Info.plist;
514 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
515 | PRODUCT_BUNDLE_IDENTIFIER = com.tingxins.TXScrollLabelViewDemoUITests;
516 | PRODUCT_NAME = "$(TARGET_NAME)";
517 | TEST_TARGET_NAME = TXScrollLabelViewDemo;
518 | };
519 | name = Release;
520 | };
521 | /* End XCBuildConfiguration section */
522 |
523 | /* Begin XCConfigurationList section */
524 | 97886D8F1DB8E0AF00A0B326 /* Build configuration list for PBXProject "TXScrollLabelViewDemo" */ = {
525 | isa = XCConfigurationList;
526 | buildConfigurations = (
527 | 97886DBF1DB8E0AF00A0B326 /* Debug */,
528 | 97886DC01DB8E0AF00A0B326 /* Release */,
529 | );
530 | defaultConfigurationIsVisible = 0;
531 | defaultConfigurationName = Release;
532 | };
533 | 97886DC11DB8E0AF00A0B326 /* Build configuration list for PBXNativeTarget "TXScrollLabelViewDemo" */ = {
534 | isa = XCConfigurationList;
535 | buildConfigurations = (
536 | 97886DC21DB8E0AF00A0B326 /* Debug */,
537 | 97886DC31DB8E0AF00A0B326 /* Release */,
538 | );
539 | defaultConfigurationIsVisible = 0;
540 | defaultConfigurationName = Release;
541 | };
542 | 97886DC41DB8E0AF00A0B326 /* Build configuration list for PBXNativeTarget "TXScrollLabelViewDemoTests" */ = {
543 | isa = XCConfigurationList;
544 | buildConfigurations = (
545 | 97886DC51DB8E0AF00A0B326 /* Debug */,
546 | 97886DC61DB8E0AF00A0B326 /* Release */,
547 | );
548 | defaultConfigurationIsVisible = 0;
549 | defaultConfigurationName = Release;
550 | };
551 | 97886DC71DB8E0AF00A0B326 /* Build configuration list for PBXNativeTarget "TXScrollLabelViewDemoUITests" */ = {
552 | isa = XCConfigurationList;
553 | buildConfigurations = (
554 | 97886DC81DB8E0AF00A0B326 /* Debug */,
555 | 97886DC91DB8E0AF00A0B326 /* Release */,
556 | );
557 | defaultConfigurationIsVisible = 0;
558 | defaultConfigurationName = Release;
559 | };
560 | /* End XCConfigurationList section */
561 | };
562 | rootObject = 97886D8C1DB8E0AF00A0B326 /* Project object */;
563 | }
564 |
--------------------------------------------------------------------------------
/TXScrollLabelViewDemo/TXScrollLabelViewDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/TXScrollLabelViewDemo/TXScrollLabelViewDemo.xcodeproj/xcshareddata/xcschemes/TXScrollLabelViewDemo.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
43 |
49 |
50 |
51 |
52 |
53 |
59 |
60 |
61 |
62 |
63 |
64 |
74 |
76 |
82 |
83 |
84 |
85 |
86 |
87 |
93 |
95 |
101 |
102 |
103 |
104 |
106 |
107 |
110 |
111 |
112 |
--------------------------------------------------------------------------------
/TXScrollLabelViewDemo/TXScrollLabelViewDemo/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // TXScrollLabelViewDemo
4 | //
5 | // Created by tingxins on 20/10/2016.
6 | // Copyright © 2016 tingxins. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface AppDelegate : UIResponder
12 |
13 | @property (strong, nonatomic) UIWindow *window;
14 |
15 |
16 | @end
17 |
18 |
--------------------------------------------------------------------------------
/TXScrollLabelViewDemo/TXScrollLabelViewDemo/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // TXScrollLabelViewDemo
4 | //
5 | // Created by tingxins on 20/10/2016.
6 | // Copyright © 2016 tingxins. All rights reserved.
7 | //
8 |
9 | #import "AppDelegate.h"
10 | #import "ViewController.h"
11 |
12 | @interface AppDelegate ()
13 |
14 | @end
15 |
16 | @implementation AppDelegate
17 |
18 |
19 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
20 | // Override point for customization after application launch.
21 | // self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
22 | // self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:[[ViewController alloc] init]];
23 | // [self.window makeKeyAndVisible];
24 |
25 | return YES;
26 | }
27 |
28 |
29 | - (void)applicationWillResignActive:(UIApplication *)application {
30 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
31 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
32 | }
33 |
34 |
35 | - (void)applicationDidEnterBackground:(UIApplication *)application {
36 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
37 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
38 | }
39 |
40 |
41 | - (void)applicationWillEnterForeground:(UIApplication *)application {
42 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
43 | }
44 |
45 |
46 | - (void)applicationDidBecomeActive:(UIApplication *)application {
47 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
48 | }
49 |
50 |
51 | - (void)applicationWillTerminate:(UIApplication *)application {
52 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
53 | }
54 |
55 |
56 | @end
57 |
--------------------------------------------------------------------------------
/TXScrollLabelViewDemo/TXScrollLabelViewDemo/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | }
43 | ],
44 | "info" : {
45 | "version" : 1,
46 | "author" : "xcode"
47 | }
48 | }
--------------------------------------------------------------------------------
/TXScrollLabelViewDemo/TXScrollLabelViewDemo/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/TXScrollLabelViewDemo/TXScrollLabelViewDemo/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | ScrollLabel
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/TXScrollLabelViewDemo/TXScrollLabelViewDemo/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
59 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
86 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
--------------------------------------------------------------------------------
/TXScrollLabelViewDemo/TXScrollLabelViewDemo/NSString+AttributedString.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSString+AttributedString.h
3 | // TXScrollLabelViewDemo
4 | //
5 | // Created by 陈应平 on 2016/12/5.
6 | // Copyright © 2016年 tingxins. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface NSString (AttributedString)
12 |
13 | // 传递一个字符串数组,可以渲染不同的颜色,后期有需要可以把 color 和 font 也以数组的形式传递,配对使用
14 | - (NSMutableAttributedString *)setAttributedWithIdentifyStringArray:(NSArray *)identifyStringArray color:(UIColor *)color font:(UIFont *)font;
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/TXScrollLabelViewDemo/TXScrollLabelViewDemo/NSString+AttributedString.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSString+AttributedString.m
3 | // TXScrollLabelViewDemo
4 | //
5 | // Created by 陈应平 on 2016/12/5.
6 | // Copyright © 2016年 tingxins. All rights reserved.
7 | //
8 |
9 | #import "NSString+AttributedString.h"
10 |
11 | @implementation NSString (AttributedString)
12 |
13 | - (NSMutableAttributedString *)setAttributedWithIdentifyStringArray:(NSArray *)identifyStringArray color:(UIColor *)color font:(UIFont *)font
14 | {
15 | if (!self && !identifyStringArray) {
16 | return nil;
17 | }
18 |
19 | if (!identifyStringArray.count) {
20 | return nil;
21 | }
22 |
23 | NSMutableAttributedString *attributedStr = [[NSMutableAttributedString alloc]initWithString:self];
24 | for (NSString *identifyString in identifyStringArray) {
25 | NSRange range = [self rangeOfString:identifyString];
26 | if (font) {
27 | [attributedStr addAttribute:NSFontAttributeName value:font range:range];
28 | }
29 | if (color) {
30 | [attributedStr addAttribute:NSForegroundColorAttributeName value:color range:range];
31 | }
32 | }
33 |
34 | return attributedStr;
35 | }
36 |
37 | @end
38 |
--------------------------------------------------------------------------------
/TXScrollLabelViewDemo/TXScrollLabelViewDemo/ViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.h
3 | // TXScrollLabelViewDemo
4 | //
5 | // Created by tingxins on 20/10/2016.
6 | // Copyright © 2016 tingxins. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ViewController : UIViewController
12 |
13 | @property (assign, nonatomic) IBInspectable BOOL isArray;
14 |
15 | @end
16 |
17 |
--------------------------------------------------------------------------------
/TXScrollLabelViewDemo/TXScrollLabelViewDemo/ViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.m
3 | // TXScrollLabelViewDemo
4 | //
5 | // Created by tingxins on 20/10/2016.
6 | // Copyright © 2016 tingxins. All rights reserved.
7 | // 如果在使用 TXScrollLabelView 的过程中出现bug,请及时联系,我会尽快进行修复。如果有更好的点子,直接 Open an issue 或者 submit a pr。
8 | /**
9 | Blog : https://tingxins.com
10 | 简书 :http://www.jianshu.com/u/5141561e4d59
11 | GitHub : https://github.com/tingxins
12 | Weibo : http://weibo.com/tingxins
13 | Twitter : http://twitter.com/tingxins
14 | */
15 |
16 | #import "ViewController.h"
17 | #import "TXScrollLabelView.h"
18 |
19 | @interface ViewController ()
20 |
21 | @property (weak, nonatomic) TXScrollLabelView *scrollLabelView;
22 |
23 | @end
24 |
25 | @implementation ViewController
26 |
27 | - (void)viewDidLoad {
28 | [super viewDidLoad];
29 |
30 | [self setViewInfos];
31 |
32 | [self setSubviews];
33 |
34 | }
35 |
36 | - (void)setViewInfos {
37 | self.view.backgroundColor = [UIColor whiteColor];
38 | self.navigationController.navigationBar.translucent = NO;
39 | self.title = @"TXScrollLabelView";
40 | }
41 |
42 | - (void)setSubviews {
43 |
44 | [self addWith:TXScrollLabelViewTypeLeftRight velocity:1 isArray:_isArray];
45 |
46 | [self addWith:TXScrollLabelViewTypeUpDown velocity:2 isArray:_isArray];
47 |
48 | [self addWith:TXScrollLabelViewTypeFlipRepeat velocity:2 isArray:_isArray];
49 |
50 | [self addWith:TXScrollLabelViewTypeFlipNoRepeat velocity:2 isArray:_isArray];
51 | }
52 |
53 | - (void)addWith:(TXScrollLabelViewType)type velocity:(CGFloat)velocity isArray:(BOOL)isArray {
54 | /** Step1: 滚动文字 */
55 |
56 | NSString *scrollTitle = @"如果在使用 TXScrollLabelView 的过程中出现bug,请及时联系,我会尽快进行修复。如果有更好的点子,直接 Open an issue 或者 submit a pr on GitHub。Thanks.";
57 |
58 | NSArray *scrollTexts = @[@"If you need help or ask general question,",
59 | @"just @tingxins in Weibo or Twitter, ofcourse, you can follow me. Welcome access to my blog.",
60 | @"If you found a bug, just open an issue.",
61 | @"If you have a feature request, just open an issue.",
62 | @"If you want to contribute, fork this repository, and then submit a pull request.",
63 | @"Blog : https://tingxins.com",
64 | @"简书 :http://www.jianshu.com/u/5141561e4d59",
65 | @"GitHub : https://github.com/tingxins",
66 | @"Weibo : http://weibo.com/tingxins",
67 | @"Twitter : http://twitter.com/tingxins"];
68 |
69 | /** Step2: 创建 ScrollLabelView */
70 | TXScrollLabelView *scrollLabelView = nil;
71 | if (isArray) {
72 | scrollLabelView = [TXScrollLabelView scrollWithTextArray:scrollTexts type:type velocity:velocity options:UIViewAnimationOptionCurveEaseInOut inset:UIEdgeInsetsZero];
73 | }else {
74 | scrollLabelView = [TXScrollLabelView scrollWithTitle:scrollTitle type:type velocity:velocity options:UIViewAnimationOptionCurveEaseInOut];
75 | }
76 |
77 | /** Step3: 设置代理进行回调 */
78 | scrollLabelView.scrollLabelViewDelegate = self;
79 |
80 | /** Step4: 布局(Required) */
81 | scrollLabelView.frame = CGRectMake(50, 100 * (type + 0.7), 300, 30);
82 |
83 | [self.view addSubview:scrollLabelView];
84 |
85 | //偏好(Optional), Preference,if you want.
86 | scrollLabelView.tx_centerX = [UIScreen mainScreen].bounds.size.width * 0.5;
87 | scrollLabelView.scrollInset = UIEdgeInsetsMake(0, 10 , 0, 10);
88 | scrollLabelView.scrollSpace = 10;
89 | scrollLabelView.font = [UIFont systemFontOfSize:15];
90 | scrollLabelView.textAlignment = NSTextAlignmentCenter;
91 | scrollLabelView.backgroundColor = [UIColor blackColor];
92 | scrollLabelView.layer.cornerRadius = 5;
93 |
94 | /** Step5: 开始滚动(Start scrolling!) */
95 | [scrollLabelView beginScrolling];
96 | }
97 |
98 | - (void)scrollLabelView:(TXScrollLabelView *)scrollLabelView didClickWithText:(NSString *)text atIndex:(NSInteger)index{
99 | NSLog(@"%@--%ld",text, index);
100 | }
101 |
102 | @end
103 |
--------------------------------------------------------------------------------
/TXScrollLabelViewDemo/TXScrollLabelViewDemo/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // TXScrollLabelViewDemo
4 | //
5 | // Created by tingxins on 20/10/2016.
6 | // Copyright © 2016 tingxins. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "AppDelegate.h"
11 |
12 | int main(int argc, char * argv[]) {
13 | @autoreleasepool {
14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/TXScrollLabelViewDemo/TXScrollLabelViewDemoTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/TXScrollLabelViewDemo/TXScrollLabelViewDemoTests/TXScrollLabelViewDemoTests.m:
--------------------------------------------------------------------------------
1 | //
2 | // TXScrollLabelViewDemoTests.m
3 | // TXScrollLabelViewDemoTests
4 | //
5 | // Created by tingxins on 20/10/2016.
6 | // Copyright © 2016 tingxins. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface TXScrollLabelViewDemoTests : XCTestCase
12 |
13 | @end
14 |
15 | @implementation TXScrollLabelViewDemoTests
16 |
17 | - (void)setUp {
18 | [super setUp];
19 | // Put setup code here. This method is called before the invocation of each test method in the class.
20 | }
21 |
22 | - (void)tearDown {
23 | // Put teardown code here. This method is called after the invocation of each test method in the class.
24 | [super tearDown];
25 | }
26 |
27 | - (void)testExample {
28 | // This is an example of a functional test case.
29 | // Use XCTAssert and related functions to verify your tests produce the correct results.
30 | }
31 |
32 | - (void)testPerformanceExample {
33 | // This is an example of a performance test case.
34 | [self measureBlock:^{
35 | // Put the code you want to measure the time of here.
36 | }];
37 | }
38 |
39 | @end
40 |
--------------------------------------------------------------------------------
/TXScrollLabelViewDemo/TXScrollLabelViewDemoUITests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/TXScrollLabelViewDemo/TXScrollLabelViewDemoUITests/TXScrollLabelViewDemoUITests.m:
--------------------------------------------------------------------------------
1 | //
2 | // TXScrollLabelViewDemoUITests.m
3 | // TXScrollLabelViewDemoUITests
4 | //
5 | // Created by tingxins on 20/10/2016.
6 | // Copyright © 2016 tingxins. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface TXScrollLabelViewDemoUITests : XCTestCase
12 |
13 | @end
14 |
15 | @implementation TXScrollLabelViewDemoUITests
16 |
17 | - (void)setUp {
18 | [super setUp];
19 |
20 | // Put setup code here. This method is called before the invocation of each test method in the class.
21 |
22 | // In UI tests it is usually best to stop immediately when a failure occurs.
23 | self.continueAfterFailure = NO;
24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
25 | [[[XCUIApplication alloc] init] launch];
26 |
27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
28 | }
29 |
30 | - (void)tearDown {
31 | // Put teardown code here. This method is called after the invocation of each test method in the class.
32 | [super tearDown];
33 | }
34 |
35 | - (void)testExample {
36 | // Use recording to get started writing UI tests.
37 | // Use XCTAssert and related functions to verify your tests produce the correct results.
38 | }
39 |
40 | @end
41 |
--------------------------------------------------------------------------------