How to set UIPageControl with image in iOS8 Objective c? - ios

I want to set UIPageControl with images in the place of dots. I implemented the following code but it always crashing.Please help me.
-(void)updateDots
{
for (int i=0; i<[_pageControl.subviews count]; i++) {
UIImageView *dot = [_pageControl.subviews objectAtIndex:i];
if (i==_pageControl.currentPage)
dot.image = [UIImage imageNamed:#"on.png"];
else
dot.image = [UIImage imageNamed:#"off.png"];
}
}
In iOS8,i got the following error
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIView setImage:]:
unrecognized selector sent to instance 0x7f9dd9eaabb0'

You shouldn't assume that the UIPageControl will contain UIImageViews (it doesn't).
Here's how to do this with public APIs:
- (void)updateDots
{
// this only needs to be done one time
// 7x7 image (#1x)
_pageControl.currentPageIndicatorTintColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"on.png"]];
_pageControl.pageIndicatorTintColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"off.png"]];
}

you are getting UIView in for loop. check if dot is UIImageView Class then set image.
id object = [_pageControl.subviews objectAtIndex:i];
if([object isKindOfClass:[UIImageView Class]])
{
UIImageView *dot = (UIImageView *)object;
if (i==_pageControl.currentPage)
dot.image = [UIImage imageNamed:#"on.png"];
else
dot.image = [UIImage imageNamed:#"off.png"];
}
Hope it will help you.

Remember, subviews don't always have to be UIImageViews. For example, UITableViewCells often have enclosing views or so within them. You need to make the change below.
-(void)updateDots
{
for (int i=0; i<[_pageControl.subviews count]; i++) {
if ([[_pageControl.subviews objectAtIndex:i] isKindOfClass:[UIImageView Class]])
{
UIImageView *dot = (UIImageView *)[_pageControl.subviews objectAtIndex:i];
if (i==_pageControl.currentPage)
dot.image = [UIImage imageNamed:#"on.png"];
else
dot.image = [UIImage imageNamed:#"off.png"];
}
}
}
I've noticed that in a UITableViewCell, there is always an enclosing UIView for the cell content. You need to recursively go into this view to find the UIImageView you are looking for.

Related

Getting frame of subview enumeration

So, I have repeating views containing thumbnails, once a thumbnail is pressed the thumbnail ID is sent as the tag.
With this information I want to get the frame of the subview of that view;
- (IBAction)thumbPressed:(id)sender {
NSLog(#"Thumb %i pressed", (int)[sender tag]);
for (int i = 0; i < _thumbCounter; i++) {
if (i == [sender tag]) {
NSLog(#"thumb view %i", i);
//Up To HERE
break;
}
}
// [self moveToVideoControllerWithInfoID:[NSString stringWithFormat:#"%li", (long)[sender tag]]];
}
For the thumbnails to be drawn they're drawn in a random order retrieved by JSON.
The Button
UIButton *thumbButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[thumbButton addTarget:self
action:#selector(thumbPressed:)
forControlEvents:UIControlEventTouchUpInside];
thumbButton.frame = CGRectMake(0, 0, _thumbView.frame.size.width, _thumbView.frame.size.height);
thumbButton.tag = _thumbCounter;
[_thumbView addSubview:thumbButton];
The subview I want to get the frame of
NSString *string = [NSString stringWithFormat:#"***.jpg",Link];
NSURL * imageURL = [NSURL URLWithString:string];
NSData * imageData = [NSData dataWithContentsOfURL:imageURL];
UIImage * image = [UIImage imageWithData:imageData];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(thumbGap, thumbGap, thumbHeight - 5, thumbHeight - 5)];
imageView.image = image;
[_thumbView addSubview:imageView];
Where the thumbnail shell is drawn
_thumbView = [[ThumbView alloc] initWithFrame:CGRectMake(0, margin, _scrollView.frame.size.width, thumbHeight)];
_thumbView.backgroundColor = [UIColor whiteColor];
_thumbView.thumbId = _thumbCounter;
[_scrollView addSubview:_thumbView];
_thumbview is a class of UIVIEW with the added thumbId
How once that button is pressed can I locate the imageView frame inside of _thumbview ( bare in mind there are multiple ).
First off, let's make life easier for you:
- (IBAction)thumbPressed:(UIButton*)sender {
NSLog(#"Thumb %i pressed", (int)[sender tag]);
ThumbView *thumbView = (ThumbView*)[sender superView];
for(UIView* subview in thumbView.subViews) {
if([subView iKindOfClass:[UIImageView class]]) {
//you got it here
}
}
}
You could shortcut the whole thing by making ThumbView have an imageView property as well.
I've tried to determine that this is what you are doing:
_scrollView
->_thumbView[0]
--->thumbButton
--->imageView
->_thumbView[1]
--->thumbButton
--->imageView
...
->_thumbView[N]
--->thumbButton
--->imageView
Assumed that you want the image view who is in the same thumbView as the button who is pressed.
Best Possible Solution (IMHO):
#Interface ThumbView()
#property (nonatomic,weak) UIImageView *imageView;
#end
AND:
(After making sure to first add, and THEN SET .imageView)
- (IBAction)thumbPressed:(UIButton*)sender {
NSLog(#"Thumb %i pressed", (int)[sender tag]);
UIImageView *imageView = ((ThumbView*)[sender superView]).imageView
}
for (UIView *i in _scrollView.subviews) {
if ([i isKindOfClass:[ThumbView class]]) {
ThumbView *tempThumb = (ThumbView *)i;
if (tempThumb.thumbId == (int)[sender tag]) {
for (UIView *y in tempThumb.subviews) {
if ([y isKindOfClass:[UIImageView class]]) {
UIImageView *tempIMG = (UIImageView *)y;
[self playVideo:[loadedInput objectForKey:#"link"] frame:tempIMG.frame andView:tempThumb];
}
}
}
}
}

UIImageView Transition Betwen Multiple Images

I am using the below code to change the UIImageView's image after a short duration. The images being used are stored in an array as you can see.
The problem is, no matter what 'duration' or 'delay' I set, the imageview changes almost instantly to the last image in the array.
Should I instead be using the main thread to add a delay between each image transition?
////////////////////////////////////////////////////////////////
animationCount = 0;
imageArray =[NSMutableArray new];
[imageArray addObject:[UIImage imageNamed:#"gauge1final.png"]];
[imageArray addObject:[UIImage imageNamed:#"gauge2final.png"]];
[imageArray addObject:[UIImage imageNamed:#"gauge3final.png"]];
[imageArray addObject:[UIImage imageNamed:#"gauge4final.png"]];
[imageArray addObject:[UIImage imageNamed:#"gauge5final.png"]];
[self multiStageAnimate];
////////////////////////////////////////////////////////////////
-(void) multiStageAnimate{
[UIView animateWithDuration:5.0
delay:5.0
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^
{
self.gauge.image = [imageArray objectAtIndex:animationCount];
}
completion:^(BOOL finished){
animationCount ++;
if(animationCount < imageArray.count){
[self multiStageAnimate];
}
else
{
animationCount = 0;
}
}];
}
UIImageView does have a mechanism to accomplish your need.
UIImageView *imageView = [[UIImageView alloc] init];
imageView.animationImages = [NSArray arrayWithObjects:
[UIImage imageNamed:#"image1"],
[UIImage imageNamed:#"image2"],
[UIImage imageNamed:#"image3"], nil];
imageView.animationRepeatCount = 0; // 0 means repeat without stop.
imageView.animationDuration = 1.5; // Animation duration
[imageView startAnimating];
If you are using multiple screens with the same animation, it's better to create one .plist file and then use this anywhere in your project. The steps are as follows:
First, generate one .plist file File-> New File-> Resource ->Property List
Write your code like this:
ViewController.h
#property (weak, nonatomic) IBOutlet UIImageView *dataImageView;
ViewController.m
NSDictionary *picturesDictionary = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"PhotesArray" ofType:#"plist"]];
NSArray *imageNames = [picturesDictionary objectForKey:#"Photos"];
NSMutableArray *images = [[NSMutableArray alloc] init];
for (int i=0; i<[imageNames count]; i++) {
[images addObject:[UIImage imageNamed:[imageNames objectAtIndex:i]]];
}
//Normal animation
self.dataImageView.animationImages = images;
self.dataImageView.animationDuration = 5.0;
[self.dataImageView startAnimating];
The image property of a UIImageView won't animate. What you need to do is have 2 UIImageView widgets one on top of another. Then, you can animate their alpha properties from 0 to 1 (and vice-versa) with each transition.

Problems with changing the image property of a UIImageView

I have a UIImageView that when a function called I want to change to a different ("active") image and when another called change back to the image before. This is the code:
- (NavButton *)initWithFrame:(CGRect *)fr andImage:(UIImage *)img andActiveImage:(UIImage *)acImg {
NavButton *a = [[NavButton alloc] initWithFrame:*fr];
[a setBackgroundColor:[UIColor clearColor]];
UIImageView *aImg = [[UIImageView alloc] initWithFrame:CGRectMake(8.5, 8.5, 28, 28)];
aImg.tag = 13;
aImg.image = img;
self.orginalImage = img;
self.activeImage = acImg;
[a addSubview:aImg];
return a;
}
- (void)setIsActive:(NSNumber *)isActive {
self.active = isActive;
if ([isActive isEqualToValue:[NSNumber numberWithBool:NO]]) {
[self undoActive];
} else {
[self redoActive];
}
}
- (void)undoActive {
UIImageView *a = (UIImageView *)[self viewWithTag:13];
a.image = self.orginalImage;
}
- (void)redoActive {
UIImageView *a = (UIImageView *)[self viewWithTag:13];
a.image = self.activeImage;
}
When I call [btn setIsActive:[NSNumber numberWithBool:YES]]; or [btn setIsActive:[NSNumber numberWithBool:NO]]; both times it removes the image, but when I don't call either the image stays there. So, how do I make it so when I call them it changes the images of the button to the correct image?
Instead of repeatedly assigning image to imageview, you can assign two images to the image view: one to "image" property and other to "highlightedImage" property. When you want to switch between the images, set the Boolean property "highlighted" as YES or NO.
It will be easier just to do your check as:
if (![isActive boolValue]) {
Then, do some debugging, add some breakpoints and / or logging. Check what values are actually being received. Are the flags set correctly. Are the images set correctly. Is anything nil.

UIImage animation not working for all Button

I have this simple function where i sap rate the button animation and then start animation for every button but i dont know why only one button animate not others which clicked, please help me with this
- (IBAction)startAnimation:(UIButton *)button {
NSMutableArray* imagesArray = [[NSMutableArray alloc] init];
for (int images = 0; images < 15; images++) {
UIImage* buttonImage = [UIImage imageNamed:[NSString stringWithFormat:#"aaqqq00%02d.png", images]];
[imagesArray addObject:buttonImage];
}
NSArray* reversedAnim = [[imagesArray reverseObjectEnumerator] allObjects];
int buttonTag = button.tag;
animButton.adjustsImageWhenHighlighted = NO;
for (int images = 0; images < 15; images++) {
UIButton *animButton = (UIButton *)[self.view viewWithTag:buttonTag];
if (images <= buttonTag) {
animButton.imageView.animationImages = imagesArray;
[animButton setImage:
[UIImage imageNamed:#"aaqqq0014.png"] forState:UIControlStateNormal];
} else {
animButton.imageView.animationImages = reversedAnim;
[animButton setImage:
[UIImage imageNamed:#"aaqqq0000.png"] forState:UIControlStateSelected];
}
NSLog(#"%#", animButton.imageView.animationImages);
animButton.imageView.animationDuration = 1; //whatever you want (in seconds)
animButton.imageView.animationRepeatCount = 1;
[animButton.imageView startAnimating];
}
}
You're passing the button, so doing the tag lookup seem pointless and error prone (if there are multiple views with the same tag in the hierarchy).
Setting the buttons image view animation images (animButton.imageView.animationImages) and then after that setting a single image ([animButton setImage:...) is also pointless.
What does your log statement say about the animation images?

How to add images dynamically inside UIScrollView in iPhone

In my iPhone app i am getting around 300 images url from web server, i need to display all the images on UIScrollView in 3x3 row and column format. Once i get all the url from web server, convert them into UIImage and display image. Everything works fine, however after loading 200 images app crashes, I have read a lot its some thing memory kind of issue with UIScrollView, so how can we work on this. I have read apple documentation also, however its not clear.
here is the solution, i've implemented it in my app. Here is my code
sv_port is my scrollView.
Download SDWebImageDownloader class files and import it in your project. Add relevant framework in your project. like imageIO.framework, QuartzCore
Now, in your .m add
#import "UIImageView+WebCache.h"
#import "SDImageCache.h"
#import "SDWebImageCompat.h"
//function for adding image in your scrollview
-(void)populateImages
{
int x=6,y=6;
for(UIView * view in sv_port.subviews){
if([view isKindOfClass:[UIImageView class]])
{
[view removeFromSuperview]; view = nil;
}
if([view isKindOfClass:[UIButton class]])
{
[view removeFromSuperview]; view = nil;
}
}
for(int p=0;p<[Manufacturer count];p++)
{
UIButton *btnImageButton = [UIButton buttonWithType:UIButtonTypeCustom];
btnImageButton.frame = CGRectMake(x,y,70,70);
[btnImageButton setTag:p];
[btnImageButton addTarget:self action:#selector(nextview:) forControlEvents:UIControlEventTouchUpInside];
UIActivityIndicatorView *spinny = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
spinny.frame=CGRectMake(btnImageButton.frame.origin.x+25,btnImageButton.frame.origin.y+25, 20, 20);
spinny.backgroundColor=[UIColor clearColor];
[spinny startAnimating];
[sv_port setScrollEnabled:YES];
[sv_port addSubview:spinny];
UIImageView *asyncImageView = [[[UIImageView alloc] initWithFrame:btnImageButton.frame] autorelease];
asyncImageView.backgroundColor=[UIColor clearColor];
CALayer *layer;
layer = asyncImageView.layer;
layer.borderWidth = 0.5;
layer.cornerRadius = 5;
layer.masksToBounds = YES;
[asyncImageView setImageWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#", yourUrl] ] placeholderImage:[UIImage imageNamed:nil] options:0 andResize:CGSizeMake(btnImageButton.frame.size.width,btnImageButton.frame.size.height) withContentMode:UIViewContentModeScaleAspectFit];
asyncImageView.contentMode = UIViewContentModeScaleAspectFit;
[sv_port addSubview:btnImageButton];
[sv_port addSubview:asyncImageView];
int imgCntPort=0;
imgCntPort=(sv_port.frame.size.width/(asyncImageView.frame.size.width));
////NSLog(#"imgport %d",imgCntPort);
if((p+1)%imgCntPort==0)
{
x=5;
y=y+80;
}
else
{
x=x+80;
}
}
sv_port.contentSize = CGSizeMake(0, y);
glob_x =0; glob_y =y;
}
hope it helps..
-(void)scrollimage
{
[AsyncImageLoader sharedLoader].cache = nil;
NSArray *viewsToRemove = [_scrollview_gallary subviews];
for (UIView *v in viewsToRemove) {
[v removeFromSuperview];
}
CGFloat width =_scrollview_gallary.bounds.size.width;
_scrollview_gallary.contentSize=CGSizeMake(width*[tmpArr count]-1, 360);
[_scrollview_gallary setShowsHorizontalScrollIndicator:NO];
[_scrollview_gallary setShowsVerticalScrollIndicator:NO];
int x=0;
int y=0;
for (int i=0; i<[tmpArr count]; i++)
{
AsyncImageView *imgv;
imgv =[[AsyncImageView alloc] initWithFrame:CGRectMake(x,y,width,360)];
imgv.contentMode = UIViewContentModeScaleToFill;
imgv.activityIndicatorStyle = UIActivityIndicatorViewStyleWhite;
NSString *strimag=[NSString stringWithFormat:#"%#",[tmpArr objectAtIndex:i]];
imgv.imageURL=[NSURL URLWithString:[tmpArr objectAtIndex:i]];
[_scrollview_gallary addSubview:imgv];
x=x+width;
}
_pageview.numberOfPages=([tmpArr count]);
_scrollview_gallary.pagingEnabled = YES;
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
int page;
CGFloat pageWidth = _scrollview_gallary.frame.size.width;
page = floor((_scrollview_gallary.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
self.pageview.currentPage = page;
}
I am getting an impression that you are downloading all 300 images together at once and keeping in memory and adding to the UIScrollView..
There is a technique called LazyLoad, means don't load all the images at once, load it in queue..
You can refer to this link http://lazyloadinginuiscrollviewiniphone.blogspot.in/2011/12/iphone-uiscrollview-lazy-image-loading.html it might help you to achieve things smoothly..
All the best.
If you want to display images in Gridview format then you can use PSTCollectionView. And for the lazy loading of the image you can use SDWebImage.
Are you releasing the elements that are not visible anymore? UITableView does that (that's why Sandro suggested it).
Your implementation of the UIScrollView should do that.
You can also consider UICollectionView or GMGridView for grid implementations that take this into consideration.
I do not see why what you're doing is a problem. May be you've got memory issue. In that case simulator and device result should be different.
If this is a memory problem, you should use a tableview instead of a scroll view. Put 3 images in each table view cell, and that should do the trick.
Cdt

Resources