UIButton cannot be displayed - ios

in my app i'm using a scroll View (paging). each view in the scroll view (UIImageView) contains an image and each image has tags (buttons) scattered all over the pic. so here is my code:
for (int i = 0; i < self.pictures.count; i++)
{
//The first loop is to loop to every picture
int nbOfTags = classObject.tagsImages.count;
for (int j = 0; j < nbOfTags; j++)
{
//Second loop is to loop to each tag corresponding to the picture
ListTags *listTags = [[ListTags alloc]init];
NSMutableArray *tagInfo = [[NSMutableArray alloc]init];
listTags = [tagInfo objectAtIndex:j];
float tagX = [listTags.tag_x floatValue];
float tagY = [listTags.tag_y floatValue];
float x = 1024*i+ tagX;
float y = tagY;
CGRect rect = CGRectMake(x, tagY, 20, 20);
UIButton *button = [[UIButton alloc] initWithFrame:rect];
UIImage * buttonImage = [UIImage imageNamed:#"blueCircle.png"];
[button setBackgroundImage:buttonImage forState:UIControlStateNormal];
[self.scrollView addSubview:button];
}
}
problem: when i run the code i can't see the buttons (tags) on the picture. if i replace "i" with "j" in
float x = 1024*i+ tagX;
the buttons can be seen, however it's not the desired coordinates. so why "i" can't work? am i doing anything wrong or missing anything?

In interface builder (or storyboard - IB) uncheck autolayout (if it's checked) then your button will be displayed where you want.

See my comments in the code below:
for (int i = 0; i < self.pictures.count; i++)
{
//The first loop is to loop to every picture
/*
* This will give you the same number of tags for every image.
* Is that what you want?
*/
int nbOfTags = classObject.tagsImages.count;
for (int j = 0; j < nbOfTags; j++)
{
//Second loop is to loop to each tag corresponding to the picture
/* This allocates a brand new ListTags object EVERY time through the loop. */
ListTags *listTags = [[ListTags alloc]init];
/* This allocates a brand new EMPTY array EVERY time through the loop. */
NSMutableArray *tagInfo = [[NSMutableArray alloc]init];
/*
* This discards the new ListTags object that you just created two lines ago
* and replaces it with an object from tagInfo. Which doesn't exist because
* you just created a new array in the previous line. This really should
* crash, which leads me to believe that this isn't the actual code that you
* are using. Post the actual code that you are using so that we can help you
* better.
*/
listTags = [tagInfo objectAtIndex:j];
/* None of this is valid since listTags is nil/we never should have gotten here. */
float tagX = [listTags.tag_x floatValue];
float tagY = [listTags.tag_y floatValue];
float x = 1024*i+ tagX;
float y = tagY;
CGRect rect = CGRectMake(x, tagY, 20, 20);
UIButton *button = [[UIButton alloc] initWithFrame:rect];
UIImage * buttonImage = [UIImage imageNamed:#"blueCircle.png"];
[button setBackgroundImage:buttonImage forState:UIControlStateNormal];
[self.scrollView addSubview:button];
}
}

Related

Displaying UILabel dynamcially from the NSMutableArray

I have a mutable array as below
labelArrays = [NSMutableArray arrayWithObjects:#"One”, #“Two”, #“Three", nil];
I want to display all the list array values as individual label. This is like displaying the UILabel dynamically using the array values. What i did is as below,
int count=20;
for(int i = 0; i < [labelArrays count]; i++){
label1 = [[UILabel alloc]init];
label1.text = [labelArrays componentsJoinedByString:#" "];
label1.textColor = [UIColor colorWithRed:0.643 green:0.643 blue:0.639 alpha:1];
label1.layer.borderWidth = 1.0;
label1.layer.cornerRadius = 8;
count+=20;
[self addSubview:label1];
}
Here I can only display all the array values inside the single label. How can i display the array values in multiple labels dynamically.
//viewcontroller
myView.label1.frame =CGRectMake(588,200,200,28);
your coding is fine , but you are not added the frame , try this
label1 = [[UILabel alloc] initWithFrame: CGRectMake(0,count,aslikeyourwidth,aslikeyourheight)];
Define a public method for view in which you are willing to add the UILabel, pass a CGRect to that method and then according to your design, with each iteration update the x coordinate or y coordinate. Follow the below steps:
// code in your viewcontroller
[myView designYourMultipleLabelsWithStartingFrame:CGRectMake(588,200,200,28)]; // pass the frame of the first label.
Now add the multiple UILabel in your view class, let's assume you have set labelArrays.
// code in view class
-(void) designYourMultipleLabelsWithStartingFrame:(CGRect) frame{
float xCoordinate = frame.origin.x;
float yCoordinate = frame.origin.y;
for(int counter = 0; counter < [labelArrays count]; counter++){
UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(xCoordinate,yCoordinate,labelWidth,labelHeight)];
label.text = [labelArrays objectAtIndex:counter];
[self addSubview:label];
// update the x coordinate or y coordinate according to your design. Let's say we need the labels in vertical order, so update the y Coordinate by labelHeight and gap between two labels.
yCoordinate = yCoordinate + labelHeight + gapBetweenTwoLabels.
}
}
Hope this will help.
Just a thought - would you not be better using a tableview to show the array?
It looks like you may need to just handle their position on the view as the code looks like it is adding the labels but it is placing them over each other.

How to get UIButton position from UIScrollView

I have a scrollView with many buttons on it. I'm trying to get the Button position form the scroll so I can scroll it to that position. My issue is I always get the same value in _btnV.frame.origin.x once I click on each button. So please how I can resolve this issue?
- (void)scrollView{
segmentWidth = screenWidth / 5;
NSArray *images = #[#"Smiley-1.png",#"Smiley-2.png",#"Smiley-3.png",#"Smiley-4.png",#"Smiley-5.png",#"Smiley-5.png",#"Smiley-5.png",#"Smiley-4.png",#"Smiley-1.png",#"Smiley-2.png",#"Smiley-3.png",#"Smiley-4.png"];
long ScrollContentSize = ((images.count -1)*segmentWidth)+screenWidth;
_scrlView.contentSize = CGSizeMake(ScrollContentSize, _scrlView.frame.size.height);
float screenX2 = screenHeight/2 - segmentWidth/2;
__block float screenX = (screenWidth-segmentWidth)/2;
NSMutableArray *arr = [[NSMutableArray alloc] init];
for(int i=0; i<images.count; i++)
{
_btnV = [[UIButton alloc]init];
[_btnV setFrame:CGRectMake(screenX, screenX2, segmentWidth, segmentWidth)];
[_btnV setImage:[UIImage imageNamed:[NSString stringWithFormat:#"%#",[images objectAtIndex:i]]] forState:UIControlStateNormal];
[_btnV setBackgroundColor:[UIColor redColor]];
[_btnV addTarget:self action:#selector(scrollToMe:) forControlEvents:UIControlEventTouchUpInside];
[_btnV setTag:i];
[arr addObject:_btnV];
[_scrlView addSubview:_btnV];
screenX = screenX+segmentWidth;
}
_menuItems = arr;
[self.view addSubview:_scrlView];
}
-(void) scrollToMe:(id)sender{
int scrollX = _scrlView.contentOffset.x;
int mod = scrollX % segmentWidth;
int position = scrollX/segmentWidth;
float positionOffset = (float) mod / segmentWidth;
scrollX = position * segmentWidth;
NSLog(#"position:%f",_btnV.frame.origin.x);
//scrollX = ...
[_scrlView setContentOffset:CGPointMake(scrollX, scrollX) animated:YES];
}
Find the button using its tag value
-(void) scrollTo:(id)sender{
UIButton * button = (UIButton *)sender;
int position = button.tag;
scrollX = position * segmentWidth;
NSLog(#"position:%f",_btnV.frame.origin.x);
//scrollX = ...
[_scrlView setContentOffset:CGPointMake(scrollX, scrollX) animated:YES];
}
You are calling selector method of UIButton. so in this method, you can directly get UIButton position with respect to UIScrollView. like
-(void) scrollTo:(id)sender{
UIButton* btnClick = (UIButton*)sender;
NSLog(#"X position : %f",btnClick.frame.origin.x);
}
Hope this help you.
try this , it will log position of all your button correctly
-(void) scrollTo:(id)sender{
int scrollX = _scrlView.contentOffset.x;
int mod = scrollX % segmentWidth;
int position = scrollX/segmentWidth;
float positionOffset = (float) mod / segmentWidth;
scrollX = position * segmentWidth;
for(int i=0; i<images.count; i++)
{ if([[[_scrlView subviews] objectAtIndex:i] isKindOfClass:[UIButton class]]) {
Button btn = [[_scrlView subviews] objectAtIndex:i];
NSLog(#"position:%f",btn.frame.origin.x);
}
}
//scrollX = ...
[_scrlView setContentOffset:CGPointMake(scrollX, scrollX) animated:YES];
}

Randomly swap the positions of 4 UIButtons

I have 4 UIButtons, positioned in my VC. I want to randomly swap the positions of each button. I've placed all of the UIButton positions into a NSMutableArray
self.frameArray = [[NSMutableArray alloc] init];
[self.frameArray addObject:[NSValue valueWithCGRect:CGRectMake(60,171,64,64)]];
[self.frameArray addObject:[NSValue valueWithCGRect:CGRectMake(198,171,64,64)]];
[self.frameArray addObject:[NSValue valueWithCGRect:CGRectMake(60,333,64,64)]];
[self.frameArray addObject:[NSValue valueWithCGRect:CGRectMake(198,333,64,64)]];
`
and all of my buttons are in a NSArray
self.buttons = #[self.button1, self.button2, self.button3, self.button4];
but i'm really not sure where to go from here, to make the positions of the UIButtons to randomly swap. Any help would be appreciated
Basically you want to create the frameArray then randomize the order of the frames and then apply them to the buttons.
Step One: Randomize the frameArray (place code after creation of frameArray)
NSUInteger count = [self.frameArray count];
for (NSUInteger i = 0; i < count; ++i) {
NSInteger remainingCount = count - i;
NSInteger exchangeIndex = i + arc4random_uniform((u_int32_t )remainingCount);
[self.frameArray exchangeObjectAtIndex:i withObjectAtIndex:exchangeIndex];
}
Step Two: Set Button Frames
for (int i = 0; i < [self.buttons count]; i++) {
[[self.buttons objectAtIndex:i] setFrame:[self.frameArray objectAtIndex:i]];
}
You can use arc4random_uniform() to get a random button and a random Rect from the arrays, and then assign the random Rect to the random button's frame:
NSInteger randomButton = arc4random_uniform((u_int32_t)self.buttons.count);
NSInteger randomRect = arc4random_uniform((u_int32_t)self.frameArray.count);
UIButton *button = self.buttons[randomButton];
NSValue *theRectValue = self.frameArray[randomRect];
CGRect rect = [theRectValue CGRectValue];
button.frame = rect;
I think this will work.

ios: Naming views through loops

Just wondering how i can dynamically name Uiviews or variables in general and then reference them in Obj C(X code), and once created the best way to reference them.
I read somewhere else that you should define the list in an array and then create, but the problem is that my users number is dynamic.
for(int x = 0; x <= 10; x++)
{
UIView *"User_"&(x) = [[UIView Alloc] init];
User_x.frame = CGRectMake( 10 * x , 10 , 10 ,10);
}
What is the best way to approach doing something like this?
If your project has ARC=Yes, the compiler will delete reference foreach cycle of your view.
However you can add a tag on your views:
for(int x = 0; x <= 10; x++)
{
UIView *user = [[UIView Alloc] init];
user.tag=x;
User.frame = CGRectMake( 10 * x , 10 , 10 ,10);
[yourSuperView addSubview:user];
}
It can be done like this
NSMutableArray *viewArr= [#[] mutableCopy];
for(int x = 0; x < 10; x++)
{
UIView *view = [[UIView Alloc] init];
view.frame = CGRectMake( 10 * x , 10 , 10 ,10);
[viewArr addObject:view];
}

UIImageView animationDuration with fade effects

I'am searching for a (very) simple way to crossfade images within animationDuration time. I tried using NSTimer and some other stuff I found here, but no solution satisfy or helps me.
I create this stuff in a method (without comments) ...
- (UIImageView *)playSequence{
NSArray *structureArray = self.contenManager.ImageViewControllerSize;
NSMutableArray *structuresToPlay = [[NSMutableArray alloc] init];
// walk thru current collection
for(NSInteger i = 0; i < [self.currentCollection count]; i++)
{
NSInteger index = [[self.currentCollection objectAtIndex:i] integerValue];
[structuresToPlay addObject:[UIImage imageNamed:[structureArray objectAtIndex:index]]];
}
_playSequence = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)];
_playSequence.animationImages = structuresToPlay;
_playSequence.animationDuration = 5 * structuresToPlay.count;
[_playSequence startAnimating];
return _playSequence;
}
Here is the part where the method is called ...
- (void)justPlaySelection
{
UIView *justPlaySelection = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)];
// some background music code ...
// add play sequence
[justPlaySelection addSubview:self.playSequence];
// add close button
// { ... }
[self presentSemiView:justPlaySelection];
}
- (UIImageView *)playSequence
{
if (_playSequence == nil)
{
NSArray *structureArray = self.contenManager.ImageViewControllerSize;
NSMutableArray *structuresToPlay = [[NSMutableArray alloc] init];
// walk thru current collection
for(NSInteger i = 0; i < [self.currentCollection count]; i++)
{
NSInteger index = [[self.currentCollection objectAtIndex:i] integerValue];
[structuresToPlay addObject:[UIImage imageNamed:[structureArray objectAtIndex:index]]];
}
_playSequence = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)];
}
_playSequence.animationImages = structuresToPlay;
_playSequence.animationDuration = 5 * structuresToPlay.count;
[_playSequence startAnimating];
return _playSequence;
}
Here is another way to switch between to UIImageViews, it wouldn't be hard to add in the fade in and out.
- (void) performAnimationOfFrameAtIndex:(NSNumber*)indexNum
{
int index = indexNum.intValue;
BOOL completedSequece = index >= [self.frames count];
if (completedSequece) return;
UIImageView *imgIn;
UIImageView *imgOut;
if (index % 2 == 0) {
imgIn = self.animationImageViewOne;
imgOut = self.animationImageViewTwo;
}
else {
imgIn = self.animationImageViewTwo;
imgOut = self.animationImageViewOne;
}
imgIn.image = [self.frames objectAtIndex:index];
[self.view sendSubviewToBack:imgOut];
double speed = 0.1;
[self performSelector:#selector(performAnimationOfFrameAtIndex:) withObject:[NSNumber numberWithInt:index + 1] afterDelay:speed];
}
I created a project that does exactly what you describe (an effect like UIImageView animation sequence, but with a cross-fade between images.)
The project is on github: https://github.com/DuncanMC/Animate-Img
You need to have 2 image views.
The trick I use is to stack them on top of each other, and simply animate the top image view from alpha 1 -> 0, then switch images in the top image view and animate it from alpha 0 -> 1.0, so the new image is revealed.
The project demos a morph transition using only 5 frames. Each frame is marked with a number so you can see the frame changes. It has a switch which lets you turn cross-fading on or off.

Resources