I'm looking for advice about how best to implement a Karaoke text effect to an IOS app. I'm new to IOS so am not familiar with all the various animation apis and libraries and am hoping that I can save some time if I am pointed in the right direction of what libraries to study.
In Javascript I would have used an array with the various words and timings of the audio track, and setTimeout to write the next element in the array to a div on the page. I did consider using this approach in a UIWebView but after some quick tests with UIWebview I wasn't really happy with how smooth it looked.
I did come across one very simple animation tutorial that loops through an array of images but it has a uniform animation duration which in my use case would not work, as the length of time the words needs to display on the screen will vary according to the audio. Here is the sample code that I was looking at.
NSArray *imageNames = #[#"win_1.png", #"win_2.png", #"win_3.png", #"win_4.png",
#"win_5.png", #"win_6.png", #"win_7.png", #"win_8.png",
#"win_9.png", #"win_10.png", #"win_11.png", #"win_12.png",
#"win_13.png", #"win_14.png", #"win_15.png", #"win_16.png"];
NSMutableArray *images = [[NSMutableArray alloc]init];
for (int i= 0; i < imageNames.count; i++) {
[images addObject:[UIImage imageNamed:[imageNames objectAtIndex:i]]];
}
UIImageView *animationImageView = [[UIImageView alloc] initWithFrame: CGRectMake(60,95, 86, 193)];
animationImageView.animationImages = images;
animationImageView.animationDuration = 0.5;
[self.view addSubview:animationImageView];
[animationImageView startAnimating];
UIImageView *slowAnimationImageView = [[UIImageView alloc] initWithFrame:CGRectMake(160, 95, 86, 193)];
slowAnimationImageView.animationImages = images;
slowAnimationImageView.animationDuration = 5;
[self.view addSubview:slowAnimationImageView];
[slowAnimationImageView startAnimating];
And I found that tutorial here: http://www.appcoda.com/ios-programming-animation-uiimageview/
thanks in advance for any suggestions of which approach is best to take.
So, I have already implemented what you describe and I can tell you that CoreText is the API you need to use. Only via CoreText rendering will you be able to render specific word portions in different colors and apply the color changes at specific times. But, the bad news is that this API is not really easy to use. You can find working example code in the files MutableAttrString.m and AVOfflineComposition.m at the following github project link github. The minimum code you would need is in the MutableAttrString.m file, it shows how to use CoreText to properly implement the logic you describe. You could try to roll your own solution with animated bitmaps, but the CoreText approach just renders text so it is way better for many reasons.
Related
I've been searching all over the internet over the past couple of days to no avail. Unfortunately, the apple documentation about this specific issue is vague and no sample code is available (at least thats what I found out). What seems to be the issue you may ask...
I'm trying to set a uiview's layer as the contents of the material that is used to render an iPhone model's screen (Yep, trippy :P ). The iPhone's screen's UV mapping is set from 0 to 1 so that no issue persists in mapping the texture/layer onto the texels.
So, instead of getting this layer to appear rendered on the iPhone, same as left image, Instead, I get this rendered onto the iPhone like right image
Correct Render Incorrect Render
Also note, that when I set a breakpoint and debug the actual iPhone node and view it in Xcode, a completely different render is shown and the layer gets half-fixed when I continue execution:
Now then... HOW do I fix this issue??? I've tried playing with the diffuse's contents transform matrix but nothing gets fixed. I've also tried resizing the UIView to 256x256 (since the UV seems to be 256x256 as shown in blender - the 3d modelling package), but that doesn't fix anything.
Here is the code for the layer:
UIView *screen = [[UIView alloc] initWithFrame:self.view.bounds];
screen.backgroundColor = [UIColor redColor];
UIView *temp = [[UIView alloc] initWithFrame:CGRectMake(0, 0, screen.bounds.size.width, 60)];
temp.backgroundColor = [UIColor colorWithRed:0 green:(112.f/255.f) blue:(235.f/255.f) alpha:1];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectInset(temp.bounds, 40, 0)];
label.frame = CGRectOffset(label.frame, 40, 0);
label.textColor = [UIColor colorWithRed:0 green:(48.f/255.f) blue:(84.f/255.f) alpha:1];
label.text = #"Select Track";
label.font = [UIFont fontWithName:#"HelveticaNeue-Light" size:30];
label.minimumScaleFactor = 0.001;
label.adjustsFontSizeToFitWidth = YES;
label.lineBreakMode = NSLineBreakByClipping;
[temp addSubview:label];
UIView *separator = [[UIView alloc] initWithFrame:CGRectMake(0, temp.bounds.size.height - 2, temp.bounds.size.width, 2)];
separator.backgroundColor = [UIColor colorWithRed:0 green:(48.f/255.f) blue:(84.f/255.f) alpha:1];
[temp addSubview:separator];
[screen addSubview:temp];
screen.layer.contentsGravity = kCAGravityCenter;
Edit
What's even weirder is that if I capture a UIImage of the view using:
- (UIImage *) imageWithView:(UIView *)view
{
UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
and use that as the diffuse's content... everything works out perfectly fine?! It's really weird and frustrating since the image's size is exactly the same as the uiview's...
Edit 2
I ended up just using an image of the view as the texture, which makes things much more static than I needed. I won't set this as the answer because I'll still be waiting for a correct fix to this issue even if it in a long time. So, if you have an answer and this topic has been opened for a long time, please bump it if you can. The documentation on this section is just so poor.
New post on an old thread, but this day-in-age, it's possible to set the UIView itself as SCNMaterialProperty (diffuse) contents. Intention to support this feature is communicated directly from SceneKit engineering at Apple, though the documentation has not yet been updated to reflect it.
To tied back to the original post, do not set a UIView.layer as material property contents; instead set contents to the UIView itself.
[Update: according to Lance's comment below, support for views may be getting worse rather than getting better.]
The SceneKit docs pretty strongly suggest that, while there are cases where you can use animated CALayers as material content, that doesn't include UIView layers:
SceneKit cannot use a layer that is already being displayed elsewhere (for example, the backing layer of a UIView object).
That suggests that if you want to make animated content for your material, you're better off with either Core Animation used entirely on its own or SpriteKit.
I am currently learning iOS development and I want to develop an iOS app where there is an animated image at the beginning top of the View Controller and a lot of text just after it. Please have a look at the picture below:
I have thought about the codes for both the image animation at the top and the large amount of text just after it. I was wondering whether someone could please review them and tell me whether they are fine or not.
The codes for both the image animation and the large amount of text will be placed inside the viewDidLoad method of the implementation file of the controller like this:
- (void)viewDidLoad
{
[super viewDidLoad];
// codes for image animation
// codes for large amount of text to be displayed
}
IMAGE ANIMATION CODES
For the image animation, I am going to use 5 png pictures: A.png, B.png, C.png, D.png and E.png. The slide show will start from A, then move on to B, then to C, to D and finally to E. All the 5 pictures are added to my project in Xcode. Below are the codes:
NSArray *imagelist = [[NSArray alloc] initWithObjects: [UIImage imageNamed:#"A.png"], [UIImage imageNamed:#"B.png"], [UIImage imageNamed:#"C.png"], [UIImage imageNamed:#"D.png"], [UIImage imageNamed:#"E.png"],nil];
UIImageView *animationImageView = [[UIImageView alloc] initWithFrame: CGRectMake(5,5,90,180)];
animationImageView.animationImages = imagelist;
animationimageView.animationDuration = 10;
[self.view addSubView:animationimageView];
[animationImageView startAnimating];
LARGE AMOUNT OF TEXT CODES
For the text, I have not added all the necessary text....because there is a lot more. That is why I need the text object to be scrollable. Below are the codes:
UITextView *largeText = [[UITextView alloc] initWitthFrame: CGRectMake(5,100,90,180)];
largeText.text = #"In organizations, we must work with and for others. To be able to mutually achieve our goals, we must be able to relate to others effectively. These leadership tips will help you do just that:
1)Catch people doing things right and then let them know that they are doing things right
2)Use feedback to stay informed about what other people are doing in your area of responsibility and authority
3)Have regular, focused meetings regarding the projects that you are responsible for
4)Provide adequate instructions. Time is lost if things are not done correctly
5)Train others to do jobs. You cannot do them all, nor can others do them if they have not been trained
6)Expect others to succeed. It becomes a self-fulfilling prophecy when you believe others are loyal, dedicated and doing a good job";
largeText.font = [UIFont fontWithName:#"TimesNewRomanPSMT" size:18];
largeText.editable = NO;
largeText.scrollEnabled = YES;
[self.view addSubView:largeText];
Please review the codes and can someone tell me whether the codes are fine or not.
Thanks for reading.
NSArray *imagelist = [[NSArray alloc] initWithObjects: [UIImage imageNamed:#"A.png"], [UIImage imageNamed:#"B.png"], [UIImage imageNamed:#"C.png"], [UIImage imageNamed:#"D.png"], [UIImage imageNamed:#"E.png"],nil];
UIImageView *animationImageView = [[UIImageView alloc] initWithFrame: CGRectMake(5,5,90,180)];
[self.view addSubView:animationimageView];
NSTimeInterval delay=0.0;
for (NSInteger i=0; i<[imagelist count]; i++) {
delay+=3.0;
[UIView animateWithDuration:0.5 delay:delay options:UIViewAnimationOptionCurveLinear animations:^{
animationImageView.image=[imagelist objectAtIndex:i];
}completion:nil];
}
I have a simple application which consists of a UITableViewController with cells of Languages. When the user clicks a specific language, it brings up a UIPageViewController to show horizontally, 6 images in a pageView. That part is working really well and the images are loading.
I have implemented this, using this tutorial: http://code.tutsplus.com/tutorials/using-scrollstyle-with-uipageviewcontroller--mobile-13551.
I would like to achieve a zoom and pan functionality within this as well now.
I have zoom working with the following code.
CGFloat scale = pinchRecognizer.scale;
self.pageViewController.view.transform = CGAffineTransformScale(self.pageViewController.view.transform, scale, scale);
pinchRecognizer.scale = 1.0;
The problem is that the zoom is always in the centre of the image with no way to pan around the image like you can in a normal Photo on an iOS device.
I have found lots of good tutorials on how to achieve this, like http://iosdeveloperzone.com/2012/07/07/tutorial-all-about-images-part-2-panning-zooming-with-uiscrollview/ as an example. However, my confusion stems from the very first part.
I am loading my UIPageViewController using a NSArray:
self.modelArray = [NSMutableArray arrayWithObjects:[[ImageModel alloc] initWithImageName:#"3facts-english-page1.jpg"], [[ImageModel alloc] initWithImageName:#"3facts-english-page2.jpg"], [[ImageModel alloc] initWithImageName:#"3facts-english-page3.jpg"], nil];
How to I extract each image into a UIImageView?
I can see that fundamentally, I need to have most of this code to enable the Pan:
UIImage* image = [UIImage imageNamed:#"KinkakuJi"];
self.imageView.image = image;
[self.imageView sizeToFit];
self.scrollView.contentSize = image.size;
In my case however, I'm not loading a single UIImage but rather a NSArray. How do I extract the UIImage from the NSArray to make this pan happen?
Any thoughts on this would really be appreciated.
I am not sure about how to present this question because I don't know the animation term that I should use.
I need to know about this tree presentation animation. As it is appearing form root to top.
Please take a look on attached .gif file and let me know if anyone know about this animation or if you can guide me with example.
I will really appreciate.
Thanks for your time.
The best option for you is to split up the gif into multiple images and then do the following:
NSArray *gifImagesArray = [NSArray arrayWithObjects:imageOne, imageTwo, imageThree, nil];
imageView.animationImages = animateImagesArray;
imageView.animationRepeatCount = 1;
imageView.animationDuration = 1.0f;
[imageView startAnimating];
Edit following comments:
If you can't use multiple images you have to write the animation yourself.
One suggestion is to add a circular mask to the UIImage and animate it's removal.
This link explains how to draw a circular CALayer: Circular Progress Bars in IOS
This one here will show you how to create a mask on a UIImage: Simply mask a UIView with a rectangle
now all you have to do is a simple animation.
I have a solution that will work for this problem.
We can use gif image and convert it into UIImage object. So image object will work same as animation.
Thanks all for your answers.
In my opinion, I will separate this animation to 4 parts:
animation to show full black tree from center.
animation to show Texts
animation to show blue leafs.
animation to show 2 buttons at bottom.
You can use this framework https://github.com/facebook/pop to operate all animations step by step or even Core Animation.
Please do more research... I think you will success to make one.
You can achieve this animation using simple UIImageView, that can load multiple images using animationImages property of UIImageView.
First, create one NSMutablerArray of images.
then asssign that images to imageView, and animationDuration for that images.
UIImageView *animationImageView = [[UIImageView alloc] initWithFrame:CGRectMake(60, 95, 86, 193)];
animationImageView.animationImages = images;
animationImageView.animationDuration = 0.5;
add the imageview to view.
[self.view addSubview:animationImageView];
[animationImageView startAnimating];
I want to place an animated background on my app. I have looked into the UIMotionEffect class and yes that does seem beneficial. However, what I am really looking for is something like the dynamic wallpapers provided in iOS settings. The way those colored circles move around is exactly what I am looking for.
I've tried this with no luck:
self.view.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"circle"]];
[UIView animateWithDuration:5.0 animations:^{
self.view.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"circle"]];
}];
My only problem is I have no idea where to start. I looked into OpenGL. I assume it could be done that way, but it seems like a possible rabbit trail that I might not need to take. I also found some videos on YouTube but they involve Adobe Flash, which I do not have. Any suggestions on where to venture for this?
If it's a simple GIF you don't need to get fancy. Just separate the images (many tools to do that) and use the following code (might be some typos):
NSArray *array = [NSArray arrayWithObjects:
[UIImage imageNamed:#"image1.png"],
[UIImage imageNamed:#"image2.png"],
........,
nil];
UIImage *image = [UIImage animatedImageWithImages:array duration:6.0f];
[image startAnimating];