Search code examples
iosswiftuitableviewswift3

Add shadow to every section in grouped table view


As shown in image I want to add shadow to my table view sections. As like table view has 4 section then there would be 4 shadow view in table view.

func numberOfSections(in tableView: UITableView) -> Int { return 3 }

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 3
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    switch processIndex {
        return cell
}

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return  44
}

func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        return UIView
}

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return 40
}


Solution

  • I have tried with custom [String : UIView] . This will work for minimum number of rows. If your cell's design is static, this will satisfy your design. If you want to access some property inside UITableViewCell, you have to go with subviews.

    • Multiple section with only one row. Only one view (lookView) inside that respective row.
    • We have to create n number of UIView programatically based on requirement.
    • UITapGesture to TableView . TableView format is Grouped, Separator as .none.

    Following code will give output like:

    screenShot

    //Global Variable:
    
    
    @IBOutlet weak var tblVw: UITableView!
    
    var rowItemsDict = [String : [String]]()
    var rowHeight = [String : CGFloat]()
    var eachRowSubViews = [String : UIView]()
    
    
    override func viewDidAppear(_ animated: Bool) {
    
        rowItemsDict = ["0" : ["welcome", "hello", "wow", "Good", "Bad"], "1" : ["Asia", "Europe", "America"], "2" : ["Mcdonald", "Pizza", "Fries"]]
    
        for i in 0..<rowItemsDict.count
        {
            let numOfSubItemsArr : [String] = rowItemsDict[String(i)]!
            let eachRowHeight : CGFloat = getShadowViewHeight(defaultHeight: 44.0, numberOfItems: numOfSubItemsArr.count)
    
            var subArrView = UIView()
    
            for j in 0..<numOfSubItemsArr.count
            {
                let sublabel = UILabel(frame: CGRect(x: 0, y: 0, width: tblVw.frame.size.width - 42, height: 39))
                sublabel.text = numOfSubItemsArr[j]
                sublabel.isUserInteractionEnabled = true
                sublabel.textAlignment = .right
                sublabel.textColor = UIColor.red
                let subView = UIView(frame: CGRect(x: 0, y: CGFloat((j * 40)), width: tblVw.frame.size.width, height: 39))
                subView.addSubview(sublabel)
                subView.backgroundColor = UIColor.clear
                subView.tag = ((i+1) * 100) + j
    
                if j == (numOfSubItemsArr.count - 1)
                {
    
                }
                else
                {
                    let LinesubView = UIView(frame: CGRect(x: 0, y: 38, width: tblVw.frame.size.width - 8, height: 1))
                    LinesubView.backgroundColor = UIColor.lightGray.withAlphaComponent(0.2)
                    subView.addSubview(LinesubView)
                }
    
                subView.isUserInteractionEnabled = true
                subArrView.addSubview(subView)
                subArrView.isUserInteractionEnabled = true
            }
    
            eachRowSubViews[String(i)] = subArrView
            rowHeight[String(i)] = eachRowHeight
        }
    
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(tapEachView))
        tblVw.addGestureRecognizer(tapGesture)
        tblVw.reloadData()
    }
    
    
    // TABLEVIEW DELEGATES
    func numberOfSections(in tableView: UITableView) -> Int {
    
    
        return rowItemsDict.count
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    
        return 1
    }
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! SampleTableViewCell
    
        print("\n\ncellFor")
        cell.backgroundColor = UIColor(red: 240/255, green: 240/255, blue: 240/255, alpha: 0.0)
        cell.separatorVw.backgroundColor = UIColor(red: 250/255, green: 250/255, blue: 250/255, alpha: 0.0)
        tableView.clipsToBounds = true
        let gettingVw : UIView = eachRowSubViews[String(indexPath.section)]!
        cell.lookVw.addSubview(gettingVw)
        cell.lookVw.layer.cornerRadius = 10
        cell.separatorVw.backgroundColor = UIColor.clear
    
        cell.selectionStyle = .none
        return cell
    }
    
    
    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    
        let cell = cell as! SampleTableViewCell
    
        cell.lookVw.dropOnlyOneShadowLeft(getSize: CGSize.zero)
        cell.lookVw.backgroundColor = UIColor.white
    
    
    }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    
        return (rowHeight[String(indexPath.section)]! )
    
    }
    
    
    //ROW HEIGHT CALCULATION
    func getShadowViewHeight(defaultHeight: CGFloat, numberOfItems: Int) -> CGFloat
    {
        let requiredHeight = CGFloat(Int(defaultHeight) * numberOfItems)
    
        return requiredHeight
    }
    
    //TAP GESTURE ACTION
    @objc func tapEachView(sender: UITapGestureRecognizer)
    {
        let touchPoint = sender.location(in: tblVw)
        let index = tblVw.indexPathForRow(at: touchPoint)
    
        if (index == nil)
        {
                print("long press on table view but not on a row");
        }
        else
        {
            let cell = tblVw.cellForRow(at: index!) as! SampleTableViewCell
            let pointInCell = cell.convert(touchPoint, from: tblVw)
    
            let innerSubVw = cell.lookVw.subviews
            print("pointInCellpointInCell)  ", pointInCell)
            for sVw in innerSubVw[0].subviews
            {
                let pointY = pointInCell.y - 5
                let comparePoint = sVw.frame.origin.y
    
                if pointY >= comparePoint && pointY <= comparePoint + 39
                {
                    print("sVwsVwsVwsVwsVw    ", sVw.tag)
    
                    //DO YOUR ACTION IN RESPECTIVE VIEW CLICK
                    return
                }
    
            }
    
        }
    }
    
    
    extension UIView {
        func dropOnlyOneShadowLeft(getSize: CGSize) {
            self.layer.shadowColor = UIColor.lightGray.cgColor
            self.layer.shadowOpacity = 0.6
            self.layer.shadowOffset = getSize
            self.layer.shadowRadius = 3
        }
    }