I'm trying to toggle between 2 tableviews based on a segment control. To do this, I've tested 2 implementations:
Option A: Have 2 container views stacked in a storyboard (same constraints), then toggle the container views based on the segment control.
Option B: Have 1 container view setup, add and remove the views programmatically.
The problem with both implementations is that the first view to display is always aligned correctly (no matter if its view A or view B), the second one is wrong aligned! rrrr
Why is the second view to display wrong aligned!?!?
Here is the code for example A:
class MainViewController: UIViewController {
#IBOutlet weak var viewOne: UIView!
#IBOutlet weak var viewTwo: UIView!
#IBOutlet weak var segmentContrl: UISegmentedControl!
override func viewDidLoad() {
super.viewDidLoad()
showView(0)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func showView(index:Int){
switch index
{
case 0:
viewOne.hidden = false
viewTwo.hidden = true
break;
case 1:
viewOne.hidden = true
viewTwo.hidden = false
break;
default:
break;
}
}
#IBAction func onSegmentChanged(sender: AnyObject) {
print("onSegmentChanged \( segmentContrl.selectedSegmentIndex)")
showView(segmentContrl.selectedSegmentIndex);
}
Storyboard, the container views are stacked:
The container views constraints, both have the same!
Fixed the problem by removing "Adjust scroll view insets" in all 3 view controllers shown above.
Then I repositioned the container views to top and bottom align then to the layout guides.
WORKS! :P
Related
OK, so here's the relevant bit of my code:
class MyViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var questionView: QuestionView!
#IBOutlet weak var answerView: AnswerView!
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var tableViewTopConstraint: NSLayoutConstraint! // Active at start, attaches tableView.topAnchor to questionView.bottomAnchor
#IBOutlet weak var tableViewTopAlternateConstraint: NSLayoutConstraint! // Inactive at start, attaches tableView.topAnchor to answerView.bottomAnchor
func submitAnswer() {
tableViewTopConstraint.isActive = false
tableViewTopAlternateConstraint = true
}
func newQuestion() {
tableViewTopConstraint.isActive = true
tableViewTopAlternateConstraint = false
}
}
I'm building a question/answer type of app and the two subviews are different sizes for design reasons. I have it set so that it toggles between the two subviews depending on the current state (toggling back for a new question when the user taps to advance), and it works fine...
...until I go to a different tab on the UITabView that encloses everything (e.g. to change the settings then resume testing)
The moment the tab changes it's like the NSLayoutConstraint outlets no longer exist. The orders to change them still process (I've verified this in the console), but they do nothing.
I've tried declaring the outlets as strong (there was no difference in behavior)
I've removed the outlets and managed them in code (it worked the first time, but afterward it stretched the shorter QuestionView's height to match tableView's new top position instead of moving tableView up to the bottom of QuestionView as was intended)
I've tried implementing a UITabViewController so that I could call tabBar(_:didSelect:) and replace the view controller with a brand new instance of MyViewController() whenever I switch back to that tab (It loads the first time, but when I try to switch tabs it finds nil when accessing any of the IBOutlets...even though I didn't tap on the tab for the testing view and filtered by item.tag when replacing the existing view controller)
Any suggestions on how else to attack this problem?
First, don't set #IBOutlet properties to weak. I know that's the default, but it's not correct.
If you have this:
#IBOutlet weak var tableViewTopAlternateConstraint: NSLayoutConstraint!
connected to a constraint via Storyboard, and you do this:
tableViewTopAlternateConstraint.isActive = false
you just removed that constraint from existence.
In addition, if you have two different Top constraints in Storyboard, you should be getting an Error indicator as they cannot be satisfied.
Better to either change the Priorities, or use a single constraint and change the .constant value.
So, two constraints in Storyboard:
set the "default" constraint to Priority: High (750)
set the "alternate" constraint to PriorityL Low (250)
and your code becomes:
func submitAnswer() {
tableViewTopConstraint.priority = .defaultLow
tableViewTopAlternateConstraint.priority = .defaultHigh
}
func newQuestion() {
tableViewTopAlternateConstraint.priority = .defaultLow
tableViewTopConstraint.priority = .defaultHigh
}
I've read a lot of material on this topic but most of them create custom view programatically.
Is it possible to use InputAccessoryView with a custom view created in IB? In storyboard I've added textInputView, inside which I've added text view and send button etc as seen in the screenshot below.
I've following code so which removes Table View for some reason so I can't get it working. I've added tableview in the storyboard.
I've shown here only InputAccessoryView related code.
class InputAccViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var textView: UITextView!
#IBOutlet weak var textInputView: UIView!
// other code
override var canBecomeFirstResponder: Bool { return true }
override var inputAccessoryView:UIView {
get{
return self.textInputView
}
}
override func viewDidLoad() {
super.viewDidLoad()
textInputView.removeFromSuperview()
// other code
}
// other code tableview delegates etc...
}
Left screenshot is with the accessory view code which doesn't show table view. If I comment out accessory view related code it does show table view as in the right screenshot.
Seems you might be constraining the UITableView's bottom to the textInputView's top. When you are setting the textInputView as the inputAccessoryView of the UIViewController this no longer works as expected. When setting the textInputView as the inputAccessoryView make sure you constraint the bottom of UITableView to the bottom of UIViewController's view.
I am trying to hide and remove the space of the MainUIView.I tried to make the MainUIView heightConstarint to 0 . But it is not hiding the views inside them.
I want to hide all the view and labels inside the MainUIView.
hope you understand my problem.Thank you in advance
Here is my code
#IBOutlet weak var heightConstarint:NSLayoutConstraint!
//#IBOutlet weak var viewhide: UIView!
override func viewDidLoad() {
super.viewDidLoad()
heightConstarint.constant = 0
//self.viewhide.setNeedsUpdateConstraints()
self.view.layoutIfNeeded()
}
Updating Constraints will Never work in
override func viewDidLoad(){}
If you want to change constraints programmatically then you must put your code in
override fun viewWillLayoutSubviews(){}
So your code will look like
override func viewWillLayoutSubviews() {
clipToBounds = true
heightConstarint.constant = 0
//self.viewhide.setNeedsUpdateConstraints()
self.view.layoutIfNeeded()
}
I don't know updating constraints will work or not in viewDidLoad. But there are another constraints for MainUIView.
I think you should remove top or bottom space.
I have a bottomView with opacity set to 0.65, and embedded in that View I have 5 buttons - which also gets the 0.65 opacity attribute - but How do I make the buttons get rid of the opacity?
I want the buttons to be very clear
I have tried to make outlets of the View and the Buttons and set the buttons to the front - view, but it doesn't change the appearance of the button??
#IBOutlet weak var bottomView: UIView!
#IBOutlet weak var findVejOutlet: UIButton!
#IBOutlet var superViewOutlet: UIView!
#IBAction func findVejButton(_ sender: Any) {
superViewOutlet.bringSubview(toFront: findVejOutlet)
}
override func viewDidLoad() {
super.viewDidLoad()
settingView()
}
func settingView(){
bottomView.bringSubview(toFront: findVejOutlet)
}
If you set the opacity of a view to a value of less than 1, it makes all the contents of a view partly transparent (including subviews). You can't change that, and opacity has nothing to do with the front-to-back ordering of the views.
You either need to make the parent view fully opaque and the non-button subviews partly transparent, or remove the buttons from the translucent view and instead put them in the common parent view.
I am using a segmented control to rotate through content, but when I scroll to the end of a subview and switch to another segment, the new segment shows roughly in the same position as the previous segment (i.e. if I scroll to the bottom of segment A and switch segments, segment B is also at the bottom of the scroll). How can I reset each segment so that it is positioned at the top each time I change segments?
Sample code:
class AboutUsViewController: UIViewController {
#IBOutlet weak var welcomeContainer: UIView!
var views: [UIView]!
override func viewDidLoad() {
super.viewDidLoad()
views = [UIView]()
views.append(ViewController1().view)
views.append(ViewController2().view)
views.append(ViewController3().view)
views.append(ViewController4().view)
for view in views {
welcomeContainer.addSubview(view)
}
welcomeContainer.bringSubview(toFront: views[0])
}
#IBAction func swichViewAction(_ sender: UISegmentedControl) {
self.welcomeContainer.bringSubview(toFront: views[sender.selectedSegmentIndex])
}
}