it-swarm.com.ru

UIView установить только боковые границы

Есть ли способ установить стороны границы UIView одного цвета и оставить верх и низ другого?

16
Mason

Нет, границы CALayer не поддерживают такое поведение. Самый простой способ выполнить то, что вы хотите, - это добавить непрозрачное подпредставление n - по всей точке с желаемым цветом рамки в качестве фона на каждой стороне вашего вида.

Пример:

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 - левые и правые границы всегда будут внутри границ их суперпредставления.

26
Noah Witherspoon

Ответ с представлениями, работающими как границы, очень приятный, но помните, что каждое представление - это объект пользовательского интерфейса, который стоит много памяти.

Я бы использовал слой 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];

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

7
daniel kilinskas

Обновлено для Swift 3.0

Я написал расширение Swift (для кнопки UIB), которое имитирует установку границы на любой стороне 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
    }
  }
}    
7
SuitedSloth

Это звучит как один из двух ответов:

Если ваш вид имеет статический размер, просто поместите UIView позади него, который на 2 пикселя шире и на 2 пикселя короче вашего вида спереди.

Если он нестатического размера, то вы можете сделать то же самое, изменяя размер заднего вида при каждом изменении размера переднего плана, или реализовать пользовательский объект, который реализует UIView, и реализовать (переопределить) вашу собственную процедуру drawRect. 

2
trumpetlicks
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
}
0
Debaprio B

NAUIViewWithBorders сделал трюк для меня. Смотрите также пост автора SO здесь . Стоит проверить, нужна ли вам эта функциональность для более чем пары просмотров.

0
weienw