Label not display in subview of UITableView - ios

I am designing an iOS hamburger menu with a table view in swift3
I want to display the number of notifications in menu tab.
let pieNotifi = UIImageView(frame: CGRectMake(cell.contentView.frame.size.width-40, cell.contentView.frame.size.height/2-7, 30, 20))
let pieLabNotifi = UILabel(frame: CGRectMake(cell.contentView.frame.size.width-40, cell.contentView.frame.size.height/2-7, 30, 20))
let subviews = self.view.viewWithTag(100001)
if myGlobal.unreaddot != 0 { //just a count for notifcaiton
if subviews == nil {
pieNotifi.tag = 100001;
cell.addSubview(pieNotifi)
let pieShape = pieNotifi.layer;
pieShape.backgroundColor = UIColor.red.cgColor
pieShape.cornerRadius = pieShape.bounds.width / 4
pieLabNotifi.textColor = UIColor.white
pieLabNotifi.adjustsFontSizeToFitWidth = true;
pieLabNotifi.minimumScaleFactor = 0.5
pieLabNotifi.textAlignment = NSTextAlignment.center
pieNotifi.addSubview(pieLabNotifi)
pieLabNotifi.text = String(myGlobal.unreaddot)
}
else{
pieLabNotifi.text = String(myGlobal.unreaddot)
}
}else{
let subviews = cell.viewWithTag(100001)
subviews?.removeFromSuperview()
print("remove red dot")
}
however, it only display the red colour layer but do not have the label. refer to the picture shown below
enter image description here
I had tried to set
.sendSubview(to back:)
.bringSubview(toFront: )
.layer.zPosition = 1
all these key word not work for me.
Can anyone advise me to solve this problem?

You are not adding subview to UITableView. According to your code you are adding a subview to the cell of UITableView.
Try to add the subview to the content view of the cell, like:
cell.contentView.addSubView(pieNotifi)

i think the issue is with the positions of your label. You are giving your label x coordinate as cell.contentView.frame.size.width-40, but you want to add it inside the red image view. Changing the x position and y position to 0 (or whatever value you need )for your label will solve your problem. I have modified your code accordingly :
let pieNotifi = UIImageView(frame: CGRectMake(cell.contentView.frame.size.width-40, cell.contentView.frame.size.height/2-7, 30, 20))
let pieLabNotifi = UILabel(frame: CGRectMake(0,0, 30, 20))
let subviews = self.view.viewWithTag(100001)
if myGlobal.unreaddot != 0 { //just a count for notifcaiton
if subviews == nil {
pieNotifi.tag = 100001;
cell.addSubview(pieNotifi)
let pieShape = pieNotifi.layer;
pieShape.backgroundColor = UIColor.red.cgColor
pieShape.cornerRadius = pieShape.bounds.width / 4
pieLabNotifi.textColor = UIColor.white
pieLabNotifi.adjustsFontSizeToFitWidth = true;
pieLabNotifi.minimumScaleFactor = 0.5
pieLabNotifi.textAlignment = NSTextAlignment.center
pieNotifi.addSubview(pieLabNotifi)
pieLabNotifi.text = String(myGlobal.unreaddot)
}
else{
pieLabNotifi.text = String(myGlobal.unreaddot)
}
}else{
let subviews = cell.viewWithTag(100001)
subviews?.removeFromSuperview()
print("remove red dot")
}
Also try to see your label position in UiDebugger , you might discover that label is added at wrong position.

Related

Modifying images of generated imageViews on button click

I am creating a quiz app and having trouble changing the image which is displayed of a specific imageview that is generated in a for loop.
The following code is responsible for generating the imageviews based on the amount of questions in that specific quiz. It is called in the viewDidLoad() method:
var imageView = UIImageView()
func addProgressImages(to view: UIView, count: Int){
let screenSize = UIScreen.main.bounds.size
for i in 0..<count {
let spacing: CGFloat = 2
let tag = i + 888
let width: CGFloat = screenSize.width/CGFloat(count)
let height: CGFloat = width
if let view = view.viewWithTag(tag){
view.removeFromSuperview()
}
let x = spacing + CGFloat(i) * width
imageView = UIImageView(frame: CGRect(x: x, y: 100, width: width - spacing, height: height))
imageView.image = UIImage(named: "question_progress_empty")
imageView.tag = tag
imageView.contentMode = .scaleAspectFit
view.addSubview(imageView)
//print("imageviews displaying")
}
}
I have made an attempt to change some of the images to another image when the user selects an answer to that question with an if statement:
func changeImage() {
if (optA != questionAns){
imageView.image = UIImage(named: "wrong_answer")
print("opta")
}else if(optB == questionAns){
imageView.image = UIImage(named: "wrong_answer")
print("optb")
}else if(optC == questionAns){
print("optc")
imageView.image = UIImage(named: "wrong_answer")
}else{
print("if statement not initialised")
}
}
https://imgur.com/a/zwJ4EVn - This is the output of the above code
Currently, only the last image will be changed when a user clicks a button.
I need help with modifying the imageview which is related to that specific question, e.g. if question 2 is answered, only that imageview will change while the rest remain unmodified.
Hopefully that explanation made any sense, any input would be appreciated,
Thanks.
See you are doing few things wrong.
you have taken UIImageView as instance variable as below, so after
creating all the images its holding the reference to the last
imageView.
var imageView = UIImageView()
Make the var imageView as local variable and in the func
changeImage() get the proper imageView using its tag value then
try to change its image.
If any doubt plz comment.
How to get the imageView back in changeImage() check below code.
let tag = 888 + (questionNumber - 1)
if let imageView = view.viewWithTag(tag) as? UIImageView {
// Change imageView's image here
}
You will probably want to create an array of image views:
var imageViews = [UIImageView]()
And add your UIImagesViews to that array in your loop:
for i in 0..<count {
var imageView = UIImageView()
// additional setup...
imageViews.append(imageView)
}
Then, you can later iterate over your array and change the images:
for imageView in imageViews {
imageView.image = UIImage(named: "wrong_answer")
// etc.
}

Change UITextView text by using its tag number to identify the element due for change

//UITextView Creation
let textarea = UITextView (frame : CGRect (x: 40, y: 100 ,width:100 , height:100))
textarea.delegate = self
textarea.tag = self.numarr
textarea.backgroundColor = UIColor(red: 0.9686, green: 0.9686, blue: 0.9686, alpha: 1.0)
textarea.layer.cornerRadius = 20.0
textarea.contentInset = UIEdgeInsetsMake(5, 5, 5, 5);
textarea.layer.masksToBounds = true
self.scrollviewxp.addSubview(textarea)
//Later after, the button function
#IBAction func loadbutton(_ sender: Any) {
if let hellatextview = self.scrollviewxp.viewWithTag(index) as? UITextView
{
hellatextview.text = "success"
}
}
The above code is not flagged as an error on Xcode but doesn't change the UITextView (hellatextview) value upon execution. A textView with a tag number (index) exists but isn't being changed.
Any ideas why it isn't working? Ive had the same issue with UIButtons
You only need to make sure that the scrollviewxp is the very
superview for the view trying to get with tag.
Otherwise, there is absolutely 0 reasons to fail.
SWIFT 4 Working solutions:
1.
if let hellaTextView = scrollviewxp.subviews.first(where: { $0.tag == index }) as? UITextView {
hellaTextView.text = "success"
}
or
2.
for subview in scrollviewxp.subviews
{
if let hellatextview.text = subview as? UITextView
{
if hellatextview.tag == index {
hellatextview.text = "success"
}
}
}

Multiple lines in UITabBarItem Label

I've tried many things but impossible to find a way to put the label of a UITabBarItem with a lineNumber customised.0 (i would like to get the title on 2 lines).
Is there a way to do it?
Now it contains two subviews. At 0 it is imageView and at 1 it is label.
Now make the height of imageview a bit smaller so that you can give the height of label a bit larger to have multiple lines. Set the property ofnumberoflines of the label to 0 via code.
let viewTabBar = tabBarItem.value(forKey: "view") as? UIView
let imageView = viewTabBar?.subviews[0] as? UIImageView
let label = viewTabBar?.subviews[1] as? UILabel
and now play with this label.
More stable solution:
guard let view = tabBarItem?.value(forKey: "view") as? UIView,
let label = (view.subviews.flatMap{ $0 as? UILabel }).first,
let imageView = (view.subviews.flatMap{ $0 as? UIImageView }).first else { return }
this is my solution for that
we need to implement this inside viewwillLayoutSubviews. to update the ui and make it works
in this example in going to customize my 3rd tab bar item only
override func viewWillLayoutSubviews() {
// acess to list of tab bar items
if let items = self.tabBar.items {
// in each item we have a view where we find 2 subviews imageview and label
// in this example i would like to change
// access to item view
let viewTabBar = items[2].value(forKey: "view") as? UIView
// access to item subviews : imageview and label
if viewTabBar.subviews.count == 2 {
let label = viewTabBar?.subviews[1]as? UILabel
// here is the customization for my label 2 lines
label?.numberOfLines = 2
label?.textAlignment = .center
label!.text = "tab_point".localized
// here customisation for image insets top and bottom
items[2].imageInsets = UIEdgeInsets(top: 8, left: 0, bottom: -5, right: 0)
}
}
}
and here is the result
you can not do this with UIBarButtonItem because it doesn't have property titleView like UINavigationItem!
You can set only string as title and tab image! that's it!
If you have option to set label as titleview of tabbaritem then you can take label with numberofline 0 but here you can set string only!
tabBar.items?.forEach {
$0.imageInsets = UIEdgeInsets(top: 8, left: 0, bottom: -15, right: 0)
guard let view = $0.value(forKey: "view") as? UIView,
let label = (view.subviews.compactMap{ $0 as? UILabel }).first,
let imageView = (view.subviews.compactMap{ $0 as? UIImageView }).first else { return }
label.numberOfLines = 2
if CBServerManagerApi.sharedManager().currentUser.type == "Local" {
label.text = titles[element]
}
label.lineBreakMode = .byTruncatingTail
label.textAlignment = .center
label.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
label.heightAnchor.constraint(equalToConstant: 30)
])
}

Swift: how to make search bar animate when focused? Used to work?

Ok, I feel as though a few versions of Xcode ago this was the default, and I have it working in a past project, just do not know why I cant get this search bar animation to happen with this search bar now in Xcode 9.
What I want to happen is when the search bar ISNT focused, the placeholder text is centered:
Then when its tapped and becomes first responder, the text is left aligned (the transition between the two seems to animate automatically):
I swear search bars used to do this without any customization. How can I achieve this? Right now in my tableview custom header I set up my search bar programmatically like this:
searchBar.placeholder = "Find an Episode."
searchBar.backgroundColor = UIColor.clear
searchBar.searchBarStyle = .minimal
searchBar.layer.shadowOpacity = 0.0
searchBar.barTintColor = thirdColorStr
searchBar.tintColor = thirdColorStr
searchBar.frame = CGRect(x: 0, y: 0, width: self.bounds.width, height: screenSize.height * (40/screenSize.height))
self.addSubview(searchBar)
// searchBar.center = CGPoint(x: self.bounds.width/2, y: (searchBar.bounds.height/2))
searchBar.center = CGPoint(x: self.bounds.width/2, y: (searchBar.bounds.height)*0.8)
searchBar.delegate = listVC
for subView in searchBar.subviews {
for subViewOne in subView.subviews {
if let textField = subViewOne as? UITextField {
subViewOne.backgroundColor = secondColorStr
//print("HEREE:", textField.bounds.width/screenSize.width)
//use the code below if you want to change the color of placeholder
if let t = textField.value(forKey: "placeholderLabel") as? UILabel
{
t.textColor = thirdColorStr
t.font = iphoneFontThin
t.tintColor = thirdColorStr
t.backgroundColor = UIColor.clear
}
// if let clearButton = textField.value(forKey: "_clearButton") as? UIButton {
// // Create a template copy of the original button image
// let img = UIImage(named: "clear")
// clearButton.setImage(img, for: .normal)
//
// // Finally, set the image color
// //clearButton.tintColor = .red
// }
if let t = searchBar.value(forKey: "searchField") as? UITextField
{
t.textColor = barColorStr
t.font = iphoneFontThin
t.backgroundColor = secondColorStr
Then
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
self.searchBar.showsCancelButton = true
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
//searchBar.showsCancelButton = true
resetCategory(newCat: overallCategory)
searchBar.text = ""
searchBar.resignFirstResponder() //kills keyboard
}
I cant find any differences between the code that produces and animation and the one above that does not.

ViewController won't reload properly on first Simulator launch

I have a weird issue that I just found out when I re-installed and launched my project first time on Simulator
My main ViewController has a collection view that will show a list of recipes. After a recipe is added and navigated back to this screen, the list will reflect the update.
There is also a ScrollView that appears when recipe.count > 0 with subview containing buttons (to filter list by category). The scrollview reflect the update on the recipes but it won't work on the very first launch in Simulator.
I've tried reloading collectionview, fetching recipe data on viewDidAppear, viewWillAppear but no luck with the first-time launch.
How can I make sure the first app launch experience is the same with the subsequent launches? Is there any known issue with first-time launch on Simulator that I should know about?
Here is the code that creates buttons and add to ScrollView.
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
fetchRecipe()
collection.reloadData()
if recipes.count == 0 {
categoryScrollView.hidden = true
categoryScrollViewHeight.constant = 0
} else {
populateCategoryScrollView()
}
}
func populateCategoryScrollView() {
//Create category sort buttons based on fetched category.name and add to scrollview
if recipes.count > 0 {
var categories: [String] = []
for recipe in recipes {
if let value = recipe.category {
let category = value as! RecipeCategory
categories.append(category.name!)
}
}
var distinctCategories = Array(Set(categories))
var widthStack = 0
if distinctCategories.count != 0 {
for subView in categoryScrollView.subviews {
subView.removeFromSuperview()
}
for i in 0..<distinctCategories.count {
//Pilot button creation to get width
let frame1 = CGRect(x: 0, y: 6, width: 80, height: 40 )
let button = UIButton(frame: frame1)
button.setTitle("\(distinctCategories[i])", forState: .Normal)
button.sizeToFit()
let buttonWidth = Int(button.frame.size.width)
var frame2: CGRect
if i == 0 {
frame2 = CGRect(x: 10, y: 6, width: buttonWidth+20, height: 30 )
} else {
frame2 = CGRect(x: 10 + widthStack, y: 6, width: buttonWidth+20, height: 30 )
}
widthStack += buttonWidth+32
let button1 = UIButton(frame: frame2)
let attributedTitle = NSAttributedString(string: "\(distinctCategories[i])".uppercaseString, attributes: [NSKernAttributeName: 1.0, NSForegroundColorAttributeName: UIColor.blackColor()])
button1.setAttributedTitle(attributedTitle, forState: .Normal)
button1.titleLabel!.font = UIFont(name: "HelveticaNeue", size: 13.0)
button1.layer.borderWidth = 2.0
button1.layer.borderColor = UIColor.blackColor().CGColor
button1.backgroundColor = UIColor.whiteColor()
button1.addTarget(self, action: "filterByCategory:", forControlEvents: UIControlEvents.TouchUpInside)
self.categoryScrollView.addSubview(button1)
}
}
}
}
The first time you enter the application, the recipes.count is 0, so you are hiding the scroll view by the constraint categoryScrollViewHeight.constant = 0. So next time you create a new recipe, the scroll view is still with a zero height. That's why you didn't see the scroll on first time launch.

Resources