UIStackView의 배경색을 변경하는 방법은 무엇입니까?


163

UIStackViewStoryboard inspector에서 배경을 투명에서 흰색 으로 변경하려고 했지만 시뮬레이션 할 때 스택 뷰의 배경색이 여전히 선명한 색상으로 유지됩니다.
의 배경색을 어떻게 변경할 수 UIStackView있습니까?


3
이것은 대답이 완전히 잘못된 경우의 드문 경우 중 하나입니다 . ... 배경보기 만 추가하면됩니다. 매우 간단합니다. 그것을 설명하는 예제 기사 : useyourloaf.com/blog/stack-view-background-color
Fattie

@Fattie 작동했습니다! 대답으로도 추가 할 수 있습니까?
absin

안녕하세요 @AbSin-kurrodu와 MariánČerný의 답변은 완벽합니다.
Fattie

하하,이 큰 비 렌더링 요소는 배경 색상 속성을 가지고있다
브래드 토마스

답변:


303

당신은 이것을 할 수 없습니다 – 이것은 UIStackView비-그리기 뷰입니다. 이것은 drawRect()결코 호출되지 않고 배경색이 무시 된다는 것을 의미합니다 . 배경색을 필사적으로 원한다면 스택 뷰를 다른 뷰에 배치하고 UIView해당 뷰에 배경색을 부여하는 것을 고려하십시오.

여기 에서 참조 .

편집하다:

여기 또는 이 답변 (아래) 에서 UIStackView언급 한 것처럼 subView를 추가 하고 색상을 지정할 수 있습니다. 아래 에서 확인하십시오 .extension

extension UIStackView {
    func addBackground(color: UIColor) {
        let subView = UIView(frame: bounds)
        subView.backgroundColor = color
        subView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        insertSubview(subView, at: 0)
    }
}

다음과 같이 사용할 수 있습니다.

stackView.addBackground(color: .red)

12
이것은 아주 잘못된 것 입니다. HackingWithSwift에 대한 Paul의 기사가 완전히 잘못된 경우는 드뭅니다 . 다른보기 ( 정렬 된 보기 중 하나 가 아님) 를 추가하기 만하면 그게 답입니다.
Fattie

12
여기 설명하는 문서입니다, 그것은 간단하다 : useyourloaf.com/blog/stack-view-background-color
Fattie

1
그렇다면 스택 뷰의 용도는 무엇입니까? 단순히 뷰를 다른 뷰에 추가하고 수평 또는 수직으로 정렬하는 제약 조건을 부여하면 스택 뷰를 완전히 피할 수 있습니다. stackview 내부에 뷰가 있고 UIView 내부에 해당 stackview가 있고이 UIView를 구성 요소에 추가하는 것은 우스꽝스럽지 않습니까?
Shivam Pokhriyal

적어도 drawRect()호출됩니다. 당신은 단순히 서브 클래스 테스트 할 수 있습니다UIStackView
khcpietro

1
iOS14에서는 배경색을 설정할 수 있습니다. useyourloaf.com/blog/stack-view-background-color-in-ios-14
norbDEV

47

나는 이것을 이렇게한다 :

@IBDesignable
class StackView: UIStackView {
   @IBInspectable private var color: UIColor?
    override var backgroundColor: UIColor? {
        get { return color }
        set {
            color = newValue
            self.setNeedsLayout() // EDIT 2017-02-03 thank you @BruceLiu
        }
    }

    private lazy var backgroundLayer: CAShapeLayer = {
        let layer = CAShapeLayer()
        self.layer.insertSublayer(layer, at: 0)
        return layer
    }()
    override func layoutSubviews() {
        super.layoutSubviews()
        backgroundLayer.path = UIBezierPath(rect: self.bounds).cgPath
        backgroundLayer.fillColor = self.backgroundColor?.cgColor
    }
}

매력처럼 작동


이것은 backgroundColor get / set 메서드로 업데이트 된 답변을 포함하여 스토리 보드에서 사용할 때 작동하지 않습니다. :-/ (iOS 10.2.1, Xcode 8.2.1, iPad)
webjprgm 2017

죄송합니다. 알아 냈습니다. Interface Builder는 클래스 아래의 "모듈"필드를 생략 했으므로로드하지 않았습니다. 그것을 수정 한 다음 뷰 컨트롤러의 viewDidLoad에서 배경을 설정하여 수정했습니다.
webjprgm

1
또한 클래스를 IBDesignable로 만드십시오-> @IBDesignable class StackView스토리 보드에서 디자인 할 수 있습니다. 나는 실행시 배경을 추가하기위한 많은 관심을 해달라고하지만, 스토리 보드에 어떤 컬러가없는 stackview 설계하는 것은 매우 어렵다
FlowUI합니다. SimpleUITesting.com

@Fattie Care가 왜 그것이 나쁜 접근 방식인지 설명하기 위해?
Arbitur

아마 매우 나쁜 조금 거친 @Arbitur는 :)입니다 :)하지만 레이어와 플레이 할 필요는 방금 (그러나 중매 한) 다른보기를 추가하기 때문에, 없다
Fattie

34

UIStackView렌더링되지 않는 요소이므로 화면에 그려지지 않습니다. 이것은 변화가 backgroundColor본질적으로 아무것도하지 않는다는 것을 의미합니다 . 배경색을 변경하려면 UIView아래와 같이 하위 뷰 (정렬되지 않음)로를 추가하면 됩니다.

extension UIStackView {

    func addBackground(color: UIColor) {
        let subview = UIView(frame: bounds)
        subview.backgroundColor = color
        subview.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        insertSubview(subview, at: 0)
    }

}

1
이 답변도 완벽합니다. 개인적으로 나는 네 가지 제약 조건을 모두 입력했습니다 (kurrodu의 답변에서와 같이)
Fattie dec

1
배경색을 변경하지 않는다고 가정하면 괜찮습니다. 그러나이 메서드를 여러 번 호출하면 이전 시점의 뷰가 여전히 유지됩니다. 또한이 방법으로 배경색을 쉽게 제거 할 수있는 방법도 없습니다.
keji

12

어쩌면 가장 쉬운, 더 읽기 덜 해키 방법은을 포함하는 것 UIStackViewUIView보기 및 설정 배경 색상.

그리고 그 두 뷰 사이의 자동 레이아웃 제약 조건을 적절하게 구성하는 것을 잊지 마십시오… ;-)


2
예,하지만 그 재미는 어디입니까? :-)
webjprgm

1
지금까지 가장 좋은 방법 - 그것은 혼자 빌더 인터페이스에서 작동 코드의 라인없이
블라디미르 Grigorov

11

Pitiphong이 정확합니다. 배경색이있는 stackview를 얻으려면 다음과 같이하십시오.

  let bg = UIView(frame: stackView.bounds)
  bg.autoresizingMask = [.flexibleWidth, .flexibleHeight]
  bg.backgroundColor = UIColor.red

  stackView.insertSubview(bg, at: 0)

그러면 내용이 빨간색 배경에 배치되는 스택 뷰가 제공됩니다.

내용이 가장자리와 같지 않도록 stackview에 패딩을 추가하려면 코드 또는 스토리 보드에 다음을 추가합니다.

  stackView.isLayoutMarginsRelativeArrangement = true
  stackView.layoutMargins = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8)

2
stackView.insertSubview (bg, belowSubview : stackView.arrangedSubviews [0])를 사용해야했습니다. 그렇지 않으면 컬러 뷰가 스택 위에 배치되었습니다.
iCyberPaul

이 대답은 거의 정확하지만 틀 렸습니다 . 그냥 0에서 삽입을 사용합니다.
Fattie

1
@iCyberPaul-단순히 0에서 삽입을 사용합니다.
Fattie

뷰가 뷰 계층 구조에서 마지막이되도록 0에 삽입하도록 편집 된 샘플 코드를 참고하십시오. (나는 다음과 같은 것을 말
Michael Long

9

요약 : 공식적인 방법은 addSubview:메서드를 사용하여 스택 뷰에 빈 뷰를 추가하고 대신 추가 된 뷰 배경을 설정하는 것입니다.

설명 : UIStackView는 그리기가 아닌 레이아웃 만 수행하는 특수 UIView 하위 클래스입니다. 너무 많은 속성이 평소처럼 작동하지 않습니다. UIStackView는 배열 된 하위 뷰만 레이아웃하므로 addSubview:메서드를 사용 하여 UIView에 추가 하고 제약 조건과 배경색을 설정 하기 만하면 됩니다. 이것은 WWDC 세션에서 인용 한 원하는 것을 달성하는 공식적인 방법입니다.


3

이것은 Swift 3 및 iOS 10에서 나를 위해 작동합니다.

let stackView = UIStackView()
let subView = UIView()
subView.backgroundColor = .red
subView.translatesAutoresizingMaskIntoConstraints = false
stackView.addSubview(subView) // Important: addSubview() not addArrangedSubview()

// use whatever constraint method you like to 
// constrain subView to the size of stackView.
subView.topAnchor.constraint(equalTo: stackView.topAnchor).isActive = true
subView.bottomAnchor.constraint(equalTo: stackView.bottomAnchor).isActive = true
subView.leftAnchor.constraint(equalTo: stackView.leftAnchor).isActive = true
subView.rightAnchor.constraint(equalTo: stackView.rightAnchor).isActive = true

// now add your arranged subViews...
stackView.addArrangedSubview(button1)
stackView.addArrangedSubview(button2)

3

iOS10에서 @Arbitur의 답변에는 색상이 설정된 후 setNeedsLayout이 필요합니다. 이것이 필요한 변경입니다.

override var backgroundColor: UIColor? {
    get { return color }
    set { 
        color = newValue
        setNeedsLayout()
    }
}

당신은 설정하면 당신은, 일을 설정 한 방법에 따라 달라집니다 backgroundColor당신이에 추가하기 전에 superview이 ios10 및 ios9에서 작동 업데이트 된 경우, 그러나, backgroundColor그 후 layoutSubviews()기능은 단순히 wouldnt가 업데이트를 불렀다 backgroundColor(가)의 backgroundLayer시각적 업데이 트를 의미합니다. 지적 해 주셔서 감사합니다.
Arbitur

3

iOS 14 부터 UIStackViews가 배경색을 렌더링 한다는 점을 지적 할 가치가 있습니다. Background 속성을 사용하여 Storyboard에서 UIStackView의 배경을 설정할 수 있습니다.

여기에 이미지 설명 입력

또는 다음과 같은 코드에서 :

if #available(iOS 14.0, *) {
    stackView.backgroundColor = .green
} else {
    // Fallback for older versions of iOS
}

2

다음은 스택보기 배경색 추가에 대한 간략한 개요입니다.

class RevealViewController: UIViewController {

    @IBOutlet private weak var rootStackView: UIStackView!

모서리가 둥근 배경보기 만들기

private lazy var backgroundView: UIView = {
    let view = UIView()
    view.backgroundColor = .purple
    view.layer.cornerRadius = 10.0
    return view
}()

배경으로 보이게하기 위해 인덱스 0에있는 루트 스택 뷰의 subviews 배열에 추가합니다. 그러면 스택 뷰의 정렬 된 뷰 뒤에 배치됩니다.

private func pinBackground(_ view: UIView, to stackView: UIStackView) {
    view.translatesAutoresizingMaskIntoConstraints = false
    stackView.insertSubview(view, at: 0)
    view.pin(to: stackView)
}

UIView의 작은 확장을 사용하여 backgroundView를 스택보기의 가장자리에 고정하는 제약 조건을 추가합니다.

public extension UIView {
  public func pin(to view: UIView) {
    NSLayoutConstraint.activate([
      leadingAnchor.constraint(equalTo: view.leadingAnchor),
      trailingAnchor.constraint(equalTo: view.trailingAnchor),
      topAnchor.constraint(equalTo: view.topAnchor),
      bottomAnchor.constraint(equalTo: view.bottomAnchor)
      ])
  }
}

부르는 pinBackground에서을viewDidLoad

override func viewDidLoad() {
  super.viewDidLoad()
  pinBackground(backgroundView, to: rootStackView)
}

참조 : 여기


2

Xamarin, C # 버전 :

var stackView = new UIStackView { Axis = UILayoutConstraintAxis.Vertical };

UIView bg = new UIView(stackView.Bounds);
bg.AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight;
bg.BackgroundColor = UIColor.White;
stackView.AddSubview(bg);

2

당신은 작은 확장을 만들 수 있습니다 UIStackView

extension UIStackView {
    func setBackgroundColor(_ color: UIColor) {
        let backgroundView = UIView(frame: .zero)
        backgroundView.backgroundColor = color
        backgroundView.translatesAutoresizingMaskIntoConstraints = false
        self.insertSubview(backgroundView, at: 0)
        NSLayoutConstraint.activate([
            backgroundView.topAnchor.constraint(equalTo: self.topAnchor),
            backgroundView.leadingAnchor.constraint(equalTo: self.leadingAnchor),
            backgroundView.bottomAnchor.constraint(equalTo: self.bottomAnchor),
            backgroundView.trailingAnchor.constraint(equalTo: self.trailingAnchor)
            ])
    }
}

용법:

yourStackView.setBackgroundColor(.black)

0
UIStackView *stackView;
UIView *stackBkg = [[UIView alloc] initWithFrame:CGRectZero];
stackBkg.backgroundColor = [UIColor redColor];
[self.view insertSubview:stackBkg belowSubview:stackView];
stackBkg.translatesAutoresizingMaskIntoConstraints = NO;
[[stackBkg.topAnchor constraintEqualToAnchor:stackView.topAnchor] setActive:YES];
[[stackBkg.bottomAnchor constraintEqualToAnchor:stackView.bottomAnchor] setActive:YES];
[[stackBkg.leftAnchor constraintEqualToAnchor:stackView.leftAnchor] setActive:YES];
[[stackBkg.rightAnchor constraintEqualToAnchor:stackView.rightAnchor] setActive:YES];

0

하위 클래스 UIStackView

class CustomStackView : UIStackView {

private var _bkgColor: UIColor?
override public var backgroundColor: UIColor? {
    get { return _bkgColor }
    set {
        _bkgColor = newValue
        setNeedsLayout()
    }
}

private lazy var backgroundLayer: CAShapeLayer = {
    let layer = CAShapeLayer()
    self.layer.insertSublayer(layer, at: 0)
    return layer
}()

override public func layoutSubviews() {
    super.layoutSubviews()
    backgroundLayer.path = UIBezierPath(rect: self.bounds).cgPath
    backgroundLayer.fillColor = self.backgroundColor?.cgColor
}
}

그런 다음 수업에서

yourStackView.backgroundColor = UIColor.lightGray

0

StackView에 하위 계층을 삽입 할 수 있습니다.

@interface StackView ()
@property (nonatomic, strong, nonnull) CALayer *ly;
@end

@implementation StackView

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        _ly = [CALayer new];
        [self.layer addSublayer:_ly];
    }
    return self;
}

- (void)setBackgroundColor:(UIColor *)backgroundColor {
    [super setBackgroundColor:backgroundColor];
    self.ly.backgroundColor = backgroundColor.CGColor;
}

- (void)layoutSubviews {
    self.ly.frame = self.bounds;
    [super layoutSubviews];
}

@end

0

나는 서브 클래 싱 UI 컴포넌트에 약간 회의적입니다. 이것이 제가 사용하는 방법입니다.

struct CustomAttributeNames{
        static var _backgroundView = "_backgroundView"
    }

extension UIStackView{

var backgroundView:UIView {
        get {
            if let view = objc_getAssociatedObject(self, &CustomAttributeNames._backgroundView) as? UIView {
                return view
            }
            //Create and add
            let view = UIView(frame: .zero)
            view.translatesAutoresizingMaskIntoConstraints = false
            insertSubview(view, at: 0)
            NSLayoutConstraint.activate([
              view.topAnchor.constraint(equalTo: self.topAnchor),
              view.leadingAnchor.constraint(equalTo: self.leadingAnchor),
              view.bottomAnchor.constraint(equalTo: self.bottomAnchor),
              view.trailingAnchor.constraint(equalTo: self.trailingAnchor)
            ])

            objc_setAssociatedObject(self,
                                     &CustomAttributeNames._backgroundView,
                                     view,
                                     objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)

            return view
        }
    }
}

그리고 이것은 사용법입니다.

stackView.backgroundView.backgroundColor = .white
stackView.backgroundView.layer.borderWidth = 2.0
stackView.backgroundView.layer.borderColor = UIColor.red.cgColor
stackView.backgroundView.layer.cornerRadius = 4.0

참고 :이 방법을 사용하면 테두리를 설정 layoutMargins하려면 테두리가 보이도록 stackView 를 설정해야합니다 .


0

stackview에 배경을 추가 할 수 없습니다. 그러나 당신이 할 수있는 일은 뷰에 스택 뷰를 추가 한 다음 뷰의 배경을 설정하는 것입니다. * 스택 뷰의 흐름을 방해하지 않습니다. 이것이 도움이되기를 바랍니다.


0

다음 StackView과 같은 사용자 정의 클래스를 가질 수 있습니다 .

class StackView: UIStackView {
    lazy var backgroundView: UIView = {
        let otherView = UIView()
        addPinedSubview(otherView)
        return otherView
    }()
}

extension UIView {
    func addPinedSubview(_ otherView: UIView) {
        addSubview(otherView)
        otherView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            otherView.trailingAnchor.constraint(equalTo: trailingAnchor),
            otherView.topAnchor.constraint(equalTo: topAnchor),
            otherView.heightAnchor.constraint(equalTo: heightAnchor),
            otherView.widthAnchor.constraint(equalTo: widthAnchor),
        ])
    }
}

그리고 다음과 같이 사용할 수 있습니다.

let stackView = StackView()
stackView.backgroundView.backgroundColor = UIColor.lightGray

이것은 func addBackground(color: UIColor)다른 사람들이 제안한 확장 기능 을 추가하는 것보다 약간 낫습니다 . 배경보기는 지연되어 실제로를 호출 할 때까지 생성되지 않습니다 stackView.backgroundView.backgroundColor = .... 배경색을 여러 번 설정 / 변경해도 스택 뷰에 여러 하위 뷰가 삽입되지 않습니다.


0

디자이너 자체에서 제어하려면이 확장을 스택보기에 추가하십시오.

 @IBInspectable var customBackgroundColor: UIColor?{
     get{
        return backgroundColor
     }
     set{
        backgroundColor = newValue
         let subview = UIView(frame: bounds)
         subview.backgroundColor = newValue
         subview.autoresizingMask = [.flexibleWidth, .flexibleHeight]
         insertSubview(subview, at: 0)
     }
 }

-1

다음과 같이 할 수 있습니다.

stackView.backgroundColor = UIColor.blue

다음을 재정의하는 확장을 제공합니다 backgroundColor.

extension UIStackView {

    override open var backgroundColor: UIColor? {

        get {
            return super.backgroundColor
        }

        set {

            super.backgroundColor = newValue

            let tag = -9999
            for view in subviews where view.tag == tag {
                view.removeFromSuperview()
            }

            let subView = UIView()
            subView.tag = tag
            subView.backgroundColor = newValue
            subView.translatesAutoresizingMaskIntoConstraints = false
            self.addSubview(subView)
            subView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
            subView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
            subView.leftAnchor.constraint(equalTo: self.leftAnchor).isActive = true
            subView.rightAnchor.constraint(equalTo: self.rightAnchor).isActive = true
        }

    }

}

당신은 subview의 정확한 위치를 설정해야합니다, 삽입을 사용하십시오
Fattie

-1

BoxView를 사용해보십시오 . UIStackView와 유사하지만 렌더링 중이며 더 많은 레이아웃 옵션을 지원합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.