Swift: Embed a scrollView in a custom UITableViewCell - iphone

I am working on this UITableViewCell customization to get something similar to a Facebook feed look.
I need a cell to contain 2 labels followed by a scroll view(to display some images). I have tried with having these 3 elements inside a uiView as such,
-Cell
--contentView
---UIView
----Label
----Label
----ScrollView
#IBOutlet weak var dateLabel: UILabel!
#IBOutlet weak var contentLabel: UILabel!
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var cardView: UIView!
I need the cells to adjust the height based on the length of the text.
Where I am stuck at is where the cell adjusts the height based on the text, but the scrollview that is displayed, is split into two cells.
Needless to say I am new to swift. This is the basic flow of what I have so far in cellForRowAtIndexPath
cell.dateLabel.text = somedatelabel
cell.contentLabel.text = someContent
let width = cell.scrollView.frame.width
let height = cell.scrollView.frame.height
var mainCardView = UIView(frame: CGRectMake(cell.frame.origin.x, cell.frame.origin.y, cell.frame.width, cell.frame.height))
var scrollview = UIScrollView(frame: CGRectMake(cell.contentLabel.frame.origin.x, cell.contentLabel.frame.origin.y+cell.contentLabel.frame.height, width, height))
scrollview.contentSize = CGSizeMake(width*2, height)
var imageOne = UIImageView(frame: CGRectMake(0, 0, width , height))
var imageTwo = UIImageView(frame: CGRectMake(width, 0, width, height))
imageOne.image = UIImage(named: "one.jpg")
imageTwo.image = UIImage(named: "two.jpg")
scrollview.addSubview(imageOne)
scrollview.addSubview(imageTwo)
scrollview.contentSize = CGSizeMake(width*2, height)
scrollview.contentMode = UIViewContentMode.ScaleAspectFit
mainCardView.addSubview(scrollview)
cell.cardView = mainCardView
cell.contentView.addSubview(mainCardView)
cell.layoutSubviews()
cell.layoutIfNeeded()
I also added this in viewDidLoad
tableView.estimatedRowHeight = 150.0
tableView.rowHeight = UITableViewAutomaticDimension
Any suggestions on how to size the cell so that scrollView is part of the contentView?

Related

Center ImageView in ScrollView with paging enabled - Swift

I need to create a paging ScrollView which shows a sequence of images.
I created a ScrollView in the main view of the Storyboard and set this constraints (to center the ScrollView in the view):
Constraint
Then I activated paging and disabled the "Content layout guides" option.
Next, in the view class I set up the UIScrollViewDelegate delegate and I wrote the following code to show 3 images (they are 3 colored squares):
class ViewController: UIViewController, UIScrollViewDelegate {
// Outlet
#IBOutlet weak var scrollview: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
scrollview.delegate = self;
let infoArray = ["01", "02", "03"];
for i in 0..<infoArray.count {
let imageView = UIImageView();
imageView.contentMode = .scaleToFill;
imageView.image = UIImage(named: infoArray[i]);
let xPos = CGFloat(i) * scrollview.bounds.size.width;
imageView.frame = CGRect(x: xPos, y: 0, width: scrollview.bounds.size.width, height: scrollview.bounds.size.height);
imageView.layer.borderWidth = 1;
scrollview.contentSize.width = scrollview.frame.size.width * CGFloat(i+1);
scrollview.contentSize.height = scrollview.frame.size.height;
scrollview.addSubview(imageView);
}
scrollview.layer.borderWidth = 1;
}
}
I have set that the images must have the same width and height as the scrollview. But these are larger in the simulator (and in my iPhone 11) and therefore the display is incorrect. I show you the sequence of the 3 squares:
Page 1
Page 2
Page 3
Page 4
I can't understand where I'm wrong. Why don't the 3 images take the size of the scrollview?
Why are there 4 pages?
Thanks for your help
Okay, here is how you do it:
Your scrollview is created in storyboard and its layout is set. Make sure content layout guides is unchecked in the size inspector and paging is checked in the attribute inspector.
Add a stackview as a subview to your scrollview (this will act as the content view). Pin your stackView to all 4 edges of the scrollView.
Set Height and Width Equal to the scrollView height and width. Set the Width priority to 250. (that indicates that the scrollview will scroll horizontally)
Set the stackView to horizontal axis, fill alignment and fillEqually distribution.
Now, go back to viewDidLoad and add the following code below. ScrollViewContentView is the stackView that acts as a contentView for the scrollView. Note that since stackView is set to fillEqually, you only need set one of the image's width constraint.
scrollViewContentView.addArrangedSubview(image1)
scrollViewContentView.addArrangedSubview(image2)
scrollViewContentView.addArrangedSubview(image3)
image1.translatesAutoresizingMaskIntoConstraints = false
image2.translatesAutoresizingMaskIntoConstraints = false
image3.translatesAutoresizingMaskIntoConstraints = false
image1.backgroundColor = .blue
image2.backgroundColor = .yellow
image3.backgroundColor = .red
image1.widthAnchor.constraint(equalTo: scrollView.widthAnchor).isActive = true
I think you need to state the frame of the scrollview before you declare the imageViews x positions or widths.
class ViewController: UIViewController, UIScrollViewDelegate {
// Outlet
#IBOutlet weak var scrollview: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
scrollview.frame = view.frame // declared here
scrollview.delegate = self;
let infoArray = ["01", "02", "03"];
for i in 0..<infoArray.count {
let imageView = UIImageView();
imageView.contentMode = .scaleToFill;
imageView.image = UIImage(named: infoArray[i]);
let xPos = CGFloat(i) * scrollview.bounds.size.width;
imageView.frame = CGRect(x: xPos, y: 0, width: scrollview.bounds.size.width, height: scrollview.bounds.size.height);
imageView.layer.borderWidth = 1;
scrollview.contentSize.width = scrollview.frame.size.width * CGFloat(i+1);
scrollview.contentSize.height = scrollview.frame.size.height;
scrollview.addSubview(imageView);
}
scrollview.layer.borderWidth = 1;
}
}

Try to create a scrollView with labels

I'm a little new in swift. I'm trying to make a simple scrollview with a label that changes its value, but I can not get it to work properly.
This is my code:
class ConsejosController: UIViewController, UIScrollViewDelegate {
var asunto = ["value1", "value2"]
#IBOutlet weak var lbl_asunto: UILabel!
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var pageControl: UIPageControl!
var contentWidth: CGFloat = 0.0
override func viewDidLoad() {
super.viewDidLoad()
scrollView.delegate = self
for etiqueta in 0...1{
contentWidth += view.frame.width
lbl_asunto.text = asunto[etiqueta]
}
scrollView.contentSize = CGSize(width: contentWidth, height: view.frame.height)
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
pageControl.currentPage = Int(scrollView.contentOffset.x / CGFloat(375) )
}
}
This don't work properly. Directly show "value2" and don't scroll
Any advice?
I made the for cycle in this way:
for etiqueta in 0...1{
contentWidth += view.frame.width
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 21))
label.center = CGPoint(x: 160, y: 285)
label.textAlignment = .center
label.text = asunto[etiqueta]
self.scrollView.addSubview(label)
}
Now scrolling well, but show two labels 'value1' and 'value2' in the same page one over another, and the second page empty.

Customizing the UIImage View

How to programmatically change the borderWidth of a Image view which is on a UIView and present inside a prototypeCell
I have tried changing the borderWidth in interface Builder, but it is not working.1
looking forward for a better solution.2
you can try something like this
#IBOutlet weak var imageView: UIImageView!
// makes it circle if Width == Height
imageView.layer.cornerRadius = imageView.frame.width / 2
//Bordering
imageView.layer.borderColor = UIColor.black.cgColor
imageView.layer.borderWidth = 1

How to make a stretchable image view by scroll view

I have a scroll view and an imageView at the top, I want to pin and make a stretchable image view but if I add this image view to the view the image won't disappear when the user scroll down the view and if I add the image to the scroll view this won't be pinned at the top when the user scroll down.
So how can I pin the image at the top and then when the user scroll down the image will disappear.
Like that: http://blog.enabled.com.au/stretchy-layouts-on-ios/ but not with his framework.
class LocalsVC: UIViewController, UIScrollViewDelegate {
#IBOutlet weak var imageView: UIImageView!
#IBOutlet weak var scrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
setNavBarSettings()
scrollView.delegate = self
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
view.addSubview(imageView)
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let y = 300 - (scrollView.contentOffset.y + 300)
let height = min(max(y, 60), 400)
imageView.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: height)
}
Add the image to the scrollView and not to the view: scrollView.addSubview(imageView).

How to fix AutoLayout for my ScrollView?

I have a view controller that has a UIView(ParentView) and then UIScrollview(ScrollView). The ParentView is anchored to the leading, trailing, top and bottom of the ViewController. The ScrollView is anchored to the leading, trailing, top and bottom of the ParentView. The structure is like this:
-UIView
--ParentView
---ScrollView
Then I created a xib file that has an image and a label. The xib will be added dynamically to the ScrollView. The xib frame height and width are equal to the ScrollView height and width.
When I run the simulator on iphone 6 plus the scroll works perfectly; the width of the xib is exactly the width of the screen. But when i run the simulator with iphone 6, the width of the xib is the same size of the screen, there is an extra space when scrolling to the next item. What should I do to removed it!?
This is a screen shot for iphone 6 plus
This is a screen shot for iphone 6. Notice the extra space of the second screen
And here is my code:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var ParentView: UIView!
#IBOutlet weak var ScrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let photos = ["joe", "john"]
let userNames = ["joe", "john"]
self.ScrollView.frame = CGRectMake(0, 0, self.ParentView.frame.size.width, self.ParentView.frame.size.height)
self.ScrollView.contentSize = CGSizeMake(self.ParentView.frame.size.width * CGFloat(photos.count), self.ParentView.frame.size.height)
self.ScrollView.pagingEnabled = true
var i: Int = 0
while i < 2 {
if let userXib = NSBundle.mainBundle().loadNibNamed("User", owner: self, options: nil)[0] as? User {
userXib.frame = CGRect(x: self.ScrollView.frame.size.width * CGFloat(i), y: 0, width: self.ScrollView.frame.size.width, height: userXib.frame.size.height)
userXib.assignValues(photos[i], myName: userNames[i])
self.ScrollView.addSubview(userXib)
}
i = i + 1
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
UPDATE #1 - Coder1000 solution:
I tried implementing #3 & #4 in your answer by adding the UIView layer inside the scroll. I called it ScrollMainView. In the storyboard, I set its leading, trailing, top and bottom to fill its superview: Scrollview and then in the loop added those elements to it instead of the scrollview. But now the scroll doesn't scroll! My code and final display look like this:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var ParentView: UIView!
#IBOutlet weak var ScrollView: UIScrollView!
#IBOutlet weak var ScrollMainView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
let photos = ["joe", "john"]
let userNames = ["joe", "john"]
self.ScrollView.frame = CGRectMake(0, 0, self.ParentView.frame.size.width, self.ParentView.frame.size.height)
self.ScrollView.contentSize = CGSizeMake(self.ParentView.frame.size.width * CGFloat(photos.count), self.ParentView.frame.size.height)
self.ScrollView.pagingEnabled = true
self.ScrollMainView.frame = CGRectMake(0, 0, self.ScrollView.frame.size.width, self.ScrollView.frame.size.height)
print("the frame for parentview is: \(self.ParentView.frame)")
var i: Int = 0
while i < 2 {
if let userXib = NSBundle.mainBundle().loadNibNamed("User", owner: self, options: nil)[0] as? User {
userXib.frame = CGRect(x: self.ScrollMainView.frame.size.width * CGFloat(i), y: 0, width: self.ScrollMainView.frame.size.width, height: userXib.frame.size.height)
userXib.assignValues(photos[i], myName: userNames[i])
self.ScrollMainView.addSubview(userXib)
}
i = i + 1
}
self.ScrollView.addSubview(ScrollMainView)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
There are several solutions, in viewDidLoad the frame is not set correctly, so when you ask it, it is wrong.
The parentView and your scrollView are adjusted by the autolayout constraint later, but you User view is not...
A simple solution may be to put the code in:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
self.ScrollView.frame = CGRectMake(0, 0, self.ParentView.frame.size.width, self.ParentView.frame.size.height)
self.ScrollView.contentSize = CGSizeMake(self.ParentView.frame.size.width * CGFloat(photos.count), self.ParentView.frame.size.height)
self.ScrollView.pagingEnabled = true
for subView: UIView in self.ScrollView.subviews {
if subView is User { subView.removeFromSuperview()
}
var i: Int = 0
while i < 2 {
if let userXib = NSBundle.mainBundle().loadNibNamed("User", owner: self, options: nil)[0] as? User {
userXib.frame = CGRect(x: self.ScrollView.frame.size.width * CGFloat(i), y: 0, width: self.ScrollView.frame.size.width, height: userXib.frame.size.height)
userXib.assignValues(photos[i], myName: userNames[i])
self.ScrollView.addSubview(userXib)
}
i = i + 1
}
}
Or you can add constraints to your custom xib programmatically.
Or you can keep an array of your costom xibs and just adjust their frames, AND THE SCROLLVIEW CONTENTSIZE, in viewDidLayoutSubviews()
Or you can put the code in viewDidAppear()