I have UITableView with static cells. I have set equal Content View height constraint equals to UIPicker view height. I have also implemented didSelectRowAt method with changing UITableViewCell content view.
https://youtu.be/lJuTLQ1oTaE
Magic happens, changing height of TableViewCell is animated. But the following change of UIPickerView height is happening simultaneously, with no animation. I have tried to put UIView.animate with layoutIfNeeded(), but it did not help.
How to animate such auto change of UIPickerView height?
// TableView functions
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) {
let reuseIdentifier = cell.reuseIdentifier
guard reuseIdentifier != nil else {return}
if reuseIdentifier == "currencyPickerTableViewCell" && self.selectedCellIndexPath == nil {
self.skipCellsFromGestureRecognition.append(indexPath)
self.selectedCellIndexPath = indexPath
print(currencyPicker.constraints)
tableView.beginUpdates()
tableView.endUpdates()
} else if reuseIdentifier == "currencyPickerTableViewCell" && self.selectedCellIndexPath != nil {
self.selectedCellIndexPath = nil
self.tableView.beginUpdates()
self.tableView.endUpdates()
}
}
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if self.selectedCellIndexPath == indexPath {
return self.selectedCellHeight
} else {
return self.unselectedCellHeight
}
}
The animation actually happens but as the font of the UIPicker stays the same you can't see it , so change the font inside UIView.animate , also note that your width of the picker is static so, number of trimmed characters will be increased as the font becomes larger . . .
Related
I have a tableView and cells. The Cells are loaded from a xib and they have a label with automatic height. I need to narrow one cell if the user taps on it.
I have tried hiding - doesn't work
I have tried removeFromSuperView()- doesn't work
Is there any alternative?
When setting up your tableViewCell store the height anchor you want to update
var yourLabelHeightAnchor: NSLayoutConstraint?
private func setupLayout() {
yourLabelHeightAnchor = yourLabel.heightAnchor.constraint(equalToConstant: 50)
// Deactivate your height anchor as you want first the content to determine the height
yourLabelHeightAnchor?.isActive = false
}
When the user clicks on a cell, notify the tableView that the cell is going to change, and activate the height anchor of your cell.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.dequeueReusableCell(withIdentifier: "YourTableViewCellIdentifier") as? YourCell
self.tableView.beginUpdates()
cell?.yourLabelHeightAnchor?.isActive = true
self.tableView.endUpdates()
}
Did you try to do something like this:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
var result: CGFloat
if (indexPath.row==0) {
result = 50 }
else {result = 130}
return result
}
This is just an example where height is changed for the first row. I tested on my application and it gave result like this.
No article explains it clearly regarding my query, I have three cells in a static table and I want to hide second cell when users taps on first cell. Any kind of help is appreciated.
Although you cannot stop the static table from trying to show your cells, you can set their height to zero, making them effectively invisible:
Add this method to your table view controller delegate class:
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
let cell = super.tableView(tableView, cellForRowAtIndexPath: indexPath)
return cell == myHiddenCell ? 0 : super.tableView(tableView, heightForRowAtIndexPath:indexPath)
}
In the didSelectCellAtIndexPath method, you can set the height to 0 to hide it :
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if indexPath.row == 0 {
let indexPath = NSIndexPath(forItem: 1, inSection : 0)
let secondCell = tableview.cellForRowAtIndexPath(indexPath)
secondCell.frame.size.height = 0;
self.view.layoutSubviews()
}
}
If you want an animation, just put self.view.layoutSubviews() in an UIView animation method UIView.animateWithDuration... etc
For me, setting the height to 0 for some cells and another height for other cells wasn't an option, as all my cells have different height.
I created another cell in Storyboard, and set row height of 0 (in size inspector). Then in the code, I show the cell with height = 0 if I want to hide it, if not, I show the other cell:
if (hideCell) {
let hiddenCell = tableView.dequeueReusableCell(withIdentifier: "hiddenCell",for: indexPath) as! TheWallTableViewCell
return hiddenCell
}
else {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell",for: indexPath) as! TheWallTableViewCell
return cell
}
I have a tableview which uses UITableViewAutomaticDimension to calculate cell height. I am trying to make the cells expand when tapped a la Twitter but I'm having trouble with the cell expansion even though cell returning to normal size works fine. I want each cell to expand by a constant value (e.g. 50) but I can't seem to grab the selected cell height and add 50 to it since heightForRowAtIndexPath is called before cellForRowAtIndexPath. Anyone have any insight on what I can do?
Here's my code:
var selectedIndexPath: NSIndexPath? = nil
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if !hasImageAtIndexPath(indexPath) {
var cell = tableView.cellForRowAtIndexPath(indexPath) as! TimelineTableViewCell
} else {
var cell = tableView.cellForRowAtIndexPath(indexPath) as! TimelineTableViewCellImage
}
switch selectedIndexPath {
case nil:
selectedIndexPath = indexPath
default:
if selectedIndexPath! == indexPath {
selectedIndexPath = nil
} else {
selectedIndexPath = indexPath
}
}
tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
let smallHeight: CGFloat = UITableViewAutomaticDimension
//Here is where I'm having trouble. Cells have a height of 50 and not current height +50
let expandedHeight: CGFloat = UITableViewAutomaticDimension+50
let ip = indexPath
if selectedIndexPath != nil {
if ip == selectedIndexPath! {
return expandedHeight
} else {
return smallHeight
}
} else {
return smallHeight
}
}
-tableView:heightForRowAtIndexPath: should always return UITableViewAutomaticDimension. In fact you can just do self.tableView.rowHeight = UITableViewAutomaticDimension.
To make your cell higher, you change the cell constraints in -tableView:cellForRowAtIndexPath: so either your content constraint is higher or your cell height constant constraint is taller.
i'm trying to Hide a cell from a UITableView. just like the delete action do but i just want to hide it to later show it in the same position.
i know that UITableViewCell has a property called "Hidden" but when i hide the Cell using this property it hide but no animated and they leave a blank space
Example:
first cell
second cell
third cell
it's possible that when i hide the second cell, that third cell change position to 2 ?
thanks
One way to effectively "hide" a row with animation and without actually removing it is to set it's height to zero. You'd do so by overriding -tableView:heightForRowAtIndexPath:.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
CGFloat height = 0.0;
if (isRowHidden) {
height = 0.0;
} else {
height = 44.0;
}
return height;
}
(You'd only want to return 0.0 for the specific row or rows you want to hide of course, not unconditionally).
Simply changing the return value of this method doesn't make the table view automatically adjust the row's height, to make it do so you make the following calls.
isRowHidden = YES;
[tableView beginUpdates];
[tableView endUpdates];
If you do so you'll see an animated appearance/disappearance transition between the two.
In SWIFT you need to do two things,
HIDE your cell. (because reusable cell may conflict)
Set Height of cell to ZERO.
Look at here,
HIDE cell
func tableView(tableView: UITableView,
cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
if indexPath.row == 1 {
cell?.hidden = true
} else {
cell?.hidden = false
}
return cell
}
Set Height of cell to ZERO.
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
var rowHeight:CGFloat = 0.0
if(indexPath.row == 1){
rowHeight = 0.0
} else {
rowHeight = 55.0 //or whatever you like
}
return rowHeight
}
Using this you can remove reusable cell conflict issues.
You can do the same for cell?.tag also to hide specific cell by tag.
Ref: https://stackoverflow.com/a/28020367/3411787
You can't simply hide a UITableViewCell. You have to remove that cell from the table view then insert it again when you would like it to reappear in the table.
The methods you're looking for are deleteRowsAtIndexPaths:withRowAnimation: and insertRowsAtIndexPaths:withRowAnimation:. These are well documented in the UITableView documentation here. You're going to have to remember where you removed the cell from then insert it at the same position later.
Keep in mind that if you add cells to your table with a lesser row index than the row index of the deleted row, you will have to add on to the index to maintain it's relative position.
Hope this helps.
Same as Zaid Pathan but for Swift 4:
//HIDE you cell.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: NSIndexPath) -> UITableViewCell {
let myCell = tableView.dequeueReusableCell(withIdentifier: "cellID", for: indexPath) as! UITableViewCell
//hide second cell
indexPath.row == 1 ? (cell.isHidden = true): (cell.isHidden = false)
return myCell
}
//Set Height of cell to ZERO.
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
var rowHeight:CGFloat = 0.0
indexPath.row == 1 ? (rowHeight = 0.0): (rowHeight = 49.0)
return rowHeight
}
If you want the other cells to have a dynamic height:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.row == 1 { // Or any other row
return 0
}
return -1.0
}
I am using Hidden in Attributes Inspector of TableViewCell -> ContentView and then implement method:
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if shouldHideSection(indexPath.section) {
return 0.0
} else if let isHidden = tableView.cellForRow(at: indexPath)?.contentView.isHidden, isHidden {
return 0.0
}
return super.tableView(tableView, heightForRowAt: indexPath)
}
You should delete row and reload table view
[tbv reloadData];
cell display, depending on the data source, so you need to deal with the data source.
if dataArr is the table view datasource,first of all, you should delete the data source where the cell,then
[dataArr removeObjectAtIndex:indexpath.row];
[self.tableView beginUpdates];
[self.tableView deleteRowsAtIndexPaths:#[indexpath] withRowAnimation:UITableViewRowAnimationFade];
[self.tableView endUpdates];
at last ,you can insert data source when you should add a cell
[dataArr insertObjectAtIndex:indexpath.row];
[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:#[indexpath] withRowAnimation:UITableViewRowAnimationFade];
[self.tableView endUpdates];
Best way to set rowHeight value in condition check
Dataarray where value stored .
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//set up here
let cell = myTableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! myCustomCell
if (dataArray?[indexPath.row].somevalue == "true")
{
cell.isHidden = true
tableview.rowHeight = 0.0
}
else{
// show cell values
tableview.rowHeight = 130
}
`
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let dicttemp : Dictionary = arrAllCoursesList[indexPath.row] as! Dictionary<String,Any>
var rowHeight:CGFloat = 0.0
if let getStatus = dicttemp["status"] as? String
{
if getStatus == "1"
{
rowHeight = 240.0
}
else
{
rowHeight = 0.0
}
}
return rowHeight
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CompetitionTableViewCell") as! CompetitionTableViewCell
let dicttemp : Dictionary = arrAllCoursesList[indexPath.row] as! Dictionary<String,Any>
if let getStatus = dicttemp["status"] as? String
{
if getStatus == "1"
{
cell.isHidden = false
}
else
{
cell.isHidden = true
}
}
cell.selectionStyle = UITableViewCellSelectionStyle.none
return cell
}
I'm trying to put a UIDatePicker into a UITableViewCell which is opened/closed by clicking on the cell above it. The picker seems to be rendering all wrong. Firstly, here is the related code from the UITableView class:
// Determines if the date picker should be shown
var editingDate: Bool = false
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if indexPath.section == 1 && indexPath.row == 1 { // Picker cell
if !self.editingDate {
return 0
}
}
return super.tableView(tableView, heightForRowAtIndexPath: indexPath)
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if indexPath.section == 1 && indexPath.row == 0 { // Date cell
self.editingDate = !self.editingDate
tableView.reloadRowsAtIndexPaths([NSIndexPath(forRow: 1, inSection: 1)], withRowAnimation: .Fade)
}
}
The table in the storyboard:
I have set the Table Cell to a custom height of 219 in the storyboard. Below is an animated GIF of what happens when I currently click the date field. Sorry for the terrible quality.
I noticed that we can see from the animated gif above that the cell background becomes transparent (not white) which means the Content View of the cell is not stretching to the full height. I wonder why that could be?
Edit: Here is the constraints used for the DatePicker:
If you use static cells, you can specify the height of the cell holding the picker in the storyboard editor and your code could look like this:
if (indexPath.section == 1 && indexPath.row == 1 && !editingDate) { // Picker cell
return 0
}
return super.tableView(tableView, heightForRowAtIndexPath: indexPath)
Update
Replace:
tableView.reloadRowsAtIndexPaths([NSIndexPath(forRow: 1, inSection: 1)], withRowAnimation: .Fade)
With:
tableView.beginUpdates()
tableView.endUpdates()
Are you using AutoLayout?
If so try pinning your DatePicker by the cell's edges in IB by CTRL-dragging from it to the cell. After all 4 edges have been pinned give it another try.