I have a table view and I need to show author_img in section header. In ViewForSectionHeader method, I want to make the image to be circular. But If I did that, the images are not showing at all, no matter in simulator or in real device. If I remove the code, uiimageview will show the images normally. I set up the width and height constraint for uiimageview because I want to get fixed size of showing images. So Any ideas, please?
cell.author_img.layer.cornerRadius = cell.author_img.frame.size.width/2
cell.author_img.layer.masksToBounds = true
// add a boundary for thumb
cell.author_img.layer.borderWidth = 1.5
cell.author_img.layer.borderColor = UIColor.whiteColor().CGColor
It may come from the fact that you are setting the cornerRadius too early, the final size of your author_img is not fixed yet.
Try to set that cornerRadius when you are sure that the layout of your cell has been entirely calculated.
For test purpose, just to make sure it is coming from this behaviour, try to hardcode the cornerRadius.
cell.author_img.layer.cornerRadius = 10
If your image has a slight cornerRadius, it means that the issue is coming from what I explained earlier, if it is still not showing, it is coming from something else.
If it does come from the fact the size of your image is not fixed, try to set your cornerRadius in something like viewDidAppear, I mean the latest you can do.
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView : UIView = UIView.init(frame: CGRectMake(0, 0, tableView.frame.size.width, 40))
headerView.backgroundColor = UIColor(red: 75/255.0, green: 193/255.0, blue: 210/255.0, alpha: 1.0)
let iconimage: UIImageView = UIImageView(frame: CGRectMake(10, 0, 40, 40))
iconimage.image = UIImage(named: "original.jpg")
iconimage.layer.cornerRadius = iconimage.frame.size.height / 2
iconimage.layer.borderColor = UIColor.whiteColor().CGColor
iconimage.layer.borderWidth = 1.0
iconimage.clipsToBounds = true
let subjectNameLabel = UILabel(frame: CGRect(x: 60, y: 4, width: 250, height: 35))
subjectNameLabel.textAlignment = NSTextAlignment.Center
subjectNameLabel.font = UIFont (name: "HelveticaNeue", size: 16)
subjectNameLabel.textColor = UIColor.whiteColor()
headerView.userInteractionEnabled = true
if isFristtime == true {
let subjectNameTxtValue = "Mile Ho Tum Humko"
subjectNameLabel.text = subjectNameTxtValue
}else{
let subjectNameTxtValue = "Saiyaan"
subjectNameLabel.text = subjectNameTxtValue
}
subjectNameLabel.backgroundColor = UIColor(red: 75/255.0, green: 193/255.0, blue: 210/255.0, alpha: 1.0)
headerView.addSubview(iconimage)
headerView.addSubview(subjectNameLabel)
return headerView
}
func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 40
}
Related
I'm building an app with a messenger like interface. I use a tableView to accomplish this. Each cell contains a UIView - the message bubble and a UILabel - the message that is nested in the UIView.
It works great on texts of small sizes but for some reason when the UILabel is supposed to break lines it doesn't and it all is in one line. The amount of lines is set to zero.
This is my message handling class:
func commonInit() {
print(MessageView.frame.height)
MessageView.clipsToBounds = true
MessageView.layer.cornerRadius = 15
myCellLabel.numberOfLines = 0
let bubbleSize = CGSize(width: self.myCellLabel.frame.width + 28, height: self.myCellLabel.frame.height + 20)
print(bubbleSize.height)
MessageView.frame = CGRect(x: self.frame.origin.x, y: self.frame.origin.y, width: bubbleSize.width, height: bubbleSize.height)
if reuseIdentifier! == "Request" {
MessageView.layer.maskedCorners = [.layerMaxXMinYCorner, .layerMinXMinYCorner, .layerMinXMaxYCorner]
MessageView.backgroundColor = UIColor(red: 0, green: 122/255, blue: 1.0, alpha: 1.0)
} else {
MessageView.layer.maskedCorners = [.layerMaxXMinYCorner, .layerMinXMinYCorner, .layerMaxXMaxYCorner]
MessageView.backgroundColor = UIColor.lightGray
}
}
Cell calling function:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if queryCounter % 2 == 0 && indexPath.row % 2 == 0{
cellReuseIdentifier = "Answer"
} else {
cellReuseIdentifier = "Request"
}
let cell:MessageCell = self.tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as! MessageCell
cell.myCellLabel.textColor = UIColor.white
cell.myCellLabel.text = self.messages[indexPath.row]
let height = cell.myCellLabel.text!.height(withConstrainedWidth: cell.myCellLabel.frame.width, font: cell.myCellLabel.font)
print(height)
cell.contentView.transform = CGAffineTransform(scaleX: 1, y: -1)
return cell
}
The height variable is calculated based on text size. It shows that the text size is calculated normally - accounting for line break.
I was unable to modify the cell height based on this calculation - nothing I tried works.
I think it might be a constraints issue.
My Constraints:
How do I make the lines break? Please help.
EDIT: I just notice that the MessageView.frame = CGRect(x: self.frame.origin.x, y: self.frame.origin.y, width: bubbleSize.width, height: bubbleSize.height) has no affect what so ever on the message bubbles.
Setting the frame while using autolayout won't work.
I can't say what exactly happens here without the entire context, but some common pitfalls when reusing cells and autolayout are:
Forgetting to set automatic height for your cells (expanding cell in a storyboard manually will override this setting)
Tableview also needs estimatedHeight sometimes to work properly
Sometimes you need to call setNeedsLayout after you add content to
the cell
Check the console and if there are some warnings about breaking constraints, you can easily find issues there.
Try to find the label height based on label width and text font and then set your label height constraint to that.
extension String {
func height(withConstrainedWidth width: CGFloat, font: UIFont) -> CGFloat {
let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSAttributedStringKey.font: font], context: nil)
return ceil(boundingBox.height)
}
}
something like this:
let textHeight = yourtext.height(withConstrainedWidth: yourlabel.frame.width, font: font)
yourLabel.heightAnchor.constraint(equalToConstant: textHeight).isActive = true
After multiple hours of trying everything I managed to fix it. The problem was with the constraints.
1. As you can see the in this old layout. The UIView was constrained everywhere except the left -> that's where the text goes.
The commonInit() method of the UITableViewCell was called before any text was initialized. That's not good because all of the cell resizing is based on text which was not yet passed to the cell -> Move the method after cell initialization.
let cell:MessageCell = self.tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as! MessageCell
cell.myCellLabel.text = self.messages[indexPath.row]
//Before calling commonInit() we need to adjust the cell height.
let height = cell.myCellLabel.text!.heightForView(text: cell.myCellLabel.text!, font: cell.myCellLabel.font, width: self.view.frame.width / 2)
// Then we set the width of the UILabel for it to break lines at 26 characters
if cell.myCellLabel.text!.count > 25 {
tableView.rowHeight = height + 20
cell.myCellLabel.widthAnchor.constraint(equalToConstant: cell.frame.width / 2).isActive = true
cell.updateConstraints()
}
// Calling commonInit() after adjustments
cell.commonInit()
cell.contentView.transform = CGAffineTransform(scaleX: 1, y: -1)
return cell
Then we need to update the constraints so that the UIView and UILabel resize with the cell height.
Done. Now it works as needed. Thank you for all of the suggestions!
I tried to add UIView over my UIImage. But it doesn't work for me.
When I reduce and increase my image, UIView moved down and doesn't cover completely my image.
I use double click for zooming.
#objc func doubleTap(gestureRecognizer: UITapGestureRecognizer) {
if self.productScrollView.zoomScale == 1 {
self.productScrollView.zoom(to: self.zoomRectForScale(scale: self.productScrollView.maximumZoomScale, center: gestureRecognizer.location(in: gestureRecognizer.view)), animated: true)
} else {
self.productScrollView.setZoomScale(1, animated: true)
}
}
I tried to use these codes, but it doesn't work for me.
first:
let tintView = UIView()
tintView.backgroundColor = UIColor(white: 0, alpha: 0.5)
tintView.frame = CGRect(x: 0, y: 0, width: imageView.frame.width,
height: imageView.frame.height)
imageView.addSubview(tintView)
Second:
let tintView = UIView()
tintView.backgroundColor = UIColor(white: 0, alpha: 0.5)
tintView.translatesAutoresizingMaskIntoConstraints = false
imageView.addSubview(tintView)
NSLayoutConstraint.activate([
tintView.bottomAnchor.constraint(equalTo: imageView.bottomAnchor),
tintView.leadingAnchor.constraint(equalTo: imageView.leadingAnchor),
tintView.trailingAnchor.constraint(equalTo: imageView.trailingAnchor),
tintView.topAnchor.constraint(equalTo: imageView.topAnchor),
])
also, I tried to add on storyboard, but it also doesn't work for me.
Does anyone have ideas or suggestions?
Try to add your UIView to the main view of your viewController instead of UIImageView and set constraints to the imageView
i am trying to get a cell to resize to the text/or image inside it. But also the labels have some rounded corners depending on their position. I have tried using snippets like:
let path = UIBezierPath(roundedRect:cell.receivedText!.bounds, byRoundingCorners:[.TopRight, .BottomLeft, .BottomRight], cornerRadii: CGSizeMake(30, 30))
let maskLayer = CAShapeLayer()
maskLayer.path = path.CGPath
cell.receivedText!.layer.mask = maskLayer
and
tableView.estimatedRowHeight = 44
tableView.rowHeight = UITableViewAutomaticDimension
but i cant get the two to work in conjunction.
Here is my current code minus snippets that didnt work:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
createConversation()
let cell: ConversationCell = tableView.dequeueReusableCellWithIdentifier("ConversationCell") as! ConversationCell
if conversation.conversationArray[indexPath.row].isAReceivedMessage == true {
cell.receivedText!.text = conversation.conversationArray[indexPath.row].text
cell.receivedText!.textAlignment = .Left
cell.receivedText!.sizeToFit()
cell.receivedProfileImage!.image = self.conversationProfileImage!.image
cell.receivedText!.backgroundColor = UIColor(red: 44/255, green: 99/255, blue: 105/255, alpha: 5/100)
} else {
cell.sentText!.text = conversation.conversationArray[indexPath.row].text
cell.sentText!.textAlignment = .Right
cell.sentText!.backgroundColor = UIColor(red: 204/255, green: 115/255, blue: 115/255, alpha: 1)
cell.sentText!.sizeToFit()
}
return cell
}
This is what im trying to achieve
Thanks for any help in advance.
but i cant get the two to work in conjunction.
There are two problems:
Timing. When a view is resized, its mask is not resized. Thus, if you attach the mask before you know the final size of the view, you will get the wrong answer.
Resuse. Don't forget that a cell is reused. Thus, in cellForRow, you always need to remove the existing mask if there is one, because you're doing to be making another one to fit the new resized cell.
I have tableView cellForRowAtIndexPath function:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: ProjectCell = tableView.dequeueReusableCellWithIdentifier("Cell") as! ProjectCell
let rightUtilityButtons = NSMutableArray()
rightUtilityButtons.sw_addUtilityButtonWithColor(UIColor(red: 255.0/255.0, green: 200.0/255.0, blue: 122.0/255.0, alpha: 1.0), icon: UIImage(named: "ic_edit"))
rightUtilityButtons.sw_addUtilityButtonWithColor(UIColor(red: 255.0/255.0, green: 120.0/255.0, blue: 122.0/255.0, alpha: 1.0), icon: UIImage(named: "ic_close"))
cell.setRightUtilityButtons(rightUtilityButtons as [AnyObject], withButtonWidth: 70)
cell.delegate = self
let project = projects[indexPath.row] as! Project
cell.projectNameLabel.text = project.name
cell.projectDescriptionLabel.text = project.desc
cell.projectDateLabel.text = project.duedate
cell.customView.backgroundColor = getColor(indexPath.row * 10)
cell.backView.layer.cornerRadius = 6
cell.backView.layer.shadowColor = UIColor.blackColor().CGColor
cell.backView.layer.shadowOffset = CGSize(width: -1, height: 1)
cell.backView.layer.shadowOpacity = 0.5
return cell
}
And Problem is here:
cell.backView.layer.shadowColor = UIColor.blackColor().CGColor
cell.backView.layer.shadowOffset = CGSize(width: -1, height: 1)
cell.backView.layer.shadowOpacity = 0.5
Without this code, my table view works great. How to solve this problem. Maybe better place for my cell view will be willDisplayCell, but how to put this code there?
Move the code you are setting the shadow to cell's initialization. Right now, the shadow is set every time delegate returns cell to the table view. You don't have to do this for cells that are just being reused and already have shadow configured.
Remember to set shadowPath when dealing with shadows. It improves performance.
[view.layer setShadowPath:[[UIBezierPath bezierPathWithRect:view.bounds] CGPath]];
You can try next things to improve shadow performance:
Move shadow initialization to cell's initialization methods.
Rasterize your layer, using shouldRasterize property of CALayer (also you should set rasterizationScale property to UIScreen.mainScreen().scale)
Use shadowPath property of CALayer instead shadowOffset, like this:
_
var shadowBounds = self.bounds
shadowBounds = CGRectOffset(shadowBounds, -1, 1)
let cornerRadius = 6
layer.shadowPath = UIBezierPath(roundedRect: shadowBounds, cornerRadius: cornerRadius).CGPath
As an alternative way you can use resizable transparent image below your cell.
I am using a PageViewController which loads multiple images. I can slide through the images one by one. I now want to zoom that ImageView, how can I achieve it. Thanks in advance.
I have this in my viewDidLoad
var vWidth = self.view.frame.width
var vHeight = self.view.frame.height
var scrollImg: UIScrollView = UIScrollView()
scrollImg.delegate = self
scrollImg.frame = CGRectMake(0, 0, vWidth, vHeight)
scrollImg.backgroundColor = UIColor(red: 90, green: 90, blue: 90, alpha: 0.90)
scrollImg.alwaysBounceVertical = false
scrollImg.alwaysBounceHorizontal = false
scrollImg.showsVerticalScrollIndicator = true
scrollImg.flashScrollIndicators()
scrollImg.minimumZoomScale = 1.0
scrollImg.maximumZoomScale = 10.0
self.view.addSubview(scrollImg)
scrollImg.addSubview(contentImageView!)
And then the delegate of the scrollview
func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
return self.contentImageView
}
Now the image gets kind of zoomed abnormally, focusing mostly on the top. And not able to pan it.