how to redraw custom view from the controller in ios objective-c - ios

I have a custom view with 3 buttons taking full width.
I import the class to my controller where I want to hide on button (menuBtn) and make one of the one of the other buttons (searchbarBtn) be bigger to fill the empty space by doing:
`self.topMenuView.searchbarBtn.frame = CGRectMake(self.topMenuView.searchbarBtn.frame.origin.x, self.topMenuView.searchbarBtn.frame.origin.x, self.topMenuView.searchbarBtn.frame.size.width + self.topMenuView.menuBtn.frame.size.width , self.topMenuView.searchbarBtn.frame.size.height);`
I do this in viewWillLayoutSubviews (have also tried in viewWillAppear) and I call the
[self.topMenuView.searchbarBtn setNeedsDisplay];
but nothings happens.
I

The button's layout properties override your frame settings, since by definition viewWillLayoutSubvies is called before the layout pass. You should just set
self.topMenuView.menuBtn.hidden = YES;
and use autolayout constraints (in the interface builder or in the code) between menuBtn, searchbarBtn and topMenuView to make sure your buttons grow as needed.
As a general rule, we should strive to create interface so that views will correctly position themselves provided their inner state is correctly set and correct constraints are formed, without explicit corrections on our part.

Related

Swapping UIViews in and out of a ViewController's view

I'm not entirely new to iOS/Swift development but I've mostly been working on "backend" code so my UI design/development skill level is unfortunately not what I'd like it to be. With that in mind, I have a UI layout (for a view controller) that looks something like this:
In this layout, the view labeled "View To Swap" could be in one of three states:
It may be hidden (or removed?) in which case StackView B should appear directly below StackView A
It may need to show (or be replaced by?) "Subview A"
It may need to show (or be replaced by?) "Subview B"
Both Subview A and B will have a button in the upper right hand corner that, when clicked, should remove/hide the "View To Swap" view.
I've been reading about container views a little bit and I'm wondering if this is the approach that I should take here or is there a more simple, direct way to implement this? I'm currently using the storyboard and autolayout to define my primary view (the view on the left) and constraints but I understand the basics of building a UI programatically if that makes it easier to implement something like this? Thanks for any suggestions!
You need to insert the 3 main views ( top stack , viewToSwap , bottom stack ) inside a vertical UIStackView with distribution = fillEqually , and hook viewToSwap as IBOutlet, whenever you want to hide it do
self.viewToSwap.isHidden = true
this will automatically collapse it's content , and you can add any subview to it (A/B) and don't forget self.viewToSwap.clipsToBounds = true

How to assign a higher level on a uiview in order to make it override another view?

I created a uiview and added a sub-uiview on it. Then I allow user to drag the sub-view around the screen freely. But I have problem when moving the sub-view on top of the screen. Please see below picture. The sub view override the top uiview on the screen. What I want is to let the top uiview to override the sub-view. How can I change the level of a uiview in this case?
when I use self.titleView.bringSubviewToFront(sv)
I see another problem as shown in below image. The status bar is not at the top of the image view.
You can use bringSubviewToFronton parent view to bring sub view to front as follow:
objective-C:
[parentView bringSubviewToFront:childView];
swift:
parentView.bringSubviewToFront(childView)
Edit:
use below method to manage views:
bringSubviewToFront(_:)
sendSubviewToBack(_:)
removeFromSuperview()
insertSubview(_:atIndex:)
insertSubview(_:aboveSubview:)
insertSubview(_:belowSubview:)
exchangeSubviewAtIndex(_:withSubviewAtIndex:)
like,
self.view.sendSubviewToBack(myView)
For more detail check: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIView_Class/#//apple_ref/doc/uid/TP40006816-CH3-SW46
Hope this helps :)
parentView.bringSubviewToFront(view)
UPDATE
Pay attention: you must considered that parentView is the parent of your view. To explain better this concept if you have a line like this:
self.container.addSubview(view)
so self.container is the view parent's, dont confuse it with the view below your view...it may not be the same.
If your draggable view is a subview of the image view try to set masksToBounds to true:
imageView.layer.masksToBounds = True
But the reason of your issue is probably because you set zPosition of draggableView.layer to some positive number. Usually it is better to use methods such as insertSubview(_:aboveSubview:) and bringSubview(toFront:) to manage subview's order.

How to add a random view in real time when using Pure Layout

I'm using PureLayout in my iOS app and I'm following the instructions here:
https://github.com/PureLayout/PureLayout/wiki/Tips-and-Tricks
That is, using a flag called didSetupConstraints and the method updateViewConstraints.
But now I would like to add a view inside another random view when user presses a button.
The only way to do that I could imagine was creating another flag like didNewViewSetupConstraints and creating another block inside updateViewConstraints, where I use 2 UIView variables to create the new constraints between them.
Is that right? Because I think it is a lot of work for just a small thing (adding a subview and its contraints).
Note that I cannot create the constraints without installing them because I donĀ“t know the beforehand (the user will tap them). That is the reason I remark RANDOM.
I see in sample code number 10, it is used autoRemoveConstraints and autoInstallConstraints to toggle between 2 groups of constraints. Because my 2 views are random, I guess I cannot do something like that, that is the reason I created a flag and 2 variables for these 2 views to setup the constraints inside updateViewConstraints. But I'm sure that is too much.
Thanks for any suggestion or idea.
You don't have to create/activate all of your constraints inside of -updateConstraints. You can create constraints at any time, and activate them as long as both of the views you wish to constrain share a common superview (in other words, the views need to have been added to the same view hierarchy already).
I would recommend creating your default set of static constraints inside of -updateConstraints as you're doing. Then, in the callback method when the user taps the button, you can create this new view, add it as a subview, and then create & activate the new constraints for it right then and there.
If you remove this view later on, that will remove all of the constraints associated with it automatically. But if you need to adjust the constraints for this new view, you can store a separate reference to the constraints when they are created.

How can I trigger an update to all the autolayout constraints?

I modified programmatically one autolayout constraint. It takes effect on one certain view, but other views that are bound with other constraints to that view, do not change their positions. Is there an "updateAllConstraints" method?
Call those two methods on the view you want to be updated:
-setNeedsLayout
-layoutIfNeeded
The first one says to the layout system that this view needs to be laid out, because it has some changes and, everything should be recalculated. The second force the layout system to be run now, layout system is triggered at specific times during runtime, with this method you are saying:"do it now".
Yes There is a method on UIView called - (void)updateConstraintsIfNeeded
https://developer.apple.com/Library/ios/documentation/UIKit/Reference/UIView_Class/UIView/UIView.html#//apple_ref/occ/instm/UIView/updateConstraintsIfNeeded
However I don't think this is your problem
The problem was that constrains were not set up properly, and in this case non of the setNeedsLayout or updateConstraintsIfNeeded can help.
Those of you that come across this topic, and are looking where to find this in the menus.
Best I have found is:
Select the items that you want to "pop" back to your constraints
Top menu: Editor/Update Frames (or/) shortcut: command + option + =
Hopefully this helps

Add a bunch of controls dynamically to screen in iOS

I am working on a screen where user selects an option from drop-down. Based on this selection he adds a bunch of controls to screen. My drop-down is at the bottom-right corner of the screen. It takes up 20-25% of screen space at the bottom. In the remaining 75% screen at the bottom i need to add 9 labels,6 UItext fields ,2 drop-downs and 2 buttons. I am attaching a markup here.
My question is: in ASP.NET, I have a repeater which has all the above controls. In one of the buttons named "Add More". If I click that button, it adds the same repeater at the bottom of the current one. Do we have anything like that in iOS? Like a repeater which has a bunch of controls and click add and that exact repeater is added at the bottom and so-on and so forth. If any ideas/new ideas based on my explanation pop-up then please let me know. Thanks.
The link
http://dl.dropbox.com/u/40597849/mockup2.png
So, the big rectangle to the right containing 8 labels, textboxes, drop-downs and the 2 buttons below it(one is named as "Add More") should be added again when user clicks on Add More. Please ask me if you need more information.
ITMCustomView *cView = [[ITMCustomView alloc] initWithFrame:frame];
cView.delegate =self;
CGPoint scrollPoint = CGPointMake(0.0, (frame.origin.y/400)*400);
[self.scrollView setContentOffset:scrollPoint animated:YES];
[self.scrollView addSubview:cView];
Initially the very first custom view i add, i add it with this frame size (187, 585, 350, 21); . Next whenever i hit add more i call this delegate
[self.delegate addNewSize:CGRectMake(187,self.y+ 400 , 400, 400)];
This calls the above 5 lines of code and makes a new custom view and adds it to scroll view. I store the self.y as the y value of whatever frame currently being built. So how do i make my scroll view move up and down freely. The screen shows the custom view as they are added but doesnt allow me to go up anymore. I wanted to suppose add the custom view 5 times and i added 4 i just want to scroll up , see i added 4 scroll down and just add 1 more custom view and do other processing with it. But my scroll view is non-functional and its stuck at the just added custom view disabling me to scroll up. If you need more information, please ask me. Thanks.
Use a custom view that contains all your views.
1.) Make a custom class myView which subclasses UIView.
2.) Add all the controls you need in that view class.
3.) include myView in your main view.
4.) initiate as many myView as you like and add them to your main view.
I hope that is clear enough to get you going.
Update: As to elaborate more on the comment bgoers made.
When you create a new class myView sub-classing UIView you get an empty sheet. This sheet will have the frame that you specify either in the class or when you initiate (up to you). Within that frame (myView.h and myView.m in initWithFrame), you can add subViews like buttons or labels. Those subviews will placed relative to the sheet myView.
For example, your draw up is a custom view with all the controls. I can have another one looking exactly like it by simply initiating another custom view without adding more subviews. All I need to do is move the second custom view to where I would like, all the subviews will follow.
I encourage you to read up on how to subclass and how that works in iOS. It is very simple once you get the hang of it.

Resources