I am struggling to update a UIView in an NSArray. I have created an NSMutableArray and filled it with UIViews. Problem is I cannot update the position of the UViews. What am I doing wrong? Here is my code:
for (j = 0; j <200; j++) {
UIView *currentView = [self.ViewArray objectAtIndex:j];
[currentView setFrame:CGRectMake(x, y, 20, 20)];
}
Maybe you add the view on ViewDidLoad method and then you update the view?
Doesn't UIView *currentView = [self.ViewArray objectAtIndex:j]; should be UIView *currentView = (UIView *) [self.ViewArray objectAtIndex:j];
Could you also show us how you are adding views in array?
IMO, I don't think you will be able to get views in this way.
What you should do is as below.
for (int i=0;i<200;i++) {
UIView *mView = [[UIView alloc] initWithFrame:CGRectMake(0,0,0,0)];
mView.tag = 998877 + i;
[self.view addSubview:mView];
}
Now in update view do like below.
-(void) updateMyViews {
for (j = 0; j <200; j++) {
UIView *currentView = (UIView *) [self.view viewWithTag:998877+j];
[currentView setFrame:CGRectMake(x, y, 20, 20)];
}
}
Related
Perhaps I am thinking about this incorrectly, so please point me in the right direction..
I want to make many UIViews as a property so I can update them with different methods. Something like this:
#property UIView *view1
#property UIView *view2
...
#property UIView *view200
-(void)updateViews{
for (i=0; i <200; i++){
//Update view here
}
So my questions are:
How can I easily make multiple views?
How can I easily pass a message to each individual view?
So many great responses, I think I need to add a little more info.
Have tried putting my UIViews into an array to index them but I struggle to access them to update their positions within the UIViewController. I thought making them a property is the correct way to since I need to update them with the device heading. Looks like using a tag might be best. Can someone further comment on this approach:
for (i = 0 ; i < 144; i++) {
UIView *sunView =[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"sun.png"]];
sunView.tag = i;
}
//then later, in a separate method do the following:
for (i = 0 ; i < 144; i++) {
CGFloat CGx = self.acceleration.X;
CGFloat CGy = self.acceleration.Y
[sunView.tag.i setFrame:CGRectMake(CGx, CGy, 20, 20)]
}
Im not sure how to access the UView with the corresponding indexed tag. Can someone help me there too?
When they are really subviews then you could iterate through the superview's subviews array.
You could do that recursievely in order to apply it on all subivews of your subviews, if you have multiple hierarchy levels.
If you don't want to apply this to each of your superview's subviews, then tag your subviews with something like view.tag = 6502 and use that to identify those views to which you want to apply it.
Or maintain your own array or set (iterable collection) of views and iterate through them.
Create your views in a loop and store them in an NSMutableArray. That way you will have access to all of them in your view controller.
Create a property.
#property (monatomic) NSMutableArray *arrayOfViews;
self.arrayOfViews = [[NSMutableArray alloc] init];
UIView *view;
for (int i = 0; i < 10; i++)
{
view = [[UIView alloc] init];
[self.arrayOfViews addObject:view];
}
Run a loop over this array and access the views one by one and call the method you need to call.
On a side note: Why are you creating 200 UIViews? That's a lot :)
I think you need something like that:
-(void)updateViews
{
UIView *views;
UILabel *label;
for(int i = 0 ; i < numberOfViews ; i++)
{
views = [[UIView alloc] initWithFrame:CGRectMake(...)];
label = [[UILabel alloc] initWithFrame:CGRectMake(0,0,views.frame.size.width,views.frame.size.height)];
[label setText:[NSString stringWithFormat:#"%d",i]];
[views addSubview:label];
[self.view addSubview:views];
}
}
How can I easily make multiple views?
Do you want to create it in IB?
1) You can use tags in Xcode
UILabel * label = (UILabel*)[self.view viewWithTag:19];
UIView * view = (UIView*)[self.view viewWithTag:20];
2) You can use property that you also do
How can I easily pass a message to each individual view?
if your views inside another view(currentView) you can use that
for (UIView *yourView in self.currentView.subviews) {
//Update view here
}
Or if you want to create it in the code
for (int i = 0; i < 10; i++)
{
UIView * myView = [[UIView alloc]initWithFrame:CGRectMake(10*i, 10*i, 25, 25)];
int r = arc4random() % 255;
int g = arc4random() % 255;
int b = arc4random() % 255;
myView.backgroundColor = [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:1];
[self.view addSubview: myView];
}
That's what you can see
And to call all these views you can use
for (UIView *yourView in self.view.subviews) {
[yourView removeFromSuperview];
}
And that's what you'll see
If you want to call own view you can use tags like this
for (int i = 0; i < 10; i++)
{
UIView * myView = [[UIView alloc]initWithFrame:CGRectMake(10*i, 10*i, 25, 25)];
myView.tag = i + 21;
int r = arc4random() % 255;
int g = arc4random() % 255;
int b = arc4random() % 255;
myView.backgroundColor = [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:1];
[self.view addSubview: myView];
}
for (UIView *yourView in self.view.subviews) {
if (yourView.tag == 21) {
[yourView removeFromSuperview];
}
}
I'm trying to use a UIScrollView with UIViews (to manage them as xib files), for now I have an array where I store the views.
testingView is a UIViewcontroller with his own xib file and testingView2 is also an UIViewcontroller with his own different xib file
- (void) viewDidLoad {
[super viewDidLoad];
_testingView = [[TestingViewController alloc] init];
_testingView2 = [[TestingViewController2 alloc] init];
self.array = [[NSArray alloc] initWithObjects: _testingView.view, _testingView2.view, nil];
for (int i = 0; i < [array count]; i++) {
CGRect frame;
frame.origin.x = self.scrollingView.frame.size.width*i;
frame.origin.y = 0;
frame.size = self.scrollingView.frame.size;
[self.scrollingView addSubView: [self.array objectAtIndex:i]];
}
self.scrollingView.contentSize = CGSizeMake (_scrollingView.frame.size.width*[array count], _scrollingView.frame.size.height);
}
the problem is that he is taking only the first view (even if I switch them) and the second view is not shown, the same with UIImages instead of views is working, can someone explain me why? seems like he is not seeing the second view in the array order...
Why are you calculating the variable "frame" inside the for loop when you are not using it?
In my view you should make the following change to your code.
for (int i = 0; i < [array count]; i++) {
CGRect frame;
frame.origin.x = self.scrollingView.frame.size.width*i;
frame.origin.y = 0;
frame.size = self.scrollingView.frame.size;
**UIView *v=[self.array objectAtIndex:i];**
**v.frame=frame;**
**[self.scrollingView addSubView:v];**
}
Hope it works.
In the for loop, you calculate frame for newly added subview, but you don't set that frame to that subview.
In your loop, add your subview like this for example:
UIView *subview = (UIView *)[array objectAtIndex:i];
subview.frame = frame;
[self.scrollingView addSubView:subview];
You need to set the frame for each of the subviews in the scrolling view. For example, you can set the frame of _testingView2.view to be the offset of x from the _testingView1.view frame width.
_testingView2.view.frame = CGRectOffset(_testingView2.frame, CGRectGetWidth(_testingView1.frame), 0)
There are many ways to calculate the frame. Try to use the methods CGRectWidth, CGRectGetMaxX, etc.
I have a view which has details of some event,which includes imageview, some labels etc.
I have the description of the event as a small subview in the view which is scrollable as below.
CGRect descriptionTextViewRect = CGRectMake(15, 185, 280, 85);
descriptionText = [[UITextView alloc] initWithFrame:descriptionTextViewRect];
descriptionText.textAlignment = UITextAlignmentLeft;
descriptionText.text =des;
descriptionText.editable = NO;
descriptionText.layer.cornerRadius = 5.0;
descriptionText.clipsToBounds = YES;
descriptionText.userInteractionEnabled = YES;
descriptionText.font = [UIFont systemFontOfSize:15];
[scrollView addSubview: descriptionText];
I followed this link but I get scrollable for both text view as well as the scrollview
I followed like this
float sizeOfContent = 0;
int i ;
for (i=0; i<[scrollView.subviews count]; i++) {
sizeOfContent += descriptionText.frame.size.height;
}
scrollView.contentSize = CGSizeMake(descriptionText.frame.size.width, sizeOfContent)
I need to display the whole content of the description and make the whole detail page scrollable.
Am I doing it correctly? Or am I missing out somthing?
How do I do that?
Thank you.
You are adding the same item's height for several times.
This:
for (i=0; i<[scrollView.subviews count]; i++) {
sizeOfContent += descriptionText.frame.size.height;
}
Should be this:
for (UIView *view in scrollView.subviews) {
sizeOfContent += view.frame.size.height;
}
So it will correctly add all item's heights to sizeOfContent.
You are adding subView at same position every time. For example: if you are adding 5 subViews it should be like as followings:
for(int i=0; i<5; i++)
{
CGRect descriptionTextViewRect = CGRectMake(15, i*185, 280, 85);
descriptionText = [[UITextView alloc] initWithFrame:descriptionTextViewRect];
descriptionText.textAlignment = UITextAlignmentLeft;
descriptionText.text =des;
descriptionText.editable = NO;
descriptionText.layer.cornerRadius = 5.0;
descriptionText.clipsToBounds = YES;
descriptionText.userInteractionEnabled = YES;
descriptionText.font = [UIFont systemFontOfSize:15];
[scrollView addSubview: descriptionText];
}
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&¤tIndex<=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.
I have a scroll view that doesn't scroll right, I've simplified the code for below.
It draws the view and some horizontal buttons that i add more stuff to in the real code.
If you drag the whitespace between the buttons the view scrolls. If you happen to put your finger on a button, it won't scroll.
After a related suggestion, I tried to add the delaysContentTouches = YES line, but it doesn't seem to make a difference.
UIScrollview with UIButtons - how to recreate springboard?
What am I doing wrong?
TIA,
Rob
Updated the code
- (void)viewDidLoad {
l = [self landscapeView];
[self.view addSubview:l];
[l release];
}
- (UIScrollView *) landscapeView {
// LANDSCAPE VIEW
UIScrollView *landscapeView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 320, 325)];
landscapeView.backgroundColor = [UIColor whiteColor];
landscapeView.delaysContentTouches = YES;
NSInteger iMargin, runningY, n;
iMargin = 3;
runningY = iMargin;
for (n = 1; n <= 38; n++) {
//add day labels
UIButton *templabel = [[UIButton alloc] initWithFrame:CGRectMake(iMargin,runningY,320 - ( 2 * iMargin),20)];
templabel.backgroundColor = [UIColor grayColor];
[landscapeView addSubview:templabel];
[templabel release];
runningY = runningY + 30;
}
landscapeView.contentSize = CGSizeMake( 320, runningY);
return landscapeView;
}
I can't duplicate your results; when I create a scrollView and add buttons, scrolling is still active even when doing a touch-down on the button. Are you setting any other UIScrollView properties, or subclassing any methods, that aren't showing up in your simplified code?
It looks like one thing that's going on is that the getter for landScapeView is a complicated constructor...so every time you do [self landscapeView] or self.landscapeView, you're creating a whole new UIScrollView and operating on that.
I'd try something like this in your .h file:
#interface MyClass: MyParent {
UIScrollView *landscapeView;
}
#property (retain) UIScrollView *landscapeView;
...and this in your .m file:
#implementation MyClass
#synthesize landscapeView;
(void)viewDidLoad
{ l = [[[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 320, 325)] autorelease];
[self.view addSubview:self.landscapeView]; [l release];
landscapeView.backgroundColor = [UIColor whiteColor];
landscapeView.delaysContentTouches = YES;
NSInteger iMargin, runningY, n;
iMargin = 3;
runningY = iMargin;
for (n = 1; n <= 38; n++) { //add day labels
UIButton *templabel = [[UIButton alloc] initWithFrame:CGRectMake(iMargin,runningY,320 - ( 2 * iMargin),20)];
templabel.backgroundColor = [UIColor grayColor];
[landscapeView addSubview:templabel];
[templabel release]; runningY = runningY + 30;
}
landscapeView.contentSize = CGSizeMake( 320, runningY);
}