I've a ViewController like PopUp but the View not stay in position that I wants.
I want that this View stay on the center of screen. The below screen show the View in storyboard with the constraints seted and the result on simulator.
AlertViewController.swift
class AlertViewController : UIViewController {
#IBOutlet weak var frameView: UIView!
#IBOutlet weak var btCancel: UIButton!
#IBOutlet weak var lblInfo: UILabel!
var delegate : AlertViewControllerDelegate?
override func viewDidLoad() {
super.viewDidLoad()
self.frameView.layer.cornerRadius = 10
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
}
#IBAction func cancel(_ sender: Any) {
delegate?.cancelBt()
self.dismiss(animated: true, completion: nil)
}
}
MainViewController.swift (show)
let alertController = self.storyboard?.instantiateViewController(withIdentifier: "AlertVC") as! AlertViewController
alertController.providesPresentationContextTransitionStyle = true
alertController.definesPresentationContext = true
alertController.modalTransitionStyle = UIModalTransitionStyle.crossDissolve
alertController.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext
alertController.delegate = self
self.present(alertController, animated: true, completion: {})
EDIT
I tried this.
The result: (I did change the background color).
Your problem is setting top , bottom , leading and trailing constraints with static values that may break when you run in device , you need to set
width,height,centerX,centerY
* good practise to make width & height proportional to screen with multiplier or content size dependent *
top label
top , centerX
activity
top to label , centerX
mid label
centerX,Y
cancel button
centerX , bottom
Your issue doesn't seem to be with the constraints of the content for your alert, but with the placement/constraints of the view that you're presenting in respect with your Parent View. It would seem that you'd need to set your alert-viewer's height-width values and x,y coordinates manually in code to make them present correctly.
[EDIT]
I just noticed the order that your constraints are set. Make sure you're dragging from your FrameView to your SuperView and setting the constraint in that direction. That is, FIRST ITEM: FrameView.... SECOND ITEM: SuperView... That might also be a reason for your troubles.
There's also a good discussion on some issues with auto-layout and PresentViewController here: Auto layout invalid after presenting view controller (and many situation)
Either way, I would recommend using Center Horizontally and Center Vertically as opposed to fixed-static constraint values for your 'inner view' in your AlertView. This seems to work better when scaling accross different sized displays.
Some resources you might find useful:
But, seeing as what you're presenting is a rather simple alertview, I'd recommend skipping the re-invention of the wheel and making use of some ready-made libraries that will make your life alot easier.
1.EZAlertController if all you need are text and action buttons.
2.MRProgress if all you need are loading/progress indicators.
3.NYAlertView if what you are looking for is the freedom to add your own UIView inside the alert.
These libraries take care of the 'pesky' constraint issues for you and make development a lot quicker.
[EDIT]
You might want to take a look at: https://github.com/vsouza/awesome-ios#alert--action-sheet which has an excellent curated list of useful pods that really help with iOS development.
Related
I have a ViewController and a container view testcontrollerViewController inside of it. I noticed that after I'm adding constraints to that container view in the storyboard (all the edges match the safe area) its width decreases a little bit, but if I remove constraints width changes back to normal. (Switches from 724px to 712px and back)
Is it a bug or am I doing something wrong?
I print container view width in its viewDidAppear function.
class testcontrollerViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
view.backgroundColor = .red
print("container vc load \(testview.frame.width)")
}
override func viewDidAppear(_ animated: Bool) {
print("container vc appear \(testview.frame.width)")
print("container view safe area insets \(view.safeAreaInsets)")
}
#IBOutlet var testview: UIView!
In my opinion, I think because there is a gap between the superview and safearea. When you constraints the container view it relates to the safearea only - I think that is the reason the width changed above.
Requirement:
I should be able to scroll entire view if left view is visible or not (all components should scroll at a time if i scroll anywhere with in the view).
By clicking on show/hide left view button button it should be able to hide or show left view.
In cell (only cell not left view) there is a expand/collapse functionality (i can increase/decrease cell height)
And If i change font size in device settings app, it should be effect here also(So supporting dynamic font size)
What i have tried:
I have tried with tableview, scroll view but no luck. Finally want to try with collection view, can any one please help me out how to proceed with collection view. And in future do we get any complications if we use collection view.
Best Approach.
Your UI hierarchy should be like this.
StackView
CollectionView
TableView
Note: You can take both CollectionView or TableView but I prefer both different so that I don't need to put condition in delegates & datasource and I can manage easily. Choice is your's what you like to prefer.
Now your UI design looks like this
Green color button is used to show hide your left collectionview (you mentioned in your post).
Set your datas in CollectionView and TableView as per your requirement.
To toggle left menu, just use below one line code on greenButton action.
#IBAction func btnToggle(_ sender: Any) {
colView.isHidden = !colView.isHidden
}
For simple animation
#IBAction func btnToggle(_ sender: Any) {
UIView.animate(withDuration: 0.3) {
self.colView.isHidden = !self.colView.isHidden
}
}
Output:
Edit
You can take stackView in scrollview and turn off colview, tblView scrolling. Check below :
UI heirarchy
Additional code work
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
colView.isScrollEnabled = false
tblView.isScrollEnabled = false
colView.reloadData()
tblView.reloadData()
scrollView.contentSize = CGSize(width: self.view.frame.width,
height: max(colView.contentSize.height, tblView.contentSize.height))
stackHeight.constant = scrollView.contentSize.height
}
Note : It may cause some unexpected output (can be / can not be), so you need to take care of it.
Output:
What you need is UICollectionView with custom layout. You can achieve the effect you need using this approach.
There is tone of tutorials how to implement own custom layout.
Here is one of them
I have a Text View (UITextView) which displays a long text that is set on runtime like so:
#IBOutlet weak var textView: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
if something {
textView.text = "(very long text here)"
}
textView.contentOffset = CGPoint.zero // doesn't work
}
Unfortunately, when the Text View is displayed, the text is not scrolled to the top but somewhere in the middle.
I'm thinking, either setting the contentOffset is the wrong way of doing it or I am doing it at the wrong time (maybe the text gets changed after setting contentOffset?).
I have tried a lot, I even contacted Apple Code Level Support. They couldn't help me, really (which surprised the hell out of me) – can you?
I'd very much appreciate it. Thank you.
I had a very similar issue, especially when using splitview and testing on the iPhoneX, I resolved this by incorporating this bit of code in my ViewController when I needed the textView to scroll to the top:
textView.setContentOffset(.zero, animated: false)
textView.layoutIfNeeded()
If you wish to scroll to the top of the textView upon loading your ViewController:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
// Can add an if statement HERE to limit when you wish to scroll to top
textView.setContentOffset(.zero, animated: false)
}
You may need to write more information/code because if you try this piece of code in clean project with only one VC with UITextView, you'll see that it's actually working. If you're really using some condition (if something) this might be the issue. What is this something in your real code?
You need to use viewDidLayoutSubviews() so that it set the scrollview to the top.
override func viewDidLayoutSubviews() {
textView.setContentOffset(.zero, animated: false)
}
I really can't figure out what's wrong with my code. Let me explain in detail what was my aim:
I have two UIView in the same UIViewController. They're called "redSquare" and "greenSquare".
When the UIViewController is presented I want to animate the redSquare in order to move on the Y-axis till it reaches the top-border of the greenSquare.
This is how I set the xCode project:
The behavior that I got is completely the opposite and I really can't understand why and what's happening:
Any tips or explanations for this?
Okay. Part of the problem is that you're aligning the center Y... which means that you're trying to break constraints with your animation.
Another part of the problem is that you are doing your animation in viewDidLoad, which totally runs before viewWillAppear and viewDidAppear get called.
For my own animations, I usually animate a constraint.
That is, get rid of the center-Y constraint for your red box and add a new constraint putting the red box some Y distance from the bottom of the superview. Connect this new constraint to an outlet and then you can animate like this:
#IBOutlet weak var redYConstraint : NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
// This line sets the red box to be in the center Y of the green box
self.redYConstraint.constant = self.greenSquare.frame.midY
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
UIView.animate(withDuration: 3.0, delay: 2.0, options: UIViewAnimationOptions.curveEaseIn, animations: {
self.redYConstraint.constant = self.greenSquare.frame.maxY
self.view.layoutIfNeeded()
}, completion: nil)
}
I have a container view that I want to initially be off the bottom of the screen. It should be easy, but I seem to be missing something fundamental. I have previously done something similar by moving controls off the left side of the screen with:
control.center.x -= view.bounds.width
I have a very simple storyboard setup:
And my view controller looks like this:
class ViewController: UIViewController {
#IBOutlet var containerView: UIView!
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
containerView.center.y += view.bounds.height
}
}
When run, the container view is right where it shows in the storyboard and is not offscreen. Even setting the containerView's center.y to a specific value such as containerView.center.y = 50 will do nothing. The only way I can get it to show off screen is by adding animation in the viewDidAppear:
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
UIView.animateWithDuration(0, animations: {self.containerView.center.y += self.view.bounds.height})
}
But that just seems like a workaround and not the proper way to do it. I have been dealing with this for hours, reading blogs, reading other Stackoverflow questions, but I cannot find the solution. I do not have constraints on the container, although I did test it with constraints and that did not make a difference. Any help is appreciated.
It is possible that the main view's `layoutSubviews is called after you reposition the container view, so it will default to the position specified in the storyboard.
The proper way to do is to have proper layout constraints in storyboard, make an outlet for the bottom edge constraint and set this constraint's constant property.