Проблема при настройке углового радиуса просмотра внутри ячейки?
У меня есть пользовательская ячейка UITableView
. Я устанавливаю ее нижний левый и нижний правый радиус. Я устанавливаю радиус угла в cellForAtindexPath
.Below - это код для этого
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()
}
Теперь, когда я впервые запускаю tableview, он не устанавливает радиус угла. Но когда я снова прокручиваю, он устанавливает радиус угла.
Я создал расширение 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
}
Расскажите, как я могу это решить?
Ответы
Ответ 1
Я не думаю, что это хорошая идея установить угол радиуса в cellForRow atIndexPath. Причина в том, что эта функция вызывается много раз за время жизни UITableView, и вам нужно только установить радиус угла только один раз, и это тоже, когда ячейка инициализирована. Изменение радиуса углов на основе indexPath также повлияет на производительность UITableView.
Лучшим способом для этого было бы создать две ячейки: одну с угловым радиусом как 0, а другую с 10 и использование этих ячеек на основе indexPath.
Затем вы можете поместить свою логику setRadius в функцию 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)
}
Ответ 2
Попробуйте написать эти строки кода в layoutSubviews() вашего пользовательского UITableViewCell
override func layoutSubviews() {
super.layoutSubviews()
self.outerView.roundCorners(corners: [.bottomLeft, .bottomRight], radius: 10)
}
Ответ 3
введите круговой код в основной очереди следующим образом:
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)
}) }
Ответ 4
Для получения этого в 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) Это покажет вид сбоку дизайна, подобного этому
![просмотр в раскадровке]()
С этим вы даже смогли увидеть радиус тени или угла прямо в своем конструкторе, т.е. в стороне от раскадровки, как третье изображение.
Ответ 5
Вы хотите, чтобы определенная ячейка была округлена, если я правильно понимаю. вот мое решение. Хотя я немного опаздываю, но я стараюсь помогать другим.:) Я просто добавил свое решение как изображение.
Шаг 1:
Создал пользовательскую ячейку и сделал необходимые шаги.
![введите описание изображения здесь]()
Ниже приведен код для закругленного нижнего левого и нижнего правого. Прошу прощения за плохой стиль кодирования:
![введите описание изображения здесь]()
Ниже приведена конфигурация контроллера My view для отображения tableView с закругленными ячейками.
![введите описание изображения здесь]()
![введите описание изображения здесь]()
И ниже момент истины:
![введите описание изображения здесь]()