Objective-C append image thumbnails onto the end of a view - objective-c

I'm trying to append images onto a view and have them display a thumbnail in a nice neat row. The issue I'm having is that it appears all images simply get added on top on each other in the corner as only the last image in the array is dispayed.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
self.notesField.delegate = self;
NSString *userName = ((ontracAppDelegate*)[UIApplication sharedApplication].delegate).userName;
self.textField.text = [NSString stringWithFormat:#"Date Created: %# \nCreated By: %#",[NSDate date], userName];
if (self.noteText != nil) {
self.notesField.text = self.noteText;
self.notesField.editable = NO;
self.textLabel.hidden = TRUE;
}
[self.view resignFirstResponder];
if ([self.imageArray count] != 0) {
for (UIImage *image in imageArray) {
NSLog(#"Image %#", image);
[self addImageToScreen:image];
}
}
NSLog(#"imageArray %#", imageArray);
NSLog(#"self.textField.text %#", self.textField.text );
NSLog(#"self.notesField.text %#", self.notesField.text);
}
-(void) addImageToScreen:(UIImage*) image;
{
int adjustHeight = 0;
int adjustWidth = 10;
int imagesInARow = 7;
int imageHeight = 75;
int imageWidth = 75;
int count = [self.imageArray count];
self.numberOfPhotosLabel.text = [NSString stringWithFormat:#"%i",count];
if (count > 1 && count < imagesInARow) {
adjustHeight = 0;
adjustWidth = (20 * [self.imageArray indexOfObject:image]) + ([self.imageArray indexOfObject:image] * imageWidth);
}
UIButton* container = [[UIButton alloc] init ];
CGRect frame = CGRectMake(adjustWidth, 5, imageWidth, imageHeight);
[container setTag:[self.imageArray indexOfObject:image]];
[container setImage:image forState:UIControlStateNormal];
[container setFrame:frame];
[container addTarget:self action:#selector(displayFullScreenImage:) forControlEvents:UIControlEventAllTouchEvents];
UIStackView *photosView = [[UIStackView alloc] initWithFrame:frame];
container.frame = photosView.bounds;
[photosView addSubview:container];
[self.view addSubview:photosView];
}

Use addArrangedSubview of UIStackView instead of addSubview.
And you should add all the Buttons to the same UIStackView. So, add a property for the UIStackView to your class, initialize it in viewDidLoad (or in the storyboard) and add the buttons to that stack view in addImageToScreen.

Related

why is - (null) at the end of my object

I have the following class
#import <UIKit/UIKit.h>
#interface UIImageViewInfo : UIImageView
#property(nonatomic,strong) NSString* colorInfo;
#end
when creating an UIImageViewInfo in function1(post below) I get the correct result
"UIImageViewInfo: 0x1d8acd60; baseClass = UIImageView; frame = (0 0;
20 20); opaque = NO; userInteractionEnabled = NO; tag = 2000; layer =
CALayer: 0x1d8a0560>>"
but creating the something in function2(posted below) I get the -(null)
UIImageViewInfo: 0x8372c40; baseClass = UIImageView; frame = (0 0; 20
20); alpha = 0; hidden = YES; opaque = NO; userInteractionEnabled =
NO; tag = 2000; layer = CALayer: 0x8380090>> - (null)
Why is there a - (null) ??
Thanx in advance
P.S> here is more from my code
-(void)function1{
UIImageViewInfo *image;
self.solutionPinSlots = [[NSMutableArray alloc] init];
for (int i=0; i<M; i++) {
image = [[UIImageViewInfo alloc] initWithImage:[UIImage imageNamed:#"solutionPeg#2x.png"]];
image.translatesAutoresizingMaskIntoConstraints=NO;
image.hidden=YES;
image.alpha = 0;
image.colorInfo = #"clear";
image.tag = 2000*(self.brainController.slotsIndex+1) +i;
[self.solutionPinSlots addObject:image];
[self.view addSubview:(UIImageViewInfo *)self.solutionPinSlots[i]];
}
NSLog(#"solutionSlots: %#",self.solutionPinSlots);
__block int counter = 0;
[self.brainController.solution enumerateObjectsUsingBlock:^(NSString *peg, NSUInteger idx, BOOL *stop){
for (int i=0;i<M;i++) {
if ([self.brainController.slots[self.brainController.slotsIndex][i] isEqual:peg]) {
if (i==idx) {
((UIImageViewInfo *) self.solutionPinSlots[counter]).backgroundColor = [UIColor whiteColor];
((UIImageViewInfo *) self.solutionPinSlots[counter]).colorInfo=#"white";
}else{
((UIImageViewInfo *) self.solutionPinSlots[counter]).backgroundColor = [UIColor blackColor];
((UIImageViewInfo *) self.solutionPinSlots[counter]).colorInfo=#"black";}
((UIImageViewInfo *) self.solutionPinSlots[counter]).hidden=NO;
((UIImageViewInfo *) self.solutionPinSlots[counter++]).alpha=1;
}
}
}];
[self.solutionPinSlots shuffle];
[self updateSolutionPinSlots];
}
-(void)function2{
NSString *obj;
for (int idx=0; idx< M;idx++ ) {
UIImageViewInfo *image = [[UIImageViewInfo alloc] initWithImage:[UIImage imageNamed:#"solutionPeg#2x.png"]];
image.translatesAutoresizingMaskIntoConstraints=NO;
obj = (NSString *) [self.solutionPinSlots objectAtIndex:idx];
image.tag=2000*(self.brainController.slotsIndex+1)+idx;
image.hidden=NO;
image.alpha = 1;
if ([obj isEqualToString:#"clear"]) {
image.hidden=YES;
image.alpha = 0;
image.colorInfo=#"clear";
image.backgroundColor=[UIColor clearColor];
}else if ([obj isEqualToString:#"white"]){
image.colorInfo=#"white";
image.backgroundColor=[UIColor whiteColor];
}else if ([obj isEqualToString:#"black"]){
image.colorInfo=#"black";
image.backgroundColor=[UIColor blackColor];
}else{
NSLog(#"Something is Wrong!!!");
}
[self.solutionPinSlots replaceObjectAtIndex:idx withObject:image];
[self.view addSubview:image];
}
}
Never mind. It is coming from the description method of UIView, which is rather complex and dumps a bunch of information about the view. One of the conditionals is being tripped up by your configuration and causing the (null) at the end.
Safe to ignore.
There is no UIImageViewInfo class in UIKit, so the implementation must be in your project. In that implementation, there is likely a description method that is implemented something like:
- (NSString*)description {
....
return [NSString stringWithFormat:#"UIImageViewInfo:%p; %# - %#", self, [super description], someInstanceVariableThatHappensToBeNil]];
}
Only your description is likely more complex due to the sometimes does this sometimes that output.
Not that you should not prefix classes with UI when subclassing the UIKit.
It is because your NSLog call (which you do not show) is asking for a second object, and that second object is null.

UIScrollView and UIPageControl, what am I doing wrong?

I have a class which is predefining some labels and binding their values in a UIScrollView.
I've managed to show those labels, but now I'm stuck at putting a label at the 2nd part of the ScrollView.
I've pushed my project to gitHub.
I can change the label's place on the already visible part, but I must be overlooking something.
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.title = _detail.name;
UIColor *bgColor = [UIColor blackColor];
UIColor *txtColor = [UIColor grayColor];
CGRect frame;
frame.origin.x = 0;
frame.origin.y = 0;
frame.size.width = _scrollView.frame.size.width *2;
NSString *phoneNr = (_detail.phoneNr == nil) ? #"Not specified" : _detail.phoneNr;
_telLabel = [self prepareLabel:phoneNr textColor:txtColor bgColor:bgColor page:0 y:telNrYAxis];
_webLabel = [self prepareLabel:#"Visit website" textColor:txtColor bgColor:bgColor page:0 y:websiteYAxis];
_detail.address = [_detail.address stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:#"\n\t "]];
NSArray *addressArrComponents = [_detail.address componentsSeparatedByString:#","] ;
_addressLabel = [self prepareLabel:[addressArrComponents componentsJoinedByString:#"\n"] textColor:txtColor bgColor:bgColor page:0 y:addressYAxis];
UILabel *lbl = [self prepareLabel:#"Derp" textColor:txtColor bgColor:bgColor page:1 y:0];
_detailView = [[UIView alloc] initWithFrame:frame];
_detailView.backgroundColor = [UIColor blackColor];
[_detailView addSubview:_webLabel];
[_detailView addSubview:_addressLabel];
[_detailView addSubview:_telLabel];
[_detailView addSubview:lbl];
[_scrollView addSubview:_detailView];
NSLog(#"%f",self.view.frame.size.height - (_scrollView.frame.origin.y + _scrollView.frame.size.height) );
_pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(self.view.frame.size.width/2, self.view.frame.size.height - 250 , self.view.frame.size.width/4, 120)];
_pageControl.numberOfPages=2;
_pageControl.currentPage=0;
[_pageControl addTarget:self action:#selector(pageChange:) forControlEvents:UIControlEventTouchDown];
_scrollView.contentSize = CGSizeMake(800,800);
_scrollView.delegate=self;
_scrollView.backgroundColor = [UIColor blackColor];
_scrollView.pagingEnabled=YES;
_scrollView.showsHorizontalScrollIndicator = NO;
_scrollView.showsVerticalScrollIndicator = NO;
_scrollView.scrollsToTop = NO;
[self pageChange:0];
[self.view addSubview:_pageControl];
// Do any additional setup after loading the view.
}
-(UILabel*)prepareLabel:(NSString*) text textColor:(UIColor*)textColor bgColor:(UIColor*)backgroundColor page:(int)page y:(int) yPos{
int lines = [[text componentsSeparatedByString:#"\n"] count];
CGRect labelFrame = CGRectMake(_detailView.frame.size.width * page +20,yPos,self.view.frame.size.width, [UIFont systemFontSize]*lines);
UILabel *returnLabel = [[UILabel alloc] initWithFrame:labelFrame];
returnLabel.text = text;
returnLabel.backgroundColor = backgroundColor;
returnLabel.textColor = textColor;
[returnLabel setNumberOfLines:lines];
[returnLabel sizeToFit];
return returnLabel;
}
- (void)loadScrollViewWithPage:(int)page {
NSLog(#"Derped");
}
-(IBAction)pageChange:(id)sender{
int page=_pageControl.currentPage;
CGRect frame = _scrollView.frame;
frame.origin.x = _scrollView.frame.size.width * page;
frame.origin.y = 0;
//CGRect frame= (page == 0) ? _detailFrame : _reviewFrame;
NSLog(#"%f",frame.origin.x);
[_scrollView scrollRectToVisible:frame animated:YES];
}
The delegate -(IBAction)pageChange:(id)sender gets fired, but I must be doing something wrong with the frames somewhere :s
Please take a look!
Try to implement this method may help you :
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGFloat pageWidth = self.scrollView.frame.size.width;
float fractionalPage = self.scrollView.contentOffset.x / pageWidth;
NSInteger page = lround(fractionalPage);
self.pageControl.currentPage = page;
}

Why images are not showing in UIScrollView?

I am using this code to show scrolling images but I am only getting a white screen. I drag drop uiscrollview, created the iboutlet, synthesized it and rest of the code is here
#synthesize scrollView1;
const CGFloat kScrollObjHeight = 199.0;
const CGFloat kScrollObjWidth = 280.0;
const NSUInteger kNumImages = 5;
- (void)layoutScrollImages
{
UIImageView *view = nil;
NSArray *subviews = [scrollView1 subviews];
// reposition all image subviews in a horizontal serial fashion
CGFloat curXLoc = 0;
for (view in subviews)
{
if ([view isKindOfClass:[UIImageView class]] && view.tag > 0)
{
CGRect frame = view.frame;
frame.origin = CGPointMake(curXLoc, 0);
view.frame = frame;
curXLoc += (kScrollObjWidth);
}
}
// set the content size so it can be scrollable
[scrollView1 setContentSize:CGSizeMake((kNumImages * kScrollObjWidth), [scrollView1 bounds].size.height)];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
scrollView1 = [[UIScrollView alloc]init];
bgArray = [NSArray arrayWithObjects:#"Bg", #"Bg1.png", #"Bg2.png", #"Bg3.png", #"Bg4.png", #"Bg5.png", #"Bg6.png", #"Bg7.png", #"Bg8.png", nil];
[scrollView1 setBackgroundColor:[UIColor blackColor]];
[scrollView1 setCanCancelContentTouches:NO];
scrollView1.indicatorStyle = UIScrollViewIndicatorStyleWhite;
scrollView1.clipsToBounds = YES; // default is NO, we want to restrict drawing within our scrollview
scrollView1.scrollEnabled = YES;
// pagingEnabled property default is NO, if set the scroller will stop or snap at each photo
// if you want free-flowing scroll, don't set this property.
scrollView1.pagingEnabled = YES;
// load all the images from our bundle and add them to the scroll view
NSUInteger i;
for (i = 0; i < [bgArray count]; i++)
{
NSString *imageName = [NSString stringWithFormat:#"%#", [bgArray objectAtIndex:i]];
UIImage *image = [UIImage imageNamed:imageName];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
// setup each frame to a default height and width, it will be properly placed when we call "updateScrollList"
CGRect rect = imageView.frame;
rect.size.height = 199.0;
rect.size.width = 280.0;
imageView.frame = rect;
imageView.tag = i; // tag our images for later use when we place them in serial fashion
[scrollView1 addSubview:imageView];
[scrollView1 setShowsHorizontalScrollIndicator:NO];
[scrollView1 setShowsVerticalScrollIndicator:NO];
}
[self layoutScrollImages];
}
I think if you are create UIScrollView from code
scrollView1 = [[UIScrollView alloc]init];
then please add the scrollView1 in view
Example:-[self.view addSubview:scrollView1];
if you are create UIScrollView from nib then
not use this code
scrollView1 = [[UIScrollView alloc]init];
solve your probem

Issue with scroll view and accessing its subviews

I have a scroll view that contains image view sized 68x78:
As you could see, all that images except from the centered one have a shadow. It changes when user scrolls, center image is always clear. It goes perfect until for the left edge image:
Here is the code:
-(void) buildSlideView{
fotosJugadores = [[NSArray alloc] initWithObjects:#"cara5.png", #"cara7.png", #"cara8.png", #"cara9.png", #"cara11.png", #"cara13.png", #"cara14.png", #"cara15.png", #"cara18.png",#"cara19.png", #"cara20.png", #"cara32.png",#"cara44.png",#"cara51.png", #"cara100.png", #"cara101.png", #"cara102.png",#"cara103.png", #"cara104.png", #"cara105.png",#"cara106.png",#"cara107.png", nil];
numberOfViews = [fotosJugadores count];
for (int i = 0; i < [fotosJugadores count]; i++) {
UIImage *myImage = [UIImage imageNamed:[fotosJugadores objectAtIndex:i]];
CGFloat yOrigin = i * (myImage.size.width+3) + 120;
UIImageView *awesomeView = [[UIImageView alloc] initWithFrame:CGRectMake(yOrigin, 0, myImage.size.width, myImage.size.height)];
awesomeView.tag = i;
awesomeView.image = myImage;
awesomeView.alpha = 0.5f;
awesomeView.backgroundColor = [UIColor blackColor];
[self.jugadorSlide addSubview:awesomeView];
awesomeView=nil;
}
[jugadorSlide setBackgroundColor:[UIColor blackColor]];
jugadorSlide.contentSize = CGSizeMake(68 * numberOfViews+240,78);
jugadorSlide.layer.cornerRadius = 11;
jugadorSlide.layer.masksToBounds = YES;
[jugadorSlide setContentOffset:CGPointMake(((68 * numberOfViews)/2), 0)];
//jugadorSlide.decelerationRate = UIScrollViewDecelerationRateNormal;
[self scrollViewDidEndDragging:jugadorSlide willDecelerate:NO];
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
currentIndex = roundf(scrollView.contentOffset.x / 68);
NSLog(#"current end %d", currentIndex);
UIImageView *currentImage = [scrollView viewWithTag:currentIndex];
if (currentIndex>0&&currentIndex<=21){
if (currentIndex==currentImage.tag){
currentImage.alpha=1.0f;
[self changePerfilImage:currentImage.tag];}
CGPoint pointZero= CGPointMake(scrollView.contentOffset.x, currentImage.frame.origin.y);
[jugadorSlide setContentOffset:pointZero animated:YES];
}else {
UIImageView *currentImage = [scrollView viewWithTag:0];
NSLog(#"end dragging image tag %d", currentImage.tag);
currentImage.alpha=1.0f;
[self changePerfilImage:currentImage.tag];}
CGPoint pointZero= CGPointMake(currentImage.frame.origin.x+15, 0);
//[jugadorSlide setContentOffset:pointZero animated:YES];
}
As you can see, in the scrollViewDidEndDragging: "else" , I forced the tag as a desesperate solution, but images doesn't get clear.
You are incrementing the tag twice...
awesomeView.tag = i++;
Should just be:
awesomeView.tag = i+1;
I use i+1 because I never use a tag of 0 since any subview that hasn't been assigned a tag will have a tag of 0.
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
NSInteger currentIndex = roundf(scrollView.contentOffset.x / 68.0) + 1;
UIImageView *currentImage = [scrollView viewWithTag:currentIndex];
...
}
If this doesn't work you should NSLog the currentIndex each time you land on a new image and see what is happening when you land on the first one.

NSMatrix with multiple toggle buttons?

I am trying to create an NSMatrix of NSButtonCells where between zero and four buttons can be selected (toggled on). I have tried the following (test) code, but am not sure how I can provide the functionality I require. Perhaps it's not possible with NSMatrix and I need to look at an alternative control, or create my own?
#interface MatrixView : NSView
{
NSScrollView *_scrollView;
NSMatrix *_matrixView;
}
#end
#implementation MatrixView
- (id)initWithFrame:(NSRect)frameRect
{
NSLog(#"initWithFrame. frameRect=%#", NSStringFromRect(frameRect));
self = [super initWithFrame:frameRect];
if (self != nil)
{
_scrollView = [[NSScrollView alloc] initWithFrame:NSMakeRect(0, 0, frameRect.size.width, frameRect.size.height)];
[_scrollView setBorderType:NSNoBorder];
[_scrollView setHasVerticalScroller:YES];
[_scrollView setHasHorizontalScroller:NO];
[_scrollView setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
NSSize contentSize = [_scrollView contentSize];
contentSize.height = 300;
// Make it 3 x however-many-buttons-will-fit-the-height
CGFloat gap = 8.0;
CGFloat width = (contentSize.width / 3.0) - (gap * 2.0);
NSUInteger rows = (contentSize.height / (width + gap));
NSLog(#"width=%f, rows=%lu", width, rows);
NSButtonCell *prototype = [[NSButtonCell alloc] init];
[prototype setTitle:#"Hello"];
[prototype setButtonType:NSToggleButton];
[prototype setShowsStateBy:NSChangeGrayCellMask];
_matrixView = [[NSMatrix alloc] initWithFrame:NSMakeRect(0, 0, contentSize.width, contentSize.height)
mode:NSListModeMatrix
prototype:prototype
numberOfRows:rows
numberOfColumns:3];
[_matrixView setCellSize:NSMakeSize(width, width)];
[_matrixView setIntercellSpacing:NSMakeSize(gap, gap)];
[_matrixView setAllowsEmptySelection:YES];
[_matrixView sizeToCells];
[_scrollView setDocumentView:_matrixView];
[self addSubview:_scrollView];
[self setAutoresizesSubviews:YES];
[prototype release];
}
return self;
}
...
I got this to work with the following subclass of NSMatrix. I added one property, onCount, to keep track of how many buttons were in the on state:
#implementation RDMatrix
#synthesize onCount;
-(id) initWithParentView:(NSView *) cv {
NSButtonCell *theCell = [[NSButtonCell alloc ]init];
theCell.bezelStyle = NSSmallSquareBezelStyle;
theCell.buttonType = NSPushOnPushOffButton;
theCell.title = #"";
if (self = [super initWithFrame:NSMakeRect(200,150,1,1) mode:2 prototype:theCell numberOfRows:4 numberOfColumns:4]){
[self setSelectionByRect:FALSE];
[self setCellSize:NSMakeSize(40,40)];
[self sizeToCells];
self.target = self;
self.action = #selector(buttonClick:);
self.drawsBackground = FALSE;
self.autoresizingMask = 8;
self.allowsEmptySelection = TRUE;
self.mode = NSHighlightModeMatrix;
self.onCount = 0;
[cv addSubview:self];
return self;
}
return nil;
}
-(IBAction)buttonClick:(NSMatrix *)sender {
NSUInteger onOrOff =[sender.selectedCells.lastObject state];
if (onOrOff) {
self.onCount += 1;
}else{
self.onCount -= 1;
}
NSLog(#"%ld",self.onCount);
if (self.onCount == 5) {
[sender.selectedCells.lastObject setState:0];
self.onCount -= 1;
}
}
When you try to select the 5th button it will flash on, but then go off. This could be a problem depending on how you are using the state of these buttons. I just logged them with this method:
-(IBAction)checkMatrix:(id)sender {
NSIndexSet *indxs = [self.mat.cells indexesOfObjectsPassingTest:^BOOL(NSButtonCell *cell, NSUInteger idx, BOOL *stop) {
return cell.state == NSOnState;
}];
NSLog(#"%#",indxs);
}
After Edit: I didn't like the way my first method flashed the button on briefly before turning it off again when you try to click the 5th button. I found what I think is a better solution that involves overriding mouseDown in the matrix subclass (if you want to try this, you should delete the setAction and setTarget statements and delete the buttonClick method):
-(void)mouseDown:(NSEvent *) event {
NSPoint matPoint = [self convertPoint:event.locationInWindow fromView:nil];
NSInteger row;
NSInteger column;
[self getRow:&row column:&column forPoint:matPoint];
NSButtonCell *cell = [self cellAtRow:row column:column];
if (self.onCount < 4 && cell.state == NSOffState) {
cell.state = NSOnState;
self.onCount += 1;
}else if (cell.state == NSOnState) {
cell.state = NSOffState;
self.onCount -= 1;
}
}