CALayer: добавить границу только с одной стороны

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

[webView.layer setBorderColor: [[UIColor colorWithRed:0.6 green:0.7 blue:0.2 alpha:1] CGColor]];
[webView.layer setBorderWidth: 2.75];   

Но можно ли добавить границу только с одной стороны? Мне нужна только граница внизу. Или я могу достичь этого с помощью других свойств, например. рамка, границы, маска,...?

enter image description here

Спасибо за вашу помощь!


@Control-V

        UIWebView *webView = [[UIWebView alloc] init];
        CALayer *webViewLayer = webView.layer;

        // now you can do a lot of stuff like borders:
        [webViewLayer setBorderColor: [[UIColor greenColor] CGColor]];
        [webViewLayer setBorderWidth: 2.75];    

Взгляните на документацию CALayer: https://developer.apple.com/documentation/quartzcore/calayer

И посмотрите здесь: http://iosdevelopertips.com/cocoa/add-rounded-corners-and-border-to-uiwebview.html

Ответ 1

Я сделал правильную границу, используя это:

leftScrollView.clipsToBounds = YES;

CALayer *rightBorder = [CALayer layer];
rightBorder.borderColor = [UIColor darkGrayColor].CGColor;
rightBorder.borderWidth = 1;
rightBorder.frame = CGRectMake(-1, -1, CGRectGetWidth(leftScrollView.frame), CGRectGetHeight(leftScrollView.frame)+2);

[leftScrollView.layer addSublayer:rightBorder];

Ответ 2

Самый простой способ - добавить subLayer, который будет рисовать выделенные границы, но при выборе этого решения необходимо учитывать некоторые вещи, самые большие - убедиться, что пограничный subLayer всегда на вершине и что границы меняются, когда вы меняете рамку своего слоя.

Я реализовал падение в решении с открытым исходным кодом, которое заботится об этих проблемах, и позволяет объявлять селективные границы следующим образом:

myView.borderDirection = AUIFlexibleBordersDirectionRight | AUIFlexibleBordersDirectionTop;

Вы можете получить код и прочитать об этом еще здесь

Ответ 3

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

Но почему бы вам просто не добавить представление над вашим UIWebView, чтобы оно выглядело как граница?

Ответ 4

Здесь быстрый эквивалент

leftScrollView.clipsToBounds = true
let rightBorder: CALayer = CALayer()
rightBorder.borderColor = UIColor.darkGrayColor().CGColor
rightBorder.borderWidth = 1
rightBorder.frame = CGRectMake(-1, -1, CGRectGetWidth(leftScrollView.frame), CGRectGetHeight(leftScrollView.frame)+2)
leftScrollView.layer.addSublayer(rightBorder)

Ответ 5

Мое быстрое решение. Он включает в себя четыре разные функции, все расширения для UIView. Каждая функция добавляет другую границу.

extension UIView {
@discardableResult func addRightBorder(color: UIColor, width: CGFloat) -> UIView {
    let layer = CALayer()
    layer.borderColor = color.cgColor
    layer.borderWidth = width
    layer.frame = CGRect(x: self.frame.size.width-width, y: 0, width: width, height: self.frame.size.height)
    self.layer.addSublayer(layer)
    return self
    }
@discardableResult func addLeftBorder(color: UIColor, width: CGFloat) -> UIView {
    let layer = CALayer()
    layer.borderColor = color.cgColor
    layer.borderWidth = width
    layer.frame = CGRect(x: 0, y: 0, width: width, height: self.frame.size.height)
    self.layer.addSublayer(layer)
    return self
    }
@discardableResult func addTopBorder(color: UIColor, width: CGFloat) -> UIView {
    let layer = CALayer()
    layer.borderColor = color.cgColor
    layer.borderWidth = width
    layer.frame = CGRect(x: 0, y: 0, width: self.frame.size.width, height: width)
    self.layer.addSublayer(layer)
    return self
    }
@discardableResult func addBottomBorder(color: UIColor, width: CGFloat) -> UIView {
    let layer = CALayer()
    layer.borderColor = color.cgColor
    layer.borderWidth = width
    layer.frame = CGRect(x: 0, y: self.frame.size.height-width, width: self.frame.size.width, height: width)
    self.layer.addSublayer(layer)
    return self
    }
}

Ответ 6

Там другой способ сделать это. CAShapeLayer имеет свойства, называемые "strokeStart" и "strokeEnd". Учитывая, что поглаживание начинается с 0 и заканчивается на 1, когда оно достигает начала координат, таким образом, завершая путь, вы можете установить значения для начала и конца для рисования границы с одной стороны.

Относительное местоположение, с которого нужно начинать поглаживание пути. Animatable. Значение этого свойства должно быть в диапазоне от 0.0 до 1.0. Значение по умолчанию этого значения равно 0.0. В сочетании с свойством strokeEnd это свойство определяет субрегион пути к штриху. Значение в этом свойстве указывает относительную точку вдоль пути, по которой нужно начать глажение, в то время как свойство strokeEnd определяет конечную точку. Значение 0.0 представляет начало пути, а значение 1.0 представляет собой конец пути. Значения между ними интерпретируются линейно вдоль длины пути.

Пример:

let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
let mask = CAShapeLayer()
mask.path = path.CGPath
mask.strokeColor = UIColor.redColor().CGColor
mask.strokeStart = 0.45
mask.strokeEnd = 0.92
self.layer.mask = mask

Ответ 7

Следующее работает с Swift 4.2 для применения границы вдоль существующего UIView.

extension UIView {
    enum Side {
        case top
        case bottom
        case left
        case right
    }

    func addBorder(to side: Side, color: UIColor, borderWidth: CGFloat) {
        let subLayer = CALayer()
        subLayer.borderColor = color.cgColor
        subLayer.borderWidth = borderWidth
        let origin = findOrigin(side: side, borderWidth: borderWidth)
        let size = findSize(side: side, borderWidth: borderWidth)
        subLayer.frame = CGRect(origin: origin, size: size)
        layer.addSublayer(subLayer)
    }

    private func findOrigin(side: Side, borderWidth: CGFloat) -> CGPoint {
        switch side {
        case .right:
            return CGPoint(x: frame.maxX - borderWidth, y: 0)
        case .bottom:
            return CGPoint(x: 0, y: frame.maxY - borderWidth)
        default:
            return .zero
        }
    }

    private func findSize(side: Side, borderWidth: CGFloat) -> CGSize {
        switch side {
        case .left, .right:
            return CGSize(width: borderWidth, height: frame.size.height)
        case .top, .bottom:
            return CGSize(width: frame.size.width, height: borderWidth)
        }
    }
}

И вы можете назвать это так:

myView.addBorder(to: .left, color: .black, borderWidth: 2.0)

Что здесь происходит:

  • Пользователь предоставляет Side как определено в перечислении, наряду с color и borderWidth
  • Создается новый подслой, которому присваиваются borderColor и borderWidth
  • Происхождение рассчитывается по определению стороны
  • Размер рассчитывается, также как определено стороной
  • Наконец, слой получает кадр, а затем добавляется в качестве подслоя