Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to increase the height of parent view according to height of UITableView in swift?

I have below hierarchy of my screen.

-ScrollView 
 -ContentView
   -View1
   -View2
   -View3
   -Collectioview
     -CollectioviewCell 
       -Tableview 
         -Tableviewcell 
            -Content

Now here my content of tableview is dynamic so height of tableview cell can't be static.So height of tableview will increase according to number of cell & height of each cell.

Based on Tableview height, Height of collection view should increase which results in increase in height of scroll view content view.

But I am not able to understand how should achieve this with less code? or can it be done programatically ?

enter image description here

like image 773
TechChain Avatar asked Feb 16 '18 11:02

TechChain


2 Answers

The most universal way is to observe contentSize property of your scroll-/table-/collectionView and to change size accordingly.

To achieve this you should:

Note: examples will be for UIScrollView, but it can be applied for any collectionView

  • add observer to your view

    scrollViewToObserveSizeOf.addObserver(observerObject, forKeyPath: "contentSize", options: [.old, .new], context: nil)
    
  • override observeValue method

    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if let scrollView = object as? UIScrollView,
            scrollView == scrollViewToObserveSizeOf,
            keyPath == "contentSize" {
            // Do whatever you want with size
            // You can get new size from scrollView.contentSize
            // or change?[NSKeyValueChangeKey.newKey] as? CGSize for new value
            // and change?[NSKeyValueChangeKey.oldKey] as? CGSize for old value
            //
            // ! Do not force unwrap this values, just never use force unwrap, 
            // everything could happen
        } else {
            // ! Do not forget to call super.observeValue(forKeyPath:of:change:context) 
            // if it is not object you added observer to
            super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
        }
    }
    

To apply it, for example, to UITableView just check if object in observeValue method is of UITableView type.

This method is called whenever content size of your collection view is changed and you do not need to know anything about if your view has finished loading or whatever.

like image 100
LowKostKustomz Avatar answered Jan 18 '23 02:01

LowKostKustomz


Let's suppose each row in your table view has fixed height.

So height of table view would be number of row in tableview * height of row. Suppose hight of each row is 30 and there are 4 rows in table view then,

tableHeight = 4*30 = 120

You don't have to wait for tableview to reload data. You can use the count of your array from which you fill your data in tableview to get number of rows. So your number of rows would be your array's count. Till here you got the height of your tableview. Now to increase the parent height, Give fixed height to the tableview and collectionview and take a outlet of height constraint of both.

Just calculate the height of tableview before reloading and give that height to tableView's height constraint. Also give the same height plus heigh of extra space(If any) to collectionView's height constraint.

For eg : tableViewHieghtConstraint.constant = tableHeight collectionViewHieghtConstraint.constant = tableHeight

This will increase your collectionview's and tableView's height and thus result in increasing the height of your content view.

If you want to calculate the height of your tableview with dynamic height of each cell, following method can be used to get height. Though this is not recommended and does not work in every case so use this with your own consent.

func reloadData() {
        self.tableView.reloadData()
        let tableHeight: CGFloat = 0
        DispatchQueue.main.asyncAfter(deadline: .now()+0.3) {
            for i in 0...aryData.count - 1 {
                let frame = self.tableView.rectForRow(at: IndexPath(row: i, section: 0))
                tableHeight += frame.size.height
                print(frame.size.height)
            }
        }
        tableViewHieghtConstraint.constant = tableHeight 
        collectionViewHieghtConstraint.constant = tableHeight
    }  

You can avoid using delay or provide less delay. Delay is given here in case if there is large amount of data to be processed and displayed on table view then it might take some fraction of seconds.

P.S: Don't forget to give bottom constraint of collectionview to contentview.

like image 25
iOS_MIB Avatar answered Jan 18 '23 02:01

iOS_MIB