UITableView Section Header Change Style of Current Header - ios

Does anyone know of a built in method or custom way to access and change styles of the CURRENT section header in a UITableView (style plain) as the UITableView is scrolled in Swift.
My preset style for the header is:
override func tableView(tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
let header: UITableViewHeaderFooterView = view as! UITableViewHeaderFooterView //recast your view as a UITableViewHeaderFooterView
header.textLabel.font = UIFont(name: "HelveticaNeue-CondensedBold", size: 14)
header.contentView.backgroundColor = UIColor.groupTableViewBackgroundColor()
header.textLabel.textColor = UIColor.grayColor()
}
Specifically I would like to change the header background color to black and the text color to white only for the current section header as the view scrolls. The style for other headers remain in the preset style.

In a current Application of mine:
override public func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?
{
let view: UIView
if let _view: UIView = tableView.headerViewForSection(section)
{
view = _view
} else {
let dxOffset: CGFloat = 16.0
view = UIView(frame: CGRectMake(dxOffset, 0, tableView.frame.size.width - dxOffset, TableViewViewsHeight.sectionHeight))
}
// create our label
let label: UILabel = UILabel(frame: view.frame)
label.textColor = UIColor.appEmptyTextColor()
label.text = "\(self.letters[section])"
label.font = UIFont.systemFontOfSize(UIFont.smallSystemFontSize() + 4.0)
// create the separator frame
var separatorFrame: CGRect = view.frame
separatorFrame.size = CGSizeMake(separatorFrame.size.width, 1.0)
separatorFrame.offset(dx: 0.0, dy: view.frame.size.height - 1.0)
// create the separator
let imageView: UIImageView = UIImageView(frame: separatorFrame)
imageView.backgroundColor = UIColor.appEmptyGolfTrainingTextColor()
imageView.alpha = 0.4
// add subviews
view.addSubview(label)
view.addSubview(imageView)
// setup the view
view.backgroundColor = UIColor.whiteColor()
return view
}
This creates a header with a white background, a separator and a label containing a letter.
You should be using func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? to change the appearance of your section header.

Related

Swift: Continuous resizing of tableViewCell while user types in a UITextView

Introduction
Context:
I'm creating one of my first apps but I've ran into an issue I cannot figure out.
I have tableView with cells packed with quite a few UIElements. All constraints are done using the EasyPeasy library which basically just sets auto layout constraints ( I have tried setting them manually also). The UITextView in question is constrained by various numbers to the left, right, top and bottom, I have no constraints on it for height or width.
in cellForRowAt indexPath: I set the textView delegate for each cells textView to self, using a delegate property declared within the cells custom class. I also tag every textView with its cells indexPath.row (gives textView.tag integer in textViewDidChange method).
Issue/acknowledgments:
After browsing SO a lot I've found a few questions alike this but I have not been able to make them work for me, I have implemented parts of them that felt logic to my case. I believe the problem differencing my situation from those questions lies in that for my cell design to work the cells has to have a height of itemHeight or higher.
I have noticed that as I type into the textview the textview itself increases in height (even below the cells border but its not visible as it reaches that point), however the cell itself doesn't resize.
I've tried with a cell that only contains a textView so the problem must lie in the textViewDidchange or heightForRowAt indexPath methods.
Question:
What am I doing wrong here? Why doesn't the cells height change dynamically as I type in the textView?
Code:
func textViewDidChange(_ textView: UITextView) {
var newframe = textView.frame
newframe.size.height = textView.contentSize.height - textView.frame.size.height + itemHeight[textView.tag]
textView.frame = newframe
let ndxPath = IndexPath(row: textView.tag, section: 0)
let cell = tableView.cellForRow(at: ndxPath) as! EventsCell
cell.frame = CGRect(x: cell.frame.origin.x, y: cell.frame.origin.y, width: cell.frame.width, height: textView.frame.height)
tableView.beginUpdates()
tableView.setNeedsLayout() //have tried without this line
tableView.layoutIfNeeded() //have tried without this line
tableView.endUpdates()
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if UITableViewAutomaticDimension > itemHeight[indexPath.row] {
return UITableViewAutomaticDimension
} else {
return itemHeight[indexPath.row]
}
}
TextView constraints:
let containerView : UIView = {
let cv = UIView(frame: .zero)
cv.backgroundColor = .white
cv.translatesAutoresizingMaskIntoConstraints = false
cv.layer.cornerRadius = 7
return cv
}()
let eventText : GrowingTextView = { // GrowingTextView is a extension to a regular UITextView
let tv = GrowingTextView()
tv.allowsEditingTextAttributes = true
tv.isScrollEnabled = false
var delegate: UITextViewDelegate?
tv.textContainerInset = UIEdgeInsetsMake(1, 1, 0, 1)
tv.autoresizingMask = .flexibleHeight
tv.translatesAutoresizingMaskIntoConstraints = false
return tv
}()
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
containerView.addSubview(eventText)
contentView.addSubview(containerView)
containerView .easy.layout([Height(CGFloat(95 * itemCount)), Left(8), Right(8)])
eventText .easy.layout([Left(77), Right(5), Top(90), Bottom(4)])
}
Thanks for reading my post.
The constraints that determine the height should be laid out in such a way that the textView is attached directly to the top and bottom of the contentView or to views which are connected to the top and bottom of the contentView, so that autolayout can make out the height by connecting the constraints.
Make sure that you do not mention a height for the textView and disable scrolling. Let automatic dimension take care of all that.
Now all you need to do is call tableView.beginUpdates() and tableView.endUpdates() on textViewDidChange
Here is my repo which demonstrates the same.
OP Edit:
You should store the additional height that you add in a variable in the cell class so the cells can reload an appropriate height when the tableVIew is reloaded.
You should also change textViewDidChange method
cell.frame = CGRect(x: cell.frame.origin.x, y: cell.frame.origin.y, width: cell.frame.width, height: textView.frame.height)
to
let newFrame = ”originalCellHeight” - ”originalTextViewHeight” + textView.contentSize.height
cell.frame = CGRect(x: cell.frame.origin.x, y: cell.frame.origin.y, width: cell.frame.width, height: newFrame )`

Set width and height of UITextView based on the dynamic text

I'm building a chat application where each message are inserted into a row inside a table. Each row contains an avatar and a message. I want to set the width and height of the UITextArea as per the length of the text to put inside.
Below is the code I've used. But here, both height and width are constant (200x50)
PS: I'm a newbie to Swift and ios and I'm using Swift 3. Every code I got after searching is in objective-c or swift 2
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = Bundle.main.loadNibNamed("ChatBox1", owner: self, options: nil)?.first as! ChatBox1
let myTextField: UITextView = UITextView(frame: CGRect(x: 30, y: 20, width: 200.00, height: 50.00));
cell.addSubview(myTextField)
myTextField.isScrollEnabled = false
myTextField.isUserInteractionEnabled = false
myTextField.backgroundColor = UIColor.lightGray
myTextField.text = "Lorem Ipsum is simply dummy text of the printing and typesetting industry."
myTextField.layer.cornerRadius = 5
print(myTextField.intrinsicContentSize)
let image = UIImage(named: "agent")
let imageView = UIImageView(image: image)
imageView.frame = CGRect(x: 0, y: 0, width: 40, height: 40)
cell.addSubview(imageView)
return cell
}
This two methods are done to set Height and width of textview according to the text on chat.
You can use these. (swift 2.3)
var screenrect = UIScreen.mainScreen().bounds
func GET_WIDTH(textView : UITextView , text : String)-> CGFloat
{
textView.text = text;
let size = textView.bounds.size
let newSizeWidth = textView.sizeThatFits(CGSize(width: CGFloat.max, height: size.height))
// Resize the cell only when cell's size is changed
if size.width != newSizeWidth.width
{
if( newSizeWidth.width > screenrect.width-120 )
{
textView.layer.frame.size.width = screenrect.width-120;
}
else if ( newSizeWidth.width < 40 )
{
textView.layer.frame.size.width = 40
}
else
{
textView.layer.frame.size.width = newSizeWidth.width;
}
}
return textView.layer.frame.size.width + 40;
}
func GET_HEIGHT(textView : UITextView , text : String)-> CGFloat
{
textView.text = text;
let size2 = textView.bounds.size
let newSize = textView.sizeThatFits(CGSize(width: size2.width, height: CGFloat.max))
if size2.height != newSize.height
{
if( newSize.height < 40 )
{
textView.layer.frame.size.height = 40
}
else
{
textView.layer.frame.size.height = newSize.height
}
}
return textView.layer.frame.size.height + 15;
}
You have to call the functions of the textview like this to set height and width.
let textViewRight=UITextView(frame: CGRectMake(0, 4, 40, 40));
textViewRight.layer.frame.size.width = GET_WIDTH(textViewRight, text: currentObject.chat_userMessage)
textViewRight.layer.frame.size.height = GET_HEIGHT(textViewRight, text: currentObject.chat_userMessage)
Try this code:
Answer 1:
func tableView(tableView:UITableView!, numberOfRowsInSection section: Int) -> Int {
yourTableViewName.estimatedRowHeight = 44.0 // Standard tableViewCell size
yourTableViewName.rowHeight = UITableViewAutomaticDimension
return yourArrayName.count }
And also put this code inside your Cell for incase...
yourCell.sizeToFit()
Answer 2:
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
in viewDidLoad Add this
tableView.estimatedRowHeight = 44.0
tableView.rowHeight = UITableViewAutomaticDimension
Just add these two lines and your problem will b solved
Take textView height constraint and set it equal to the content size of the textView.
Alternatively, if you use autolayout you can set the content hugging and compression property to 1000. It should expand your cell according to the content.

Resizable TableView Cell

So I have been trying to create a generic chat bubble-ish look with a resizable view and label inside a UITableView cell. Things were working well until I tried to add in the resizable feature. It cuts off just a bit at the bottom (or does not give any margin), and I have not worked with completely dynamic cells like this before so I am not sure how to fix this. I tried adding a 20px buffer but it did not help. I appreciate the help!
(Code below)
import QuartzCore
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
var listOfStrings = [String] ()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// When I Uncomment the 2 lines below, the cell cuts off and only displays a little bit of the blue view.
// self.tableView.rowHeight = UITableViewAutomaticDimension
// self.tableView.estimatedRowHeight = 75
listOfStrings.append("Switch, Button, Segmented Control, Slider, Textfield")
listOfStrings.append("Switch, Button, Segmented Control, Slider, Textfield")
listOfStrings.append("Switch, Button, Segmented Control, Slider, Textfield")
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print(indexPath.row)
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("someCell") as! SomeTableViewCell
cell.contentView.viewWithTag(0)!.backgroundColor = UIColor.clearColor()
let size = cell.layer.bounds
let tableSize = self.tableView.layer.bounds
let viewCGR = CGRect(x: size.minX, y: size.height/2, width: tableSize.width, height: size.height/2)
let view: UIView = UIView(frame: viewCGR)
let labelCGR = CGRect(x: 0, y: 0, width: viewCGR.width, height: viewCGR.height)
let label: UILabel = UILabel(frame: labelCGR)
label.numberOfLines = 0
label.preferredMaxLayoutWidth = CGRectGetWidth(tableView.bounds)
label.textAlignment = NSTextAlignment.Center
label.text = listOfStrings[indexPath.row]
label.sizeToFit()
self.tableView.updateConstraints()
let newViewCGR = CGRect(x: viewCGR.minX, y: viewCGR.minY, width: label.frame.width+20, height: label.frame.height+20)
view.frame = newViewCGR
view.sizeToFit()
label.textColor = UIColor.blackColor()
label.center.x = view.center.x
// self.tableView.updateConstraints()
view.addSubview(label)
self.tableView.updateConstraints()
view.backgroundColor = UIColor.blueColor()
view.layer.cornerRadius = 6
cell.addSubview(view)
self.tableView.updateConstraints()
return cell
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return listOfStrings.count
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Btw I am not using autolayout + constraints to get the functionality of having the bubble be able to appear on the left or right (depending on incoming or outgoing).
After the new API by apple you don't calculate height. You just use autolayout to do the work. I think this link could help you a lot. By the way there is a nice tutorial Self-sizing Table View Cells
you don't have to calculate height row for height cell .
you add this code in viewDidLoad()
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 50
#Ryan find the height of the cell with the text using following method,
CGRect textRect =
[attributedText boundingRectWithSize:CGSizeMake(cellWidth, CGFLOAT_MAX)
options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
context:nil];
call this method from
heightForRowAtIndexPath:
and set the height of the cell here as textRect.size.height

View for Header in section with different height in different UITableViews

This is my Split View Controller with two controllers. In both I use UITableView. In both I implement tableView(viewForHeaderInSection:) method.
override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
var title = "Some Title"
return UIView.viewForHeaderInSectionWithTitle(title)
}
My UIView extesion:
extension UIView {
class func viewForHeaderInSectionWithTitle(title: String) -> UIView? {
var headerView: UIView?
headerView = UIView(frame: CGRectMake(0, 0, CGRectGetWidth(UIScreen.mainScreen().bounds), 25))
headerView!.backgroundColor = UIColor.catskillWhite()
let frame = CGRectMake(15, 3, CGRectGetWidth(headerView!.frame) - 15, 19)
let label = UILabel(frame: frame)
label.text = title
label.numberOfLines = 0
label.textColor = UIColor.curiousBlue()
label.font = UIFont.latoLightFontWithSize(15)
label.sizeToFit()
headerView!.addSubview(label)
return headerView
}
}
So same source, but different result. Why? The height is different, and label is not centered in the second one. Any ideas?

Subview in cell loses color when tableview is changing

I have an UITableView which has a dynamic subview.
When the table is static it looks like this:
The round view with the T is the custom subview
But when I choose edit and drag the table cell the it looses it's color and the T.
Whats the reason for this?
I initialize the cell like this (It's an prototype IB Cell):
func configureCell(cell: UITableViewCell, atIndexPath indexPath: NSIndexPath) {
let object = self.fetchedResultsController.objectAtIndexPath(indexPath) as Item
//cell.textLabel.text = object.valueForKey("name")!.description
let cSubView = cell.viewWithTag(100) as RoundedIcon
cSubView.setUpViewWithFirstLetter(String(first(object.name)!).uppercaseString)
}
And the RoundedIcon works like this:
override init(frame: CGRect) {
super.init(frame: frame)
self.layer.cornerRadius = self.frame.size.width / 2;
self.layer.borderWidth = 1.0;
self.layer.borderColor = UIColor.lightGrayColor().CGColor;
self.clipsToBounds = true;
}
func setUpViewWithFirstLetter(letter:String){
self.backgroundColor = RoundedIcon.UIColorFromRGB(0x68C3A3)
let theLetterLabel = UILabel()
theLetterLabel.text = letter
theLetterLabel.textColor = UIColor.whiteColor()
theLetterLabel.textAlignment = .Center
theLetterLabel.font = UIFont.systemFontOfSize(25)
self.addSubview(theLetterLabel)
theLetterLabel.frame = CGRect(origin: CGPoint(x: 0, y: 0), size: self.frame.size)
}
#rdelmar's comment pointed me in the right direction that an UITableview changes the background color of all it's cells to:
UIColor(white:0,alpha:0)
If you don't want your view to change it's color you should change the backgroundColor property setter, which works in swift like this:
//override this setter to avoid color resetting on drag
override var backgroundColor:UIColor?{
didSet {
//check the color after setting - you also can do it earlier
if let bgCol = backgroundColor{
println(bgCol)
if bgCol == UIColor(white: 0, alpha: 0){ //check if it's settled by the table
super.backgroundColor = yourColor //set it back to your color
}
}
}
}

Resources