Identify UIImageView and UITextView created in loop iOS - ios

I'm working in Xcode and i have a loop cycle in which i dynamically create UIImageViews and UITextviews and insert them in a UIScrollView. In every row, i create 4 UIImageViews and 2 UITextViews, so the code looks like this:
for (int i=0; i<dim; i++){
UITextView *textView1= [[UITextView alloc] initWithFrame:CGRectMake(0, 0, screenWidth/2, 37)];
UITextView *textView2= [[UITextView alloc] initWithFrame:CGRectMake(screenWidth/2, 0, screenWidth/2, 37)];
UIImageView *imageView1 = [[UIImageView alloc] initWithFrame:CGRectMake(0,50,screenWidth/4,100)];
UIImageView *imageView2 = [[UIImageView alloc] initWithFrame:CGRectMake(screenWidth/4,50,screenWidth/4,100)];
UIImageView *imageView3 = [[UIImageView alloc] initWithFrame:CGRectMake(screenWidth/2,50,screenWidth/4,100)];
UIImageView *imageView4 = [[UIImageView alloc] initWithFrame:CGRectMake(screenWidth*3/4,50,screenWidth/4,100)];
}
The code to set images in UIImageViews, text in UITextViews and show them in the UIScrollView works great and i don't post it because it's too long.
My problem is: when i click on an image, i call methods in which i want to make change to the ImageViews and TextViews of the same row, how can i identify them?
Detecting the image clicked is not a problem using the recognizer.view, to detect other images of the same row i tried to set a tag to the views and then call "viewWithTag" to find them, but i have problems because the elements of the same row have the same tag value and i make confusion.
My target is for example:
When i click on imageView1 in the first row should change image in imageView3 of the same row.
When i click on imageView3 in the fourth row should change text in textView2 of the same row.
And so on..
Is there any alternative method without using the tag attribute?
I hope I explained myself

You can use the tag property, but without using the same tag more then once. Some little math should do the trick to identify views in the same row by their tags...
BUT:
I wouldn't recommend using tags. Make yourself a custom view class, e.g. MyRow, containing the 6 views belonging together as subviews. From there you can go anywhere.
Got a problem, invent an object. Always works.
BIGGER BUT: I'd strongly recommend to go with UICollectionView or UITableView.

UIView has a "tag" property, which you can use for anything you want. The default value is 0 and it doesn't do anything at all, except store the value.
Typically you would set the tag to be an array index.
So you could do:
textView1.tag = i;
textView2.tag = i;
imageView1.tag = i;
imageView2.tag = i;
imageView3.tag = i;
imageView4.tag = i;
Or perhaps something more clever, like:
textView1.tag = 1000000 + i;
textView2.tag = 2000000 + i;
imageView1.tag = 3000000 + i;
imageView2.tag = 4000000 + i;
imageView3.tag = 5000000 + i;
imageView4.tag = 6000000 + i;
Or maybe you could have an array property mapping them:
#property NSMutableArray tagMap;
textView1.tag = self.tagMap.count;
[self.tagMap addObject:#{#"var": #"textView1", #"index":[NSNumber numberWithInteger:i]}];

Related

How to set UILabel height dynamically in Objective c?

I am new in iOS and I am facing problem regarding to create UILabel dynamically. I need to change its hight and the Y position according to data from webservice.
My code is like this
NSMutableArray *remarkarray =[[NSMutableArray alloc] init];
remarkarray=[responsedict valueForKey:#"Key"];
NSString *RemarkString=[NSString stringWithFormat:#"%#",[remarkarray objectAtIndex:0]];
remarklbl.text=RemarkString;
remarklbl.numberOfLines=0;
[remarklbl sizeToFit];
I have create UILabel like this
But its Y Position is fix. I need to create a UILabel in which I can change the height and the Y position according to text in it. Like this
Thanks in Advance!
You can do it very easily by declaring two labels in Storyboard.
Here are steps.
Drag two UILabels in your viewController and select the first one and set constraints like below image.
Select the second label and add following constraints.
Select both labels and set numberOfLines to zero.
Now u can set text dynamically from code.
All you have to do is:
float x=10.0,y=10.0,height=40;
float verticalSpace=20.0;
for (int i = 0; i < 10; i++)
{
UILabel *label = [[UILabel alloc] initWithFrame: CGRectMake(x, y,50,height)];
label.text = #"dummy text";// It could be from array as well if you want to add different text for each label. Eg: label.text = [arr objectAtIndex:i];
[self.view addSubview:label];
y = y +height+ verticalSpace;
}
You could search around with key word "auto layout dynamic label height"

Adding Images By incrementing label count

Here,when button taps label count is increments & decrements.While label count increments images will be added by respective count.here my code for incrementing label count
if (counter >= 9 )
return;
[_count setText:[NSString stringWithFormat:#"%d",++counter]];
but i need to display while incrementing the label count then automatically increments images one by one.like this
Can you please help me how can i implement,thank you.
Add a UIScrollView in place of where you want to show images. When click on '+' button, call following method by passing the 'counter' value.
-(void)addImage:(int) count {
UIScrollView * scView = [[UIScrollView alloc] init];
scView.frame = CGRectMake(30, 60, self.view.frame.size.width, 60);
UIButton * btn;
UIImageView * imgV;
float imgWidth = 44;
for(int i=0;i<count;i++) {
imgV = [[UIImageView alloc] init];
imgV.frame = CGRectMake(i*imgWidth, 0, imgWidth, 44);
imgV.image = [UIImage imageNamed:#"gitar"];
[scView addSubview:imgV];
}
[scView setContentSize:CGSizeMake(imgWidth*count, 50)];
[scView setBackgroundColor:[UIColor redColor]];
[self.view addSubview:scView];
}
- (IBAction)descrese:(id)sender {
counter -= 1;
[self addImage:counter];
}
- (IBAction)btnTap:(id)sender {
counter += 1;
[self addImage:counter];
}
This adds as many images as you want in horizontal scroll view.
use a uiscrollview with cells of images, that simple.
Use UIScrollView.
As number of elements is increasing/decreasing:
1) increse/deacrease UIScrollView size respectively
2) add/remove elements
I guess, the screenshot was taken from MMT app. They're using this feature in their app. I believe, they might have developed a separate control to handle this thing, where they can only pass few arguments like image to show (people), count etc.
You can also develop such kind of UI with following way:
Create a custom view, take a UICollectionView inside it, take argument of image to show and number of rows count, fixed the cell size in layouts. Add a method which will reloads UI (inside logic: reloading UICollectionView) to refresh content when user taps on [ + ] or [ - ] button. Why, we're not taking UIScrollView, with it we can't reuse contents. I believe this step will need you to create everything programmatically.
When user taps on [ + ], you should increase width of our custom view, inside
you should override layoutSubview method to update frame of UICollectionView as well. You may require to refresh(reload) cells inside UICollectionView.
Do reverse when user taps [ - ].
You may require to set some logic so user can't add more/less numbers when selection.
This is just an idea, you may require to check each cases which the reference app has having.

Find iOS UIView by tag dynamically

I'm developing an app for iPhone and I have a strange problem. I tried to solve this by myself but after 3 days I didn't found a solution anyway.
I have a scrollview in which I dynamically create other views and subviews, this is the code:
for (int i=0; i<dim; i++) {
UITextView *posted_nick= [[UITextView alloc] initWithFrame:CGRectMake(paddWidth, heightUpdateImageScrollview+paddHeight/2, screenWidth-2*paddWidth, 37)];
//textview customization...
[imagesScrollView addSubview:posted_nick];
row_images_like = [[UIView alloc] initWithFrame:CGRectMake(paddWidth,heightUpdateImageScrollview+paddHeight+37+heightImageInScrollView,screenWidth-2*paddWidth,80)];
//set the tag = id
row_images_like.tag = [id_image intValue];
UIImageView *like_mini = [[UIImageView alloc] initWithFrame:CGRectMake(0,15,25,25)];
//imageview customization...
//tag = id+1..
NSInteger x = [id_image intValue] + 1;
number_like.tag = x;
[row_images_like addSubview:like_mini];
UITextView *number_like = [[UITextView alloc] initWithFrame:CGRectMake(paddWidth*5/2,10,55,37)];
//textview customization...
//tag = id+2..
NSInteger x = [id_image intValue] + 2;
number_like.tag = x;
[row_images_like addSubview:number_like];
[imagesScrollView addSubview:row_images_like];
}
Now, all works great and when I click on the image view "like_mini", I can find the other views in the same row with the appropriate tag
(UIView *thisView = (UIView*)[imagesScrollView viewWithTag:ID_IMAGE];)
The problem is where I update my scrollview. When the user scrolls to the top, if there are new images to show, I call the same function that creates the views, and all the other views (that already exist) are moved some down. Why, when I try to find a view by tag in my scrollview, all works at the first time, but don't work for the new images created with the same code?
If i remove all the views in the scrollview, before adding the new views, it works. But i don't want to remove the oldest view.
When it works, I have in my console the view (row_images_like) with tag.
When it doesn't work, I receive a _UITextContainerView. What is this?
Hope I explained myself.
Hi there the only reason the images moves down is because you are not assigning the proper tags, please give appropriate value of tag to uiview, uiimageview and uitextview.
row_images_like.tag = [id_image intValue] + 1000;
For fetching the view get it done similarly what you did before only add thousand to it.
UIView *thisView = (UIView*)[imagesScrollView viewWithTag:ID_IMAGE+1000];
Also one error :
number_like.tag = x;
How does the above line object i.e "Number_like" comes before initialising it and change the tag value of other objects to "+2000" and "+3000"
Try removing all views added to scrollview, before loading scrollview again
Write this line above for loop
for (UIView *v in [imagesScrollView subviews])
{
[v removeFromSuperview];
v = nil;
}

Creating object programmatically and changing that object's position

I am trying to create a couple of UIImageViews (preferably with a for loop) and then afterwards move them, but I don't know how because I'm having trouble figuring out how to reference them if they will be made programmatically.
So I want something like this:
for (int i = 0; i < 2; i++)
{
UIImageView *iv = [[UIImageView alloc]initWithImage:[UIImage imageNamed: picturo]];
CGRect rect = CGRectMake((i * 50) + 50,30, 25, 25);
[iv setFrame:rect];
iv.tag = i;
[self.view addSubview:iv];
}
(iv with tag of 0).center.y = 80; // <-- How do I do that!!
Obviously this example has no practical use and I could just change y value of 'rect' above to 80, but I want to know how to:
a. Create multiple uiimageviews (or any object for that matter) and be able to identify/reference/manipulate each one individually (I don't know how but I would assume by either naming them uniquely or using tags) and
b. Be able to identify/reference/manipulate an object that was created programmatically.
creating views with tags works the way you have it.
To access those views use the viewWithTag property on a view to identify one of it's subviews:
UIView* subview = [self.view viewWithTag:0];
subview.center = CGPointMake(subview.center.x, 80);
(you cannot write to a view.center's x or y, you have to recreate the whole thing. Likewise with other geometric structs such as CGSize, CGRect)

Get UIImageView programmatically from View.

I'm creating a UIImageView within the code and I want to get it later on and set an image. How do I do this please help?
for (int x = 1; x <= 5; x++) {
UIImageView *Game_ImageViews = [[UIImageView alloc]
initWithFrame:CGRectMake(0, 0, 100, 100)];
Game_ImageViews.tag = x;
[Game_View addSubview:Game_ImageViews];
}
UIImage *image = [[UIImage alloc] initWithContentsOfFile:[[[NSBundle mainBundle] resourcePath]
stringByAppendingPathComponent:#"Test.png"]];
(UIImageView*)[self.view viewWithTag:100].image = image;
[image release];
viewWithTag will give you the view with the tag if a subview with that tag exists. So for example, your self.view would have to have a subview that has a tag of 100.
Initially, you are setting up subviews of Game_View with tags of 1, 2, 3, 4, 5.
So, to retrieve a subview by tag you would have to do, assuming you want to retrieve the view tagged by id 1:
((UIImageView*)[Game_View viewWithTag:1]).image = image;
A couple of other things worth mentioning. You're not releasing Game_ImageViews in your loop above, so that will give a memory leak.
Also, if you use the imageNamed method of UIImage, that will give you a couple of benefits. First, you'll have a cached image which could improve performance. Secondly, you'll have an autoreleased object which saves you the bother of releasing it yourself. Unless of course you want maximum performance and control by doing it as you have done above.

Resources