Как изменить цвет фона UIStackView?

Я попытался изменить фон UIStackView с четкого на белый в инспекторе раскадровки, но при имитации цвет фона в представлении стека по-прежнему имеет четкий цвет.
Как изменить цвет фона UIStackView?

Ответ 1

  Вы не можете сделать это - UIStackView это вид без рисунка, что означает, что drawRect() никогда не вызывается, а его цвет фона игнорируется. если ты отчаянно хотите цвет фона, рассмотрите возможность размещения стека внутри другого UIView и предоставив этому виду цвет фона.

Ссылка от ЗДЕСЬ.

EDIT:

Вы можете добавить подпункт к UIStackView, как упомянуто ЗДЕСЬ или в этом ответе (ниже), и назначить ему цвет. Проверьте ниже 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)

Ответ 2

Я делаю это так:

@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
    }
}

Работает как шарм

Ответ 3

UIStackView - это элемент без рендеринга, и, как таковой, он не отображается на экране. Это означает, что изменение backgroundColor сути ничего не делает. Если вы хотите изменить цвет фона, просто добавьте к нему UIView как подпредставление (которое не организовано), как UIView ниже:

extension UIStackView {

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

}

Ответ 4

Возможно, самый простой, более читаемый и менее хакерский способ - вставить UIStackView в UIView и установить цвет фона для представления.

И не забудьте правильно настроить ограничения автоматического макета между этими двумя видами...;-)

Ответ 5

TL; DR: официальный способ сделать это - добавить пустой вид в стек, используя метод addSubview:, и вместо этого установить вместо этого дополнительный фон.

Объяснение: UIStackView - это специальный подкласс UIView, который выполняет только макет, а не чертеж. Так что многие из его свойств не будут работать как обычно. И поскольку UIStackView будет компоновать только расположенные подразделы, это означает, что вы можете просто добавить его UIView с помощью метода addSubview:, установить его ограничения и цвет фона. Это официальный способ достижения желаемого цитируемого на сессии WWDC

Ответ 6

Pitiphong верен, чтобы получить вид стека с цветом фона, сделайте что-то вроде следующего...

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

  stackView.insertSubview(bg, at: 0)

Это даст вам представление стека, содержимое которого будет размещено на красном фоне.

Чтобы добавить отступы в представление стека, чтобы содержимое не совпадало с краями, добавьте следующее в код или раскадровку...

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

Ответ 7

В iOS10 для ответа @Arbitur требуется setNeedsLayout после установки цвета. Это изменение необходимо:

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

Ответ 8

Это работает для меня в 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)

Ответ 9

Ниже приведен краткий обзор добавления цвета фона в стеке.

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
}()

Чтобы он отображался в качестве фона, мы добавляем его в массив subviews в представлении корневого стека с индексом 0. Это ставит его за расположенные виды представления стека.

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

Добавьте ограничения, чтобы привязать backgroundView к краям представления стека, используя небольшое расширение в UIView.

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)
}

Ссылка из: ЗДЕСЬ

Ответ 10

Вы можете сделать небольшое расширение 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)

Ответ 11

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

Ответ 12

Xamarin, С# версия:

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

Ответ 13

Подкласс 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

Ответ 14

Вы можете вставить подслой в 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

Ответ 15

Я немного скептически отношусь к компонентам UC. Вот как я это использую,

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, чтобы граница была видимой.

Ответ 16

Вы не можете добавить фон в стек просмотра. Но то, что вы можете сделать, это добавить представление стека в представление, а затем установить фон представления, и это сделает работу. * Он не будет прерывать потоки стека. Надеюсь, это поможет.

Ответ 17

Вы можете сделать это следующим образом:

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
        }

    }

}