Swift - Adjust size on separator of UITableViewCell - ios

I have at problem with my cells in a UITableView. I have used the Attribute Inspector to adjust the size. Like this:
But the adjustment only applied on the cells with content. How do I make the separator to be the same size for the whole tableview using Swift or the Attribute Inspector?

For your question, you can try this
tableView.tableFooterView = UIView()
Another way you can do like this.
Then,
In cellForRowAtIndexPath
tableView.separatorStyle = .none
let horizontalGap = 15.0 as CGFloat
// As you want to have equal gaping in left & right side, you have to position the view's origin.x to the constant and have to have the width minus the double of that constant.
let seperatorView = UIView(frame: CGRect(x: horizontalGap, y: cell.frame.size.height - 1, width: cell.frame.size.width - horizontalGap * 2.0, height: 1))
seperatorView.backgroundColor = UIColor.red
cell.addSubview(seperatorView)
In Storyboard
Change Separator as None in Attributes Inspector. Drag UIView and place it inside your cell . Give constraints like, Leading 15, Trailing 15, Bottom 0 and height 1. Change background color to red

Related

How to change the height of the UISegmentedControl? [duplicate]

This question already has answers here:
iOS: change the height of UISegmentedcontrol
(16 answers)
Closed 3 years ago.
I am using an UISegmentedControl in an UITableView as follows-
let segmentedControl = UISegmentedControl(items: ["Segment1", "Segment2"])
tableView.tableHeaderView = segmentedControl
The above code works as expected. I would like to change the height of the UISegmentedControl. I tried to set a height constraint on the UISegmentedControl as follows-
let segmentedControl = UISegmentedControl(items: ["Segment1", "Segment2"])
segmentedControl.translatesAutoresizingMaskIntoConstraints = false
segmentedControl.heightAnchor.constraint(equalToConstant: 50).isActive = true
tableView.tableHeaderView = segmentedControl
When the above code is run, the height of the UISegmentedControl is set to the expected custom height. However, the leading and trailing edges of the UISegmentedControl do not snap to the leading and trailing edges of the UITableView.
I also tried to create a custom UISegmentedControl to specify the height of the UISegmentedControl without setting a height constraint as follows-
class CustomSegmentedControl: UISegmentedControl {
override var intrinsicContentSize: CGSize {
return CGSize(width: super.intrinsicContentSize.width, height: 50)
}
}
The above code does not work as expected. Can anyone point out how to set the height of the UISegmentedControl so that it appears as expcted when used in UITableView?
By setting segmentedControl.translatesAutoresizingMaskIntoConstraints = false you're losing the default constraints.
If you are happy with the appearance and layout of the segmented control, you just want to change its height, try this approach:
// probably in
override func viewDidLoad() {
super.viewDidLoad()
let segmentedControl = UISegmentedControl(items: ["Segment1", "Segment2"])
segmentedControl.frame.size.height = 50.0
tableView.tableHeaderView = segmentedControl
}
Same question as this:
iOS: change the height of UISegmentedcontrol
By the way, you can also change the scale by changing views transform.
var segmentedControl = UISegmentedControl(frame: CGRect(x: 0, y: 0, width: w, height: h))
segmentedControl.transform = CGAffineTransform(scaleX: x, y: y)
Just set the frame to tableView.tableHeaderView. Don't use constraints.
tableView.tableHeaderView?.frame.size.height = 50

Image adding in a Custom TableView

Is it possible to design the below UI using tableview ?
I know, I can define numberOfSections in the tableview. In each cell, I can define number of column. But, i am not sure how to add the image in the tableView ? What i understand is the image will be on the right side merging some cells. But how to do it or is it possible or not ?
Any help will be highly appreciated.
You will not be able to add an image to those 4 cells at once.
As I see it, there are two options:
create a single cell for those 4 cells, in which use UIStackViews or just autolayout to lay the contents out along with the image.
Change the tableView to a collectionView with custom layout implementation, then you can have the image as a single cell laid out to the right of those cells.
I myself would chose the first approach, because I believe it will be easier and faster to implement.
Yeah its possible. You need to do some calculation for Y Position, trailing space from tableview, etc
Add your image view into tableView.
let imageWidth: CGFloat = 150.0
let imageHeight: CGFloat = 150.0 //Addition of height of meging cells
let trailingSpace: CGFloat = 25.0
let yPosition: CGFloat = 100 //Calculate Y position depend on NavigationBar, Name cell, etc...
let imgView = UIImageView(frame: CGRect(x: view.frame.width - imageWidth - trailingSpace, y: yPosition, width: imageWidth, height: imageHeight))
imgView.backgroundColor = .clear
imgView.image = UIImage(named: "Waterfall")
imgView.contentMode = .scaleAspectFit
tableView.addSubview(imgView)

How to add a 10px space around a tableViewCell?

I'm trying to create a tableViewCell with a 10px spacing around it so the cell doesn't touch the edges of the screen. I tried doing something like this I saw on another stackOverflow post in my cellForRowAtIndexPath but all I got was a black screen once I ran it in simulator:
cell.contentView.backgroundColor = UIColor.white
let whiteRoundedView : UIView = UIView(frame: CGRect(x: 10, y: 10, width: self.view.frame.size.width - 20, height: 188))
whiteRoundedView.layer.backgroundColor = CGColor(colorSpace: CGColorSpaceCreateDeviceRGB(), components: [1.0, 1.0, 1.0, 0.8])
whiteRoundedView.layer.masksToBounds = false
whiteRoundedView.layer.cornerRadius = 10
cell.contentView.addSubview(whiteRoundedView)
cell.contentView.sendSubview(toBack: whiteRoundedView)
I think that it's better assign this 10px from storyboard (or xib).
You can insert a leading space constraint in your UIView (designed in your tableViewCell).
So automatically you no longer work with frames that which often gives problem...
You should bring your whiteRoundedView to the front of the contentView. Right now the whiteRoundedView is behind the cell's contentView.
cell.contentView.bringSubview(toFront: whiteRoundedView)

Updating UICollectionViewFlowLayout when the height of my CollectionView changes during runtime

I have a MyCollectionView that has a constraint that is:
BottomLayoutGuide.Top = MyCollectionView.Bottom + 100
In my IB, but this constraint's constant changes according to the height of the keyboard
func keyboardWillShow(notification: NSNotification) {
let keyboardHeight = getKeyboardHeight(notification)
keyboardHeightConstraint.constant = keyboardHeight + 20
self.cardCollectionView.configureCollectionView()
self.cardCollectionView.reloadInputViews()
}
Where configureCollectionView is:
func configureCollectionView() {
self.backgroundColor = UIColor.clearColor()
// Create the layout
let space = 10.0 as CGFloat
let flowLayout = UICollectionViewFlowLayout()
let width = (self.frame.size.width) - 4 * space
let height = (self.frame.size.height)
let edgeInsets = UIEdgeInsetsMake(0, 2 * space, 0, 2 * space)
// Set top and bottom margins if scrolling horizontally, left and right margins if scrolling vertically
flowLayout.minimumLineSpacing = space
flowLayout.minimumInteritemSpacing = 0
// Set horizontal scrolling
flowLayout.scrollDirection = .Horizontal
// Set edge insets
flowLayout.sectionInset = edgeInsets
flowLayout.itemSize = CGSizeMake(width, height)
print(self.frame)
print(flowLayout.itemSize)
self.setCollectionViewLayout(flowLayout, animated: true)
// Always allow it to scroll
self.alwaysBounceHorizontal = true
}
Before the keyboard is shown, everything is fine and these are the values of the frame of MyCollectionView and it's CollectionViewCell
self.frame: (0.0, 75.0, 375.0, 492.0)
flowLayout.itemSize: (335.0, 492.0)
But after the keyboard is shown and configureCollectionView() is called which basically just resets the flowLayout for MyCollectionView everything breaks. And oddly, even though the height of MyCollectionView has decreased the console outputs says that it has actually increased.
self.frame: (0.0, 55.0, 375.0, 512.0)
flowLayout.itemSize: (335.0, 512.0)
Here is a screenshot after the keyboard has appeared:
As you can see, it seems like the CollectionViewCells are being clipped and it has lost it's initial alpha value. Moreover, after randomly scrolling the console outputs:
2016-04-29 09:43:24.012 DeckWheel[15363:2028073] the behavior of the UICollectionViewFlowLayout is not defined because:
2016-04-29 09:43:24.012 DeckWheel[15363:2028073] the item height must be less than the height of the UICollectionView minus the section insets top and bottom values, minus the content insets top and bottom values.
I know that this is due to the height of MyCollectionView changing but, I don't know why it is going wrong as everything works perfectly before the keyboard shows. For example, I can scroll randomly between the cells and if I get to the last cell it will automatically create a new one without any crashes.
I've tried MyCollectionView.invalidateLayout() and then callingconfigureCollectionView() to reset the flowLayout but nothing seems to work. What is the correct way to update MyCollectionView so that this does not happen?

How to create percentage of total width using autolayout?

I need to create three dynamic columns, each with a fixed percentage of the total width. Not thirds, but different values. For example, the following illustration shows three columns: the first being 42% wide, the second being 25% wide, and the third being 33% wide.
For a 600 pixel across viewcontroller, that would be 252, 150, and 198 pixels respectively.
However, for any subsequent display sizes (i.e. iPhone 4 landscape (960 wide) or iPad 2 portrait (768 wide), I would like the relative percentages to be the same (not the pixel widths quoted above).
Is there a way to do this using Storyboards (i.e. without code)? I can do this easily in code, but my goal is to put as much of this display logic as possible into the Storyboard.
If, as you say, you know how to do it in code, then you already know how to do it in the storyboard. It's exactly the same constraints, but you are creating them visually rather than in code.
Select both a view and its superview.
Choose Editor -> Pin -> Widths Equally to constrain the width to be equal to the superview's width (actually the "pin" popup dialog at the bottom of the canvas works best here).
Edit the constraint and set the Multiplier to the desired fraction, e.g. 0.42. And so too for the other views.
As Apple introduces UIStackView it made job much easy.
Method 1: Using Nib/StoryBoard:
You have to just add three view in interface builder & embed them into stackview
Xcode ► Editor ► Embed in ► StackView
Select stackView & give constraint with leading, trailing, top & equal height with safeArea
Click to Attribute inspector area &
Set StackView horizontal & distribution to fill proportionally
[3
Give constraint of three view with leading, trailing, top, bottom with respective of sides.
Method 2: Programmatically:
import UIKit
class StackViewProgramatically: UIViewController {
var propotionalStackView: UIStackView!
///Initially defining three views
let redView: UIView = {
let view = UIView()//taking 42 % initially
view.frame = CGRect(x: 0, y: 0, width: 42 * UIScreen.main.bounds.width/100, height: UIScreen.main.bounds.height)
view.backgroundColor = .red
return view
}()
let greenView: UIView = {
let view = UIView()//taking 42* initially
view.frame = CGRect(x: 42 * UIScreen.main.bounds.width/100, y: 0, width: 25 * UIScreen.main.bounds.width/100, height: UIScreen.main.bounds.height)
view.backgroundColor = .green
return view
}()
let blueView: UIView = {
let view = UIView()//taking 33*initially
view.frame = CGRect(x: 67 * UIScreen.main.bounds.width/100, y: 0, width: 33 * UIScreen.main.bounds.width/100, height: UIScreen.main.bounds.height)
view.backgroundColor = .blue
return view
}()
///Changing UIView frame to supports landscape mode.
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
DispatchQueue.main.async {
self.redView.frame = CGRect(x: 0, y: 0, width: 42 * self.widthPercent, height: self.screenHeight)
self.greenView.frame = CGRect(x: 42 * self.widthPercent, y: 0, width: 25 * self.widthPercent, height: self.screenHeight)
self.blueView.frame = CGRect(x: 67 * self.widthPercent, y: 0, width: 33 * self.widthPercent, height: self.screenHeight)
}
}
override func viewDidLoad() {
super.viewDidLoad()
//Adding subViews to the stackView
propotionalStackView = UIStackView()
propotionalStackView.addSubview(redView)
propotionalStackView.addSubview(greenView)
propotionalStackView.addSubview(blueView)
propotionalStackView.spacing = 0
///setting up stackView
propotionalStackView.axis = .horizontal
propotionalStackView.distribution = .fillProportionally
propotionalStackView.alignment = .fill
view.addSubview(propotionalStackView)
}
}
//MARK: UIscreen helper extension
extension NSObject {
var widthPercent: CGFloat {
return UIScreen.main.bounds.width/100
}
var screenHeight: CGFloat {
return UIScreen.main.bounds.height
}
}
Output:
Works with landscape & portrait
Demo project - https://github.com/janeshsutharios/UIStackView-with-constraints
https://developer.apple.com/videos/play/wwdc2015/218/
I think this can be explained in more detail so it can be more easily applied to any number of views requiring fixed percentage layouts within a superview.
Left-most view
Anchored to SuperView.Leading
Defines its fixed percentage as a multiplier on the SuperView.Height
Intermediate views
Defines its fixed percentage as a multiplier on the SuperView.Height
Pins its left to its neighbor's right
Right-Most view
Does not define a fixed percentage (it is the remainder of the available view)
Pins its left to its neighbor's right
Pins its right to SuperView.Trailing
All Views
Define their non-fixed heights by anchoring to Top Layout Guide.Top and Top Layout Guide.bottom. In the answer above, it is noted that this can also be done by setting equal height to the neighboring view.

Resources