Проблема в настройке радиуса угла обзора внутри ячейки?

У меня есть обычай UITableView Я устанавливаю его нижний левый и правый нижний угловой радиус. Я устанавливаю угловой радиус в cellForAtindexPathНиже приведен код для этого

  if indexPath.row == 9 {

    recipeInfoCell.outerView.roundCorners(corners: [.bottomLeft, .bottomRight], radius: 10)
    recipeInfoCell.layoutSubviews()
    recipeInfoCell.layoutIfNeeded()
  }
  else  {

    recipeInfoCell.outerView.roundCorners(corners: [.bottomLeft, .bottomRight], radius: 0)
    recipeInfoCell.layoutSubviews()


  }

Теперь, когда я впервые запускаю просмотр таблицы, он не устанавливает никакого углового радиуса. Но когда я снова прокручиваю, он устанавливает угловой радиус.

Я создал расширение UIView в котором есть одна функция, которая устанавливает угловой радиус

  func roundCorners(corners:UIRectCorner, radius: CGFloat) {

    let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
    let mask = CAShapeLayer()
    mask.path = path.cgPath
    self.layer.mask = mask
  }

Подскажите пожалуйста, как мне это решить?

8 ответов

Решение

Я не думаю, что это хорошая идея, чтобы установить радиус угла в cellForRow atIndexPath. Причина в том, что эта функция вызывается много раз за время существования UITableView, и вам нужно только один раз установить радиус угла, и то же самое, когда ячейка инициализируется. Изменение радиуса угла на основе indexPath также повлияет на производительность UITableView.

Лучшим способом для этого было бы создать две ячейки, одну с угловым радиусом 0 и другую с 10, и использовать эти ячейки на основе indexPath.

Затем вы можете поместить свою логику установки cornerRadius в функцию layoutSubview в своей пользовательской ячейке.

Если вы хотите сделать это только в своих методах tableView, правильный способ - сделать это в willDisplayCell, потому что после этого вызова вызывается функция layoutSubviews ячейки.

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        if indexPath.row % 2 == 0 {
            let path = UIBezierPath(roundedRect: cell.contentView.bounds, byRoundingCorners: [.bottomRight, .bottomLeft], cornerRadii: CGSize(width: 10, height: 10))
            let mask = CAShapeLayer()
            mask.path = path.cgPath
            cell.contentView.layer.mask = mask
        } else {
            let path = UIBezierPath(roundedRect: cell.bounds, byRoundingCorners: [.bottomRight, .bottomLeft], cornerRadii: CGSize(width: 0, height: 0))
            let mask = CAShapeLayer()
            mask.path = path.cgPath
            cell.contentView.layer.mask = mask
        }
    }

ОБНОВЛЕНИЕ: 19 мая 2017 г.

Вышеприведенная концепция будет хорошо работать, когда представление, которое вы хотите округлить и наложить тень, имеет тот же размер, что и представление содержимого ячейки. Но если это что-то другое, это не сработает.

Причина приведенного выше утверждения заключается в том, что во время вызова willDisplayCell, где используется приведенный выше код cell.contentView.boundsдругие виды еще не рассчитаны. Поэтому, когда мы будем использовать другое представление, нам нужно будет использовать границы этого представления для вычисления рамки маски, которая будет отличаться от фактической.

Прочитав немного об этом, я обнаружил, что делать подобные вещи, переопределяя draw(_ rect: CGRect) функция UITableViewCell. Потому что на этом этапе размер представления был правильно рассчитан, и мы можем создать правильный кадр.

Ниже приведен код из пользовательского класса UITableViewCell:

override func draw(_ rect: CGRect) {
        let path = UIBezierPath(roundedRect: self.outerView.bounds, byRoundingCorners: [.bottomRight, .bottomLeft], cornerRadii: CGSize(width: 10, height: 10))
        let mask = CAShapeLayer()
        mask.path = path.cgPath
        self.outerView.layer.mask = mask

        let shadowLayer = CAShapeLayer()
        shadowLayer.shadowPath = path.cgPath
        shadowLayer.frame = self.outerView.layer.frame
        print(shadowLayer.frame)
        shadowLayer.shadowOffset = CGSize(width: 0, height: 0)
        shadowLayer.shadowColor = UIColor.black.cgColor
        shadowLayer.shadowOpacity = 0.9
        self.contentView.layer.insertSublayer(shadowLayer, below: self.outerView.layer)
        super.draw(rect)
    }

Поместите код закругленного угла в основную очередь следующим образом:

if indexPath.row == 9 { dispatch_async(dispatch_get_main_queue(),{
recipeInfoCell.outerView.roundCorners(corners: [.bottomLeft, .bottomRight], radius: 10)
   })} else{
 dispatch_async(dispatch_get_main_queue(),{
recipeInfoCell.outerView.roundCorners(corners: [.bottomLeft, .bottomRight], radius: 0)
}) }

Попробуйте написать эти строки кода в layoutSubviews() вашего Custom UITableViewCell

override func layoutSubviews() {
super.layoutSubviews()
self.outerView.roundCorners(corners: [.bottomLeft, .bottomRight], radius: 10)
}

Для получения этого только в Swift я использую для создания одного подкласса UIButton, как показано ниже

(в любом.swift файле проекта)

//MARK: Custom Class for UIView
open class CustomView: UIView {
    open func drawViewsForRect(_ rect: CGRect) {
        fatalError("\(#function) must be overridden")
    }

    open func updateViewsForBoundsChange(_ bounds: CGRect) {
        fatalError("\(#function) must be overridden")
    }

}

Затем определите методы ниже в том же или другом файле.swift, как это

    //MARK: - UIView Property Class
@IBDesignable open class CView : CustomView{

    @IBInspectable dynamic open var borderColor: UIColor = UIColor.clear{
        didSet{
            updateBorderColor()
        }
    }

    @IBInspectable dynamic open var borderWidth: CGFloat = 1.0{
        didSet{
            updateBorderWidth()
        }
    }

    @IBInspectable dynamic open var cornerRadius: CGFloat = 0.0{
        didSet{
            updateBorderRadius()
        }
    }

    @IBInspectable dynamic open var shadowColor: UIColor?{
        didSet{
            updateShadowColor()
        }
    }

    @IBInspectable dynamic open var shadowRadius: CGFloat = 0.0{
        didSet{
            updateShadowRadius()
        }
    }

    @IBInspectable dynamic open var shadowOpacity: Float = 0.0{
        didSet{
            updateShadowOpacity()
        }
    }

    @IBInspectable dynamic open var shadowOffSet: CGSize = CGSize(width: 0.0, height: 0.0){
        didSet{
            updateShadowOffset()
        }
    }

    //Update Borders Properties
    open func updateBorderColor(){
        self.layer.borderColor = borderColor.cgColor
    }
    open func updateBorderRadius(){
        self.layer.cornerRadius = cornerRadius
    }
    open func updateBorderWidth(){
        self.layer.borderWidth = borderWidth
    }

    //Update Shadow Properties
    open func updateShadowColor(){
        self.layer.shadowColor = shadowColor?.cgColor
        self.clipsToBounds = false;
        self.layer.masksToBounds = false;
    }
    open func updateShadowOpacity(){
        self.layer.shadowOpacity = shadowOpacity
        self.clipsToBounds = false;
        self.layer.masksToBounds = false;
    }
    open func updateShadowRadius(){
        self.layer.shadowRadius = shadowRadius
        self.clipsToBounds = false;
        self.layer.masksToBounds = false;
    }
    open func updateShadowOffset(){
        self.layer.shadowOffset = CGSize(width: shadowOffSet.width, height: shadowOffSet.height)
        self.layer.shadowColor = shadowColor?.cgColor
        self.clipsToBounds = false;
        self.layer.masksToBounds = false;
    }
}

Затем просто назначьте CView класс в раскадровке во время разработки для любого контроллера представления и просто предоставьте требуемые значения для свойств для этого в стороне инспектора атрибута для этого представления

В раскадровке

1) Класс просмотра

установить вызовы зрения

2) Установите свойство как это

Недвижимость как это

3) Это покажет вид в сторону дизайна, как это

посмотреть в раскадровке

Благодаря этому вы даже смогли увидеть теневой или угловой радиус непосредственно в конструкторе, то есть в виде раскадровки, как на третьем изображении.

Вы хотите, чтобы определенная клетка за углом, если я правильно понимаю. Вот мое решение. Хотя я немного опоздал, но я стараюсь помогать другим.:) Я просто добавил свое решение в виде картинки.

Шаг 1:

Создал пользовательскую ячейку и сделал несколько необходимых шагов.

Ниже приведен код для закругленных внизу слева и внизу справа. Извините за плохой стиль кодирования:

Ниже приведена конфигурация контроллера My View для отображения tableView с закругленными ячейками.

А ниже момент истины:

Я взял ссылку ( /questions/3344471/problema-v-nastrojke-radiusa-ugla-obzora-vnutri-yachejki/3344473#3344473) и изменил код, и теперь он работает для меня:

Добавьте приведенный ниже код в свой собственный класс ячейки:

enum cellStyle: Int {
    case Normal = 0, Rounded
}

class CustomTableCell:UITableViewCell {
    var cellType: Int = 0 {
        didSet {
            let maskLayer = CAShapeLayer()
            let cell: cellStyle = cellStyle(rawValue: cellType)!
            
            switch cell {
            case .Normal:
                let normal = UIBezierPath(roundedRect: self.viewMain.bounds, byRoundingCorners: [.bottomLeft, .bottomRight], cornerRadii: CGSize(width: 0, height: 0))
                
                maskLayer.path = normal.cgPath
                self.viewMain.layer.mask = maskLayer
            case .Rounded:
                let rounded = UIBezierPath(roundedRect: self.viewMain.bounds, byRoundingCorners: [.bottomLeft, .bottomRight], cornerRadii: CGSize(width: 10, height: 10))
                
                maskLayer.path = rounded.cgPath
                self.viewMain.layer.mask = maskLayer
            }
        }
    }
}

В вашем ViewController->cellForRowAt --- Вызовите код ниже в основной очереди

DispatchQueue.main.async {
            if totalRows == index + 1 { //write your condition
                cell.cellType = cellStyle.Rounded.rawValue
            } else {
                cell.cellType = cellStyle.Normal.rawValue
            }
            cell.layoutSubviews()
            cell.layoutIfNeeded()
        }

Это сработало для меня:

view.clipsToBounds = true
view.layer.cornerRadius = value
view.layer.maskedCorners = [.layerMaxXMaxYCorner, .layerMinXMaxYCorner]

Исходя из моего опыта, это то, что у меня работает, чтобы слои с динамическим размером работали должным образом.

      //Inside the cell or the view class
override func layoutSublayers(of layer: CALayer) {
    super.layoutSublayers(of: layer)
    
    if layer === self.layer {
        //Do any dynamic-layer update here
        myViewToRound.layer.cornerRadius = myViewToRound.bounds.width/2
    }
}

здесь замените с подклассом UIView, который вы хотите округлить внутри своей ячейки / представления

Другие вопросы по тегам