Store Views in an array - ios

I have three buttons and one view controller. I want to link three buttons to those three
different views (pages).
I've tried this by making three views and storing it in an mutable array.
ViewArray= [[NSMutableArray alloc]initWithCapacity:15];
CGRect viewRect = CGRectMake(10, 10, 100, 10);
//VIEW1
UIView* view1 = [[UIView alloc] initWithFrame:viewRect];
view1.backgroundColor = [UIColor redColor];
//VIEW2
UIView* view2 = [[UIView alloc] initWithFrame:viewRect];
view2.backgroundColor = [UIColor greenColor];
I added three buttons programmatically. After that for the action of each button I used this:
//action for each button
self.view = [ViewArray objectAtIndex:i];//where i={1,2,3} for different functions
but I am not getting what I want.

A better design would be to add all of the views invisibly, then change their opacity 0.0-1.1 to hide and show. (also, a key mistake in the OP is that the code replaces the view controller view with the subviews, instead of adding them)
CGRect viewRect = CGRectMake(10, 10, 100, 10);
//VIEW1
UIView* view1 = [[UIView alloc] initWithFrame:viewRect];
view1.backgroundColor = [UIColor redColor];
view1.tag = 1;
view1.alpha = 0.0;
[self.view addSubview:view1];
//VIEW2
UIView* view2 = [[UIView alloc] initWithFrame:viewRect];
view2.backgroundColor = [UIColor greenColor];
view1.tag = 2;
view1.alpha = 0.0;
[self.view addSubview:view2];
Add a property in your vc's interface that keeps track of the visible view:
#property(nonatomic, weak) UIView *visibleSubview;
Then the button action:
UIView *subview = [self.view viewWithTag:i];
//where i={1,2,3} for different functions
// i really needs to be 1,2,3 here, to correspond to the tags
[UIView animateWithDuration:0.5 animations:^{
subview.alpha = 1.0;
self.visibleSubview.alpha = 0.0;
} completion:^(BOOL finished) {
self.visibleSubview = subview;
}];

Well I'm not sure exactly what you want. But in general if you want to access any change multiple objects such as a UIView or UILabels, etc... You can just use and NSArray and a for loop to access and make all the changes without any extra code copies like so:
First of all, setup the NSArray with all your objects like so:
NSArray *_viewArray = #[view1, view2]; //etc....
And also setup an array with the different UIColors like so:
NSArray *_colourArray = #[[UIColor redColor], [UIColor greenColor]]; //etc....
And then when you want to access them and edit multiple UIViews or what ever objects, you can just use a for loop like so:
for (int loop = 0; loop < ([_viewArray count] - 1); loop++) {
((UIView*)_viewArray[loop]).backgroundColor = ((UIColor*)_colourArray[loop]);
}
I hope this helps you :)

Related

Programmatically added subview frames don't show up right in scrollview

I'm creating a scrollView programmatically, and all the views in it. However, when I add more then 1 view, the other views layers don't show up right in their respective frames.
For example:
-(void)viewDidLoad {
[super viewDidLoad];
self.scrollView = [[UIScrollView alloc] init];
self.scrollView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
self.scrollView.contentSize = CGSizeMake(self.view.frame.size.width, 150*5);
self.scrollView.backgroundColor = [UIColor lightGrayColor];
self.scrollView.scrollEnabled = YES;
self.scrollView.showsVerticalScrollIndicator = NO;
[self.view addSubview:self.scrollView];
[self setUpLogInButtons];
}
Then I set the subViews to scrollView up here:
-(void)setUpLogInButtons {
CGFloat subviewWidth = self.scrollView.frame.size.width/2;
CGFloat subviewHeight = 150;
UIView *facebookView = [[UIView alloc] init];
facebookView.frame = CGRectMake(0, 0, subviewWidth, subviewHeight);
[facebookView.layer insertSublayer:[self gradientLayerForViewFrame:facebookView.frame withColors:[self colorArrayWithValues:0x4A5C81 v2:0x495B82 v3:0x495B82 v4:0x475B85 v5:0x465B87 v6:0x455A88 v7:0x445A8A v8:0x435A8B v9:0x425A8D v10:0x41598F v11:0x405990 v12:0x3F5992 v13:0x3E5993 v14:0x3D5895 v15:0x3C5896 v16:0x3B5898 v17:0x3A589A]] atIndex:0];
[facebookView addSubview:[self label:self.facebookLabel forView:facebookView withName:#"Facebook" loggedIn:NO]];
[self.scrollView addSubview:facebookView];
}
When it's one subView it works fantastic, when I add the other one it's not right:
-(void)setUpLogInButtons {
...
UIView *facebookView = [[UIView alloc] init];
...
[self.scrollView addSubview:facebookView];
UIView *twitterView = [[UIView alloc] init];
twitterView.frame = CGRectMake(subviewWidth, 0, subviewWidth, subviewHeight);
[twitterView.layer insertSublayer:[self gradientLayerForViewFrame:twitterView.frame withColors:[self colorArrayWithValues:0x2BA8D5 v2:0x28A8D6 v3:0x25A8D8 v4:0x22A8D9 v5:0x20A9DB v6:0x1DA9DC v7:0x1AA9DE v8:0x18AADF v9:0x15AAE1 v10:0x12AAE3 v11:0x10ABE4 v12:0x0DABE6 v13:0x0AABE7 v14:0x08ACE9 v15:0x05ACEA v16:0x02ACEC v17:0x00ADEE]] atIndex:0];
[twitterView addSubview:[self label:self.twitterLabel forView:twitterView withName:#"Twitter" loggedIn:NO]];
[self.scrollView addSubview:twitterView];
}
This one does not show up, the layers specifically are off. However, here is the kicker, the label shows in the right spot because the labels frame is based on it's parent view frame.
-(UILabel *)label:(UILabel *)viewLabel forView:(UIView *)accountView withName:(NSString *)name loggedIn:(BOOL)loggedinStatus {
UILabel *label = viewLabel;
label.frame = CGRectMake(0, accountView.frame.size.height - 50, accountView.frame.size.width, 50);
label.text = [self setAccountLabelForName:name loggedIn:loggedinStatus];
label.textColor = [UIColor whiteColor];
label.textAlignment = NSTextAlignmentLeft;
return label;
}
here is a picture that shows you that the label is based off the parents view frame, and it shows up correctly, but the gradient does not, and it's based off the same frame.
and my gradient method:
-(CAGradientLayer *)gradientLayerForViewFrame:(CGRect)viewFrame withColors:(NSArray *)colors {
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = viewFrame;
gradient.colors = colors;
return gradient;
}
For some reason when inserting my gradient layer to the views layer I had to change it:
//INSTEAD OF THIS:
[... insertSublayer:[self gradientLayerForViewFrame:facebookView.frame...];
//THIS WORKED FLAWLESSLY:
[... insertSublayer:[self gradientLayerForViewFrame:facebookView.bounds...];

Hardcoded UIView vs. XIB UIView resizing

I'm stumbled on how to layout a UITextField when there is a hardcoded UIImageView. UIImageView is hardcoded, let me show it:
// Image
CGFloat xCenter = self.view.frame.size.width / 2.00;
CGFloat yCenter = self.view.frame.size.height / 2.00;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
self.imageFrame = CGRectMake(xCenter + 115, yCenter - 425, 250, 250);
}
else if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
self.imageFrame = CGRectMake(xCenter - 125 , yCenter, 250, 250);
}
if ([[BNRImageStore sharedStore] imageForKey:self.item.itemKey]) {
self.imageView = [[UIImageView alloc] initWithFrame:self.imageFrame];
self.imageView.image = [[BNRImageStore sharedStore] imageForKey:self.item.itemKey];
[self.imageView.layer setBorderColor:(__bridge CGColorRef)([UIColor blackColor])];
[self.imageView.layer setBorderWidth:3.0];
self.imageView.contentMode = UIViewContentModeScaleAspectFill;
self.imageView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:self.imageView];
NSDictionary *nameMap =#{#"imageView": self.imageView,
#"nameLabel": self.nameLabel,
#"nameField": self.nameField};
NSArray *horizontalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:#"H:|-[nameLabel]-[nameField]-[imageView(==250)]-|" options:0 metrics:nil views:nameMap];
[self.view addConstraints:#[horizontalConstraints]];
}
else {
UIView *imageCanvasView = [[UIView alloc] initWithFrame:self.imageFrame];
imageCanvasView.backgroundColor = [UIColor colorWithWhite:1.00 alpha:0.4];
imageCanvasView.layer.borderWidth = 1.0f;
imageCanvasView.layer.borderColor = [UIColor colorWithWhite:0.00 alpha:0.9].CGColor;
[self.view addSubview:imageCanvasView];
UILabel *addImageLabel = [[UILabel alloc] initWithFrame:self.imageFrame];
addImageLabel.text = #"(tap to add image)";
addImageLabel.font = [UIFont fontWithName:#"AvenirNext-UltraLight"
size:20];
addImageLabel.textColor = [UIColor WHITE_COLOR_DEBUG_FIX];
addImageLabel.textAlignment = NSTextAlignmentCenter;
addImageLabel.hidden = NO;
[self.view addSubview:addImageLabel];
}
Seems it's what I need:
But not in iPad:
Except UIImageView *imageView property, I made the constants with Auto Layout. Since XIB file doesn't recognize imageView I couldn't set the constraints of it. Instead I can use VFL, but constraints intersect at some point. Thus I couldn't managed it out.
Any ideas? (or is it possible in some way?)
I had a similar problem, I resolved it by creating two holder UIViews either on storyboard or programmatically - one holding the form and one holding the hardcoded UIImageView.
If you're using storyboards : Set the constraints on those two holding views and in the subviews of the one containing the form. And just place your UIImageView programmatically in the center of your image-holding view.

Cannot add dznsegmentedcontrol to UIView

I am trying to add the following control to a UIView that is inside a viewcontroller. The control does not seem to appear inside the view.
https://www.cocoacontrols.com/controls/dznsegmentedcontrol
NSArray *items = #[#"Kicks", #"Re-kicks", #"Interested"];
DZNSegmentedControl *control = [[DZNSegmentedControl alloc] initWithItems:items];
control.tintColor = [UIColor blueColor];
control.delegate = self;
control.selectedSegmentIndex = 2;
[control addTarget:self action:#selector(selectedSegment:) forControlEvents:UIControlEventValueChanged];
[cell.segmentView addSubview:control];
I think what you are looking for is to add the controller somehow.
[self.navigationController.navigationBar addSubview:self.control];
or as in the example code givin by dzenbot:
self.tableView.tableHeaderView = self.control;

Is there a way to send an object via UITapGestureRecognizer?

I have an object created from a class of type UIView to produce an unlimited number of views which then appear in smaller sizes in the middle of the screen. I used UITapGestureRecognizer to enlarge one of the views to fit the screen but the issue here is that the object is only usable within the first class and cannot be transferred to the second class which is the selector.
What are your suggestions regarding this particular issue?
How can I send my object to the selector to be able to use it there?
Thank you
Here is the first class which creates the object (derived from iCarousel) :
- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSUInteger)index reusingView:(UIView *)view
{
UILabel *label = nil;
UIButton *close = [UIButton buttonWithType:UIButtonTypeRoundedRect];
//create new view if no view is available for recycling
if (view == nil)
{
view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320.0f, 460.0f)];
view.contentMode = UIViewContentModeCenter;
view.backgroundColor = [UIColor whiteColor];
label = [[UILabel alloc] initWithFrame:CGRectMake(100, -100, 100, 100)];
label.backgroundColor = [UIColor clearColor];
label.textAlignment = NSTextAlignmentCenter;
label.font = [label.font fontWithSize:50];
label.tag = 1;
[view addSubview:label];
close.frame = CGRectMake(0, 0, 30, 30);
[close setTitle:#"x" forState:UIControlStateNormal];
close.titleLabel.font = [UIFont systemFontOfSize:25];
[close addTarget:self action:#selector(closeMe:) forControlEvents:UIControlEventTouchUpInside];
[view addSubview:close];
UITapGestureRecognizer* tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapToMaximize:)];
tap.numberOfTapsRequired = 1;
[view addGestureRecognizer:tap];
}
else
{
//get a reference to the label in the recycled view
label = (UILabel *)[view viewWithTag:1];
}
label.text = [items[index] stringValue];
return view;
}
And the selector:
- (void)tapToMaximize:(UITapGestureRecognizer*)recognizer {
[UIView animateWithDuration:0.3
delay:0
options:UIViewAnimationOptionCurveLinear
animations:^{
carousel.transform = CGAffineTransformMakeScale(1, 1);
}
completion:^(BOOL finished) {
}];
}
So instead of using "carousel" which represents all the views, I want to use "view" so that I can only enlarge the current view and not all of them.
UITapGestureRecognizer inherits the view property from UIGestureRecognizer, which you can use to enlarge just that tap gesture recognizer's view:
- (void)tapToMaximize:(UITapGestureRecognizer*)recognizer {
UIView *viewToMaximize;
if ([recognizer.view isEqual:_maximizedView]) {
viewToMaximize = nil;
} else {
viewToMaximize = recognizer.view;
}
UIView *viewToUnmaximize = _maximizedView; // _maximizedView should be an instance variable on your view controller
[UIView animateWithDuration:0.3
delay:0
options:UIViewAnimationOptionCurveLinear
animations:^{
viewToMaximize.transform = CGAffineTransformMakeScale(1.1, 1.1);
viewToUnmaximize.transform = CGAffineTransformIdentity;
}
completion:^(BOOL finished) {
}];
_maximizedView = viewToMaximize;
}
Also, CGAffineTransformMakeScale(1, 1) will scale the view to its original size, so I bumped the scale up in my code snippet.
If I'm understanding this correctly you want to transform the UIView that you tapped on, which should be the carousel?
Assuming you added the tap gesture recognizer to self.view, then this is how you get the view you just tapped on:
- (void)tapToMaximize:(UITapGestureRecognizer*)recognizer
{
UIView *view = [self.view hitTest:[recognizer locationInView:self.view] withEvent:nil];
// you can now check to see if this view is the carousel
}
Once you know whether or not you tapped on the carousel, you can store it, pass it on to another class, transform it, or anything you like.

Removing subviews when bar button is tapped

I am trying to trigger adding two subviews when a Bar Button is tapped. But adding the subviews works just fine, but when I try removing the subviews, it doesn't work.
Here is the code I am implementing
-(IBAction)showPopover:(id)sender{
UIView *popoverView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 100)];
UIView *popoverViewBackground = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 1000)];
popoverView.alpha = 0.0;
popoverView.layer.cornerRadius = 2;
popoverView.layer.borderWidth = 0.1f;
popoverView.layer.backgroundColor = [UIColor whiteColor].CGColor;
popoverView.layer.masksToBounds = YES;
popoverViewBackground.layer.backgroundColor= [UIColor blackColor].CGColor;
if (popoverCount == 0) {
[self.view addSubview:popoverViewBackground];
[self.view addSubview:popoverView];
popoverCount = 1;
}else if (popoverCount ==1){
[popoverView removeFromSuperview];
[popoverViewBackground removeFromSuperview];
popoverCount = 0;
}
[popoverViewBackground setAlpha:0.5];
[popoverView setAlpha:1.0];
}
Problem is that you are creating new view every time you click the button so old view not removing put your code like thi, then it will work fine.I have tested it.
in .h file
#interface secondViewController : UIViewController
{
int popoverCount;
UIView *popoverView ;
UIView *popoverViewBackground;
}
in .m file
- (void)viewDidLoad
{
[super viewDidLoad];
popoverView = [[UIView alloc] initWithFrame:CGRectMake(0, -100, 320, 100)];
popoverViewBackground = [[UIView alloc] initWithFrame:CGRectMake(0, -100, 320, 100)];
popoverView.alpha = 0.0;
popoverView.layer.cornerRadius = 2;
popoverView.layer.borderWidth = 0.1f;
popoverView.layer.backgroundColor = [UIColor whiteColor].CGColor;
popoverView.layer.masksToBounds = YES;
popoverViewBackground.layer.backgroundColor= [UIColor blackColor].CGColor;
}
-(IBAction)showPopover:(id)sender {
if (popoverCount == 0) {
[self.view addSubview:popoverViewBackground];
[self.view addSubview:popoverView];
[UIView animateWithDuration:0.5
animations:^{
popoverView.frame = CGRectMake(0,0,320,100);
}
completion:^(BOOL finished){
;
}];
[UIView animateWithDuration:0.5
animations:^{
popoverViewBackground.frame = CGRectMake(0,0,320,100);
}
completion:^(BOOL finished){
;
}];
popoverCount = 1;
}else if (popoverCount ==1){
[UIView animateWithDuration:0.5
animations:^{
popoverView.frame = CGRectMake(0,-100,320,100);
}
completion:^(BOOL finished){
[popoverView removeFromSuperview];
}];
[UIView animateWithDuration:0.5
animations:^{
popoverViewBackground.frame = CGRectMake(0,-100,320,100);
}
completion:^(BOOL finished){
[popoverViewBackground removeFromSuperview];
}];
popoverCount = 0;
}
[popoverViewBackground setAlpha:0.5];
[popoverView setAlpha:1.0];
}
UIView *popoverView;
UIView *popoverViewBackground;
Declare popoverView and popoverViewBackground in .h file and allocate and initializes of these subview in when popoverCount is zero.
-(IBAction)showPopover:(id)sender{
if (popoverCount == 0) {
popoverView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 100)];
popoverViewBackground = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 1000)];
popoverView.alpha = 0.0;
popoverView.layer.cornerRadius = 2;
popoverView.layer.borderWidth = 0.1f;
popoverView.layer.backgroundColor = [UIColor whiteColor].CGColor;
popoverView.layer.masksToBounds = YES;
popoverViewBackground.layer.backgroundColor= [UIColor blackColor].CGColor;
[self.view addSubview:popoverViewBackground];
[self.view addSubview:popoverView];
popoverCount = 1;
}else if (popoverCount ==1){
[popoverView removeFromSuperview];
[popoverViewBackground removeFromSuperview];
popoverCount = 0;
}
[popoverViewBackground setAlpha:0.5];
[popoverView setAlpha:1.0];
}
At least 2 issues in your code:
Every time the method is involved, you are creating new instances of these sub-views
You are removing the newly created instances. That is, previous instances that were added still exist.
You should
save these sub-views in instance variables, so that you can refer to them and remove them correctly.
move the creation code inside the first if-block, so that you are not creating too many sub-views.
It is happening because you are applying addSubview and removeFromSuperview on different object.
When First time showPopover is called it create two object of UIView
with name popoverView and popoverViewBackground.
and add this to self.view.
Till now every thing fine but when this method call second time
New object of popoverView and popoverViewBackground created again and
You are trying to remove that new created object from self.view which is not there.
How to solve this:
There are two way to solve this:
1) Create this object in .h file so you can access it from anywhere.
2) create object in such way that it created only when method call first time.
Give this UIView tag and when you remove find this tag in UIView.subview
Way 1 is easy way 2 require some code but you can make it efficient in turm of memory.
All the best

Resources