I am loading Lyrics of song on UILabel With Timer. Now I want to highlight Each word of that label with different color. How can I do this ?
I am showing lyrics like this
- (void)setCurrentAudioProgress:(NSTimeInterval)time duration:(NSTimeInterval)duration
{
float progress = time/duration;
long currentPlaybackTime = audioPlayer.currentTime;
long remainingTime = (duration-time);
int remainingHours = (remainingTime /3600);
int remainingMinutes = ((remainingTime /60 -remainingHours*60));
int remainingSeconds = (remainingTime %60);
int currentHours = (currentPlaybackTime / 3600);
int currentMinutes = ((currentPlaybackTime / 60) - currentHours*60);
int currentSeconds = (currentPlaybackTime % 60);
currentTimeLabel.text = [NSString stringWithFormat:#"%i:%02d:%02d", currentHours, currentMinutes, currentSeconds];
remainingTimeLabel.text = [NSString stringWithFormat:#"%i.%02d.%02d", remainingHours , remainingMinutes, remainingSeconds];
[progressView setProgress:progress];
for (int i = 0; i<[lyricsArray count]; i++) {
NSString *lyricsTime = [[lyricsArray objectAtIndex:i]valueForKey:#"startTime" ] ;
if ([currentTimeLabel.text isEqualToString:lyricsTime]) {
songLyricsLabel.text = [NSString stringWithFormat:#"%#",[[lyricsArray objectAtIndex:i]valueForKey:#"songLyrics" ]];
}
}
}
You have to use the trick some thing like this one label doesn't support the highlighting
iPhone "slide to unlock" animation
You can use following whenever you want to highlight the label text then just add the following lines for respective label
label.highlighted = YES;
label.highlightedTextColor = [UIColor blueColor];
for different color you can add an array with color names and select randomly....
Related
In my app I am trying to make an custom UIPickerView which contains three components(days, hours and minutes). I have already made the custom picker with three components. And Now I am stuck at how I can add the labels to the selection indicator which shows which component is for days, hours or minutes.
I have already gone through each and every link or question posted on this site but none them helped me.
I am trying to implement something like this image
Can any one suggest me how can I achieve this?
Thats how I achieve this....I have made my Custom PickerView with the help of some code I found...
In .h file:
// LabeledPickerView.h
// LabeledPickerView
#import <UIKit/UIKit.h>
#interface LabeledPickerView : UIPickerView
{
NSMutableDictionary *labels;
}
/** Adds the label for the given component. */
-(void)addLabel:(NSString *)labeltext forComponent:(NSUInteger)component forLongestString:(NSString *)longestString;
#end
and In the .m file...
// LabeledPickerView.m
// LabeledPickerView
#import "LabeledPickerView.h"
#implementation LabeledPickerView
/** loading programmatically */
- (id)initWithFrame:(CGRect)aRect {
if (self = [super initWithFrame:aRect]) {
labels = [[NSMutableDictionary alloc] initWithCapacity:3];
}
return self;
}
/** loading from nib */
- (id)initWithCoder:(NSCoder *)coder {
if (self = [super initWithCoder:coder]) {
labels = [[NSMutableDictionary alloc] initWithCapacity:3];
}
return self;
}
- (void) dealloc
{
[labels release];
[super dealloc];
}
#pragma mark Labels
// Add labelText to our array but also add what will be the longest label we will use in updateLabel
// If you do not plan to update label then the longestString should be the same as the labelText
// This way we can initially size our label to the longest width and we get the same effect Apple uses
-(void)addLabel:(NSString *)labeltext forComponent:(NSUInteger)component forLongestString:(NSString *)longestString {
[labels setObject:labeltext forKey:[NSNumber numberWithInt:component]];
NSString *keyName = [NSString stringWithFormat:#"%#_%#", #"longestString", [NSNumber numberWithInt:component]];
if(!longestString) {
longestString = labeltext;
}
[labels setObject:longestString forKey:keyName];
}
//
- (void) updateLabel:(NSString *)labeltext forComponent:(NSUInteger)component {
UILabel *theLabel = (UILabel*)[self viewWithTag:component + 1];
// Update label if it doesn’t match current label
if (![theLabel.text isEqualToString:labeltext]) {
NSString *keyName = [NSString stringWithFormat:#"%#_%#", #"longestString", [NSNumber numberWithInt:component]];
NSString *longestString = [labels objectForKey:keyName];
// Update label array with our new string value
[self addLabel:labeltext forComponent:component forLongestString:longestString];
// change label during fade out/in
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.75];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
theLabel.alpha = 0.00;
theLabel.text = labeltext;
theLabel.alpha = 1.00;
[UIView commitAnimations];
}
}
/**
Adds the labels to the view, below the selection indicator glass-thingy.
The labels are aligned to the right side of the wheel.
The delegate is responsible for providing enough width for both the value and the label.
*/
- (void)didMoveToWindow {
// exit if view is removed from the window or there are no labels.
if (!self.window || [labels count] == 0)
return;
UIFont *labelfont = [UIFont boldSystemFontOfSize:15];
// find the width of all the wheels combined
CGFloat widthofwheels = 0;
for (int i=0; i<self.numberOfComponents; i++) {
widthofwheels += [self rowSizeForComponent:i].width;
}
// find the left side of the first wheel.
// seems like a misnomer, but that will soon be corrected.
CGFloat rightsideofwheel = (self.frame.size.width - widthofwheels) / 2;
// cycle through all wheels
for (int component=0; component<self.numberOfComponents; component++) {
// find the right side of the wheel
rightsideofwheel += [self rowSizeForComponent:component].width;
// get the text for the label.
// move on to the next if there is no label for this wheel.
NSString *text = [labels objectForKey:[NSNumber numberWithInt:component]];
if (text) {
// set up the frame for the label using our longestString length
NSString *keyName = [NSString stringWithFormat:#"%#_%#", [NSString stringWithString:#"longestString"], [NSNumber numberWithInt:component]];
NSString *longestString = [labels objectForKey:keyName];
CGRect frame;
frame.size = [longestString sizeWithFont:labelfont];
// center it vertically
frame.origin.y = (self.frame.size.height / 2) - (frame.size.height / 2) - 0.5;
// align it to the right side of the wheel, with a margin.
// use a smaller margin for the rightmost wheel.
frame.origin.x = rightsideofwheel - frame.size.width -
(component == self.numberOfComponents - 1 ? 5 : 7);
// set up the label. If label already exists, just get a reference to it
BOOL addlabelView = NO;
UILabel *label = (UILabel*)[self viewWithTag:component + 1];
if(!label) {
label = [[[UILabel alloc] initWithFrame:frame] autorelease];
addlabelView = YES;
}
label.text = text;
label.font = labelfont;
label.backgroundColor = [UIColor clearColor];
label.shadowColor = [UIColor whiteColor];
label.shadowOffset = CGSizeMake(0,1);
// Tag cannot be 0 so just increment component number to esnure we get a positive
// NB update/remove Label methods are aware of this incrementation!
label.tag = component + 1;
if(addlabelView) {
/*
and now for the tricky bit: adding the label to the view.
kind of a hack to be honest, might stop working if Apple decides to
change the inner workings of the UIPickerView.
*/
if (self.showsSelectionIndicator) {
// if this is the last wheel, add label as the third view from the top
if (component==self.numberOfComponents-1)
[self insertSubview:label atIndex:[self.subviews count]-3];
// otherwise add label as the 5th, 10th, 15th etc view from the top
else
[self insertSubview:label aboveSubview:[self.subviews objectAtIndex:5*(component+1)]];
} else
// there is no selection indicator, so just add it to the top
[self addSubview:label];
}
if ([self.delegate respondsToSelector:#selector(pickerView:didSelectRow:inComponent:)])
[self.delegate pickerView:self didSelectRow:[self selectedRowInComponent:component] inComponent:component];
}
}
}
And call this addLabel: method with the label text and component tag and thats it..!!
Download the Source code Of custom UIPickerView Control .
Custom UiPickerView.
Hope it Helps to You :)
I have created a storyboard with 12 buttons, 12 smaller buttons and 12 labels.
It is like that:
btnBig1.tag = 1
btnSmall1.tag = 1
lbl1.tag = 1
btnBig2.tag = 2
btnSmall2.tag = 2
lbl2.tag = 2
etc...
Now when a procedure is called
- (IBAction)processButtonUpInside:(id)sender
{
UIButton *nButton = (UIButton*)sender;
int nInt = nButton.tag;
}
... I would like to do something with all 3 controls (big button, small button and label).
It should look like this (pseudo-code):
- (IBAction)processButtonUpInside:(id)sender
{
UIButton *nButton = (UIButton*)sender;
int nInt = nButton.tag;
UIButton *nButtonBig (UIButton*)CastFromTagID(nInt)
//do something with the big button
UIButton *nButtonSmall (UIButton*)CastFromTagID(nInt)
//do something with the small button
UILabel *nLabel (UILabel*)CastFromTagID(nInt)
//do something with the label
}
As you can see, the CastFromTagID is my "own invention". I don't know how I should actually do this.
Can somebody help?
Thank you very much.
You can use 3 a different starting point for each button family:
enum {
kTagFirstBigButton = 1000,
kTagFirstSmallButton = 2000,
kTagFirstLabel = 3000,
}
Assign the tags using them:
btnBig1.tag = kTagFirstBigButton + 1;
btnSmall1.tag = kTagFirstSmallButton + 1;
lbl1.tag = kTagFirstLabel + 1;
btnBig2.tag = kTagFirstBigButton + 2;
btnSmall2.tag = kTagFirstSmallButton + 2;
lbl2.tag = kTagFirstLabel + 2;
...
Now it's easy to find anything:
- (IBAction)processButtonUpInside:(id)sender
{
UIButton *nButton = (UIButton*)sender;
/* I'm not sure what button is `sender` here
If it's a big or small one you can guess
comparing its tag with the first tag
*/
int offset = nButton.tag;
UIButton *nButtonBig = (UIButton*)[view viewWithTag:kTagFirstBigButton + offset];
//do something with the big button
UIButton *nButtonSmall = (UIButton*)[view viewWithTag:kTagFirstSmallButton + offset];
//do something with the small button
UILabel *nLabel = (UILabel*)[view viewWithTag:kTagFirstLabel + offset];
//do something with the label
}
You shouldn't assign the same tag id to different views.
Indeed, do something like this:
btnBig1.tag = 11 btnSmall1.tag = 12 lbl1.tag = 13;
btnBig2.tag = 21 btnSmall2.tag = 22 lbl2.tag = 23;
Then consider the last digit of the tag id:
UIView *nView = (UIView *)sender;
if (lastDigit(sender.tag) == 3)
// this is a label
{
UIButton *nButtonBig = [nView.superview viewWithTag:nInt-2];
UIButton *nButtonSmall = [nView.superview viewWithTag:nInt-1];
UILabel *nLabel = (UILabel *)sender;
}
else if (lastDigit(sender.tag) == 2)
.....
where lastDigit(sender.tag) is a function that returns the last digit of a given integer.
In my case where I don't have a reference to the subviews that I want to edit under the same tag I just grab all of the subviews for a given view then loop through all of them and check the tag, if the tag match I execute some code. For example..
#define kSameViewTag 9500001
for (int i = 0; i < 10; i++) // add a bunch of same tag views //
{
UIView *someview = [UIView new];
someview.tag = kSameViewTag;
[YourParent addSubview:someview];
}
Then later on or whenever you need to loop through your views you can do.
NSArray *subviews = [[YourParent subviews] copy];
for (UIView *v in subviews)
{
if (v.tag == kSameViewTag)
{
// Do some code //
}
}
Now this may become an performance issue if you have a lot of subviews so you can always run it on the background thread then jump into the main thread to do UI updates. For Example:
NSArray *subviews = [[YourParent subviews] copy];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
for (UIView *v in subviews)
{
if (v.tag == kSameViewTag)
{
dispatch_async(dispatch_get_main_queue(), ^{
// Do Some UI Stuff Here //
});
}
}
});
I have many no. of buttons on my view and I want to shuffle the buttons(change in position) then how can I shuffle the button in my view.
use arc4random()
and change position of your buttons
In your .h file : UIButton *buttonsarray[10];
In your .m file :
// Make array of button using following way.I used this method to creates button and you can use yours.
- (void)viewDidLoad {
[super viewDidLoad];
float y = 5;
int x = 0;
int count = 0;
for (int i = 0 ; i < 10; i++)
{
count ++;
buttonsarray[i] = [UIButton buttonWithType:UIButtonTypeRoundedRect];
buttonsarray[i].frame = CGRectMake(x, y, 100, 100);
[buttonsarray[i] setTitle:[NSString stringWithFormat:#"%d",i+1] forState:UIControlStateNormal];
x = x + 105;
[self.view addSubview:b[i]];
if(count == 3)
{
count = 0;
x = 0;
y = y+ 105;
}
}
}
// This function will soufflé your buttons
- (IBAction)btnClicked:(id)sender
{
int n = 10;
int swaper;
for (int i = 0 ; i < 10 ; i++)
{
int r = arc4random()%n;
if(r != swaper){
swaper = r;
CGRect r1 = buttonsarray[i].frame;
buttonsarray[i].frame = buttonsarray[swaper].frame;
buttonsarray[swaper].frame = r1;
n--;
}
}
}
Hope,this will help you..
You can do this
Make an Array with a group of CGPoints you will need to store the points as strings.
In the layoutSubViews method set something like this:
-(void)layoutSubViews{
[self.subviews enumerateObjectsUsingBlock:^(id object, NSUInteger idx, BOOL *stop) {
CGPoint newPoint = CGPointFromString([positionsArray objectAtIndex:idx]);
object.frame = CGRectMake(newPoint.x,newPoint.y,object.frame.size.width,object.frame.size.height);
}];
}
Then you will need to shuffle the positions in the positions array, you can see an example method here :How to Shuffle an Array
Now every time you need to Shuffle the positions you can call -(void)setNeedsLayout on your view.
There are more options but that was the first I thought of.
Good Luck
I want to add a textfield dynamically with tag so that it can give unique value every time. And than add those values and show on label. When I click button one textfield add "n" give the value, and that value adds to the previous value.
Value adding Successfully. But when I edit anything, change or give another value such as (10 instead of 12) the loop will run again because of this line
[Txt_New_Estimated addTarget:self action:#selector(C6Loop) forControlEvents:UIControlEventEditingDidEnd];
2nd problem is that when I add a new textfield then the previous textfield did not modify and do not add in rest of textfields... before adding a new textfield it works properly but when edit anything loop will run again.... i want to overCome this problem, so please check this code and give some possible solution. I am sending my code here Please check this code.
-(void)CreateTextFeildOnRun
{
if (tag ==0)
{
textPosY = 420;
}
for ( i =tag; i<= tag; i++)
{
Txt_New_Estimated = [[UITextField alloc]initWithFrame:CGRectMake(360, textPosY , 130, 65)];
Txt_New_Estimated.delegate = self;
Txt_New_Estimated.text=#"";
//[Txt_New_Estimated setTag:1234];
Txt_New_Estimated.tag = i;
Txt_New_Estimated.clearButtonMode = UITextFieldViewModeWhileEditing;
[Txt_New_Estimated addTarget:self action:#selector(C6Loop) forControlEvents:UIControlEventEditingDidEnd];
Txt_New_Estimated.placeholder = #"Estimated";
Txt_New_Estimated.font = [UIFont fontWithName:#"Arial" size:23];
Txt_New_Estimated.backgroundColor = [UIColor whiteColor];
Txt_New_Estimated.textAlignment = UITextAlignmentCenter;
[scrollview addSubview:Txt_New_Estimated];
}
}
-(void)C6Loop{
Txt_New_ONU.text=Txt_New_Estimated.text;
[self Calculate2];
}
-(void)Calculate2{
int y14=([Txt_New_Estimated.text intValue]);
y14=n;
n=d;
c14= y14+([Txt_New_Estimated.text floatValue]);
n = c14;
[self addest];
}
-(void)addest{
float c1= ([Txt_Engring_Est.text floatValue]) + ([Txt_Weddring_Est.text floatValue]) + ([Txt_Bridal_Est.text floatValue])+ ([Txt_Veil_Est.text floatValue])+ ([Txt_Shoe_Est.text floatValue])+n;
Txt_Total_Est.text = [[NSString alloc] initWithFormat:#"%.2f",c1];
}
Thank You.
Why don't you add those TextField when created to to an NSMutableArray. something like this:
-(void)createTextFieldOnRun
{
if (tag ==0)
{
textPosY = 420;
}
for ( i =tag; i<= tag; i++)
{
UITextField *Txt_New_Estimated = [[UITextField alloc]initWithFrame:CGRectMake(360,textPosY ,130,65)];
Txt_New_Estimated.delegate = self;
//....other code..
[scrollview addSubview:Txt_New_Estimated];
[textFieldArray addObject:Txt_New_Estimated];
}
}
and when calculating do something like this:
int result = 0;
for(UITextField *field in textFieldArray) // will iterate all UITextField which was added
{
result += [field.text intValue]; //or floatValue
}
NSLog(#"the result is %d", result); //here you have sum of all the text fields' text
It doesn't matter whether you change the value or not, it will recalculate all the values.
Just as a practice, I am working on an app that solves the famous middle school pythagorean theorem, a squared + b squared = c squared. Unfortunately, the out-coming answer has, in my eyes, nothing to do with the actual answer. Here is the code used during the "solve" action.
- (IBAction)solve {
int legoneint;
int legtwoint;
int hypotenuseint;
int lonesq = legoneint * legoneint;
int ltwosq = legtwoint * legtwoint;
int hyposq = hypotenuseint * hypotenuseint;
hyposq = lonesq + ltwosq;
if ([legone.text isEqual:#""]) {
legtwoint = [legtwo.text intValue];
hypotenuseint = [hypotenuse.text intValue];
answer.text = [NSString stringWithFormat:#"%d", legoneint];
self.view.backgroundColor = [UIColor blackColor];
}
if ([legtwo.text isEqual:#""]) {
legoneint = [legone.text intValue];
hypotenuseint = [hypotenuse.text intValue];
answer.text = [NSString stringWithFormat:#"%d", legtwoint];
self.view.backgroundColor = [UIColor blackColor];
}
if ([hypotenuse.text isEqual:#""]) {
legoneint = [legone.text intValue];
legtwoint = [legtwo.text intValue];
answer.text = [NSString stringWithFormat:#"%d", hypotenuseint];
self.view.backgroundColor = [UIColor blackColor];
}
}
By the way, legone, legtwo, and hypotenuse all represent the UITextField that corresponds to each mathematical part of the right triangle. Answer is the UILabel that tells, you guessed it, the answer. Does anyone see any flaws in the program? Thanks in advance!
Did not checked the program carefully but in the first lines there is already a big problem:
int lonesq = legoneint * legoneint;
int ltwosq = legtwoint * legtwoint;
int hyposq = hypotenuseint * hypotenuseint;
This vars are defined using vars that are still not assigned at all. You need to set the value of the vars taken from the text fields, then do the math. C is a sequential language, everything is executed from top to bottom, you can't say "a = bc" and a will be bc in any place of the program.