web-dev-qa-db-ja.com

UIViewはサイドボーダーのみを設定します

UIViewの境界線の側面を1つの色に設定し、上部と下部を別の色のままにする方法はありますか?

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

境界線のように機能するビューの答えは非常に優れていますが、すべてのビューは大量のメモリを消費するUIオブジェクトであることを忘れないでください。

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];

だから...私たちはポイントを取り、実際にビューの上から下に線を描きます。その結果、1ピクセル幅の境界線のように見える線ができます。

7

Swift 3.0用に更新

UIViewの任意の側の境界線を特定の色と幅に設定することをシミュレートするSwift拡張機能(UIButton用))を作成しました。これは@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

これは、次の2つの答えのいずれかのように聞こえます。

ビューが静的サイズの場合は、前面ビューより2ピクセル広く、2ピクセル短いUIViewを背後に配置するだけです。

静的でないサイズの場合は、同じことを実行して、前景ビューのサイズが変更されるたびにバッキングビューのサイズを変更するか、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投稿はこちら も参照してください。 2つ以上のビューでこの機能が必要かどうかを確認する価値があります。

0
weienw