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.
I faced with a flash of viewController, where searchField is first responder, when I am returning to that controller. i tried i on ios9 , but there is no such a problem, so it looks that it is caused in ios10.
Could you please advice what could be a reason of it and how to solve it?
Thank you in advance for any suggestion.
EDIT:
My View hierarchy is quite simple(its just a demo), but cause the issue happends here as well i am investigating it here. The code looks like that:
class ViewController: UIViewController {
#IBOutlet weak var searchBar: UISearchBar!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func viewWillAppear(_ animated: Bool) {
searchBar.becomeFirstResponder()
}
}
I faced this problem too. In my case, the screen on the first page was a stack view inside of a scroll view and I'm still not sure why this was happening, but setting the content inset of the scrollview in viewWillAppear fixed this issue for me. I used this code for that:
let insets = UIEdgeInsetsMake(0.0, 0.0, 0.0, 0.0)
scrollView.contentInset = insets
scrollView.scrollIndicatorInsets = insets
scrollView.contentSize = CGSize(width: stackView.frame.width, height: stackView.frame.height)
If this type of solution won't work for you, could you add some more details about the hierarchy of objects on your view?
Maybe setting the contentInset of the UISearchBarController would fix this problem.
I have what I believe to be a standard UITextView in a ViewController which has a substantial amount of text in it, enough that not all of it can fit on the screen. What I would like to happen is that when that view is loaded, the user can start reading at the top of the text and then scroll down the page as they progress through the text. Makes sense, right? What I want is not unrealistic.
The problem is that when the view loads, the text in the UITextView is already scrolled all the way down to the bottom. I have scoured SO and there are a number of similar posts but none of the solutions therein are resolving my problem. Here is the code in he view controller:
import UIKit
class WelcomeTextVC: UIViewController {
var textString: String = ""
#IBOutlet weak var welcomeText: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.navigationBar.translucent = false
self.welcomeText.text = textString
self.welcomeText.scrollRangeToVisible(NSMakeRange(0, 0))
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(true)
self.welcomeText.scrollRangeToVisible(NSMakeRange(0, 0))
welcomeText.setContentOffset(CGPointMake(0, -self.welcomeText.contentInset.top), animated: true)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
I have tried most of the standard solutions to no avail. The one common suggestion which I have not tried is to "Uncheck the Adjust Scroll View Insets in the Attributes Inspector". The reason I have not tried it is because I cannot locate this fabled check box.
What do I need to do to make the text start out aligned to the top?
There's a couple ways I know of. Both ways are implemented programmatically through the viewDidLayoutSubviews() method in your view controller. After the call to super.viewDidLayoutSubviews(), you could add:
myTextView.scrollRangeToVisible(NSMakeRange(0, 1))
This would automatically scroll the textView to the first character in the textView. That however might add some unwanted animation when the view appears. The second way would be by adding:
myTextView.setContentOffset(CGPoint.zero, animated: false)
This scrolls the UITextView to point zero (the beginning) and gives you control over whether you want it animated or not.
A better Solution is to call the textView.setContentOffset(.zero, animated: false) inside the viewWillAppear(_ animated: Bool) lifecycle method instead of in the viewDidLayoutSubviews() method. Just override the default implementation in your custom UIViewController subclass:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
textView.setContentOffset(.zero, animated: false)
}
This will scroll to the top of the UITextView only when the view appears and not always when the layout changes (which happens more often as you might think).
If you only want that the UITextView scrolls to the top once and not every time the view appears, you can add a flag. This is really helpful if your UITextView is inside a UINavigationController and the user can push another UIViewController on top of it. After the user returns to the UITextView it keeps the scroll position of the UITextField and does not reset the position to the top:
private var didAppearOnce = false
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if !didAppearOnce {
didAppearOnce = true
textView.setContentOffset(.zero, animated: false)
}
}
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.
I'll get right to it. I have a UItextView placed in my view that when needs to scroll to see all the text (when a lot of text is present in the textView) the textView starts in the middle of the text sometimes and the bottom of the text other times.
Editing is not enabled on the textView. I need a way to force the textView to start at the top, every time. I saw some questions somewhat like this where other people used a content offset, but I do not really know how that works or if it would even be applicable here.
Thanks for your help.
That did the trick for me!
Objective C:
[self.textView scrollRangeToVisible:NSMakeRange(0, 0)];
Swift:
self.textView.scrollRangeToVisible(NSMakeRange(0, 0))
Swift 2 (Alternate Solution)
Add this override method to your ViewController
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
textView.setContentOffset(CGPointZero, animated: false)
}
Swift 3 & 4 (syntax edit)
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
textView.contentOffset = .zero
}
All of the answers above did not work for me. However, the secret turns out to be to implement your solution within an override of viewDidLayoutSubviews, as in:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
welcomeText.contentOffset = .zero
}
HTH :)
In Swift 2
You can use this to make the textView start from the top:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
myTextView.setContentOffset(CGPointZero, animated: false)
}
Confirmed working in Xcode 7.2 with Swift 2
Try this below code -
if ( [self respondsToSelector:#selector(setAutomaticallyAdjustsScrollViewInsets:)]){
self.automaticallyAdjustsScrollViewInsets = NO;
}
Or you can also set this property by StoryBoard -
Select ViewController then select attributes inspector now unchecked Adjust Scroll View Insets.
For Swift >2.2, I had issues with iOS 8 and iOS 9 using above methods as there are no single answer that works so here is what I did to make it work for both.
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
if #available(iOS 9.0, *) {
textView.scrollEnabled = false
}
self.textView.scrollRangeToVisible(NSMakeRange(0, 0))
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
if #available(iOS 9.0, *) {
textView.scrollEnabled = true
}
}
Update your UINavigationBar's translucent property to NO:
self.navigationController.navigationBar.translucent = NO;
This will fix the view from being framed underneath the navigation bar and status bar.
If you have to show and hide the navigation bar, then use below code in your viewDidLoad
if ([self respondsToSelector:#selector(edgesForExtendedLayout)])
self.edgesForExtendedLayout = UIRectEdgeNone; // iOS 7 specific
Hope this helps.
Xcode 7.2 7c68; IOS 9.1
My ViewController which contains UITextView is complicated, and changed a lot during the project (IDE version changed maybe 2~3 times too).
I've tried all above solutions, if you encounter the same issue, be PATIENT.
There are three possible 'secret codes' to solve:
textView.scrollEnabled = false
//then set text
textView.scrollEnabled = true
textView.scrollRangeToVisible(NSMakeRange(0, 0))
textView.setContentOffset(CGPointZero, animated: false)
And there are two places you can put those codes in:
viewDidLoad()
viewDidLayoutSubviews()
Combine them, you'll get 3*2=6 solutions, the correct combination depends on how complicated you ViewController is (Believe me, after delete just a view above textView, I need to find a new combination).
And I found that:
When put 'secret codes' in viewDidLayoutSubviews(), but textView.text = someStrings in viewDidLoad(), the content in textView will 'shake' sometimes. So, put them in the same place.
Last word: try ALL combinations, this is how I solve this stupid bug more than three times during two months.
With a lot of testing, i found must add below in viewWillLayoutSubviews() function to make sure the UITextView show up from the very beginning:
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
textViewTerms.scrollRangeToVisible(NSMakeRange(0, 0))
}
UITextView scrolling seems to be a problem to a lot of people. Gathering from the answers here around (especially this) and the Apple Developer documentation, using some of my own wit, here is a solution that works for me. You can modify the code to suit your needs.
My use case is as follows: the same UITextView is used for different purposes, displaying varying content in different circumstances. What I want is that when the content changes, the old scroll position is restored, or at times, scrolled to the end. I don't want too much animation when this is done. Especially I don't want the view to animate like all the text was new. This solution first restores the old scroll position without animation, then scrolls to the end animated, if so desired.
What you need to do (or should I say can do) is extend UITextView as follows:
extension UITextView {
func setText(text: String, storedOffset: CGPoint, scrollToEnd: Bool) {
self.text = text
let delayInSeconds = 0.001
let popTime: dispatch_time_t = dispatch_time(DISPATCH_TIME_NOW, Int64(delayInSeconds * Double(NSEC_PER_SEC)))
dispatch_after(popTime, dispatch_get_main_queue(), {
self.setContentOffset(storedOffset, animated: false)
if scrollToEnd && !text.isEmpty {
let popTime: dispatch_time_t = dispatch_time(DISPATCH_TIME_NOW, Int64(delayInSeconds * Double(NSEC_PER_SEC)))
dispatch_after(popTime, dispatch_get_main_queue(), {
self.scrollRangeToVisible(NSMakeRange(text.lengthOfBytesUsingEncoding(NSUTF8StringEncoding) - 1, 0))
})
}
})
}
}
What this does is it updates the text, then uses a stored value of the UITextView.contentOffset property (or anything you pass as a parameter), and sets the offset of the view accordingly. If desired, after this, it scrolls to the end of the new, potentially changed content.
I'm new to iOS programming and I don't know why it works so well it does, if someone has some information on this it would be nice to know. Also the approach may not be perfect so I'm open to improvement ideas as well.
And of course thanks to NixonsBack for posting the answer behind the link above.
My first post :), cheers!
Put this one line of code in ViewDidLoad
self.automaticallyAdjustsScrollViewInsets = false
The following code should give you effect you want.
[self.scrollView setContentOffset:CGPointMake(0, -self.scrollView.contentInset.top) animated:YES];
You'll need to replace "self.scrollView" with the name of your scroll view. You should put this code in after you've set the text of the scroll view.
This worked for me:
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
textView.scrollRectToVisible(CGRect(origin: CGPointZero, size: CGSizeMake(1.0, 1.0)), animated: false)
}
This worked for me with Xcode 8.3.3:
-(void)viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
[self.txtQuestion scrollRangeToVisible:NSMakeRange(0, 0)];
}
Create an outlet for your UITextView in the ViewController.swift file. In the ViewDidLoad section put the following:
Swift:
self.textView.contentOffset.y = 0
I have tried:
self.textView.scrollRangeToVisible(NSMakeRange(0, 0))
I translated zeeple's answer to MonoTouch/Xamarin (C#).
public override void ViewDidLayoutSubviews()
{
base.ViewDidLayoutSubviews();
myForm.SetContentOffset(new CoreGraphics.CGPoint(0,0), animated: false);
}
I had to implement two answers here to get my view working as I want:
From Juan David Cruz Serrano:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
textView.setContentOffset(CGPoint.zero, animated: false)
}
And from Murat Yasar:
automaticallyAdjustsScrollViewInsets = false
This gave a UITextView that loads with the scroll at the very top and where the insets are not changed once scrolling starts. Very strange that this is not the default behaviour.
To force the textView to start at the top every time, use the following code:
Swift 4.2:
override func viewDidLayoutSubviews() {
textView.setContentOffset(CGPoint(x: 0, y: 0), animated: false)
}
Objective-C:
- (void)viewDidLayoutSubviews {
[self.yourTextView setContentOffset:CGPointZero animated:NO];
}
Swift 4.2 & Swift 5
set content offset both before and after setting the text. (on the main Thread)
let animation = false //or whatever you want
self.mainTextView.setContentOffset(.zero, animated: animation)
self.mainTextView.attributedText = YOUR_ATTRIBUTED_TEXT
self.mainTextView.setContentOffset(.zero, animated: animation)
In my case I was loading a textView in a Custom tableview cell. Below is what I did to make sure the text in a textview loads at the top of the text in my textview in my custom cell.
1.) In storyboard, set the textview ScrollEnabled = false by unchecking the button.
2.) You set the isScrollEnabled to true on the textview after the view loads. I set mine in a small delay like below:
override func awakeFromNib() {
super.awakeFromNib()
let when = DispatchTime.now() + 1
DispatchQueue.main.asyncAfter(deadline: when){
self.textView.isScrollEnabled = true
}
}
Regardless, if you are in my situation or not, try setting scrollEnabled to false and then when the view loads, set scrollEnabled to true.