In my tableHeaderView I have a UILabel that is resizing based on its text. With some text it works, with other text it does not.
Not working example: There's no twelve
Working example: Everything there from one to fifteen
Here's the code I use:
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.delegate = self
self.tableView.dataSource = self
self.testLabel.preferredMaxLayoutWidth = self.tableView.frame.width - 30.0
self.headerView = self.tableView.tableHeaderView
self.tableView.tableHeaderView = nil
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
guard self.tableView.tableHeaderView == nil else { return }
self.headerView.setNeedsUpdateConstraints()
self.headerView.updateConstraintsIfNeeded()
self.headerView.frame = CGRect(x: 0, y: 0, width: tableView.bounds.width, height: CGFloat.greatestFiniteMagnitude)
var newFrame = self.headerView.frame
self.headerView.setNeedsLayout()
self.headerView.layoutIfNeeded()
let newSize = self.headerView.systemLayoutSizeFitting(UILayoutFittingCompressedSize)
newFrame.size.height = newSize.height
self.tableHeaderHeight = newSize.height
self.headerView.frame = newFrame
self.tableView.tableHeaderView = self.headerView
}
Related
I'm trying to zoom an image that is inside a UIScrollView, and that UIScrollView it's inside of a root UIScrollView that allow paging, similar to the Photos app.
In the viewDidLoad() inside the view that contains the root scrollView I call prepareScrollView()
func prepareScrollView(){
let tap = UITapGestureRecognizer(target: self, action: #selector(hideNavigationItem))
scrollView.addGestureRecognizer(tap)
scrollView.delegate = self
scrollView.minimumZoomScale = 1.0
scrollView.maximumZoomScale = 4.0
scrollView.zoomScale = 1.0
let width = self.view.bounds.width
let height = self.view.bounds.height
totalWidth = width * CGFloat((imageArray!.count)!) //The width must be the width of the screen by the number of the images in the array
scrollView.contentSize = CGSize(width: totalWidth, height: height)
scrollView.isPagingEnabled = true
loadPages()
}
The loadPages() function load every scrollView with their image and add it to the root scrollview.
func loadPages(){
for i in 0...((imageArray!.count)! - 1){
let pageScroll = Page(frame: CGRect(x: self.view.bounds.size.width * CGFloat(i), y: self.view.frame.origin.y, width: self.view.bounds.size.width, height: self.view.bounds.size.height))
pageScroll.minimumZoomScale = 1.0
pageScroll.maximumZoomScale = 4.0
pageScroll.zoomScale = 1.0
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: self.view.bounds.size.width, height: self.view.bounds.size.height))
imageView.image = UIImage(data: (imageArray![i])!)
imageView.contentMode = .scaleToFill
pageScroll.addSubview(imageView)
scrollView.addSubview(pageScroll)
}
}
The Page object it's just a UIScrollView object.
class Page: UIScrollView {
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return self.subviews[0]//Return the image
}
}
And inside the root scrollView viewForZooming function it calls the viewForZooming function of the correspond child scrollview.
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
if(self.scrollView.subviews.count > 0){
let childScrollView = self.scrollView.subviews[currentPage] as! Page
let image = childScrollView.viewForZooming(in: scrollView)
return image
}
return nil
}
With this approach I can navigate horizontally but I can't zoom in the current image. The viewForZooming function executes in both objects. What I'm doing wrong?
Finally I solve my issue. I changed the Page object to a simple UIScrollView and then set the delegate of the scrollView object to self.
func loadPages(){
for i in 0...((comic?.comicsPages!.count)! - 1){
let pageScroll = UIScrollView(frame: CGRect(x: self.view.bounds.size.width * CGFloat(i), y: self.view.frame.origin.y, width: self.view.bounds.size.width, height: self.view.bounds.size.height))
pageScroll.minimumZoomScale = 1.0
pageScroll.maximumZoomScale = 4.0
pageScroll.zoomScale = 1.0
pageScroll.isUserInteractionEnabled = true
pageScroll.delegate = self //Here
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: self.view.bounds.size.width, height: self.view.bounds.size.height))
imageView.image = UIImage(data: (imageArray![i])!)
imageView.contentMode = .scaleToFill
pageScroll.addSubview(imageView)
scrollView.addSubview(pageScroll)
}
}
And then in the viewForZooming function of the root scrollView I change the code for this:
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
if(scrollView.subviews.count > 0){
return scrollView.subviews[0]
}
return nil
}
The scrollView parameter is the child scrollview so it works as expected.
I am trying to make a page control associated with an image array. I had it setup correctly just changing the background color and load in the initial image, but when I scroll nothing further is shown. Here is my code:
var images: [UIImage] = [
UIImage(named: "slide1.png")!,
UIImage(named: "loginButton.png")!,
UIImage(named: "slide1.png")!,
UIImage(named: "slide1.png")!
]
func setPageViewinScroll() {
for index in 0..<4 {
frame.origin.x = self.scrollView.frame.size.width * CGFloat(index)
frame.size = self.scrollView.frame.size
self.scrollView.pagingEnabled = true
self.imageView.image = images[index]
let subview = UIView(frame: frame)
self.scrollView.addSubview(subview)
}
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * 4, self.scrollView.frame.size.height)
pageControl.addTarget(self, action: Selector("changePage:"), forControlEvents: UIControlEvents.ValueChanged)
}
func changePage(sender: AnyObject) -> () {
let x = CGFloat(pageControl.currentPage) * scrollView.frame.size.width
scrollView.setContentOffset(CGPointMake(x, 0), animated: true)
}
Does anyone know where I am going wrong here?
How about adding your UIImageview to UIScrollview instead of UIView like this code?
var imageOne:UIImageView!
var imageTwo:UIImageView!
var imageThree:UIImageView!
var imageFour:UIImageView!
func functionCalledFromViewDidLoad() {
scrollView.frame = CGRectMake(0, 0, self.view.frame.width,self.view.frame.height)
let scrollViewWidth = scrollView.frame.width
let scrollViewHeight = scrollView.frame.height
imageOne = UIImageView(frame: CGRectMake(0, 0,scrollViewWidth, scrollViewHeight))
imageTwo = UIImageView(frame: CGRectMake(scrollViewWidth*1, 0,scrollViewWidth, scrollViewHeight))
imageThree = UIImageView(frame: CGRectMake(scrollViewWidth*2, 0,scrollViewWidth, scrollViewHeight))
imageFour = UIImageView(frame: CGRectMake(scrollViewWidth*3, 0,scrollViewWidth, scrollViewHeight))
scrollView.addSubview(imageOne)
scrollView.addSubview(imageTwo)
scrollView.addSubview(imageThree)
scrollView.addSubview(imageFour)
}
override func viewDidLayoutSubviews() {
scrollView.contentSize = CGSizeMake(scrollView.frame.width * 4, scrollView.frame.height)
imageOne.frame.size.height = scrollView.frame.height
imageTwo.frame.size.height = scrollView.frame.height
imageThree.frame.size.height = scrollView.frame.height
imageFour.frame.size.height = scrollView.frame.height
}
You also seem to need to add this code.
func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
// Test the offset and calculate the current page after scrolling ends
let pageWidth:CGFloat = CGRectGetWidth(scrollView.frame)
let currentPage = Int(floor((scrollView.contentOffset.x-pageWidth/2)/pageWidth)+1)
// Change the page indicator
self.pageControl.currentPage = Int(currentPage)
}
There is a very good tutorial related to this topic, here
You are setting the image on the imageView and not on the subView. I.o.w. You are adding the subview to each page, but not setting the image on it.
Change the subview code to the following
let subview = UIImageView(frame: frame)
subview.image = images[index]
self.scrollView.addSubview(subview)
Swift(iOS) problem: how can I insert UIImage array to subview? I wanted to make a horizontal scroll view in view controller with very little experience with swift. Here is the code:
override func viewDidLoad() {
super.viewDidLoad()
configurePageControl()
var pictures:[UIImage] = [ ]
pictures.append(UIImage(named: "SOVERMENT1.jpg")!)
pictures.append(UIImage(named: "SOVERMENT2.jpg")!)
pictures.append(UIImage(named: "SOVERMENT3.jpg")!)
pictures.append(UIImage(named: "SOVERMENT4.jpg")!)
scrollView.delegate = self
self.view.addSubview(scrollView)
for index in 0..<4 {
frame.origin.x = self.scrollView.frame.size.width * CGFloat(index)
frame.size = self.scrollView.frame.size
self.scrollView.pagingEnabled = true
var subView = UIView(frame: frame)
**subView.backgroundColor = [UIColor colorWithPatternImage : ]**
self.scrollView.addSubview(subView)
}
This is first problem. How can I insert pictures into subview.backgroundColor? I searched it for 1~2hours, but I couldn't find any answer.
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * 4, self.scrollView.frame.size.height)
pageControl.addTarget(self, action: Selector("changePage:"), forControlEvents: UIControlEvents.ValueChanged)
}
func configurePageControl() {
** self.pageControl.numberOfPages = pictures.count **
self.pageControl.currentPage = 0
And here. Why array pictures cannot be counted?
Unless these are repeatable pattern images, I think you want to use a UIImageView. I also don't think you need to use a UIPageControl, because you're only using one UIViewController. You can say something like:
override func viewDidLoad() {
super.viewDidLoad()
var pictures:[UIImage] = [ ]
pictures.append(UIImage(named: "SOVERMENT1.jpg")!)
pictures.append(UIImage(named: "SOVERMENT2.jpg")!)
pictures.append(UIImage(named: "SOVERMENT3.jpg")!)
pictures.append(UIImage(named: "SOVERMENT4.jpg")!)
self.scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * CGFloat(pictures.count), scrollView.frame.size.height)
for index in 0..<pictures.count {
var frame = CGRectZero
frame.origin.x = scrollView.frame.size.width * CGFloat(index)
frame.size = scrollView.frame.size
scrollView.pagingEnabled = true
var subView = UIImageView(frame: frame)
subView.image = pictures[index]
subView.contentMode = .ScaleAspectFit
self.scrollView.addSubview(subView)
}
}
You better use UICollectionView for such purposes
For setting the backgroundColor call the UIColor initializer:
for picture in pictures {
subView.backgroundColor = UIColor(patternImage: picture)
}
I have a table view where rows are populated with data from an array.
Row height is set dynamically in viewDidLoad() by calling this function:
func configureTableView() {
/* When you set the rowHeight as UITableViewAutomaticDimension, the table view knows to use the auto layout constraints to determine each cell’s height. This also reuqires a estimetedRowHeoght, an arbitary number */
println("Configure Table View called")
tableView.estimatedRowHeight = 74.0;
tableView.rowHeight = UITableViewAutomaticDimension;
tableView.separatorStyle = UITableViewCellSeparatorStyle.None;
}
The data to populate each row is loading into arrays aysnrounscly from Parse.
Once data is loaded into arrays I then call:
self.tableView.reloadData();
self.configureTableView();
... in order to reload table row data and then re-conguire the row height dynamically, according to size of comments populating label within a row.
Problem is two fold:
Only some rows have the height set dynamically, other rows the row height appears to be fixed you can't view the comments if more than one line
When user scrolls the tableview, the refreshed view all rows are static, none appear to have height set dynamically, only one line of comment can be seen.
Any input appreciated
I am also using a footer view which is created programmictally with code to allow fro showing and hiding the keyboard, i think this may of something to do with it ....
// viewDidlOad
/* Setup the keyboard notifications so does not block textview for adding comments */
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyBoardWillShow:", name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyBoardWillHide:", name: UIKeyboardWillHideNotification, object: nil)
/* Setup the contentInsets fo keyboard */
self.tableView.contentInset = UIEdgeInsetsZero
self.tableView.scrollIndicatorInsets = UIEdgeInsetsZero
self.edgesForExtendedLayout = UIRectEdge.None
/* Make sure the content doesn't go below tabbar/navbar */
self.extendedLayoutIncludesOpaqueBars = true
self.automaticallyAdjustsScrollViewInsets = false
Apologies in advance but Allot of code here for setting up footer view and handling user input....
func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
footerView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.bounds.width, height: FOOTERHEIGHT))
footerView?.backgroundColor = UIColor(red: 243.0/255, green: 243.0/255, blue: 243.0/255, alpha: 1)
commentView = UITextView(frame: CGRect(x: 10, y: 5, width: tableView.bounds.width - 80 , height: 40))
commentView?.backgroundColor = UIColor.whiteColor()
commentView?.textContainerInset = UIEdgeInsetsMake(5, 5, 5, 5)
commentView?.layer.cornerRadius = 2
commentView?.scrollsToTop = true
footerView?.addSubview(commentView!)
let button = UIButton(frame: CGRect(x: tableView.bounds.width - 65, y: 10, width: 60 , height: 30))
button.setTitle("Reply", forState: UIControlState.Normal)
button.backgroundColor = UIColor(red: 155.0/255, green: 189.0/255, blue: 113.0/255, alpha: 1)
button.layer.cornerRadius = 5
button.addTarget(self, action: "reply", forControlEvents: UIControlEvents.TouchUpInside)
footerView?.addSubview(button)
commentView?.delegate = self
return footerView
}
func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
if self.footerView != nil {
return self.footerView!.bounds.height
}
return FOOTERHEIGHT
func keyBoardWillShow(notification: NSNotification) {
// Called in viewDidlOad, make sure keyoard doe snot cover add comments textview in table voew footer
var info:NSDictionary = notification.userInfo!
var keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as NSValue).CGRectValue()
var keyboardHeight:CGFloat = keyboardSize.height - 40
var animationDuration:CGFloat = info[UIKeyboardAnimationDurationUserInfoKey] as CGFloat
var contentInsets: UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardHeight, 0.0);
self.tableView.contentInset = contentInsets
self.tableView.scrollIndicatorInsets = contentInsets
}
func keyBoardWillHide(notification: NSNotification) {
//As above
self.tableView.contentInset = UIEdgeInsetsZero
self.tableView.scrollIndicatorInsets = UIEdgeInsetsZero
}
func textViewDidChange(textView: UITextView) {
// Allow for dynamic changing if TableView Footer textview size when commenst added
if (contentHeight == 0) {
contentHeight = commentView!.contentSize.height
}
if(commentView!.contentSize.height != contentHeight && commentView!.contentSize.height > footerView!.bounds.height) {
UIView.animateWithDuration(0.2, animations: { () -> Void in
let myview = self.footerView
println(self.commentView!.contentSize.height)
println(self.commentView?.font.lineHeight)
let newHeight : CGFloat = self.commentView!.font.lineHeight
let myFrame = CGRect(x: myview!.frame.minX, y: myview!.frame.minY - newHeight , width: myview!.bounds.width, height: newHeight + myview!.bounds.height)
myview?.frame = myFrame
let mycommview = self.commentView
let newCommHeight : CGFloat = self.commentView!.contentSize.height
let myCommFrame = CGRect(x: mycommview!.frame.minX, y: mycommview!.frame.minY, width: mycommview!.bounds.width, height: newCommHeight)
mycommview?.frame = myCommFrame
self.commentView = mycommview
self.footerView = myview
for item in self.footerView!.subviews {
if(item.isKindOfClass(UIButton.self)){
let button = item as UIButton
let newY = self.footerView!.bounds.height / 2 - button.bounds.height / 2
let buttonFrame = CGRect(x: button.frame.minX, y: newY , width: button.bounds.width, height : button.bounds.height)
button.frame = buttonFrame
}
}
})
println(self.footerView?.frame)
println(self.commentView?.frame)
contentHeight = commentView!.contentSize.height
}
}
func reply() {
// When Add button clicked in custom TabkeView Footer
println("User added comment: \(commentView?.text)");
self.commentView?.resignFirstResponder()
//userComments = commentView!.text;
//addComment();
self.tableView.reloadData()
//self.configureTableView();
}
I need to put my tab bar at the top of the screen.
I've tried and I did, this is the code:
override func viewDidLoad() {
self.tabBar.frame = CGRectMake(0, 90, self.view.bounds.size.width, self.view.bounds.size.height);
self.tabBar.autoresizingMask = UIViewAutoresizing.FlexibleWidth
}
the problem is I when I turn the screen of my device.
I should regenerate the layout and change in this way:
self.tabBar.frame = CGRectMake(0, 80, self.view.bounds.size.width, self.view.bounds.size.height);
How can I change this every time you turn the screen?
EDIT:
New Code:
override func viewDidLayoutSubviews()
{
//check tabBar not null
if (self.tabBar != nil)
{
//make changes in frame here according to orientation if any
self.tabBar.frame = CGRect(x: 00, y: 20, width:self.view.bounds.size.width, height: 49)
}
}
override func viewDidLoad()
{
//Make changes in frame according to your requirement
self.tabBar.frame = CGRectMake(0, 20, self.view.bounds.size.width,49);
//resizing here
self.tabBar.autoresizingMask = UIViewAutoresizing.FlexibleTopMargin;UIViewAutoresizing.FlexibleLeftMargin;UIViewAutoresizing.FlexibleWidth;UIViewAutoresizing.FlexibleRightMargin;
}
Define UITabBar in viewDidLoad
override func viewDidLoad()
{
//Make changes in frame according to your requirement
self.tabBar.frame = CGRectMake(0, 20, self.view.bounds.size.width,49);
//resizing here
self.tabBar.autoresizingMask = UIViewAutoresizing.FlexibleTopMargin;UIViewAutoresizing.FlexibleLeftMargin;UIViewAutoresizing.FlexibleWidth;UIViewAutoresizing.FlexibleRightMargin;
}
Add below method viewDidLayoutSubviews
override func viewDidLayoutSubviews()
{
//check tabBar not null
if (self.tabBar != nil)
{
//make changes in frame here according to orientation if any
self.tabBar.frame = CGRect(x: 00, y: 20, width:self.view.bounds.size.width, height: 49)
}
}