Есть ли способ установить границы границы UIView на один цвет и оставить верхнюю и нижнюю части?
UIView устанавливает только боковые границы
Ответ 1
Границы Nope-CALayer не поддерживают это поведение. Самый простой способ выполнить то, что вы хотите, - добавить непрозрачный подъярус n-point-wide с желаемым цветом границы в качестве цвета фона с каждой стороны вашего вида.
Пример:
CGSize mainViewSize = theView.bounds.size;
CGFloat borderWidth = 2;
UIColor *borderColor = [UIColor redColor];
UIView *leftView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, borderWidth, mainViewSize.height)];
UIView *rightView = [[UIView alloc] initWithFrame:CGRectMake(mainViewSize.width - borderWidth, 0, borderWidth, mainViewSize.height)];
leftView.opaque = YES;
rightView.opaque = YES;
leftView.backgroundColor = borderColor;
rightView.backgroundColor = borderColor;
// for bonus points, set the views' autoresizing mask so they'll stay with the edges:
leftView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleRightMargin;
rightView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleLeftMargin;
[theView addSubview:leftView];
[theView addSubview:rightView];
[leftView release];
[rightView release];
Обратите внимание, что это не вполне соответствует поведению границ CALayer - левый и правый границы будут всегда находиться внутри границ их супервизора.
Ответ 2
Ответ с представлениями, которые работают как границы, очень приятный, но помните, что каждое представление представляет собой объект пользовательского интерфейса, который требует больших объемов памяти.
Я использую слой uivew для рисования штриха с цветом на уже существующем UIview.
-(CAShapeLayer*)drawLineFromPoint:(CGPoint)fromPoint toPoint:(CGPoint) toPoint withColor:(UIColor *)color andLineWidth:(CGFloat)lineWidth{
CAShapeLayer *lineShape = nil;
CGMutablePathRef linePath = nil;
linePath = CGPathCreateMutable();
lineShape = [CAShapeLayer layer];
lineShape.lineWidth = lineWidth;
lineShape.strokeColor = color.CGColor;
NSUInteger x = fromPoint.x;
NSUInteger y = fromPoint.y;
NSUInteger toX = toPoint.x;
NSUInteger toY = toPoint.y;
CGPathMoveToPoint(linePath, nil, x, y);
CGPathAddLineToPoint(linePath, nil, toX, toY);
lineShape.path = linePath;
CGPathRelease(linePath);
return lineShape;}
и добавьте его к нашему представлению.
CAShapeLayer* borderLine=[self drawLineFromPoint:CGPointMake(0, 0) toPoint:CGPointMake(0,_myView.frame.size.height) withColor:[UIColor lightGrayColor] andLineWidth:1.0f];
[_myView.layer addSublayer:borderLine];
Итак... Мы берем точку и фактически рисуем линию сверху донизу нашего представления. В результате получается строка, которая выглядит как граница ширины одного пикселя.
Ответ 3
Обновлен для Swift 3.0
Я написал расширение Swift (для UIButton), которое имитирует установку границы на любой стороне UIView до заданного цвета и ширины. Он похож на подход @Noah Witherspoon, но основан на автономности и ограничении автоопределения.
// Swift 3.0
extension UIView {
enum Border {
case left
case right
case top
case bottom
}
func setBorder(border: UIView.Border, weight: CGFloat, color: UIColor ) {
let lineView = UIView()
addSubview(lineView)
lineView.backgroundColor = color
lineView.translatesAutoresizingMaskIntoConstraints = false
switch border {
case .left:
lineView.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
lineView.topAnchor.constraint(equalTo: topAnchor).isActive = true
lineView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
lineView.widthAnchor.constraint(equalToConstant: weight).isActive = true
case .right:
lineView.rightAnchor.constraint(equalTo: rightAnchor).isActive = true
lineView.topAnchor.constraint(equalTo: topAnchor).isActive = true
lineView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
lineView.widthAnchor.constraint(equalToConstant: weight).isActive = true
case .top:
lineView.topAnchor.constraint(equalTo: topAnchor).isActive = true
lineView.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
lineView.rightAnchor.constraint(equalTo: rightAnchor).isActive = true
lineView.heightAnchor.constraint(equalToConstant: weight).isActive = true
case .bottom:
lineView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
lineView.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
lineView.rightAnchor.constraint(equalTo: rightAnchor).isActive = true
lineView.heightAnchor.constraint(equalToConstant: weight).isActive = true
}
}
}
Ответ 4
Это звучит как один из двух ответов:
Если ваше представление представляет собой статический размер, просто поставьте за него UIView, который на 2 пикселя шире и на 2 пикселя меньше, чем ваш вид спереди.
Если это нестатический размер, вы можете сделать то же самое, изменив размер заднего вида при изменении размера переднего плана или реализовать пользовательский объект, который реализует UIView, и реализовать (переопределить) вашу собственную процедуру drawRect.
Ответ 5
NAUIViewWithBorders помогло. См. Также создатель SO post здесь. Стоит проверить, нужна ли вам эта функция для более чем нескольких просмотров.
Ответ 6
public extension UIView {
// Border type and arbitrary tag values to identify UIView borders as subviews
public enum BorderType: Int {
case left = 20000
case right = 20001
case top = 20002
case bottom = 20003
}
public func addBorder(borderType: BorderType, width: CGFloat, color: UIColor) {
// figure out frame and resizing based on border type
var autoresizingMask: UIViewAutoresizing
var layerFrame: CGRect
switch borderType {
case .left:
layerFrame = CGRect(x: 0, y: 0, width: width, height: self.bounds.height)
autoresizingMask = [ .flexibleHeight, .flexibleRightMargin ]
case .right:
layerFrame = CGRect(x: self.bounds.width - width, y: 0, width: width, height: self.bounds.height)
autoresizingMask = [ .flexibleHeight, .flexibleLeftMargin ]
case .top:
layerFrame = CGRect(x: 0, y: 0, width: self.bounds.width, height: width)
autoresizingMask = [ .flexibleWidth, .flexibleBottomMargin ]
case .bottom:
layerFrame = CGRect(x: 0, y: self.bounds.height - width, width: self.bounds.width, height: width)
autoresizingMask = [ .flexibleWidth, .flexibleTopMargin ]
}
// look for the existing border in subviews
var newView: UIView?
for eachSubview in self.subviews {
if eachSubview.tag == borderType.rawValue {
newView = eachSubview
break
}
}
// set properties on existing view, or create a new one
if newView == nil {
newView = UIView(frame: layerFrame)
newView?.tag = borderType.rawValue
self.addSubview(newView!)
} else {
newView?.frame = layerFrame
}
newView?.backgroundColor = color
newView?.autoresizingMask = autoresizingMask
}