[IOS] custom clickable multi-text marquee YFRollingLabel and iosyfrollinglabel

Source: Internet
Author: User
Tags truncated

[IOS] custom clickable multi-text marquee YFRollingLabel and iosyfrollinglabel

Requirement

Only one message needs to be displayed in the project. If the length is appropriate, the message is not rolled. If the length is too long, the message is rolled cyclically.

Although I did not write it, I looked at the code and put two UILabel IN A UIView,

When the previous one ends, the other displays. However, click processing is indeed a click event of UIView.

 

However, we can see that the lights in the subway and bus are displayed in many sections. Although you can combine multiple segments into one segment for display,

But what should I do if I need to click events? So I implemented the clickable multi-segment marquee myself.

Therefore, this essay includes the following effect: (5 paragraphs in the figure can trigger corresponding events by clicking different texts)

 

Detour

Remember the last article [IOS] alignment the bottom of the text with different font sizes?

Although the bottom alignment of multiple UILabel cannot be achieved, we can inherit the UILabel to change the vertical position of the text.

Therefore, my original idea was to inherit UILabel and keep it inherited. nstabel was used to directly move the text in UILable.

There are two problems @"This is the text to be moved in the Custom marquee."For example)

1. Moving can be moved, but how can I make @ "this is..." start to appear on the right when the text is moved to the left to be invisible (only "moving text" is left?

2. When the text is too long, the invisible part will be truncated, so when moving, only part of the text will be.

First, it seems that there is no way. UILabel only has one bounds of the text, and it cannot make him part on the left and some on the right.

Second, because the default NSLineBreakMode: NSLineBreakByWordWrapping attribute exists, even if the text is not truncated, it will only become a ellipsis.

So let alone this method ....

 

Implementation

First, we need to make it clear that the current marquee inherits the UIView and requires two UILabel and timer nstabel.

During initialization, input a string array and calculate the adaptive size of each string

CGRect textRect = [((NSString *)_textArray[i]) boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:kFont} context:nil];[_textRectArray addObject:[NSValue valueWithCGRect:textRect]];

If the number of input string arrays is 1 and the adaptive width is <UIView width, the image will not scroll. Write a new UILabel for display.

In other cases, two UILabel can be instantiated here and the timer is turned on:

Timer related:

_ Timer = [NSTimer failed: 0.02 target: self selector: @ selector (timerAction :) userInfo: nil repeats: YES]; [[nsunloop mainRunLoop] addTimer: _ timer forMode: nsunloopcommonmodes];
// Why should I put the timer in the LOOP?
// If this RunLoop is executing a continuous operation, timer will be delayed.
// That is to say, if you place the marquee on the scrollview, the timer will not be moved when you slide the scrollview.

// Related methods:
// [_ Timer setFireDate: [NSDate date]; Start // [_ timer setFireDate: [NSDate distantFuture]; pause
// Cancel the timer
// [_ Timer invalidate]; // _ timer = nil; // prevents wild pointers

// Timer execution event:

-(Void) timerAction :( NSTimer *) timer {}

Now we need to set two UILabel every time we enter this method.

Now let's assume four strings are passed in: @ [@ "this is 0th strings", @ "this is 1st strings", @ "this is 2nd strings ", @ "this is 3rd strings"];

There are only two Labels. No matter whether you scroll to the right or to the left, we set the Label originally displayed as Labels [0], and then show the positioning Label [1].

Defines a variable and stores the origin. X value of the previous UILabel in real time, starting from 0.

1. Each time the previous UILabel is not completely hidden, the previous UIlabel appears (there is a fixed distance between the two internalWidth)

You also need to change the value of Labels [0] based on the speed value to control the position of Labels [0] (change the offsetX value ).

With this distance and the previous position, you can calculate the location (origin. X value) of the next UILabel in real time ).

2. Each time the previous UILabel is completely hidden, you need to reset a value. At this time, the previous UILabel is completely invisible and only enters once.

At the same time, change the two UILabel positions. Scroll to the left: After A <-- B, A disappears, A goes to the right of B. After B <-- A, B disappears, it goes to the right of.

Therefore, you only need to set offsetX = _ labels [1]. frame. origin. x; // after A disappears, position B is used as the location of the next label that will disappear, and position A is changed to the next one,

// Its location is calculated in real time based on B's location. Once the previous one disappears, it is replaced cyclically.

However, only the position is changed, but the text and size are not changed. See figure 3.

3. for only one text, the AB content is the same. But for the four strings passed in, you need to change the AB content each time you reset the value.

At the same time, for strings of varying lengths, you need to set the corresponding AB Frame according to different text sizes.

Therefore, the size of the four string texts must be saved as an array. Defines the position of UIlabel that is always logged and is currently being deprecated (the first one): _ currentIndex

In Step 1: Obtain the text array labelTextArray frame: labelArray from two Arrays: labelArray)

When switching the AB position, you need to replace currentIndex + 1: namely _ currentIndex = (_ currentIndex + 1) % _ textArray. count; for use after switching.

 

Then, the current and next Text and frame values are obtained and saved to an array with a length of 2 for use.

 

Too many, too messy ...... I don't want to watch it. I don't want to watch it ......

Here is a picture: Please refer to it if you do not understand it.

 

Explanation

<==================== Left shift =============================

 

 

====================== Right shift ==============================>

Now only view the colorIt can be seen that no matter the left rolling, right rolling, green is always Labels [0] (the Label to be removed), red is always Label [1]

Normal rolling:

The green offsetX value changes with speed: self. offsetX = self. offsetX-sign * self. speed;

The red X value changes with the relationship between the green offsetX and the fixed Spacing: CGFloat nextOffX = self. offsetX + sign * (self. orientation = RollingOrientationLeft )? FirstRect. size. width: lastRect. size. width) + self. internalWidth );

Get the red and green content and size from the saved data using the _ currentIndex value, and assign a value:

When green disappears:

It should have been red on the right, and it suddenly turned green: self. offsetX = _ labels [1]. frame. origin. x;

Disappear greenYesTurns red as normal scrolling

_ CurrentIndex indicates the index with green content always: _ currentIndex = (_ currentIndex + 1) % _ textArray. count;

Use this valueYesObtains the red, green size, and text content in normal scrolling conditions.

(TwoYesThe process will be performed in the blue section of "normal rolling)

}

 

Well, it seems so tired to end up here .... Slow and click events not completed

Click Event: process the event after adding a Tap gesture to UILabel.

-(Void) labelTap :( UITapGestureRecognizer *) gesture {NSInteger tag = (UILabel *) [gesture view]). tag-100; NSInteger index; if (tag = 0) {// if it is (Labels [0]) Green index = _ currentIndex;} else if (tag = 1) {// if it is (Labels [1]), the red is the last index = (_ currentIndex + 1) % _ textArray. count;} else {index = _ currentIndex ;}
If (self. labelClickBlock) {self. labelClickBlock (index );}}

 

Endpoint

For the code, see GitHub: ===>YFRollingLabelPS: the source code and GitHub documents are all written in poor English and I don't know if anyone will read them ..

In addition, the record problems are described as follows:

The length of the input text array cannot be too short because there are only two UILabel in it. If the length is too short and the spacing is small

After the green disappears, it immediately becomes red and appears on the right side of the current green, rather than moving slowly.

If the text is too long or too long (a few hundred Chinese characters are not set in normal cases), the obtained text width will be too long and the UILabel width will be too long, so the text will not be displayed directly, however, the click event still exists... I don't understand this...

Now, I have finished writing. Long live Windows 10 Mobile !!!

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.