youngsoft / TangramKit

TangramKit is a powerful iOS UI framework implemented by Swift. It integrates the functions with Android layout,iOS AutoLayout,SizeClass, HTML CSS float and flexbox and bootstrap. So you can use LinearLayout,RelativeLayout,FrameLayout,TableLayout,FlowLayout,FloatLayout,LayoutSizeClass to build your App 自动布局 UIView UITableView UICollectionView
MIT License
1.21k stars 175 forks source link

Runtime Height #20

Closed ykorshev closed 5 years ago

ykorshev commented 6 years ago

Hi everyone.

I added few subviews to TGLinearLayout. How can I get total calculated height of all layout? For using in UITableView

youngsoft commented 6 years ago
        let tableHeaderViewLayout = TGLinearLayout(.vert)
        tableHeaderViewLayout.tg_padding = UIEdgeInsetsMake(10, 10, 10, 10)
        //frame's width must be exact and height can be zero。
        tableHeaderViewLayout.frame = CGRect(x: 0, y: 0, width: self.tableView.bounds.width, height: 0)
        tableHeaderViewLayout.tg_width.equal(.fill)
        tableHeaderViewLayout.tg_height.equal(.wrap)  //height is wrap

        let label1 = UILabel()
        label1.text = NSLocalizedString("add tableHeaderView(please touch me)", comment: "")
        label1.tg_centerX.equal(0)
        label1.sizeToFit()
        tableHeaderViewLayout.addSubview(label1)

        let label2 = UILabel()
        label2.text = NSLocalizedString(" if you use layout view to realize the dynamic height tableHeaderView, please use frame to set view's width and use wrapContentHeight to set view's height. the layoutIfNeeded method is needed to call before the layout view assignment to the UITableview's tableHeaderView.", comment: "")
        label2.tg_leading.equal(5)
        label2.tg_trailing.equal(5)
        label2.tg_height.equal(.wrap)
        label2.tg_top.equal(10)

        tableHeaderViewLayout.addSubview(label2)
        //Because tableHeaderViewLayout's height is wrap, so you must call layoutIfNeeded  before  to  set to the tableView.tableHeaderView.  layoutIfNeeded may calculate the TGLinearLayout's  runtime frame.
        tableHeaderViewLayout.layoutIfNeeded() 
        self.tableView.tableHeaderView = tableHeaderViewLayout

step 1: set the tableview's estimatedRowHeight and rowHeight in the viewDidLoad

 self.tableView.estimatedRowHeight = 60
 self.tableView.rowHeight = UITableViewAutomaticDimension

step2: derive a class from UITableViewCell, and override init like below:

       override init(style: UITableViewCellStyle, reuseIdentifier: String?)
    {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
          self.rootLayout = TGLinearLayout(.horz)
          self.rootLayout.tg_width.equal(.fill)
          self.rootLayout.tg_height.equal(.wrap)    //set rooLayout' height is wrap
          self.rootLayout.tg_cacheEstimatedRect = true   //cache will improve performance.
         self.contentView.addSubview(self.rootLayout)    

         // you can add any subviews to the self.rootLayout
    }

step3: override the UITableViewCell's systemLayoutSizeFitting:

     override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize
    {
            return self.rootLayout.sizeThatFits(targetSize) 
    }

then the UITableViewCell'height will be auto calculated!!

My English is poor, file: AllTest1ViewController.swift and AllTest1TableViewCell.swift are detailed introduction how to use TGLayout with UITableView.

SimonHolmeslm commented 6 years ago

nice shot

ykorshev commented 6 years ago

Here what I got: 2018-03-16 17 52 01

Here is the code:

Table view:

    self.tableView.register(NotificationCell.self, forCellReuseIdentifier: "notification");
    self.tableView.separatorStyle = .none;
    let bgImageView = UIImageView(image: #imageLiteral(resourceName: "innerbg"));
    bgImageView.contentMode = .scaleAspectFill
    self.tableView.backgroundView = bgImageView;
    self.tableView.estimatedRowHeight = 60
    self.tableView.rowHeight = UITableViewAutomaticDimension
    self.tableView.numberOfSectionsIn {
        return 1;
    }
    self.tableView.numberOfRows { section in
        return self.notifications.count;
    }
    /*self.tableView.heightForRowAt { indexPath in
        return self.configureHeight(for: indexPath);
    }*/
    self.tableView.cellForRow{ indexPath in
        return self.configureCell(for: indexPath);
    }

Cell: https://pastebin.com/pX4bsUZz

Please help me. What I am doing wrong?

youngsoft commented 6 years ago
override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize
    {
        var  targetSize2 = targetSize
        //Because you root layout's real width is   self.contentView.frame.width - 32, so you must sub 32.
        targetSize2.width -= 32;   
        var size = self.root!.sizeThatFits(targetSize2)
        size.height += 16   //The size is root layout's size not cell's size,  so height must add 2*8 = 16。(top and bottom margin are 8)
        return size;
    }