I have a viewController with UISegmentedControl to switch between 2 contents (by department or by recipe). When I toggle the segmentedControl (which will execute the changeColor function), I want to change the content corresponding to which segment is selected. The contents in each segment are several UILabel then add them like view.addSubview(label). However, what my current code do is placing them overlap each other.
class GroceryViewController: UIViewController {
var customSC = UISegmentedControl()
override func viewDidLoad() {
super.viewDidLoad()
setupSegmentedControl()
contentByDepartment()
}
func setupSegmentedControl() {
let items = ["BY DEPARTMENT", "BY RECIPE"]
customSC = UISegmentedControl(items: items)
customSC.selectedSegmentIndex = 0
let frame = UIScreen.main.bounds
customSC.frame = CGRect(x:frame.minX + 15, y:frame.minY + 100,
width:frame.width - 30, height:frame.height * 0.04)
customSC.layer.cornerRadius = 20
customSC.backgroundColor = UIColor(hexString: "#F7F7F7")
customSC.setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor(hexString: "#FC6A03")], for: UIControl.State.selected)
customSC.addTarget(self, action: #selector(changeColor), for: .valueChanged)
view.addSubview(customSC)
}
@objc func changeColor(_ sender: UISegmentedControl) {
switch sender.selectedSegmentIndex {
case 0:
contentByDepartment() // contents are several UILabel adding to view as SubView
case 1:
contentByRecipe() // contents are several UILabel adding to view as SubView
default:
break
}
}
}
I have searched for the solution and mostly they are "reloadData() in UITableView", which I don't have one. So I have no idea how to reload this viewController without bothering UIView or UITableView.
The question is: Is it possible to reload the viewController alone from some function so that previous content will be clear out before displaying selected contents and how to do so ?
EDIT: code of contentByDepartment and contentByRecipe
func contentByDepartment() {
let recipeHeader = UILabel(frame: CGRect(x:50, y:180, width: 200, height: 20))
recipeHeader.setActivityDescription(label: "Coffee and Tea")
recipeHeader.textColor = UIColor(hexString: "#FC6A03")
recipeHeader.font = UIFont.systemFont(ofSize: 20)
let ingredient1Name = UILabel(frame: CGRect(x:70,y:210,width:200,height:20))
ingredient1Name.setActivityDescription(label: "Green tea leaves")
ingredient1Name.font = UIFont.systemFont(ofSize: 16)
let ingredient1Amount = UILabel(frame: CGRect(x:72,y:230,width:200,height:20))
ingredient1Amount.setActivityDescription(label: "1 tablespoons")
ingredient1Amount.font = UIFont.systemFont(ofSize: 12)
let ingredient2Name = UILabel(frame: CGRect(x:70,y:260,width:200,height:20))
ingredient2Name.setActivityDescription(label: "Coffee powder")
ingredient2Name.font = UIFont.systemFont(ofSize: 16)
let ingredient2Amount = UILabel(frame: CGRect(x:72,y:280,width:200,height:20))
ingredient2Amount.setActivityDescription(label: "3 tablespoons")
ingredient2Amount.font = UIFont.systemFont(ofSize: 12)
view.addSubview(recipeHeader)
view.addSubview(ingredient1Name)
view.addSubview(ingredient1Amount)
view.layer.addSublayer(drawLine(x1:70, y1:255, x2:350, y2:255, lineWidth:0.3))
view.addSubview(ingredient2Name)
view.addSubview(ingredient2Amount)
view.layer.addSublayer(drawLine(x1:0, y1:310, x2:420, y2:310, lineWidth:0.5))
}
func contentByRecipe() {
let recipeHeader = UILabel(frame: CGRect(x:50, y:180, width: 200, height: 20))
recipeHeader.setActivityDescription(label: "Cha-yen")
recipeHeader.textColor = UIColor(hexString: "#FC6A03")
recipeHeader.font = UIFont.systemFont(ofSize: 20)
let ingredient1Name = UILabel(frame: CGRect(x:70,y:210,width:200,height:20))
ingredient1Name.setActivityDescription(label: "Vanilla extract")
ingredient1Name.font = UIFont.systemFont(ofSize: 16)
let ingredient1Amount = UILabel(frame: CGRect(x:72,y:230,width:200,height:20))
ingredient1Amount.setActivityDescription(label: "1 tablespoons")
ingredient1Amount.font = UIFont.systemFont(ofSize: 12)
let ingredient2Name = UILabel(frame: CGRect(x:70,y:260,width:200,height:20))
ingredient2Name.setActivityDescription(label: "Sugar")
ingredient2Name.font = UIFont.systemFont(ofSize: 16)
let ingredient2Amount = UILabel(frame: CGRect(x:72,y:280,width:200,height:20))
ingredient2Amount.setActivityDescription(label: "3 tablespoons")
ingredient2Amount.font = UIFont.systemFont(ofSize: 12)
view.addSubview(recipeHeader)
view.addSubview(ingredient1Name)
view.addSubview(ingredient1Amount)
view.layer.addSublayer(drawLine(x1:70, y1:255, x2:350, y2:255, lineWidth:0.3))
view.addSubview(ingredient2Name)
view.addSubview(ingredient2Amount)
view.layer.addSublayer(drawLine(x1:0, y1:310, x2:420, y2:310, lineWidth:0.5))
}
You should learn to group related views together. Right now, you are adding all your views as subviews of view
. This is very unorganised, and has led you to your current situation - not being able to show/hide certain views efficiently.
One way to organise your views is to add your "by department" views into a big UIView
, and all the "by recipe" views into another big UIView
.
var byDepartmentContainerView: UIView!
func setUpContentByDepartment() {
let recipeHeader = UILabel(frame: ...)
recipeHeader.setActivityDescription(label: "Coffee and Tea")
recipeHeader.textColor = UIColor(hexString: "#FC6A03")
recipeHeader.font = UIFont.systemFont(ofSize: 20)
let ingredient1Name = UILabel(frame: ...)
ingredient1Name.setActivityDescription(label: "Green tea leaves")
ingredient1Name.font = UIFont.systemFont(ofSize: 16)
let ingredient1Amount = UILabel(frame: ...)
ingredient1Amount.setActivityDescription(label: "1 tablespoons")
ingredient1Amount.font = UIFont.systemFont(ofSize: 12)
let ingredient2Name = UILabel(frame: ...)
ingredient2Name.setActivityDescription(label: "Coffee powder")
ingredient2Name.font = UIFont.systemFont(ofSize: 16)
let ingredient2Amount = UILabel(frame: ...)
ingredient2Amount.setActivityDescription(label: "3 tablespoons")
ingredient2Amount.font = UIFont.systemFont(ofSize: 12)
byDepartmentContainerView = UIView(frame: ...)
byDepartmentContainerView.addSubview(recipeHeader)
byDepartmentContainerView.addSubview(ingredient1Name)
byDepartmentContainerView.addSubview(ingredient1Amount)
byDepartmentContainerView.addSubview(ingredient2Name)
byDepartmentContainerView.addSubview(ingredient2Amount)
}
var byRecipeContainerView: UIView!
func setUpContentByRecipe() {
let recipeHeader = UILabel(frame: CGRect(x:50, y:180, width: 200, height: 20))
recipeHeader.setActivityDescription(label: "Cha-yen")
recipeHeader.textColor = UIColor(hexString: "#FC6A03")
recipeHeader.font = UIFont.systemFont(ofSize: 20)
let ingredient1Name = UILabel(frame: CGRect(x:70,y:210,width:200,height:20))
ingredient1Name.setActivityDescription(label: "Vanilla extract")
ingredient1Name.font = UIFont.systemFont(ofSize: 16)
let ingredient1Amount = UILabel(frame: CGRect(x:72,y:230,width:200,height:20))
ingredient1Amount.setActivityDescription(label: "1 tablespoons")
ingredient1Amount.font = UIFont.systemFont(ofSize: 12)
let ingredient2Name = UILabel(frame: CGRect(x:70,y:260,width:200,height:20))
ingredient2Name.setActivityDescription(label: "Sugar")
ingredient2Name.font = UIFont.systemFont(ofSize: 16)
let ingredient2Amount = UILabel(frame: CGRect(x:72,y:280,width:200,height:20))
ingredient2Amount.setActivityDescription(label: "3 tablespoons")
ingredient2Amount.font = UIFont.systemFont(ofSize: 12)
byRecipeContainerView = UIView(frame: ...)
byRecipeContainerView.addSubview(recipeHeader)
byRecipeContainerView.addSubview(ingredient1Name)
byRecipeContainerView.addSubview(ingredient1Amount)
byRecipeContainerView.addSubview(ingredient2Name)
byRecipeContainerView.addSubview(ingredient2Amount)
}
Note that I've omitted the frames of the views. Please give the container views a frame large enough to contain all its subviews, and adjust the subview's frames so that they are relative to the container view's coordinate system.
Also, you seem to be drawing the same lines in both methods, so it can be done once and never again.
func drawLines() {
view.layer.addSublayer(drawLine(x1:0, y1:310, x2:420, y2:310, lineWidth:0.5))
view.layer.addSublayer(drawLine(x1:70, y1:255, x2:350, y2:255, lineWidth:0.3))
}
In viewDidLoad
, you can call all three methods:
setUpContentByDepartment()
setUpContentByRecipe()
drawLines()
view.addSubview(byDepartmentContainerView)
view.addSubview(byRecipeContainerView)
byRecipeContainerView.isHidden = true
Now you can just do something like:
switch sender.selectedSegmentIndex {
case 0:
byRecipeContainerView.isHidden = true
byDepartmentContainerView.isHidden = false
case 1:
byRecipeContainerView.isHidden = false
byDepartmentContainerView.isHidden = true
default:
break
}
P.S. hardcoding view's frames is a very bad idea. It's not localisable, not adaptable to different devices, among other things. Please learn about Autolayout Constraints.