UIStackView
Storyboard inspector에서 배경을 투명에서 흰색 으로 변경하려고 했지만 시뮬레이션 할 때 스택 뷰의 배경색이 여전히 선명한 색상으로 유지됩니다.
의 배경색을 어떻게 변경할 수 UIStackView
있습니까?
UIStackView
Storyboard inspector에서 배경을 투명에서 흰색 으로 변경하려고 했지만 시뮬레이션 할 때 스택 뷰의 배경색이 여전히 선명한 색상으로 유지됩니다.
의 배경색을 어떻게 변경할 수 UIStackView
있습니까?
답변:
당신은 이것을 할 수 없습니다 – 이것은
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)
drawRect()
호출됩니다. 당신은 단순히 서브 클래스 테스트 할 수 있습니다UIStackView
나는 이것을 이렇게한다 :
@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
}
}
매력처럼 작동
@IBDesignable class StackView
스토리 보드에서 디자인 할 수 있습니다. 나는 실행시 배경을 추가하기위한 많은 관심을 해달라고하지만, 스토리 보드에 어떤 컬러가없는 stackview 설계하는 것은 매우 어렵다
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)
}
}
어쩌면 가장 쉬운, 더 읽기 덜 해키 방법은을 포함하는 것 UIStackView
에 UIView
보기 및 설정 배경 색상.
그리고 그 두 뷰 사이의 자동 레이아웃 제약 조건을 적절하게 구성하는 것을 잊지 마십시오… ;-)
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)
요약 : 공식적인 방법은 addSubview:
메서드를 사용하여 스택 뷰에 빈 뷰를 추가하고 대신 추가 된 뷰 배경을 설정하는 것입니다.
설명 : UIStackView는 그리기가 아닌 레이아웃 만 수행하는 특수 UIView 하위 클래스입니다. 너무 많은 속성이 평소처럼 작동하지 않습니다. UIStackView는 배열 된 하위 뷰만 레이아웃하므로 addSubview:
메서드를 사용 하여 UIView에 추가 하고 제약 조건과 배경색을 설정 하기 만하면 됩니다. 이것은 WWDC 세션에서 인용 한 원하는 것을 달성하는 공식적인 방법입니다.
이것은 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)
iOS10에서 @Arbitur의 답변에는 색상이 설정된 후 setNeedsLayout이 필요합니다. 이것이 필요한 변경입니다.
override var backgroundColor: UIColor? {
get { return color }
set {
color = newValue
setNeedsLayout()
}
}
backgroundColor
당신이에 추가하기 전에 superview
이 ios10 및 ios9에서 작동 업데이트 된 경우, 그러나, backgroundColor
그 후 layoutSubviews()
기능은 단순히 wouldnt가 업데이트를 불렀다 backgroundColor
(가)의 backgroundLayer
시각적 업데이 트를 의미합니다. 지적 해 주셔서 감사합니다.
다음은 스택보기 배경색 추가에 대한 간략한 개요입니다.
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)
}
참조 : 여기
당신은 작은 확장을 만들 수 있습니다 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)
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];
하위 클래스 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
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
나는 서브 클래 싱 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 를 설정해야합니다 .
다음 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 = ...
. 배경색을 여러 번 설정 / 변경해도 스택 뷰에 여러 하위 뷰가 삽입되지 않습니다.
디자이너 자체에서 제어하려면이 확장을 스택보기에 추가하십시오.
@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)
}
}
다음과 같이 할 수 있습니다.
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
}
}
}