ContentOffset doesn't do anything to UITextView the first time - ios

I'm trying to have a UIViewController to display some text centered vertically in a UITextView. When app is launched, the text is aligned to the top. But if I try to select some text, the text would then move to the center vertically. It seems like setting contentOffset doesn't do anything at the first time, unless there's some action to trigger it to readjust the layout (like selecting some text in my scenario).
Also when I log the values of height, size, contentHeight and topCorrect, the values from the first call is the same as the second call. So I'm getting the same value but UITextView somehow is not responding to the contentOffset the very first time.
I even tried moving the logic to viewDidLayoutSubviews() and viewDidAppear(). I had the same result. So I don't think it's a problem of having the logic in the wrong place.
I think some people have success with it on iOS 7 and Obj-C. I'm trying get it running on iOS 8 and Swift.
Any suggestion or help would be very much appreciated.
class PageContentViewController : UIViewController {
#IBOutlet weak var textView: UITextView!
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
self.textView.textContainerInset = UIEdgeInsetsMake(0, 16.0, 0, 16.0)
let height = self.textView.bounds.size.height
let size = CGSizeMake(self.textView.frame.width, CGFloat.max)
var contentHeight = self.textView.sizeThatFits(size).height
var topCorrect = (height - contentHeight * self.textView.zoomScale) / 2.0
topCorrect = topCorrect < 0.0 ? 0.0 : topCorrect;
self.textView.setContentOffset(CGPointMake(0, -topCorrect), animated: false)
}
}

Related

Dynamic UITextView Size (Swift 4)

I want size a UITextView dynamically to its contents by restricting both its width and its height to some maximums.
In particular, the textView should have a minimum width and height if there is little data (e.g., "Lorem"). As the data grows (e.g., "Lorem ipsum") it should expand in width as until it hits the maximum width ("Lorem ipsum dolor sit"), and then expand in height until it hits that maximum height. Once it goes beyond the max width and height it should become scrollable.
So far, I am struggling to get just the height working. I have experimented with a number of methods and, while this seemed the simplest and most promising, it just crashes.
func textViewDidChange(_ textView: UITextView ) {
resizeTextView(txtview1)
}
#IBOutlet weak var txtViewHeight: NSLayoutConstraint!
func resizeTextView(_ textView: UITextView ) {
let minHeight: CGFloat = 20.0
let maxHeight: CGFloat = 40.0
txtViewHeight.constant = min(maxHeight, max(minHeight, textView.contentSize.height))
self.view.layoutIfNeeded()
}
So, I changed the resize function to this - which kinda, sorta, sometimes works (sometimes the values show up in the text field, sometimes it doesn't display at all, sometimes the spacing within the text field is different):
func resizeTextView(_ textView: UITextView ) {
let currentHeight = textView.contentSize.height
let minHeight: CGFloat = 20.0
let maxHeight: CGFloat = 40.0
if currentHeight > maxHeight {
textView.frame.size.height = currentHeight
textView.isScrollEnabled = true
}
else if currentHeight < minHeight {
textView.frame.size.height = minHeight
textView.isScrollEnabled = false
}
else {
textView.frame.size.height = currentHeight
textView.isScrollEnabled = false
}
self.view.layoutIfNeeded()
}
I know this question has been asked an answered a dozen or more times, but none of the solutions are working for me (the above being two of the half dozen or more I have tried).
I think it is better to achieve this with Timer.
You solution above is that, UITextView's delegate methods triggers your height changing method.
Your changing method affects the UITextView's delegate method under the hood.
In other words, it is weird that you observe UITextView's property, then do something and affect the UITextView's property,
then the observation triggers again.
to achieve this with Timer, then the height changing events is from your timer source, not from Apple's UIKit
start editing, timer run
end editing, timer gone

Scroll UIView to expand into iPhone X top notch

I have the following layout:
UIImageView
UIView (with UILabel)
UITableView
As the tableView is scrolled up, the height of the imageView is decreased before actually scrolling the tableView. The following code is used for that:
let headerImageViewMaxHeight: CGFloat = 200
let headerImageViewMinHeight: CGFloat = UIApplication.shared.statusBarFrame.height
#IBOutlet var headerImageViewHeightConstraint: NSLayoutConstraint!
#IBOutlet var headerImageView: UIImageView!
#IBOutlet var subtitleView: UIView!
#IBOutlet var subtitleLabel: TextLabel!
private var contentOffsetDictionary: NSMutableDictionary!
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView.isKind(of: UICollectionView.self) {
let horizontalOffset: CGFloat = scrollView.contentOffset.x
let collectionView: UICollectionView = scrollView as! UICollectionView
contentOffsetDictionary.setValue(horizontalOffset, forKey: collectionView.tag.description)
} else if scrollView == tableView {
let y: CGFloat = scrollView.contentOffset.y
let newHeaderImageViewHeight: CGFloat = headerImageViewHeightConstraint.constant - y
if newHeaderImageViewHeight > headerImageViewMaxHeight {
headerImageViewHeightConstraint.constant = headerImageViewMaxHeight
} else if newHeaderImageViewHeight < headerImageViewMinHeight {
headerImageViewHeightConstraint.constant = headerImageViewMinHeight
} else {
headerImageViewHeightConstraint.constant = newHeaderImageViewHeight
scrollView.contentOffset.y = 0
}
}
}
The following two images shown the current states of scrolled down or up:
Scrolled down (initial state).
Scrolled up.
As you can see, initially the grey bar saying To Table -> Table 1 is scrolled down and is about 60 high.
When it's scrolled up, it scrolles until the safeArea. What I want to achieve is that once it reaches the safe area, it continues scrolling up into the safeArea (top notch), while keeping the text in exactly the same place (topSpace to safeArea of the text should stay the same). So, basically growing the UIView to go into the safeArea.
This image shows the ViewController layout.
Header View can be ignored, as that is aligned to the top of the viewController, but no constraints to anything else than superView.
TopSpace of the view in question, is 0 to the UIImageView.
Changing headerImageViewMinHeight to 0, makes it scroll up to the actual top of the screen, without expanding it. So this seems like a good start, but needs some extra logic or constraints.
As the UIView doesn't have a specific height constraint, changing its UILabel's top space from = 16 to => 16, there's the warning of missing Y constraint or height.
Otherwise that, together with UILabel's top space to the viewController's safeArea of => 8 sounds like it could work.
Any ideas are welcome.
EDIT: The following picture basically shows what I want, except that here the UILabel's top is not aligned to the safe area.
What this picture shows is achieved by changing headerImageViewMinHeight to 0.
Add constriant
Uncheck constraint to margin
double click on Align bottom/ Align top
click on last baseline (for bottom)/ first baseline (for top constrraint)
DONE

Custom header content animate while scrolling in swift

I have created custom header but I don't know how to animate while scrolling.
Please check below image and let me know how to animate while scrolling.
This animated header in Fotmob app.
First of all add header view as UIvVew and add UIScrollView or UITableView below headerView same as screenshot and follow below step.
set a fixed height constraint to the header view (125 for example) and attach it to top, left and right.
make the UIScrollView below to use all the available space so set to zero top, bottom, left and right constraints.
 connect the header view height constraint to the ViewController in order to have something like:
#IBOutlet var headerViewHeightConstraint: NSLayoutConstraint!
set the UIScrollView delegate to the ViewController
declare two properties to limit the maximum and the minimum height of the header view, fox example:
let headerViewMaxHeight: CGFloat = 125
let headerViewMinHeight: CGFloat = 44 + UIApplication.shared.statusBarFrame.height
The entire workaround is based on update the header view height constraint while the UIScrollView is scrolling, so let’s implement the UIScrollViewDelegate and the most important delegate for our case, the scrollViewDidScroll:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let headerViewMinHeight: CGFloat = 44 + UIApplication.shared.statusBarFrame.height
let yPos = mainScrollView.contentOffset.y
let newHeaderViewHeight: CGFloat = headerViewHeightConstraint.constant - yPos
if newHeaderViewHeight > headerViewMaxHeight {
// Here, Manage Your Score Format View
headerViewHeightConstraint.constant = max(headerViewMaxHeight, newHeaderViewHeight)
} else if newHeaderViewHeight < headerViewMinHeight {
headerViewHeightConstraint.constant = headerViewMinHeight
} else {
headerViewHeightConstraint.constant = newHeaderViewHeight
scrollView.contentOffset.y = 0 // block scroll view
}
}
I have created the same, Check the below image
Overview
TableView
Sample MVVM pattern
Swift 5.0 above
Xcode 11 above
Find the GIT URL for code
HeaderAnimation

Resize textField Based On Content

How can a textField be resized based on content while using auto-layout in an iOS application written in Swift?
The text field will resize as necessary to fit its content when the view loads as well as while the user is typing.
Ideally, the text field would stop resizing at a certain point, say, 6 lines, and become scrollable.
You have to use an UITextView instead of an UITextField.
Then, you can use the sizeThatFits method.
But first you have to know how high one line will be. You can get that information by using lineHeight:
var amountOfLinesToBeShown: CGFloat = 6
var maxHeight: CGFloat = yourTextview.font.lineHeight * amountOfLinesToBeShown
After that, just call the sizeThatFits method inside your viewDidLoad method and set the maxHeight (line * 6) as your textview height:
yourTextview.sizeThatFits(CGSizeMake(yourTextview.frame.size.width, maxHeight))
Swift 3
var textView : UITextView!
override func viewDidLoad() {
super.viewDidLoad()
textView = UITextView()
textView.sizeThatFits(CGSize(width: textView.frame.size.width, height: textView.frame.size.height))
}

Xcode 6 Swift cannot input into textfield on scrollview

This is my first time doing Xcode swift project, so please bear with me. I am trying to add a scroll view onto my input page. But after putting the text field on the scroll view, I cannot input anything on the text field any more. Please help me.
import UIKit
class AddInfoViewController: UIViewController, UIScrollViewDelegate {
#IBOutlet var scrollView: UIScrollView!
var containerView2: UIView!
#IBOutlet var test2: UITextField!
#IBOutlet var test1: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
let containerSize = CGSize(width: 300.0, height: 1000.0)
containerView2 = UIView(frame: CGRect(origin: CGPoint(x: 0, y: 0), size:containerSize))
scrollView.addSubview(containerView2)
//set up the minimum & maximum zoom scales
let scrollViewFrame = scrollView.frame
let scaleWidth = scrollViewFrame.size.width / scrollView.contentSize.width
let scaleHeight = scrollViewFrame.size.height / scrollView.contentSize.height
let minScale = min(scaleWidth, scaleHeight)
scrollView.minimumZoomScale = minScale
scrollView.maximumZoomScale = 1.0
scrollView.zoomScale = 1.0
}
I think your ScrollView is covering all the things on your ViewController Like this way :
And you have to arrange it like this :
May be this can help you.
Are You Adding textField in storyboard or programmatically?
i think if you are adding scrollView Programmatically Then You also have to add textfield Programmatically! Or ScrollView Override UITextField Objects in storyBoard!
///////// if You Are Adding Scroll View in Xib ////////////////
in xib Click on "Show Document Outline"(on left Bottom Corner)!
Check
View
ScrollView
Round Style Text Field
Round Style Text Field
This shows that Your textField Are on ScrollView!
if You have it like this
View
Round Style Text Field
Round Style Text Field
ScrollView
Then Your TextField Are Override By Scroll View!

Resources