The code below is supposed to display a series of images in an infinite, connected loop. Instead, it just displays a totally white field. Thanks to Aaron Hayman for getting me this far.
- (void)layoutScrollImages
{
//Arrangement
NSArray *imageViews = [NSArray arrayWithObjects:#"image1.png", #"image2.png", #"image3.png", nil];
CGRect cRect = scrollView1.bounds;
UIImageView *cView;
for (int i = 0; i < imageViews.count; i++)
{
cView = [imageViews objectAtIndex:i];
cView.frame = cRect;
[scrollView1 addSubview:cView];
cRect.origin.x += cRect.size.width;
}
scrollView1.contentSize = CGSizeMake(cRect.origin.x, scrollView1.bounds.size.height);
scrollView1.contentOffset = CGPointMake(scrollView1.bounds.size.width, 0); //should be the center page in a 3 page setup
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
scrollView1.contentOffset = CGPointMake(scrollView.bounds.size.width, 0);
}
FOLLOW UP:
Nothing I'm doing is making any difference. Currently, my code looks like this, but I'm changing everything I can think of to no avail.
- (void)layoutScrollImages
{
//Horizontal arrangement
NSObject *image1 = #"image1.png";
NSObject *image2 = #"image2.png";
NSObject *image3 = #"image3.png";
NSArray *imageViews = [NSArray arrayWithObjects:image1, image2, image3, nil];
CGRect cRect = scrollView1.bounds;
UIImageView *cView;
for (int i = 0; i < imageViews.count; i++)
{
cView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:[imageViews objectAtIndex:i]]];
cView.frame = cRect;
[scrollView1 addSubview:cView];
cRect.origin.x += cRect.size.width;
}
scrollView1.contentSize = CGSizeMake(cRect.origin.x, scrollView1.bounds.size.height);
scrollView1.contentOffset = CGPointMake(scrollView1.bounds.size.width, 0); //should be the center page in a 3 page setup
[self layoutScrollImages];
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
scrollView1.contentOffset = CGPointMake(scrollView.bounds.size.width, 0);
}
You never initiate a UIImageView. You want to do something like this:
NSArray *imageViews = [NSArray arrayWithObjects:#"image1.png", #"image2.png", #"image3.png", nil];
CGRect cRect;
UIImageView *cView;
for (int i = 0; i < imageViews.count; i++)
{
cView = [[UIImageView alloc] initWithImage:[UIImage imageName:[imageViews objectAtIndex:i]]];
cRect = cView.frame;
cRect.origin.x += scrollView1.frame.size.width;
cView.frame = cRect;
[scrollView1 addSubview:cView];
NSLog(#"imageView bounds: %#", NSStringFromCGRect(cView.frame));
}
Edit:
Try the above and see if anything shows up. Here are some thoughts:
Are you sure that you aren't setting the imageView to have 0 height/width? I threw in an NSLog statement to the loop. It will print the frame of the imageView.
Have you tried adding the images to self.view instead of scrollView1? That would be a good way to make sure that the problem doesn't have to do with the frame of scrollView1. Or use the following:
NSLog(#"imageView bounds: %#", NSStringFromCGRect(scrollView1.frame));
Related
I want photo slider like whts app has. It should access all the pics or some of the pics from in build photo library and it should be scrollable using scroll view.
I have tried with different photo viewer but everything has memory issue. So not sure if anyone has it's working solution. Really appreciate your help.
Thank you,
Ankita
This is working almost fine, but one small problem with backbord direction scrolling. Just try this out may be you can find some direction to go and may be find better solution using it.
(Have used ELCImagePicker to show first time all images and then on selecting one present the scrollview to show large images at a time 10 images are shown also have tweak the delegate method of ELCImagePickerController to get the index of selected image)
At first load ie when select image from ELCImagePickerController
- (void)elcImagePickerController:(ELCImagePickerController *)picker didFinishPickingMediaWithInfo:(NSArray *)info selectedIndex:(NSInteger)_index {
[self dismissModalViewControllerAnimated:NO];
for (UIView *v in [scrollview subviews]) {
[v removeFromSuperview];
}
infoItems = [[NSArray alloc]initWithArray:info];
CGRect workingFrame = scrollview.frame;
workingFrame.origin.x = 0;
int indexFrame = picker.selectedIndex;
newIndex = indexFrame;
for(int i = 0; i < [info count]; i++)
{
NSDictionary *dict = [info objectAtIndex:i];
UIImageView *imageview = [[UIImageView alloc] initWithImage:[dict objectForKey:UIImagePickerControllerOriginalImage]];
[imageview setContentMode:UIViewContentModeScaleAspectFit];
imageview.frame = workingFrame;
imageview.tag = i;
if(i >= indexFrame && i <= indexFrame + 9)
{
[scrollview addSubview:imageview];
workingFrame.origin.x = workingFrame.origin.x + workingFrame.size.width;
}
}
[scrollview setPagingEnabled:YES];
[scrollview setContentSize:CGSizeMake(workingFrame.origin.x, workingFrame.size.height)];
[scrollview scrollRectToVisible:CGRectMake(0, 0, workingFrame.size.width, workingFrame.size.height) animated:NO];
self.scrollview.hidden = NO;
self.pageControll.hidden = NO;
self.pageControll.numberOfPages = [[scrollview subviews]count];
index = 0;
lastContentOffset = scrollview.contentOffset.x;
NSLog(#"lastContentOffset %.2f",lastContentOffset);
}
After that on scrollViews delegate method
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
NSLog(#"ScrollViewDidEndDecelerating is called with subview(s) %d",[[scrollview subviews]count]);
if(lastContentOffset < scrollView.contentOffset.x)
{
index += (int)(scrollview.contentOffset.x - lastContentOffset)/scrollview.frame.size.width;
newIndex += (int)(scrollview.contentOffset.x - lastContentOffset)/scrollview.frame.size.width;
self.pageControll.currentPage = index;
NSLog(#"Index incremented %d \n newIndex %d",index,newIndex);
if(index == [[scrollView subviews]count]-1)
{
if(newIndex < [infoItems count]-1)
{
[self performSelector:#selector(reloadScrollViewWithNewImages)];
}
}
[Appirater userDidSignificantEvent:YES];
}
else if(lastContentOffset > scrollView.contentOffset.x)
{
index -= (int)(lastContentOffset - scrollview.contentOffset.x)/scrollview.frame.size.width;
newIndex -= (int)(int)(lastContentOffset - scrollview.contentOffset.x)/scrollview.frame.size.width;
self.pageControll.currentPage = index;
NSLog(#"Index decremented %d \n newIndex %d",index,newIndex);
if(index == 0)
{
if(newIndex > 0)
{
newIndex -= 9;
if(newIndex < 0)
newIndex = 0;
[self performSelector:#selector(reloadScrollViewWithNewImages)];
}
}
[Appirater userDidSignificantEvent:YES];
}
lastContentOffset = scrollView.contentOffset.x;
NSLog(#"New lastContentOffset %.2f",lastContentOffset);
}
and the method used for reload the scrollView is as follow
-(void)reloadScrollViewWithNewImages
{
for (UIView *v in [scrollview subviews]) {
[v removeFromSuperview];
}
CGRect workingFrame = scrollview.frame;
workingFrame.origin.x = 0;
NSLog(#"reloadScrollView newIndex %d",newIndex);
int indexFrame = newIndex;
for(int i = 0; i < [infoItems count]; i++)
{
NSDictionary *dict = [infoItems objectAtIndex:i];
UIImageView *imageview = [[UIImageView alloc] initWithImage:[dict objectForKey:UIImagePickerControllerOriginalImage]];
[imageview setContentMode:UIViewContentModeScaleAspectFit];
imageview.frame = workingFrame;
imageview.tag = i;
if(i >= indexFrame && i <= indexFrame + 9)
{
[scrollview addSubview:imageview];
workingFrame.origin.x = workingFrame.origin.x + workingFrame.size.width;
}
}
[scrollview setPagingEnabled:YES];
[scrollview setContentSize:CGSizeMake(workingFrame.origin.x, workingFrame.size.height)];
[scrollview scrollRectToVisible:CGRectMake(0, 0, workingFrame.size.width, workingFrame.size.height) animated:NO];
self.scrollview.hidden = NO;
self.pageControll.hidden = NO;
index = 0;
self.pageControll.numberOfPages = [[scrollview subviews]count];
NSLog(#"number %d",[[scrollview subviews]count]);
lastContentOffset = scrollview.contentOffset.x;
NSLog(#"reloadScrollView's lastContentOffset %.2f",lastContentOffset);
}
and all used properties and private ivars declared in .h file's interface part required in this code are
Private ivars
NSInteger index;
float lastContentOffset;
Properties
#property (nonatomic,strong) IBOutlet UIScrollView *scrollview;
#property (strong, nonatomic) NSArray *infoItems;
#property (assign, atomic) int newIndex;
Happy Coding :)
You can use CATiledLayer to draw image. CATiledLayer can be used to increase the performance of paging, panning, and zooming with high-resolution images or large sets of photos.
As i commented above you can go by reusable view approach means at a time only three imagview or view will be in memory. Let say you are showing photo number:2 so, you should have to keep photo:1,2 and3 in memory(i.e. to avoid flicker) no need to load all photos at a time. Suppose you are scrolling to photo number:3 then your logic should discard photo number:1 and should load photo number:2,3,4. If you are still not getting or don't know how to do this programmatically then don't worry. Apple's good sample code is available that is doing all you want.
Sample code
In above sample code they have displayed two way of displaying image.
One is directly showing/setting the image into image view.
Second is with drawing image with TileView using this method: - (void)displayTiledImageNamed:(NSString *)imageName size:(CGSize)imageSize
If you are thinking lot of about memory then definitely you have to use second approach.
I'm trying to take a UIImageView, resize that image and display it. Then i want to break up that image into smaller pieces and display them.
The resized image displays correctly but it appears that the "split up" images are too big; i'm thinking they are coming from the original (slightly bigger) image. The following screenshot shows the resized image on the left and the a column of split up images from the left hand side.
The fact that the resized image is displaying correctly and the smaller ones aren't has me confused. Any ideas would be appreciated - or even an alternative. Here is my code:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
width = imgOriginal.frame.size.width;
height = imgOriginal.frame.size.height;
whratio = width/height;
[self getOriginalImageInfo];
[self resizeImage];
resizedImage = [self resizeImage];
}
-(void) getOriginalImageInfo {
lblWidth.text = [NSString stringWithFormat:#"%0.2f", width];
lblHeight.text = [NSString stringWithFormat:#"%0.2f", height];
lblWHRatio.text = [NSString stringWithFormat:#"%0.2f", whratio];
}
-(UIImageView*) resizeImage {
if (whratio >= 0.7 && whratio <=0.89) {
imgOriginal.frame = CGRectMake(20, 20, 500, 600);
imgOriginal.autoresizingMask = NO;
float resizedWHRatio = (imgOriginal.frame.size.width)/(imgOriginal.frame.size.height);
lblResizedWidth.text = [NSString stringWithFormat:#"%0.2f", imgOriginal.frame.size.width];
lblResizedHeight.text = [NSString stringWithFormat:#"%0.2f", imgOriginal.frame.size.height];
lblResizedWHRatio.text = [NSString stringWithFormat:#"%0.2f", resizedWHRatio];
return imgOriginal;
}
return nil;
}
- (IBAction)easyPressed:(id)sender {
NSLog(#"Easy button pressed");
CGImageRef original = [resizedImage.image CGImage];
float pieceWidth = (resizedImage.frame.size.width) / 5;
float pieceHeight = (resizedImage.frame.size.height) / 6;
for (int i =0; i<6; i++) {
CGRect rectangle = CGRectMake(0, 0+((float)i*pieceHeight), pieceWidth, pieceHeight);
CGImageRef newTile = CGImageCreateWithImageInRect(original, rectangle);
UIImageView *puzzlePiece = [[UIImageView alloc] initWithFrame:CGRectMake(611, 20+((float)i*pieceHeight), pieceWidth, pieceHeight)];
puzzlePiece.tag = i+1;
puzzlePiece.image = [UIImage imageWithCGImage:newTile];
puzzlePiece.alpha = 0.5;
[puzzlePiece.layer setBorderColor: [[UIColor blackColor] CGColor]];
[puzzlePiece.layer setBorderWidth: 1.0];
[self.view addSubview:puzzlePiece];
}
}
Try applying the same scaling factor to the partial images as you are to the main image!!!
OR
Take the screenshot of the UIImageView being displayed and split that up instead.
I have a sprite on which there is a label (CCLabelTTF). On that label i have A,B,C,D,E, etc printed when they are clicked. I want them to scroll left. I've googled some tuorials but i am unable to find the solution and stuck here for long. Here is the screenshot of my game. You can see the characters from A to J. When i click on more incoming characters, that portion should scroll. What can i do to make the characters scroll?
Here is the code from which the characters are shown on label (lblSelectedAlpha) added on sprite:-
-(void)showSelectedAlphaBet{
fSelectedAlphaY =26;
if (tempBackground) {
[tempBackground removeFromParentAndCleanup:YES];
}
tempBackground = [CCSprite spriteWithFile:#"stripe_2.png"];
tempBackground.position = ccp(160,30);
[self addChild:tempBackground z:30];
for (int i=0; i<[arryAddSelectedChar count]; i++) {
// NSLog(#"[arryAddSelectedChar count] %#",[arryAddSelectedChar objectAtIndex:i]);
lblSelectedAlpha = [CCLabelTTF labelWithString:
[arryAddSelectedChar objectAtIndex:i]dimensions:CGSizeMake(30,30)
alignment:UITextAlignmentCenter fontName:#"Marker Felt" fontSize:30];
lblSelectedAlpha.position = ccp(fSelectedAlphaY,25);
lblSelectedAlpha.tag=i;
lblSelectedAlpha.color = ccc3(125,125,125);
[tempBackground addChild:lblSelectedAlpha z:5];
fSelectedAlphaY +=25;
}
}
Scrolling is simply a constant change in position over time. Basically something like this:
-(void) update:(ccTime)delta
{
label.position = CGPointMake(label.position.x - 1, label.position.y);
}
Well, this is how i implemented scrolling in my cocos2d game
// How to add scroll on label. This i did with a UITextView
// inside init, i took
{
scroll = [[UIScrollView alloc] initWithFrame:CGRectMake(10,430, 150, 50)]
alphabetScroll = [[UITextView alloc] initWithFrame:CGRectMake(10,0,50 ,50)];
alphabetScroll.font = [UIFont fontWithName:#"verdana" size:30.0f];
alphabetScroll.backgroundColor = [UIColor clearColor];
alphabetScroll.textColor = [UIColor colorWithRed:125.0/255.0 green:125.0/255.0 blue:125.0/255.0 alpha:1.0f];
alphabetScroll.userInteractionEnabled=NO;
[scroll addSubview:alphabetScroll];
[[[CCDirector sharedDirector]openGLView]addSubview:scroll];
}
-(void)showSelectedAlphaBet
{
NSLog(#"showSelectedAlphaBet");
fSelectedAlphaY =26; // I have 26 alphabets
if (tempBackground) {
[tempBackground removeFromParentAndCleanup:YES];
}
// Area where alphabets are added on touch
tempBackground = [CCSprite spriteWithFile:#"stripe_2.png"];
tempBackground.position = ccp(160,30);
[self addChild:tempBackground z:30];
bottomAlphabet = #" ";
for (int i=0; i<[arryAddSelectedChar count]; i++) {
NSLog(#"[arryAddSelectedChar count] %#",[arryAddSelectedChar objectAtIndex:i]);
bottomAlphabet = [bottomAlphabet stringByAppendingString:[arryAddSelectedChar objectAtIndex:i]];
}
// Implementing shifting/scrolling
int newScrollViewWidth;
int newLabelWidth;
newScrollViewWidth =25*[arryAddSelectedChar count];
newLabelWidth =50*[arryAddSelectedChar count];
[scroll setContentSize:CGSizeMake(newScrollViewWidth, 45)];
alphabetScroll.frame = CGRectMake(0, 0, newLabelWidth, 45);
alphabetScroll.text = bottomAlphabet;
if (newScrollViewWidth > 150) {
CGPoint svos;
CGPoint pt;
svos = scroll.contentOffset;
CGRect rc = [alphabetScroll bounds];
rc = [alphabetScroll convertRect:rc toView:scroll];
pt = rc.origin;
pt.y = 0;
pt.x += 20*([arryAddSelectedChar count]-5);
[scroll setContentOffset:pt animated:YES];
}
}
// In dealloc
[alphabetScroll release];
I'm new in iOS. Now I want to load view images from URL to page control using scroll view. When I run the program the first image is shown but when I try to slide to next image or I move to another page program is not responding. My guess is probably related to the size of image.
The following is my code to load the image. I put this code in -(void) viewDidLOad...
CGRect screenShot = screenView.frame;
screenShot.origin.y = description.frame.origin.y + description.frame.size.height + 30;
screenView.frame = screenShot;
pageControlBeingUsed = NO;
for (int i = 0; i < [myArrayImagesURL count]; i++) {
CGRect frame;
frame.origin.x = self.scrollView.frame.size.width * i;
frame.origin.y = 0;
frame.size = self.scrollView.frame.size;
UIImageView *iv = [[[UIImageView alloc] initWithFrame:CGRectMake(scrollView.bounds.size.width * i, 0, scrollView.bounds.size.width, scrollView.bounds.size.height)] autorelease];
iv.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:
[NSURL URLWithString:[myArrayImagesURL objectAtIndex:i]]]];
[self.scrollView addSubview:iv];
[iv release];
}
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * [myArrayImagesURL count], self.scrollView.frame.size.height);
self.pageControl.currentPage = 0;
self.pageControl.numberOfPages = [myArrayImagesURL count];
It looks like you have set the imageView to autorelease and the released it. This should be wrong. Try removing the autorelease tag when you create the imageView. It should be properly retained now.
UIImageView *iv = [[UIImageView alloc] initWithFrame:CGRectMake(scrollView.bounds.size.width * i, 0, scrollView.bounds.size.width, scrollView.bounds.size.height)];
I'm trying to dynamically add Images to a ScrollView. Before adding I check if there are any subviews in the ScrollView and delete them in a for loop.
When I release the imageview I get a runtime error stating i'm trying to acces a deallocated instance. If I remove the release statement the application will run correctly but "build and analyze" shows a leak because th reference count of imageview is not decreased..
if ([scrollView.subviews count]>0){
for (int i=0; i<[scrollView.subviews count]; ++i) {
[[scrollView.subviews objectAtIndex:i] removeFromSuperview];
}
}
//Making a scroller with results
int scrollWidth = 0.0f;
int scrollHeight = 0.0f;
for (int i = 0; i<previewImages.count;++i)
{
UIImage *image=[previewImages objectAtIndex:i];
scrollWidth = scrollWidth + image.size.width; // Width of all the images
if (image.size.height > scrollHeight)scrollHeight= image.size.height; // Maximum image height
[image release];
}
float xC = 0.0f;
for (int i=0; i<previewImages.count; ++i) {
UIImage *image=[previewImages objectAtIndex:i];
UIImageView *imageview = [[UIImageView alloc] initWithFrame:CGRectMake(xC, 0.0f, image.size.width, image.size.height)];
UILabel *subScript = [[UILabel alloc] initWithFrame:CGRectMake(xC, image.size.height-30.0f, image.size.width,30.0f)];
subScript.textColor = [UIColor whiteColor];
subScript.backgroundColor = [UIColor colorWithWhite:0.5f alpha:0.5f];
subScript.text = [imagePaths objectAtIndex:i];
imageview.image = image;
xC = xC + image.size.width;
[image release];
[scrollView addSubview:imageview];
[imageview release];
[scrollView addSubview:subScript];
[subScript release];
}
[scrollView setContentSize:CGSizeMake(scrollWidth , scrollHeight)];
Any suggestions about the memory leak or general best practices for adding and removing views from an array into a scrollView are much appreciated!
if ([scrollView.subviews count]>0){
for (int i=0; i<[scrollView.subviews count]; ++i) {
[[scrollView.subviews objectAtIndex:i] removeFromSuperview];
}
}
is wrong, because you are removing subview from subviews array. Do reverse iteration would fix that, but I would suggest keeping the view in separated array instead.