Проблема в настройке радиуса угла обзора внутри ячейки?
У меня есть обычай 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
}
}
здесь замените