Center text around specific word in table cell using Swift - swift

I have a UITableView with multiple cells, each containing a sentence of attributed text. I would like to know how to centre the text in each of these cells around a specific word contained in those sentences.
The result would be a central column of the word but each cell containing different surrounding words.
I'm guessing the place to start is to centre the text in the cell array but doing so in the "cellForRowAtIndexPath" delegate method with the line:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
self.cell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "cell")
if(cell.isEqual(NSNull)) {
self.cell = NSBundle.mainBundle().loadNibNamed("cell", owner: self, options: nil)[0] as! UITableViewCell;
}
self.cell.detailTextLabel?.text = self.synonymsCategories[indexPath.row]!
self.cell.textLabel?.attributedText = self.synonymsContext[indexPath.row]
self.cell.detailTextLabel?.textAlignment = .Right
self.cell.textLabel?.textAlignment = NSTextAlignment.Center
self.cell.textLabel?.backgroundColor = UIColor.greenColor()
return self.cell as UITableViewCell
}
But no changes I make to "self.cell.textLabel" produce any visual changes at run time.
Any ideas? Any help much appreciated.
Felix

Related

UITableViewCell title positioning

I am creating an app with UITableViewCells that expand when selected. However, when the cell expands, the title (and subtitle) are moving downwards to stay centered vertically in the cell. I'd like them to stay where they were originally but can't figure out how to do it.
I have tried setting the frame manually with cell.textLabel?.frame = myRect, but this does nothing. I am unable to find any constraints, as print(cell.textLabel?.constraints) returns optional([]).
Here are my normal cells and my expanded cells.
My code for creating the cells:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier")
if cell == nil {
cell = UITableViewCell(style: .value1, reuseIdentifier: "reuseIdentifier")
}
cell!.textLabel?.text = content[indexPath.row]
cell!.clipsToBounds = true
cell!.selectionStyle = .none
cell!.detailTextLabel?.text = detailContent[indexPath.row]
return cell!
}
Any help would be greatly appreciated.
You are using a standardized cell, the title and detail are fixed, i think you need make a custom cell for your project
Look this project I make a simple test with customized cell
https://github.com/TexugoProgramador/Teste-Celula-Customizada

textAlignent to right in cellForRowAt in Swift 3.0

I cannot manage to get my text to align to the right side of my table view. My code sets the text alignment to right but it only justifies the text if there is more that 1 line. Here is my cellforRowAt code
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .subtitle, reuseIdentifier: cellId)
cell.textLabel?.text = self.messages[indexPath.row]
cell.textLabel?.numberOfLines = 0
cell.textLabel?.textAlignment = .right
return cell
}
How can I fix this?
You're using the subtitle UITableViewCell style aren't you? This is a style that for what ever reason don't allow you to override the text label's alignment.
To solve this problem, you can make a simple subclass of UITableViewCell with a label in the same position.
Let change the style of cell to default:
let cell = UITableViewCell(style: .default, reuseIdentifier: cellId)
I created a subtitle cell in the storyboard and I realized the textLabel's size is fit to its content. So you can't align the text of textLabel. But you can do this with basic cell, its size is matched to the cell.

Dynamically add subViews to UITableViewCell

I need to add UILabels to UITableViewCell, but its dynamic, first cell can have 1 label, second can have 4 and I dont know before hand. So I tried this
func tableView(_ tableView: UITableView, cellForRowAtIndexPath indexPath: IndexPath) -> UITableViewCell {
let cell: ReviewTableViewCell = reviewTableView.dequeueReusableCell(withIdentifier: "Review", for: indexPath) as! ReviewTableViewCell
var reviewObj:Review!
reviewObj = reviewArray[(indexPath as NSIndexPath).row]
let viewsAdded = commentViewsAddedDict[indexPath.row]
if(viewsAdded == nil)
{
for comment in reviewObj.commentArray
{
let label1 = UILabel()
label1.text = “text1”
label1.textColor = UIColor(hexString: "#333333")
let label2 = UILabel()
label2.text = “text2”
label2.numberOfLines = 0
label2.sizeToFit()
label2.textColor = UIColor(hexString: "#666666")
let label3 = UILabel()
label3.text = "----------------------------------------------------------------------"
label3.textColor = UIColor(hexString: "#eeeeee")
cell.stackView1.addArrangedSubview(label1)
cell.stackView1.addArrangedSubview(label2)
cell.stackView1.addArrangedSubview(label3)
}
commentViewsAddedDict[indexPath.row] = true
}
return cell
}
But what happens, the previously added views are not removed and it again tries to add new views.
So I want to know, what is the efficient way to do this.
Secondly, where I am going wrong.
Regards
Ranjit
You are using commentViewsAddedDict to figure out whether rows have been added or not. But whether these labels were added or not is not a function of the row in the table, but rather of the cell, which is reused.
So, I'd would advise:
eliminate this commentViewsAddedDict logic; and
move the logic regarding how many labels have been added to ReviewTableViewCell.
So, you might end up with:
func tableView(_ tableView: UITableView, cellForRowAtIndexPath indexPath: IndexPath) -> UITableViewCell {
let cell = reviewTableView.dequeueReusableCell(withIdentifier: "Review", for: indexPath) as! ReviewTableViewCell
var reviewObject = reviewArray[(indexPath as NSIndexPath).row]
cell.updateLabels(for: reviewObject)
return cell
}
And in ReviewTableViewCell:
func updateLabels(for reviewObject: ReviewObjectType) {
// add label if needed
// update label `text` if needed
// remove any labels that need to be removed
}
It's a little hard to be specific on the logic in updateLabels as the provided code snippet in the question is unclear, but the basic idea is that the ReviewTableViewCell should keep track of whether its labels have been added or not, and on the basis of the reviewObject, decide whether it needs to add a label, update an existing label, or remove any labels not needed for this particular reviewObject. But all of this "label state" logic is a function of the cell (which can be reused), not of which row in the table to which the cell corresponds.

Set action for subview inside a table cell (swift)

When i clicked the subview,it didn't trigger subview's action. But i have selected whole cell. How to fix it?
Here is my code.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("idcell", forIndexPath: indexPath) as UITableViewCell
let lblTitle : UILabel = cell.contentView.viewWithTag(101) as! UILabel
lblTitle.text = (deptId[indexPath.row] as? String)! + " " + (deptDesc[indexPath.row] as? String)!
var height:CGFloat = 40
if(indexPath.row == departmentSelectedRow){
for i in 0...deptProfile.count-1{
let label = UILabel(frame: CGRectMake(0,height,400,30))
label.targetForAction("sadasdd", withSender: nil)
height = height+40
label.text = ("ewrewrewre")
label.backgroundColor = UIColor.redColor()
cell.addSubview(label)
}
}
return cell
}
If you want to interact with something inside a cell (rather than select the whole cell) then you should use a button or a gesture recogniser. These are properly interactive elements that you can add a target and action to.
You should also change how you're using cells, specifically:
Use custom cell classes, so you can directly reference the cell elements instead of using viewWithTag which is bad practice
Use multiple different cell classes (and thus identifiers) so you can use actually different cells for selected and unselected rows
Don't create and add subviews on the fly, this is what the different cell classes are for

problems with UITableView and reuseablecells

so i am experiencing two problems right now with my (pretty basic) tableview. i will paste my code below but here is the general gist: i'm making a dictionary app, so each cell contains two labels for the two languages. if a cell gets tapped, i'd like for: 1. cell height increase, 2. font size increase, 3. text align center, 4. cell background change color.
i've also included code to 'reset' a selected cell if it is selected a second time - this seems to be causing my second problem
the problem is when a cell is selected:
those four things happen to cells which are currently offscreen.
the program crashes when: i select cell 0, the cell changes which is fine, but when i click on any cell that is offscreen at the time (say cell 10) the program will crash giving me this error:
fatal error: unexpectedly found nil while unwrapping an Optional value
code:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
// reset previous cell but only if selectedRow isn't -1 which is initial value
if selectedRowIndex != -1{
let previousCell = convoTable.cellForRowAtIndexPath(NSIndexPath(forRow: selectedRowIndex, inSection: 0)) as! PhraseTableViewCell
previousCell.backgroundColor = UIColor.whiteColor()
previousCell.lang2Label.font = UIFont(name: (previousCell.lang2Label?.font?.fontName)!, size: (previousCell.lang2Label?.font?.pointSize)! - 5)
previousCell.lang2Label.textAlignment = .Right
}
//make changes to new cell that was pressed upon
if selectedRowIndex != indexPath.row{
print("new cell got selected")
cellSelected = true
// save the selected index
self.selectedRowIndex = indexPath.row
let cell = self.convoTable.cellForRowAtIndexPath(indexPath) as! PhraseTableViewCell
cell.lang2Label.font = UIFont(name: (cell.lang2Label?.font?.fontName)!, size: (cell.lang2Label?.font?.pointSize)! + 5)
cell.backgroundColor = UIColor.cyanColor()
cell.lang2Label.textAlignment = .Center
// update the height for all the cells
self.convoTable.beginUpdates()
self.convoTable.endUpdates()
cell.lang1Label.frame = CGRectMake(3,0, cell.bounds.width, cell.bounds.height/3)
cell.lang2Label.frame = CGRectMake(-3,cell.bounds.height/3, cell.bounds.width, cell.bounds.height/3 * 2)
}
else {
print("same cell pressed")
cellSelected = false
selectedRowIndex = -1
}
self.convoTable.beginUpdates()
self.convoTable.endUpdates()
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! PhraseTableViewCell
cell.lang1Label.text = items![indexPath.row].eng
cell.lang2Label.text = items![indexPath.row].prs
return cell
}
thank you all very much, this help is much appreciated.
so there is no real answer to the questions i posed, the best workaround is to just have another array which maintains the states in the cells. sucks i know but really the best "solution"