How to set xValuePosition and yValuePosition properly in Pie Chart using Swift? - ios

I am trying to put labels outside properly and lines to point them but the lines are overlapping and labels at the sides are not displayed completely. If length of the line is increased the labels are cut completely.
This is what I'm getting now.
What I want is
Code:
`class ViewController: UIViewController{
let pieView : PieChartView = {
let set = PieChartView()
set.translatesAutoresizingMaskIntoConstraints = false
set.drawHoleEnabled = false
set.chartDescription?.text = ""
return set
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
navigationItem.title = "Pie"
setChart()
chartData()
}
let surveyData = ["cat": 20, "dog": 30, "both": 5, "neither": 45]
func setChart(){
view.addSubview(pieView)
pieView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
pieView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
pieView.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.5).isActive = true
pieView.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.5).isActive = true
}
func chartData(){
var data = [PieChartDataEntry]()
for (key,value) in surveyData{
let entry = PieChartDataEntry(value: Double(value), label: key)
data.append(entry)
}
let chart = PieChartDataSet(values: data, label: "")
chart.colors = ChartColorTemplates.material()
chart.sliceSpace = 2
chart.selectionShift = 5
chart.xValuePosition = .outsideSlice
chart.yValuePosition = .outsideSlice
chart.valueTextColor = .black
chart.valueLineWidth = 0.5
chart.valueLinePart1Length = 0.2
chart.valueLinePart2Length = 4
chart.drawValuesEnabled = true
let chartData = PieChartData(dataSet: chart)
pieView.data = chartData
}}`

Try this with your data set:
chart.selectionShift = 0

Related

Can I show all the markers using iOS charts?

Can I show all the markers without clicking on a bar?
currently, I need to tap on any of the bar and it'll only show the one that is clicked. I'm trying to add a marker on each of the green bar and showing all without any bar being clicked. Is it possible?
Edit:
Below is my code changed from the github demo code
(PillMarker came from this)
import Charts
import UIKit
class BarChartViewController: DemoBaseViewController {
#IBOutlet var chartView: BarChartView!
#IBOutlet var sliderX: UISlider!
#IBOutlet var sliderY: UISlider!
#IBOutlet var sliderTextX: UITextField!
#IBOutlet var sliderTextY: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
self.options = [.animateY]
self.setup(barLineChartView: chartView)
chartView.delegate = self
chartView.drawBarShadowEnabled = false
chartView.drawValueAboveBarEnabled = false
chartView.maxVisibleCount = 60
chartView.dragEnabled = false
chartView.scaleXEnabled = false
chartView.scaleYEnabled = false
chartView.leftAxis.drawAxisLineEnabled = false
chartView.xAxis.drawGridLinesEnabled = false
chartView.legend.enabled = false
let xAxis = chartView.xAxis
xAxis.labelPosition = .bottom
xAxis.labelFont = .systemFont(ofSize: 10)
xAxis.labelTextColor = .green
xAxis.granularity = 1
xAxis.labelCount = 7
xAxis.valueFormatter = DayAxisValueFormatter(chart: chartView)
let leftAxis = chartView.leftAxis
leftAxis.labelFont = .systemFont(ofSize: 10)
leftAxis.labelTextColor = .red
leftAxis.labelCount = 8
leftAxis.labelPosition = .outsideChart
leftAxis.spaceTop = 0.15
leftAxis.axisMinimum = 0
let l = chartView.legend
l.horizontalAlignment = .left
l.verticalAlignment = .bottom
l.orientation = .horizontal
l.drawInside = false
l.form = .square
l.formSize = 9
l.font = UIFont(name: "HelveticaNeue-Light", size: 11)!
l.textColor = .blue
l.xEntrySpace = 4
//Marker
let marker = PillMarker(color: .white, font: UIFont.boldSystemFont(ofSize: 14), textColor: .black)
chartView.marker = marker
sliderX.value = 12
sliderY.value = 50
slidersValueChanged(nil)
}
override func updateChartData() {
if self.shouldHideData {
chartView.data = nil
return
}
self.setDataCount(1, range: UInt32(sliderY.value))
}
func setDataCount(_ count: Int, range: UInt32) {
let start = 1
let yVals = (start..<start+count+1).map { (i) -> BarChartDataEntry in
let mult = range + 1
let val = Double(arc4random_uniform(mult))
return BarChartDataEntry(x: Double(i), y: val)
}
var set1: BarChartDataSet! = nil
if let set = chartView.data?.first as? BarChartDataSet {
set1 = set
set1.replaceEntries(yVals)
chartView.data?.notifyDataChanged()
chartView.notifyDataSetChanged()
} else {
set1 = BarChartDataSet(entries: yVals, label: "The year 2017")
set1.colors = ChartColorTemplates.material()
set1.highlightColor = NSUIColor(red: 46/255.0, green: 204/255.0, blue: 113/255.0, alpha: 1.0)
set1.drawValuesEnabled = false
set1.drawIconsEnabled = true
let data = BarChartData(dataSet: set1)
data.setValueFont(UIFont(name: "HelveticaNeue-Light", size: 10)!)
data.barWidth = 0.3
chartView.data = data
}
}
Yes, You can show all marker on bar.
put marker code with bar drawing code.

UIScrollView overlaps other UIElements so they are not clickable anymore

Dear StackOverflowCommunity,
im currently working on a project, where I need to make a fully dynamic user interface.
For that, im building all of it programatically to make it as easy as possible.
I've now come to a problem which is as soon as I wrap my contentView(UIStackView) with an UIScrollView to make it scrollable, the scrollView is in front of all the other UIElements so that I can only scroll. I can not interact with Buttons, Sliders, Switches or anything, no event will get triggered.
I've literally done anything I could think of (working on that Problem for DAYS) but couldn't find any suiting answer whether on google directly nor on stack overflow or apple forums.
I'm pretty sure its a pretty small change that I just wasn't capable of thinking of. I really appreciate any of your help.
Structure is like this:
ViewController > UIScrollView > UIStackView > Item Wrappers (for example contains a UISwitch and a Describing Label) > Single UIElement
On User Interaction (for example choosing a different mode) the wrappers get removed and/or added to the view as the user needs.
I did only post the code that is somehow relevant for this problem (in my opinion). If you need any further information feel free to ask.
I maybe need to add:
As soon as I remove the UIScrollView and just add the StackView (named contentView in code) to the main view it all works just fine, I just can't scroll it which is a big problem as soon as I have more than like 5 element wrappers attached to the view.
var wrappers : Dictionary<String, UIView> = [:]
var elements : Dictionary<String, [UIView]> = [:]
var constraints : Dictionary = [String: [[NSLayoutConstraint]]]()
let contentView = UIStackView()
let states = [
"state_operating_hours",
"state_dim",
"state_brightness_sensor",
"state_operating_voltage",
"state_circuit_voltage",
"state_load_current_led",
"state_output_power",
"state_temperature",
"state_error",
"state_sw_version",
"state_hw_version"
]
let checkboxes = [
"summertime_wintertime",
"dali",
"error_output"
]
let sliders = [
"immediate_sensitivity",
"immediate_dawn",
"immediate_dim",
"immediate_day",
"immediate_dusk",
"immediate_night",
"aging"
]
let textInputs = [
"module_name",
"switch_delay"
]
let dropdowns = [
"mode",
"bt_state",
"config_output"
]
let timePickers = [
"phase_0",
"phase_1",
"phase_2",
"phase_3"
]
let buttons = [
"state_trigger",
"reset_trigger",
]
let l_kind_criteria = [
"immediate_dawn",
"immediate_day",
"immediate_dusk",
"immediate_night",
"immediate_sensitivity"
]
let d_kind_criteria = [
"immediate_dim"
]
let t_kind_criteria = [
"phase_0",
"phase_1",
"phase_2",
"phase_3"
]
let m_kind_criteria = [
"immediate_dawn",
"immediate_day",
"immediate_dusk",
"immediate_night",
"immediate_sensitivity",
"phase_0",
"phase_1"
]
let user_criteria = [
//"access",
//"state_trigger",
//"reset_trigger",
"mode",
"summertime_wintertime"
]
let service_criteria = [
"module_name",
//"access",
"state_trigger",
"reset_trigger",
"mode",
"bt_state",
"config_output",
"aging",
"switch_delay",
"summertime_wintertime",
"error_output",
"dali"
]
override func viewDidLoad() {
bleService.delegate = self
bleService.requestAuthMode()
view.backgroundColor = .lightGray
bleService.send(aText: "c28r:#")
bleService.send(aText: "c05r:#")
Toast.show(message: "Statuswerte werden abgerufen..." , controller: self)
buildLayout()
}
// Class - Functions
func buildLayout() {
// Building the Basic Layout
let topView = UIView()
topView.backgroundColor = .purple
self.view.addSubview(topView)
topView.translatesAutoresizingMaskIntoConstraints = false
let logoImageView = UIImageView(image: UIImage(named: "placeholder"))
logoImageView.translatesAutoresizingMaskIntoConstraints = false
logoImageView.frame = CGRect(x: 0, y: 0, width: view.frame.width/1.8, height: 30)
topView.addSubview(logoImageView)
logoImageView.leftAnchor.constraint(greaterThanOrEqualTo: view.leftAnchor, constant: 20).isActive = true
logoImageView.topAnchor.constraint(greaterThanOrEqualTo: view.topAnchor, constant: 30).isActive = true
topView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
topView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
topView.heightAnchor.constraint(equalToConstant: view.frame.height/3).isActive = true
topView.centerYAnchor.constraint(equalTo: view.topAnchor).isActive = true
topView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
//Generate and add Scroll View to Main Window
let scrollView = UIScrollView()
scrollView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(scrollView)
NSLayoutConstraint.activate([
scrollView.topAnchor.constraint(equalTo: topView.bottomAnchor, constant: 20),
scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
scrollView.centerXAnchor.constraint(equalTo: view.centerXAnchor)
])
//Add Content Stack to Scroll View
contentView.axis = .vertical
contentView.alignment = .fill
contentView.spacing = 150
contentView.distribution = .fill
contentView.backgroundColor = .blue
contentView.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(contentView)
NSLayoutConstraint.activate([
contentView.topAnchor.constraint(equalTo: scrollView.topAnchor),
contentView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 20),
contentView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: -20),
contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
contentView.widthAnchor.constraint(equalToConstant: scrollView.frame.width),
contentView.centerXAnchor.constraint(equalTo: view.centerXAnchor)
])
// programmatically creating layout elements without constraints
// Elements that change a value are always last in their respective array
for (index, dropdownName) in dropdowns.enumerated() {
constraints[dropdownName] = [[]]
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.text = dropdownName
let leadAnch = label.leadingAnchor.constraint(equalTo: contentView.leadingAnchor)
constraints[dropdownName]!.append([leadAnch])
let textField = UITextField()
textField.delegate = self
textField.translatesAutoresizingMaskIntoConstraints = false
textField.backgroundColor = .white
textField.layer.cornerRadius = 5
var trailAnch = textField.trailingAnchor.constraint(equalTo: contentView.trailingAnchor)
var widthAnch = textField.widthAnchor.constraint(equalToConstant: view.frame.width / 6)
constraints[dropdownName]!.append([trailAnch, widthAnch])
let pickerView = UIPickerView()
pickerView.backgroundColor = .white
pickerView.translatesAutoresizingMaskIntoConstraints = false
pickerView.delegate = self
pickerView.isHidden = true
pickerView.dataSource = self
trailAnch = pickerView.trailingAnchor.constraint(equalTo: textField.trailingAnchor)
widthAnch = pickerView.widthAnchor.constraint(equalTo: textField.widthAnchor)
constraints[dropdownName]!.append([trailAnch, widthAnch])
let dropdownWrapper = UIView()
dropdownWrapper.translatesAutoresizingMaskIntoConstraints = false
dropdownWrapper.addSubview(label)
dropdownWrapper.addSubview(textField)
dropdownWrapper.addSubview(pickerView)
wrappers[dropdownName] = dropdownWrapper
elements[dropdownName] = [label, textField, pickerView]
let commandID = bleService.getCommand(commandName: dropdownName)
bleService.send(aText: "c\(commandID)r:#")
}
for (index, sliderName) in sliders.enumerated() {
constraints[sliderName] = [[]]
let descLabel = UILabel()
descLabel.translatesAutoresizingMaskIntoConstraints = false
descLabel.text = sliderName
var leadAnch = descLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor)
constraints[sliderName]!.append([leadAnch])
let valueLabel = UILabel()
valueLabel.translatesAutoresizingMaskIntoConstraints = false
valueLabel.text = "0"
valueLabel.backgroundColor = .white
let widthAnch = valueLabel.widthAnchor.constraint(equalToConstant: view.frame.width/6)
var trailAnch = valueLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor)
constraints[sliderName]!.append([trailAnch, widthAnch])
let slider = UISlider()
slider.translatesAutoresizingMaskIntoConstraints = false
slider.isContinuous = false
slider.addTarget(self, action: #selector(sliderValueChanged), for: .valueChanged)
leadAnch = slider.leadingAnchor.constraint(equalTo: contentView.leadingAnchor)
trailAnch = slider.trailingAnchor.constraint(equalTo: contentView.trailingAnchor)
let topAnch = slider.topAnchor.constraint(equalTo: descLabel.bottomAnchor, constant: 5)
constraints[sliderName]!.append([trailAnch, leadAnch, topAnch])
let sliderWrapper = UIView()
sliderWrapper.translatesAutoresizingMaskIntoConstraints = false
sliderWrapper.addSubview(descLabel)
sliderWrapper.addSubview(valueLabel)
sliderWrapper.addSubview(slider)
wrappers[sliderName] = sliderWrapper
elements[sliderName] = [descLabel, valueLabel, slider]
let commandID = bleService.getCommand(commandName: sliderName)
bleService.send(aText: "c\(commandID)r:#")
}
for (index, checkboxName) in checkboxes.enumerated() {
constraints[checkboxName] = [[]]
let cbLabel = UILabel()
cbLabel.translatesAutoresizingMaskIntoConstraints = false
cbLabel.text = checkboxName
let leadAnch = cbLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor)
constraints[checkboxName]!.append([leadAnch])
let checkbox = UISwitch()
checkbox.translatesAutoresizingMaskIntoConstraints = false
checkbox.addTarget(self, action: #selector(checkboxClicked), for: .valueChanged)
let trailAnch = checkbox.trailingAnchor.constraint(equalTo: contentView.trailingAnchor)
constraints[checkboxName]!.append([trailAnch])
let checkboxWrapper = UIView()
checkboxWrapper.translatesAutoresizingMaskIntoConstraints = false
checkboxWrapper.addSubview(cbLabel)
checkboxWrapper.addSubview(checkbox)
wrappers[checkboxName] = checkboxWrapper
elements[checkboxName] = [cbLabel, checkbox]
let commandID = bleService.getCommand(commandName: checkboxName)
bleService.send(aText: "c\(commandID)r:#")
}
for (index, textInputName) in textInputs.enumerated() {
constraints[textInputName] = [[]]
let textLabel = UILabel()
textLabel.translatesAutoresizingMaskIntoConstraints = false
textLabel.text = textInputName
var leadAnch = textLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor)
constraints[textInputName]!.append([leadAnch])
let inputField = UITextField()
inputField.layer.cornerRadius = 5
inputField.translatesAutoresizingMaskIntoConstraints = false
inputField.placeholder = textInputs[index]
inputField.backgroundColor = .white
inputField.addTarget(self, action: #selector(textfieldChanged), for: .valueChanged)
let topAnch = inputField.topAnchor.constraint(equalTo: textLabel.bottomAnchor, constant: 5)
let widthAnch = inputField.widthAnchor.constraint(equalToConstant: view.safeAreaLayoutGuide.layoutFrame.width/1.1)
leadAnch = inputField.leadingAnchor.constraint(equalTo: contentView.leadingAnchor)
constraints[textInputName]!.append([topAnch, widthAnch, leadAnch])
let inputWrapper = UIView()
inputWrapper.translatesAutoresizingMaskIntoConstraints = false
inputWrapper.addSubview(textLabel)
inputWrapper.addSubview(inputField)
wrappers[textInputName] = inputWrapper
elements[textInputName] = [textLabel, inputField]
let commandID = bleService.getCommand(commandName: textInputName)
bleService.send(aText: "c\(commandID)r:#")
}
for(index, phase) in timePickers.enumerated() {
constraints[phase] = [[]]
let descLabel = UILabel()
descLabel.translatesAutoresizingMaskIntoConstraints = false
descLabel.text = "Zeitschaltung \(index+1)"
var leadAnch = descLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor)
constraints[phase]!.append([leadAnch])
let enabledSwitch = UISwitch()
enabledSwitch.translatesAutoresizingMaskIntoConstraints = false
enabledSwitch.addTarget(self, action: #selector(changeTimerState), for: .valueChanged)
var topAnch = enabledSwitch.topAnchor.constraint(equalTo: descLabel.topAnchor)
var trailAnch = enabledSwitch.trailingAnchor.constraint(equalTo: contentView.trailingAnchor)
constraints[phase]!.append([trailAnch, topAnch])
let showPickerButton = UIButton()
showPickerButton.translatesAutoresizingMaskIntoConstraints = false
showPickerButton.setTitle("Zeit auswählen", for: .normal)
showPickerButton.backgroundColor = .darkGray
showPickerButton.layer.cornerRadius = 5
showPickerButton.addTarget(self, action: #selector(showTimePicker), for: .touchUpInside)
topAnch = showPickerButton.topAnchor.constraint(equalTo: enabledSwitch.bottomAnchor, constant: 4)
trailAnch = showPickerButton.trailingAnchor.constraint(equalTo: contentView.trailingAnchor)
constraints[phase]!.append([topAnch, trailAnch])
let timePicker = UIDatePicker()
timePicker.backgroundColor = .white
timePicker.isHidden = true
timePicker.translatesAutoresizingMaskIntoConstraints = false
timePicker.datePickerMode = .time
timePicker.addTarget(self, action: #selector(changeTimer), for: .valueChanged)
topAnch = timePicker.bottomAnchor.constraint(equalTo: enabledSwitch.bottomAnchor)
trailAnch = timePicker.trailingAnchor.constraint(equalTo: enabledSwitch.trailingAnchor)
constraints[phase]!.append([topAnch, trailAnch])
//Brightness Slider Value Label
let sliderValLabel = UILabel()
sliderValLabel.translatesAutoresizingMaskIntoConstraints = false
sliderValLabel.text = "0"
sliderValLabel.backgroundColor = .white
trailAnch = sliderValLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor)
topAnch = sliderValLabel.topAnchor.constraint(equalTo: showPickerButton.bottomAnchor, constant: 10)
var widthAnch = sliderValLabel.widthAnchor.constraint(equalToConstant: view.frame.width / 6)
constraints[phase]!.append([trailAnch, topAnch, widthAnch])
//Brightness Slider
let valueSlider = UISlider()
valueSlider.isContinuous = false
valueSlider.translatesAutoresizingMaskIntoConstraints = false
topAnch = valueSlider.topAnchor.constraint(equalTo: sliderValLabel.bottomAnchor, constant: 10)
leadAnch = valueSlider.leadingAnchor.constraint(equalTo: contentView.leadingAnchor)
trailAnch = valueSlider.trailingAnchor.constraint(equalTo: contentView.trailingAnchor)
constraints[phase]!.append([topAnch, leadAnch, trailAnch])
let timePickerWrapper = UIView()
//timePickerWrapper.translatesAutoresizingMaskIntoConstraints = false
timePickerWrapper.addSubview(descLabel)
timePickerWrapper.addSubview(enabledSwitch)
timePickerWrapper.addSubview(showPickerButton)
timePickerWrapper.addSubview(timePicker)
timePickerWrapper.addSubview(valueSlider)
timePickerWrapper.addSubview(sliderValLabel)
wrappers[phase] = timePickerWrapper
elements[phase] = [descLabel, showPickerButton, enabledSwitch, timePicker, sliderValLabel, valueSlider]
let commandID = bleService.getCommand(commandName: phase)
bleService.send(aText: "c\(commandID)r:#")
}
for buttonName in buttons {
constraints[buttonName] = [[]]
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
let widthAnch = button.widthAnchor.constraint(equalToConstant: contentView.frame.width/1.1)
let xAnch = button.centerXAnchor.constraint(equalTo: view.centerXAnchor)
constraints[buttonName]!.append([widthAnch, xAnch])
let buttonWrapper = UIView()
buttonWrapper.translatesAutoresizingMaskIntoConstraints = false
wrappers[buttonName] = buttonWrapper
elements[buttonName] = [button]
}
}
func changeContent(criteria: [String]) {
for item in criteria {
if(!contentView.contains(wrappers[item]!)) {
contentView.addArrangedSubview(wrappers[item]!)
for singleView in constraints[item]! {
for singleViewConstraint in singleView {
singleViewConstraint.isActive = true
}
}
}
}
}
func removeContent() {
var criteria = [String]()
switch(previousSetupMode) {
case "d":
criteria = d_kind_criteria
break
case "l":
criteria = l_kind_criteria
break
case "m":
criteria = m_kind_criteria
break
case "t":
criteria = t_kind_criteria
break
default:
break
}
for item in criteria {
wrappers[item]!.removeFromSuperview()
}
}
func changeView() {
if(previousSetupMode != activeSetupMode) {
removeContent()
}
switch(activeSetupMode) {
case "d":
changeContent(criteria: d_kind_criteria)
break
case "l":
changeContent(criteria: l_kind_criteria)
break
case "t":
changeContent(criteria: t_kind_criteria)
break
case "m":
changeContent(criteria: m_kind_criteria)
break
default:
break
}
}
The problem is that you are not giving your "wrapper" views any height, so the controls are being placed outside the bounds of their parent views.
You can confirm this two ways...
1) In your
for (index, sliderName) in sliders.enumerated() {
block, add:
sliderWrapper.backgroundColor = .green
(after creating the sliderWrapper view, of course). When you run the app, you won't see the green background, because sliderWrapper has a height of Zero:
2) And / or add:
sliderWrapper.clipsToBounds = true
and you won't see the controls at all:
To solve this, you can add constraints:
let sliderWrapper = UIView()
sliderWrapper.translatesAutoresizingMaskIntoConstraints = false
sliderWrapper.backgroundColor = .green
sliderWrapper.addSubview(descLabel)
sliderWrapper.addSubview(valueLabel)
sliderWrapper.addSubview(slider)
// add a topAnchor constraint from the top of descLabel to the top of sliderWrapper
// center valueLabel vertically to descLabel
// and a bottomAnchor from the bottom of slider to the bottom of sliderWrapper (negative if you want "padding")
NSLayoutConstraint.activate([
descLabel.topAnchor.constraint(equalTo: sliderWrapper.topAnchor, constant: 8.0),
valueLabel.centerYAnchor.constraint(equalTo: descLabel.centerYAnchor),
slider.bottomAnchor.constraint(equalTo: sliderWrapper.bottomAnchor, constant: -8.0),
])
Now, background is visible... controls are visible... and controls can be interacted with:

Swift: How to properly configure Chat Cells for Incoming and Outgoing Message for all Kinds

I am creating a chat layout to display cell for incoming and outgoing kind of messages. I have been able to make it work by activating and deactivating Constraints, except for the Text Message Kind. I noticed that on prepareForReuse() the constraints for outgoing cell get distorted.
I will like to know how I can fix this or a better alternative to solve the problem.
This is a video of what happens when I scroll.
TextMessageCell.swift
class TextMessageCell: ChatBaseCell {
override var viewModel: ChatCommonRepresentable? {
didSet {
guard let viewModel = viewModel as? MessageModel else {return}
let isIncoming = viewModel.isIncomming
messageLabel.text = viewModel.message
self.message = viewModel.message
sentLabel.text = viewModel.sentDateString
bubbleBackgroundView.backgroundColor = isIncoming ? .white : Color.solid08.value
messageLabel.textColor = isIncoming ? .black : .white
if isIncoming {
leadingConstraint.isActive = true
trailingConstraint.isActive = false
} else {
sentLabel.setTicker(status: viewModel.status)
leadingConstraint.isActive = false
trailingConstraint.isActive = true
}
}
}
private lazy var messageLabel: UITextViewFixed = {
let label = UITextViewFixed()
label.textAlignment = .left
label.isEditable = false
label.backgroundColor = .clear
label.isScrollEnabled = false
label.dataDetectorTypes = [.flightNumber, .calendarEvent, .address, .phoneNumber, .link, .lookupSuggestion]
label.isSelectable = true
label.isUserInteractionEnabled = true
label.delaysContentTouches = true
label.font = Font(.installed(.OpenSansRegular), size: .standard(.bodySmall)).instance
label.linkTextAttributes?[NSAttributedString.Key.underlineStyle] = NSUnderlineStyle.single
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
private lazy var sentLabel: UILabel = {
let label = UILabel()
label.textAlignment = .right
label.textColor = Color.custom(hexString: "#C8CAD3", alpha: 1.0).value
label.font = Font(.installed(.OpenSansSemiBold), size: .custom(10)).instance
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
private lazy var bubbleBackgroundView: UIView = {
let view = UIView()
view.layer.cornerRadius = 12
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
var leadingConstraint: NSLayoutConstraint!
var trailingConstraint: NSLayoutConstraint!
var widthConstraint: NSLayoutConstraint!
var widthFullConstraint: NSLayoutConstraint!
var sentLabelBottomConstraint: NSLayoutConstraint!
var sentLabelCenterYConstraint: NSLayoutConstraint!
var messageLabelBottomConstraint: NSLayoutConstraint!
var messageLabelCenterYConstraint: NSLayoutConstraint!
var messageLabelTopConstraint: NSLayoutConstraint!
var message: String! {
didSet {
let constantHeight: CGFloat = message.height(withConstrainedWidth: 250 - 32 - 8, font: Font(.installed(.OpenSansRegular), size: .standard(.bodySmall)).instance)
let constantWidth: CGFloat = message.width(withConstrainedHeight: constantHeight, font: Font(.installed(.OpenSansRegular), size: .standard(.bodySmall)).instance)
print(constantWidth)
if constantHeight < 21 {
if constantWidth > 230 {
sentLabelCenterYConstraint.isActive = false
sentLabelBottomConstraint.isActive = true
messageLabelTopConstraint.isActive = true
messageLabelCenterYConstraint.isActive = false
messageLabelBottomConstraint.isActive = true
widthConstraint = bubbleBackgroundView.widthAnchor.constraint(lessThanOrEqualToConstant: 250)
widthConstraint.isActive = true
} else {
sentLabelCenterYConstraint.isActive = true
sentLabelBottomConstraint.isActive = false
messageLabelTopConstraint.isActive = false
messageLabelCenterYConstraint.isActive = true
messageLabelBottomConstraint.isActive = false
guard let user = UserDefaults().currentUser() else {return}
let isIncoming = "\(user.id!)" != viewModel!.sender.id
if isIncoming {
let fullWidth = constantWidth + 70
widthFullConstraint.constant = fullWidth
widthFullConstraint.isActive = true
} else {
let fullWidth = constantWidth + 90
widthFullConstraint.constant = fullWidth
widthFullConstraint.isActive = true
}
}
}
}
}
private func constraintViews() {
}
override func setupViews() {
addSubview(bubbleBackgroundView)
bubbleBackgroundView.addSubview(messageLabel)
bubbleBackgroundView.addSubview(sentLabel)
bubbleBackgroundView.topAnchor.align(to: topAnchor)
bubbleBackgroundView.bottomAnchor.align(to: bottomAnchor)
messageLabel.trailingAnchor.align(to: bubbleBackgroundView.trailingAnchor, offset: -8)
messageLabel.leadingAnchor.align(to: bubbleBackgroundView.leadingAnchor, offset: 8)
sentLabel.trailingAnchor.align(to: bubbleBackgroundView.trailingAnchor, offset: -10)
sentLabel.widthAnchor.equal(to: 70)
leadingConstraint = bubbleBackgroundView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 20)
leadingConstraint.isActive = false
trailingConstraint = bubbleBackgroundView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -20)
trailingConstraint.isActive = true
widthConstraint = bubbleBackgroundView.widthAnchor.constraint(lessThanOrEqualToConstant: 250)
widthConstraint.isActive = true
widthFullConstraint = bubbleBackgroundView.widthAnchor.constraint(equalToConstant: 1)
widthFullConstraint.isActive = false
messageLabelTopConstraint = messageLabel.topAnchor.constraint(equalTo: bubbleBackgroundView.topAnchor, constant: 10)
messageLabelTopConstraint.isActive = false
messageLabelBottomConstraint = bubbleBackgroundView.bottomAnchor.constraint(equalTo: bubbleBackgroundView.bottomAnchor, constant: -18)
messageLabelBottomConstraint.isActive = true
messageLabelCenterYConstraint = messageLabel.centerYAnchor.constraint(equalTo: bubbleBackgroundView.centerYAnchor)
messageLabelCenterYConstraint.isActive = false
sentLabelBottomConstraint = sentLabel.bottomAnchor.constraint(equalTo: bubbleBackgroundView.bottomAnchor, constant: -8)
sentLabelBottomConstraint.isActive = true
sentLabelCenterYConstraint = sentLabel.centerYAnchor.constraint(equalTo: bubbleBackgroundView.centerYAnchor)
sentLabelCenterYConstraint.isActive = false
}
override func prepareForReuse() {
super.prepareForReuse()
sentLabel.text = nil
messageLabel.text = nil
leadingConstraint.isActive = false
trailingConstraint.isActive = false
widthConstraint.isActive = false
sentLabelBottomConstraint.isActive = false
sentLabelCenterYConstraint.isActive = false
messageLabelBottomConstraint.isActive = false
messageLabelCenterYConstraint.isActive = false
messageLabelTopConstraint.isActive = false
widthFullConstraint.isActive = false
}
}

Can't adjust layouts on multiple devices in Swift

I'm trying to adjust layout without Storyboard in Swift. But using the code below, I can't adjust layout on iPhone Plus series (6+, 7+, and 8+).
Case1
Using images based on 640x1136 size, it works on iPhone8, 8+, and X.
class Constants {
// the image parts are based on 640x1136
static let guiPartsWidthOnDesign = CGFloat(640)
static var guiPartsMultiplier: CGFloat = UIScreen.main.bounds.width / guiPartsWidthOnDesign
}
Make buttons
for i in 1..<5 {
let subButton = UIImageView.init(frame: CGRect(
x: UIScreen.main.bounds.size.width/2-50*Constants.guiPartsMultiplier,
y: (100*Constants.guiPartsMultiplier)+CGFloat(i*100),
width: 187*Constants.guiPartsMultiplier,
height: 100*Constants.guiPartsMultiplier))
background.addSubview(subButton)
subButton.backgroundColor = UIColor.blue
subButton.alpha = 1.0
}
The results on multiple devices look the same layout.
Case2
Using images based on 750x1334 size, it didn't work well on iPhone8+.
class Constants {
// the images are based on 750x1334
static let guiPartsWidthOnDesign = CGFloat(750)
static var guiPartsMultiplier: CGFloat = UIScreen.main.bounds.width / guiPartsWidthOnDesign
}
Make buttons (same to the previous code.)
Result
As you see, the blue square's y positions are different between iPhone8 and 8 Plus.
(The results of iPhone8 and X are the same.)
How can I solve this problem?
UPDATE
I tried to use UIStackView, but it didn't work well.
UPDATE2
//Define this as class variable
fileprivate lazy var stackView: UIStackView = {
let sv = UIStackView()
sv.backgroundColor = UIColor.green
sv.translatesAutoresizingMaskIntoConstraints = false
sv.axis = .vertical
sv.alignment = .fill
sv.distribution = .fillEqually
sv.spacing = 10
return sv
}()
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(stackView)
stackView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
stackView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
let background = UIImageView.init(frame: UIScreen.main.bounds)
background.image = UIImage(named:"BG")
stackView.addSubview(background)
// background.translatesAutoresizingMaskIntoConstraints = false
// background.contentMode = .scaleAspectFill
for i in 1..<5 {
let subButton = UIImageView()
subButton.translatesAutoresizingMaskIntoConstraints = false
subButton.backgroundColor = UIColor.blue
subButton.alpha = 1.0
stackView.addArrangedSubview(subButton)
subButton.widthAnchor.constraint(equalTo: self.view.widthAnchor, multiplier: 0.3).isActive = true
}
}
*I'm sorry, I don't know but I couldn't upload the screenshot.
UPDATE3
I used the following code and the result was like this on all type devices:
//Define this as class variable
fileprivate lazy var stackView: UIStackView = {
let sv = UIStackView()
sv.translatesAutoresizingMaskIntoConstraints = false
sv.axis = .vertical
sv.alignment = .fill
sv.distribution = .fillEqually
sv.spacing = 10
return sv
}()
fileprivate lazy var catBg: UIImageView = {
let iv = UIImageView()
iv.translatesAutoresizingMaskIntoConstraints = false
iv.contentMode = .scaleAspectFill
iv.image = UIImage(named: "BG")
return iv
}()
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(catBg)
catBg.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
catBg.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
catBg.widthAnchor.constraint(equalTo: self.view.widthAnchor, multiplier: 0.7).isActive = true
catBg.heightAnchor.constraint(equalTo: catBg.widthAnchor, multiplier: 1.78).isActive = true
self.catBg.addSubview(stackView)
stackView.centerXAnchor.constraint(equalTo: catBg.centerXAnchor).isActive = true
stackView.centerYAnchor.constraint(equalTo: catBg.centerYAnchor).isActive = true
for i in 1..<5 {
let subButton = UIImageView()
subButton.translatesAutoresizingMaskIntoConstraints = false
subButton.backgroundColor = UIColor.blue
subButton.alpha = 1.0
stackView.addArrangedSubview(subButton)
subButton.widthAnchor.constraint(equalTo: catBg.widthAnchor, multiplier: 0.3).isActive = true
//If you have an image you can remove or change this anchor
subButton.heightAnchor.constraint(equalToConstant: 54).isActive = true
}
}
UPDATE4
My ideal is the center of this image. But so far the result is like the right image.
Even if you are not using storyboards, I would suggest you using UIStackview. In the stackview you specific axis to be vertical and a spacing if you'd like. Set the stackview to fill equally.
Don't using actual frames to calculate position for multiple screen layouts, it will get tedious.
You should use autolayout constraints in particular anchors.
//Define this as class variable
fileprivate lazy var stackView: UIStackView = {
let sv = UIStackView()
sv.translatesAutoresizingMaskIntoConstraints = false
sv.axis = .vertical
sv.alignment = .fill
sv.distribution = .fillEqually
sv.spacing = 10
return sv
}()
fileprivate lazy var catBg: UIImageView = {
let iv = UIImageView()
iv.translatesAutoresizingMaskIntoConstraints = false
iv.contentMode = .scaleAspectFill
iv.image = UIImage(named: "your_img_name")
return iv
}()
//Put this in viewDidLoad
//Edit
self.view.addSubview(catBg)
//catBg.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
//catBg.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
//catBg.widthAnchor.constraint(equalTo: self.view.widthAnchor, multiplier: 0.7).isActive = true
//catBg.heightAnchor.constraint(equalTo: catBg.widthAnchor, multiplier: 1.78).isActive = true
catBg.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
catBg.leftAnchor.constraint(equalTo: self.view.leftAnchor).isActive = true
catBg.rightAnchor.constraint(equalTo: self.view.rightAnchor).isActive = true
catBg.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true
self.catBg.addSubview(stackView)
stackView.centerXAnchor.constraint(equalTo: catBg.centerXAnchor).isActive = true
stackView.centerYAnchor.constraint(equalTo: catBg.centerYAnchor).isActive = true
for i in 1..<5 {
let subButton = UIImageView()
subButton.translatesAutoResizingMaskIntoConstraints = false
subButton.backgroundColor = UIColor.blue
subButton.alpha = 1.0
stackView.addArrangedSubview(subButton)
subButton.widthAnchor.constraint(equalTo: catBg.widthAnchor, multiplier: 0.3).isActive = true
//If you have an image you can remove or change this anchor
subButton.heightAnchor.constraint(equalToConstant: 54).isActive = true
}

Swift 3 segment view error

I have a segment control created programmatically in my RegisterViewController. The registerbutton works and saves everything in a Firebase database but when I switch to the loginbutton, the height of the different textfields is changed but the first one doesn't disappear... There's still a small piece of text visible from the first textfield (as you can see on the picture). Furthermore, when I test the login-function, it doesn't log me in as an existing user but it creates a new user in the database, so I guess it doesn't change the code either...
Login View:
Register View:
import UIKit
import Firebase
class RegisterViewController: UIViewController {
let inputsContainerView: UIView = {
let View = UIView()
View.backgroundColor = UIColor.white
View.translatesAutoresizingMaskIntoConstraints = false
View.layer.cornerRadius = 5
View.layer.masksToBounds = true
return View
}()
lazy var loginRegisterButton: UIButton = {
let button = UIButton(type: .system)
button.backgroundColor = UIColor(red: 80/255, green: 101/255, blue: 161/255, alpha: 1)
button.setTitle("Register", for: .normal)
button.setTitleColor(UIColor.white, for: .normal)
button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 16)
button.translatesAutoresizingMaskIntoConstraints = false
button.addTarget(self, action: #selector(handleRegister), for: .touchUpInside)
return button
}()
func handleLoginRegister() {
if loginRegisterSegmentedControl.selectedSegmentIndex == 0 {
handleLogin()
} else {
handleRegister()
}
}
func handleLogin() {
guard let email = emailTextField.text, let password = passwordTextField.text
else {
print("Form is not valid")
return
}
FIRAuth.auth()?.signIn(withEmail: email, password: password, completion: { (user, error) in
if error != nil {
print(error ?? "")
return
}
self.dismiss(animated: true, completion: nil)
})
}
func handleRegister() {
guard let email = emailTextField.text, let password = passwordTextField.text, let name = nameTextField.text
else {
print("Form is not valid")
return
}
FIRAuth.auth()?.createUser(withEmail: email, password: password, completion: { (user: FIRUser?, error) in
if error != nil {
print(error ?? "")
return
}
guard let uid = user?.uid else {
return
}
//Succesfully authenticated user
let ref = FIRDatabase.database().reference(fromURL: "https://assemble-148108.firebaseio.com/")
let usersReference = ref.child("users").child(uid)
let values = ["name": name, "email": email]
usersReference.updateChildValues(values, withCompletionBlock: { (err, ref) in
if err != nil {
print(err ?? "")
return
}
print("Saved user successfully into Firebase db")
})
})
}
let nameTextField: UITextField = {
let tf = UITextField()
tf.placeholder = "Name"
tf.translatesAutoresizingMaskIntoConstraints = false
return tf
}()
let nameSeparatorView: UIView = {
let view = UIView()
view.backgroundColor = UIColor(colorLiteralRed: 220/225, green: 220/225, blue: 220/225, alpha: 1)
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
let emailTextField: UITextField = {
let tf = UITextField()
tf.placeholder = "Email"
tf.translatesAutoresizingMaskIntoConstraints = false
return tf
}()
let emailSeparatorView: UIView = {
let view = UIView()
view.backgroundColor = UIColor(colorLiteralRed: 220/225, green: 220/225, blue: 220/225, alpha: 1)
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
let passwordTextField: UITextField = {
let tf = UITextField()
tf.placeholder = "Password"
tf.translatesAutoresizingMaskIntoConstraints = false
tf.isSecureTextEntry = true
return tf
}()
let profileImageView: UIImageView = {
let imageView = UIImageView()
imageView.image = UIImage(named: "avatar")
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.contentMode = .scaleAspectFill
return imageView
}()
lazy var loginRegisterSegmentedControl: UISegmentedControl = {
let sc = UISegmentedControl(items: ["Login", "Register"])
sc.translatesAutoresizingMaskIntoConstraints = false
sc.tintColor = UIColor.white
sc.selectedSegmentIndex = 1
sc.addTarget(self, action: #selector(handleLoginRegisterChange), for: .valueChanged)
return sc
}()
func handleLoginRegisterChange() {
let title = loginRegisterSegmentedControl.titleForSegment(at: loginRegisterSegmentedControl.selectedSegmentIndex)
loginRegisterButton.setTitle(title, for: .normal)
// change height of inputContainerView, but how???
inputsContainerViewHeightAnchor?.constant = loginRegisterSegmentedControl.selectedSegmentIndex == 0 ? 100 : 150
// change height of nameTextField
nameTextFieldHeightAnchor?.isActive = false
nameTextFieldHeightAnchor = nameTextField.heightAnchor.constraint(equalTo: inputsContainerView.heightAnchor, multiplier: loginRegisterSegmentedControl.selectedSegmentIndex == 0 ? 0 : 1/3)
nameTextFieldHeightAnchor?.isActive = true
emailTextFieldHeightAnchor?.isActive = false
emailTextFieldHeightAnchor = emailTextField.heightAnchor.constraint(equalTo: inputsContainerView.heightAnchor, multiplier: loginRegisterSegmentedControl.selectedSegmentIndex == 0 ? 1/2 : 1/3)
emailTextFieldHeightAnchor?.isActive = true
passwordTextFieldHeightAnchor?.isActive = false
passwordTextFieldHeightAnchor = passwordTextField.heightAnchor.constraint(equalTo: inputsContainerView.heightAnchor, multiplier: loginRegisterSegmentedControl.selectedSegmentIndex == 0 ? 1/2 : 1/3)
passwordTextFieldHeightAnchor?.isActive = true
}
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor(colorLiteralRed: 61/225, green: 91/255, blue: 151/255, alpha: 1)
view.addSubview(inputsContainerView)
view.addSubview(loginRegisterButton)
view.addSubview(profileImageView)
view.addSubview(loginRegisterSegmentedControl)
setupInputsContainerView()
setuploginRegisterButton()
setupProfileImageView()
setupRegisterSegmentedControl()
}
//hier moet de kleur van de tijd helemaal bovenaan aangepast worden van zwart naar wit
//override func preferredStatusBarStyle() -> UIStatusBarStyle {
// return .lightContent
//}
func setupRegisterSegmentedControl() {
// need x, y, width, height constraints
loginRegisterSegmentedControl.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
loginRegisterSegmentedControl.bottomAnchor.constraint(equalTo:inputsContainerView.topAnchor, constant: -12).isActive = true
loginRegisterSegmentedControl.widthAnchor.constraint(equalTo: inputsContainerView.widthAnchor, multiplier: 1).isActive = true
loginRegisterSegmentedControl.heightAnchor.constraint(equalToConstant: 36).isActive = true
}
func setupProfileImageView() {
// need x, y, width, height constraints
profileImageView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
profileImageView.bottomAnchor.constraint(equalTo: loginRegisterSegmentedControl.topAnchor, constant: -12).isActive = true
profileImageView.widthAnchor.constraint(equalToConstant: 100).isActive = true
profileImageView.heightAnchor.constraint(equalToConstant: 100).isActive = true
}
var inputsContainerViewHeightAnchor: NSLayoutConstraint?
var nameTextFieldHeightAnchor: NSLayoutConstraint?
var emailTextFieldHeightAnchor: NSLayoutConstraint?
var passwordTextFieldHeightAnchor: NSLayoutConstraint?
func setupInputsContainerView() {
// need x, y, width, height constraints
inputsContainerView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
inputsContainerView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
inputsContainerView.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -24).isActive = true
inputsContainerViewHeightAnchor = inputsContainerView.heightAnchor.constraint(equalToConstant: 150)
inputsContainerViewHeightAnchor?.isActive = true
inputsContainerView.addSubview(nameTextField)
inputsContainerView.addSubview(nameSeparatorView)
inputsContainerView.addSubview(emailTextField)
inputsContainerView.addSubview(emailSeparatorView)
inputsContainerView.addSubview(passwordTextField)
// need x, y, width, height constraints
nameTextField.leftAnchor.constraint(equalTo: inputsContainerView.leftAnchor, constant: 12).isActive = true
nameTextField.topAnchor.constraint(equalTo: inputsContainerView.topAnchor).isActive = true
nameTextField.widthAnchor.constraint(equalTo: inputsContainerView.widthAnchor).isActive = true
nameTextFieldHeightAnchor = nameTextField.heightAnchor.constraint(equalTo: inputsContainerView.heightAnchor, multiplier: 1/3)
nameTextFieldHeightAnchor?.isActive = true
// need x, y, width, height constraints
nameSeparatorView.leftAnchor.constraint(equalTo: inputsContainerView.leftAnchor).isActive = true
nameSeparatorView.topAnchor.constraint(equalTo: nameTextField.bottomAnchor).isActive = true
nameSeparatorView.widthAnchor.constraint(equalTo: inputsContainerView.widthAnchor).isActive = true
nameSeparatorView.heightAnchor.constraint(equalToConstant: 1).isActive = true
// need x, y, width, height constraints
emailTextField.leftAnchor.constraint(equalTo: inputsContainerView.leftAnchor, constant: 12).isActive = true
emailTextField.topAnchor.constraint(equalTo: nameTextField.bottomAnchor).isActive = true
emailTextField.widthAnchor.constraint(equalTo: inputsContainerView.widthAnchor).isActive = true
emailTextFieldHeightAnchor = emailTextField.heightAnchor.constraint(equalTo: inputsContainerView.heightAnchor, multiplier: 1/3)
emailTextFieldHeightAnchor?.isActive = true
// need x, y, width, height constraints
emailSeparatorView.leftAnchor.constraint(equalTo: inputsContainerView.leftAnchor).isActive = true
emailSeparatorView.topAnchor.constraint(equalTo: emailTextField.bottomAnchor).isActive = true
emailSeparatorView.widthAnchor.constraint(equalTo: inputsContainerView.widthAnchor).isActive = true
emailSeparatorView.heightAnchor.constraint(equalToConstant: 1).isActive = true
// need x, y, width, height constraints
passwordTextField.leftAnchor.constraint(equalTo: inputsContainerView.leftAnchor, constant: 12).isActive = true
passwordTextField.topAnchor.constraint(equalTo: emailTextField.bottomAnchor).isActive = true
passwordTextField.widthAnchor.constraint(equalTo: inputsContainerView.widthAnchor).isActive = true
passwordTextFieldHeightAnchor = passwordTextField.heightAnchor.constraint(equalTo: inputsContainerView.heightAnchor, multiplier: 1/3)
passwordTextFieldHeightAnchor?.isActive = true
}
func setuploginRegisterButton() {
// need x, y, width, height constraints
loginRegisterButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
loginRegisterButton.topAnchor.constraint(equalTo: inputsContainerView.bottomAnchor, constant: 12).isActive = true
loginRegisterButton.widthAnchor.constraint(equalTo: inputsContainerView.widthAnchor).isActive = true
loginRegisterButton.heightAnchor.constraint(equalToConstant: 30).isActive = true
}
}
If you want a quick fix, you set the nameTextField to be hidden
if loginRegisterSegmentedControl.selectedSegmentIndex == 0 {
nameTextField.isHidden = true
} else {
nameTextField.isHidden = false
}
Do this in the func handleLoginRegisterChange().
Also you don't need func handleLoginRegister(), it doesn't seem to be used.
If you want a proper fix, when you switch segments, you should remove the name label and redo the constraints.

Resources