口袋优选

MarqueeLabel.h 20KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  1. //
  2. // MarqueeLabel.h
  3. //
  4. // Created by Charles Powell on 1/31/11.
  5. // Copyright (c) 2011-2015 Charles Powell. All rights reserved.
  6. //
  7. #import <UIKit/UIKit.h>
  8. /** An enum that defines the types of `MarqueeLabel` scrolling */
  9. typedef NS_ENUM(NSUInteger, MarqueeType) {
  10. /** Scrolls left first, then back right to the original position. */
  11. MLLeftRight = 0,
  12. /** Scrolls right first, then back left to the original position. */
  13. MLRightLeft = 1,
  14. /** Continuously scrolls left (with a pause at the original position if animationDelay is set). See the `trailingBuffer` property to define a spacing between the repeating strings.*/
  15. MLContinuous = 2,
  16. /** Continuously scrolls right (with a pause at the original position if animationDelay is set). See the `trailingBuffer` property to define a spacing between the repeating strings.*/
  17. MLContinuousReverse = 3,
  18. /** Scrolls left first, then does not return to the original position. */
  19. MLLeft = 4,
  20. /** Scrolls right first, then does not return to the original position. */
  21. MLRight = 5
  22. };
  23. #ifndef IBInspectable
  24. #define IBInspectable
  25. #endif
  26. /**
  27. MarqueeLabel is a UILabel subclass adds a scrolling marquee effect when the text of a label instance outgrows the available width. Instances of `MarqueeLabel` can be configured
  28. for label scrolling direction/looping, speed/rate, and other options.
  29. */
  30. //IB_DESIGNABLE
  31. @interface MarqueeLabel : UILabel <CAAnimationDelegate>
  32. ////////////////////////////////////////////////////////////////////////////////
  33. /// @name Creating MarqueeLabels
  34. ////////////////////////////////////////////////////////////////////////////////
  35. /** Returns a newly initialized `MarqueeLabel` instance.
  36. The default scroll duration of 7.0 seconds and fade length of 0.0 are used.
  37. @param frame A rectangle specifying the initial location and size of the view in its superview's coordinates. Text (for the given font, font size, etc.) that does not fit in this frame will automatically scroll.
  38. @return An initialized `MarqueeLabel` object or nil if the object couldn't be created.
  39. */
  40. - (instancetype)initWithFrame:(CGRect)frame;
  41. /** Returns a newly initialized `MarqueeLabel` instance with the specified scroll rate and edge transparency fade length.
  42. You must specify a non-zero rate, and you cannot thereafter modify the rate.
  43. @param frame A rectangle specifying the initial location and size of the view in its superview's coordinates. Text (for the given font, font size, etc.) that does not fit in this frame will automatically scroll.
  44. @param pixelsPerSec A rate of scroll for the label scroll animation. Must be non-zero. Note that this will be the maximum rate for ease-type animation.
  45. @param fadeLength A length of transparency fade at the left and right edges of the `MarqueeLabel` instance's frame.
  46. @see fadeLength
  47. @return An initialized `MarqueeLabel` object or nil if the object couldn't be created.
  48. */
  49. - (instancetype)initWithFrame:(CGRect)frame rate:(CGFloat)pixelsPerSec andFadeLength:(CGFloat)fadeLength;
  50. /** Returns a newly initialized `MarqueeLabel` instance with the specified scroll duration and edge transparency fade length.
  51. You must specify a non-zero duration, and you cannot thereafter modify the duration.
  52. @param frame A rectangle specifying the initial location and size of the view in its superview's coordinates. Text (for the given font, font size, etc.) that does not fit in this frame will automatically scroll.
  53. @param scrollDuration A scroll duration the label scroll animation. Must be non-zero. This will be the duration that the animation takes for one-half of the scroll cycle in the case of left-right and right-left marquee types, and for one loop of a continuous marquee type.
  54. @param fadeLength A length of transparency fade at the left and right edges of the `MarqueeLabel` instance's frame.
  55. @see fadeLength
  56. @return An initialized `MarqueeLabel` object or nil if the object couldn't be created.
  57. */
  58. - (instancetype)initWithFrame:(CGRect)frame duration:(NSTimeInterval)scrollDuration andFadeLength:(CGFloat)fadeLength;
  59. /** Resizes the view to the minimum size necessary to fully enclose the current text (i.e. without scrolling), up to the maximum size specified.
  60. The current origin of the frame is retained.
  61. @param maxSize The maximum size up to which the view should be resized. Passing `CGSizeZero` will result in no maximum size limit.
  62. @param adjustHeight A boolean that can be used to indicate if the view's height should also be adjusted. Note that this has no impact on scrolling.
  63. */
  64. - (void)minimizeLabelFrameWithMaximumSize:(CGSize)maxSize adjustHeight:(BOOL)adjustHeight;
  65. ////////////////////////////////////////////////////////////////////////////////
  66. /// @name Configuration Options
  67. ////////////////////////////////////////////////////////////////////////////////
  68. /** Specifies the animation curve used in the scrolling motion of the labels.
  69. Allowable options:
  70. - `UIViewAnimationOptionCurveEaseInOut`
  71. - `UIViewAnimationOptionCurveEaseIn`
  72. - `UIViewAnimationOptionCurveEaseOut`
  73. - `UIViewAnimationOptionCurveLinear`
  74. Defaults to `UIViewAnimationOptionCurveEaseInOut`.
  75. */
  76. @property (nonatomic, assign) UIViewAnimationOptions animationCurve;
  77. /** A boolean property that sets whether the `MarqueeLabel` should behave like a normal UILabel.
  78. When set to `YES` the `MarqueeLabel` will behave like a normal UILabel, and will not begin scrolling when the text is
  79. larger than the specified frame. The change takes effect immediately, removing any in-flight animation as well as any
  80. current edge fade. Note that the `MarqueeLabel` will respect the current values of the `lineBreakMode` and `textAlignment`
  81. properties while labelized.
  82. To simply prevent automatic scrolling, use the `holdScrolling` property.
  83. Defaults to `NO`.
  84. @see holdScrolling
  85. @see lineBreakMode
  86. @warning The label will not automatically scroll when this property is set to `YES`.
  87. @warning The UILabel default setting for the `lineBreakMode` property is `NSLineBreakByTruncatingTail`, which truncates
  88. the text adds an ellipsis glyph (...). Set the `lineBreakMode` property to `NSLineBreakByClipping` in order to avoid the
  89. ellipsis, especially if using an edge transparency fade.
  90. */
  91. @property (nonatomic, assign) IBInspectable BOOL labelize;
  92. /** A boolean property that sets whether the `MarqueeLabel` should hold (prevent) label scrolling.
  93. When set to `YES`, the `MarqueeLabel` will not automatically scroll even its text is larger than the specified frame,
  94. although the specified edge fades will remain.
  95. To set the `MarqueeLabel` to act like a normal UILabel, use the `labelize` property.
  96. Defaults to `NO`.
  97. @see labelize
  98. @warning The label will not automatically scroll when this property is set to `YES`.
  99. */
  100. @property (nonatomic, assign) IBInspectable BOOL holdScrolling;
  101. /** A boolean property that sets whether the `MarqueeLabel` should only begin a scroll when tapped.
  102. If this property is set to `YES`, the `MarqueeLabel` will begin a scroll animation cycle only when tapped. The label will
  103. not automatically being a scroll. This setting overrides the setting of the `holdScrolling` property.
  104. Defaults to `NO` .
  105. @warning The label will not automatically scroll when this property is set to `YES`.
  106. @see holdScrolling
  107. */
  108. @property (nonatomic, assign) IBInspectable BOOL tapToScroll;
  109. /** Defines the direction and method in which the `MarqueeLabel` instance scrolls.
  110. `MarqueeLabel` supports four types of scrolling: `MLLeftRight`, `MLRightLeft`, `MLContinuous`, and `MLContinuousReverse`.
  111. Given the nature of how text direction works, the options for the `marqueeType` property require specific text alignments
  112. and will set the textAlignment property accordingly.
  113. - `MLLeftRight` type is ONLY compatible with a label text alignment of `NSTextAlignmentLeft`.
  114. - `MLRightLeft` type is ONLY compatible with a label text alignment of `NSTextAlignmentRight`.
  115. - `MLContinuous` does not require a text alignment (it is effectively centered).
  116. - `MLContinuousReverse` does not require a text alignment (it is effectively centered).
  117. Defaults to `MLLeftRight`.
  118. @see MarqueeType
  119. @see textAlignment
  120. */
  121. #if TARGET_INTERFACE_BUILDER
  122. @property (nonatomic, assign) IBInspectable NSInteger marqueeType;
  123. #else
  124. @property (nonatomic, assign) MarqueeType marqueeType;
  125. #endif
  126. /** Defines the duration of the scrolling animation.
  127. This property sets the amount of time it will take for the scrolling animation to complete a
  128. scrolling cycle. Note that for `MLLeftRight` and `MLRightLeft`, a cycle consists of the animation away,
  129. a pause (if a delay is specified), and the animation back to the original position.
  130. Setting this property will automatically override any value previously set to the `rate` property, and the `rate`
  131. property will be set to `0.0`.
  132. @see rate
  133. */
  134. @property (nonatomic, assign) IBInspectable CGFloat scrollDuration;
  135. /** Defines the rate at which the label will scroll, in pixels per second.
  136. Setting this property will automatically override any value previousy set to the `scrollDuration` property, and the
  137. `scrollDuration` property will be set to `0.0`. Note that this is the rate at which the label would scroll if it
  138. moved at a constant speed - with other animation curves the rate will be slightly different.
  139. @see scrollDuration
  140. */
  141. @property (nonatomic, assign) IBInspectable CGFloat rate;
  142. /** A buffer (offset) between the leading edge of the label text and the label frame.
  143. This property adds additional space between the leading edge of the label text and the label frame. The
  144. leading edge is the edge of the label text facing the direction of scroll (i.e. the edge that animates
  145. offscreen first during scrolling).
  146. Defaults to `0`.
  147. @note The value set to this property affects label positioning at all times (including when `labelize` is set to `YES`),
  148. including when the text string length is short enough that the label does not need to scroll.
  149. @note For `MLContinuous`-type labels, the smallest value of `leadingBuffer`, 'trailingBuffer`, and `fadeLength`
  150. is used as spacing between the two label instances. Zero is an allowable value for all three properties.
  151. @see trailingBuffer
  152. @since Available in 2.1.0 and later.
  153. */
  154. @property (nonatomic, assign) IBInspectable CGFloat leadingBuffer;
  155. /** A buffer (offset) between the trailing edge of the label text and the label frame.
  156. This property adds additional space (buffer) between the trailing edge of the label text and the label frame. The
  157. trailing edge is the edge of the label text facing away from the direction of scroll (i.e. the edge that animates
  158. offscreen last during scrolling).
  159. Defaults to `0`.
  160. @note For `MLContinuous`-type labels, the smallest value of `leadingBuffer`, 'trailingBuffer`, and `fadeLength`
  161. is used as spacing between the two label instances. Zero is an allowable value for all three properties.
  162. @note The value set to this property has no effect when the `labelize` property is set to `YES`.
  163. @see leadingBuffer
  164. @since Available in 2.1.0 and later.
  165. */
  166. @property (nonatomic, assign) IBInspectable CGFloat trailingBuffer;
  167. /**
  168. @deprecated Use `trailingBuffer` instead. Values set to this property are simply forwarded to `trailingBuffer`.
  169. */
  170. @property (nonatomic, assign) CGFloat continuousMarqueeExtraBuffer DEPRECATED_ATTRIBUTE;
  171. /** The length of transparency fade at the left and right edges of the `MarqueeLabel` instance's frame.
  172. This propery sets the size (in points) of the view edge transparency fades on the left and right edges of a `MarqueeLabel`. The
  173. transparency fades from an alpha of 1.0 (fully visible) to 0.0 (fully transparent) over this distance. Values set to this property
  174. will be sanitized to prevent a fade length greater than 1/2 of the frame width.
  175. Defaults to `0`.
  176. */
  177. @property (nonatomic, assign) IBInspectable CGFloat fadeLength;
  178. /** The length of delay in seconds that the label pauses at the completion of a scroll. */
  179. @property (nonatomic, assign) IBInspectable CGFloat animationDelay;
  180. /** The read-only duration of the scroll animation (not including delay).
  181. The value of this property is calculated when using the `scrollRate` property to set label animation speed. The value of this property
  182. is equal to the value of `scrollDuration` property when using the `scrollDuration` property to set label animation speed.
  183. @see scrollDuration
  184. @see scrollRate
  185. */
  186. @property (nonatomic, readonly) NSTimeInterval animationDuration;
  187. ////////////////////////////////////////////////////////////////////////////////
  188. /// @name Animation control
  189. ////////////////////////////////////////////////////////////////////////////////
  190. /** Immediately resets the label to the home position, cancelling any in-flight scroll animation, and restarts the scroll animation if the appropriate conditions are met.
  191. @see resetLabel
  192. @see triggerScrollStart
  193. */
  194. - (void)restartLabel;
  195. /** Immediately resets the label to the home position, cancelling any in-flight scroll animation.
  196. The text is immediately returned to the home position. Scrolling will not resume automatically after a call to this method.
  197. To re-initiate scrolling use a call to `restartLabel` or `triggerScrollStart`, or make a change to a UILabel property such as text, bounds/frame,
  198. font, font size, etc.
  199. @see restartLabel
  200. @see triggerScrollStart
  201. @since Available in 2.4.0 and later.
  202. */
  203. - (void)shutdownLabel;
  204. /** Resets the label text, recalculating the scroll animation.
  205. The text is immediately returned to the home position, and the scroll animation positions are cleared. Scrolling will not resume automatically after
  206. a call to this method. To re-initiate scrolling, use either a call to `restartLabel` or make a change to a UILabel property such as text, bounds/frame,
  207. font, font size, etc.
  208. @see restartLabel
  209. */
  210. - (void)resetLabel;
  211. /** Pauses the text scrolling animation, at any point during an in-progress animation.
  212. @note This method has no effect if a scroll animation is NOT already in progress. To prevent automatic scrolling on a newly-initialized label prior to its presentation onscreen, see the `holdScrolling` property.
  213. @see holdScrolling
  214. @see unpauseLabel
  215. */
  216. - (void)pauseLabel;
  217. /** Un-pauses a previously paused text scrolling animation. This method has no effect if the label was not previously paused using `pauseLabel`.
  218. @see pauseLabel
  219. */
  220. - (void)unpauseLabel;
  221. /** Overrides any non-size condition which is preventing the receiver from automatically scrolling, and begins a scroll animation.
  222. Currently the only non-size conditions which can prevent a label from scrolling are the `tapToScroll` and `holdScrolling` properties. This
  223. method will not force a label with a string that fits inside the label bounds (i.e. that would not automatically scroll) to begin a scroll
  224. animation.
  225. Upon the completion of the first forced scroll animation, the receiver will not automatically continue to scroll unless the conditions
  226. preventing scrolling have been removed.
  227. @note This method has no effect if called during an already in-flight scroll animation.
  228. @see restartLabel
  229. @since Available in 2.2.0 and later.
  230. */
  231. - (void)triggerScrollStart;
  232. ////////////////////////////////////////////////////////////////////////////////
  233. /// @name Animation Status
  234. ////////////////////////////////////////////////////////////////////////////////
  235. /** Called when the label animation is about to begin.
  236. The default implementation of this method does nothing. Subclasses may override this method in order to perform any custom actions just as
  237. the label animation begins. This is only called in the event that the conditions for scrolling to begin are met.
  238. @since Available in 1.5.0 and later.
  239. */
  240. - (void)labelWillBeginScroll;
  241. /** Called when the label animation has finished, and the label is at the home position.
  242. The default implementation of this method does nothing. Subclasses may override this method in order to perform any custom actions jas as
  243. the label animation completes, and before the next animation would begin (assuming the scroll conditions are met).
  244. @param finished A Boolean that indicates whether or not the scroll animation actually finished before the completion handler was called.
  245. @since Available in 1.5.0 and later.
  246. @warning This method will be called, and the `finished` parameter will be `NO`, when any property changes are made that would cause the label
  247. scrolling to be automatically reset. This includes changes to label text and font/font size changes.
  248. */
  249. - (void)labelReturnedToHome:(BOOL)finished;
  250. /** A boolean property that indicates if the label's scroll animation has been paused.
  251. @see pauseLabel
  252. @see unpauseLabel
  253. */
  254. @property (nonatomic, assign, readonly) BOOL isPaused;
  255. /** A boolean property that indicates if the label is currently away from the home location.
  256. The "home" location is the traditional location of `UILabel` text. This property essentially reflects if a scroll animation is underway.
  257. */
  258. @property (nonatomic, assign, readonly) BOOL awayFromHome;
  259. ////////////////////////////////////////////////////////////////////////////////
  260. /// @name Bulk-manipulation Methods
  261. ////////////////////////////////////////////////////////////////////////////////
  262. /** Convenience method to restart all `MarqueeLabel` instances that have the specified view controller in their next responder chain.
  263. This method sends a `NSNotification` to all `MarqueeLabel` instances with the specified view controller in their next responder chain.
  264. The scrolling animation of these instances will be automatically restarted. This is equivalent to calling `restartLabel` on all affected
  265. instances.
  266. There is currently no functional difference between this method and `controllerViewDidAppear:` or `controllerViewWillAppear:`. The methods may
  267. be used interchangeably.
  268. @warning View controllers that appear with animation (such as from underneath a modal-style controller) can cause some `MarqueeLabel` text
  269. position "jumping" when this method is used in `viewDidAppear` if scroll animations are already underway. Use this method inside `viewWillAppear:`
  270. instead to avoid this problem.
  271. @warning This method may not function properly if passed the parent view controller when using view controller containment.
  272. @param controller The view controller that has appeared.
  273. @see restartLabel
  274. @see controllerViewDidAppear:
  275. @see controllerViewWillAppear:
  276. @since Available in 1.3.1 and later.
  277. */
  278. + (void)restartLabelsOfController:(UIViewController *)controller;
  279. /** Convenience method to restart all `MarqueeLabel` instances that have the specified view controller in their next responder chain.
  280. Alternative to `restartLabelsOfController:`. This method is retained for backwards compatibility and future enhancements.
  281. @param controller The view controller that has appeared.
  282. @see restartLabel
  283. @see controllerViewWillAppear:
  284. @since Available in 1.2.7 and later.
  285. */
  286. + (void)controllerViewDidAppear:(UIViewController *)controller;
  287. /** Convenience method to restart all `MarqueeLabel` instances that have the specified view controller in their next responder chain.
  288. Alternative to `restartLabelsOfController:`. This method is retained for backwards compatibility and future enhancements.
  289. @param controller The view controller that has appeared.
  290. @see restartLabel
  291. @see controllerViewDidAppear:
  292. @since Available in 1.2.8 and later.
  293. */
  294. + (void)controllerViewWillAppear:(UIViewController *)controller;
  295. /**
  296. @deprecated Use `controllerViewDidAppear:` instead.
  297. */
  298. + (void)controllerViewAppearing:(UIViewController *)controller DEPRECATED_ATTRIBUTE;
  299. /** Labelizes all `MarqueeLabel` instances that have the specified view controller in their next responder chain.
  300. This method sends an `NSNotification` to all `MarqueeLabel` instances with the specified view controller in their next
  301. responder chain. The `labelize` property of these `MarqueeLabel` instances will be set to `YES`.
  302. @param controller The view controller for which all `MarqueeLabel` instances should be labelized.
  303. @see labelize
  304. */
  305. + (void)controllerLabelsShouldLabelize:(UIViewController *)controller;
  306. /** De-Labelizes all `MarqueeLabel` instances that have the specified view controller in their next responder chain.
  307. This method sends an `NSNotification` to all `MarqueeLabel` instances with the specified view controller in their next
  308. responder chain. The `labelize` property of these `MarqueeLabel` instances will be set to `NO` .
  309. @param controller The view controller for which all `MarqueeLabel` instances should be de-labelized.
  310. @see labelize
  311. */
  312. + (void)controllerLabelsShouldAnimate:(UIViewController *)controller;
  313. @end