Tentei alterar o UIStackViewplano de fundo de claro para branco no inspetor do Storyboard, mas ao simular, a cor do plano de fundo da exibição da pilha ainda tem uma cor clara.
Como posso alterar a cor de fundo de a UIStackView?
Tentei alterar o UIStackViewplano de fundo de claro para branco no inspetor do Storyboard, mas ao simular, a cor do plano de fundo da exibição da pilha ainda tem uma cor clara.
Como posso alterar a cor de fundo de a UIStackView?
Respostas:
Você não pode fazer isso -
UIStackViewé uma vista sem desenho, o que significa quedrawRect()nunca é chamado e sua cor de fundo é ignorada. Se você deseja desesperadamente uma cor de fundo, considere colocar a vista da pilha dentro de outraUIViewe dar a ela uma cor de fundo.
Referência AQUI .
EDITAR:
Você pode adicionar um subView UIStackViewcomo mencionado AQUI ou nesta resposta (abaixo) e atribuir uma cor a ele. Confira abaixo extensionpara isso:
extension UIStackView {
func addBackground(color: UIColor) {
let subView = UIView(frame: bounds)
subView.backgroundColor = color
subView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
insertSubview(subView, at: 0)
}
}
E você pode usá-lo como:
stackView.addBackground(color: .red)
drawRect()é chamado. Você pode simplesmente testar por subclasseUIStackView
if let backgroundView = self.subviews.first(where: {$0.tag == 123}) {. Nesse caso, altero a cor de fundo dessa exibição.
Eu faço assim:
@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
}
}
Funciona como um encanto
@IBDesignable class StackViewO que permitirá que você crie no Storyboard . Não me importo muito em adicionar um plano de fundo em tempo de execução, mas é muito difícil projetar o stackview quando ele não possui cores no
UIStackViewé um elemento que não é de renderização e, como tal, não é desenhado na tela. Isso significa que mudar backgroundColoressencialmente não faz nada. Se você quiser alterar a cor do plano de fundo, basta adicionar um UIViewa ela como uma subvisão (que não está organizada) como abaixo:
extension UIStackView {
func addBackground(color: UIColor) {
let subview = UIView(frame: bounds)
subview.backgroundColor = color
subview.autoresizingMask = [.flexibleWidth, .flexibleHeight]
insertSubview(subview, at: 0)
}
}
Talvez a maneira mais fácil, mais legível e menos invasiva seja incorporar o UIStackViewao UIViewe definir a cor do plano de fundo para a exibição.
E não se esqueça de configurar corretamente as restrições de Layout automático entre essas duas visualizações ... ;-)
Pitiphong está correto, para obter um stackview com uma cor de fundo, faça algo como o seguinte ...
let bg = UIView(frame: stackView.bounds)
bg.autoresizingMask = [.flexibleWidth, .flexibleHeight]
bg.backgroundColor = UIColor.red
stackView.insertSubview(bg, at: 0)
Isso fornecerá uma stackview cujo conteúdo será colocado em um fundo vermelho.
Para adicionar preenchimento ao stackview para que o conteúdo não fique alinhado com as bordas, adicione o seguinte no código ou no storyboard ...
stackView.isLayoutMarginsRelativeArrangement = true
stackView.layoutMargins = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8)
TL; DR: A maneira oficial de fazer isso é adicionando uma exibição vazia na exibição de pilha usando o addSubview:método e defina o fundo da exibição adicionada.
A explicação: UIStackView é uma subclasse UIView especial que apenas faz o layout não desenhar. Muitas de suas propriedades não funcionarão normalmente. E como o UIStackView fará o layout apenas de suas subvisões organizadas, isso significa que você pode simplesmente adicionar um UIView com o addSubview:método, definir suas restrições e cor de fundo. Esta é a maneira oficial de alcançar o que você deseja citar da sessão da WWDC
Isso funciona para mim no Swift 3 e 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)
No iOS10, a resposta do @ Arbitur precisa de um setNeedsLayout após a definição da cor. Esta é a mudança necessária:
override var backgroundColor: UIColor? {
get { return color }
set {
color = newValue
setNeedsLayout()
}
}
backgroundColorantes de adicioná-lo a um superviewfunciona no ios10 e ios9, no entanto, se você atualizou o backgroundColorapós a layoutSubviews()função ter sido chamada, ele simplesmente não atualizaria backgroundColoro backgroundLayersignificado de nenhuma atualização visual. Corrigido agora, obrigado por apontar.
Aqui está uma breve visão geral para adicionar uma cor de fundo da exibição Pilha.
class RevealViewController: UIViewController {
@IBOutlet private weak var rootStackView: UIStackView!
Criando vista de plano de fundo com cantos arredondados
private lazy var backgroundView: UIView = {
let view = UIView()
view.backgroundColor = .purple
view.layer.cornerRadius = 10.0
return view
}()
Para fazer com que apareça como plano de fundo, nós o adicionamos à matriz de subvisões da visualização da pilha raiz no índice 0. Isso o coloca atrás das visualizações organizadas da visualização da pilha.
private func pinBackground(_ view: UIView, to stackView: UIStackView) {
view.translatesAutoresizingMaskIntoConstraints = false
stackView.insertSubview(view, at: 0)
view.pin(to: stackView)
}
Adicione restrições para fixar o backgroundView nas bordas da exibição da pilha, usando uma pequena extensão no 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)
])
}
}
chame o pinBackgrounddeviewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
pinBackground(backgroundView, to: rootStackView)
}
Referência: AQUI
Você pode fazer uma pequena extensão de 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)
])
}
}
Uso:
yourStackView.setBackgroundColor(.black)
Xamarin, versão 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);
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];
Subclasse 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
}
}
Então na sua aula
yourStackView.backgroundColor = UIColor.lightGray
Você pode inserir uma subcamada no StackView, funciona para mim:
@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
Sou um pouco cético em relação aos componentes de subclassificação da interface do usuário. É assim que eu estou usando,
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
}
}
}
E este é o uso,
stackView.backgroundView.backgroundColor = .white
stackView.backgroundView.layer.borderWidth = 2.0
stackView.backgroundView.layer.borderColor = UIColor.red.cgColor
stackView.backgroundView.layer.cornerRadius = 4.0
Nota: Com essa abordagem, se você deseja definir uma borda, é necessário definir layoutMarginsno stackView para que a borda fique visível.
Você não pode adicionar plano de fundo ao stackview. Mas o que você pode fazer é adicionar o stackview em uma exibição e, em seguida, definir o plano de exibição, isso fará o trabalho. * Não interromperá os fluxos do stackview. Espero que isso ajude.
Podemos ter uma classe personalizada StackViewcomo esta:
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),
])
}
}
E pode ser usado assim:
let stackView = StackView()
stackView.backgroundView.backgroundColor = UIColor.lightGray
Isso é um pouco melhor do que adicionar uma função de extensão, func addBackground(color: UIColor)conforme sugerido por outras pessoas. A exibição em segundo plano é lenta, para que não seja criada até que você efetue a chamada stackView.backgroundView.backgroundColor = .... E definir / alterar a cor do plano de fundo várias vezes não resultará na inserção de várias subvisões na exibição da pilha.
Se você deseja controlar a partir do próprio designer, adicione esta extensão à exibição de pilha
@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)
}
}
Você poderia fazer assim:
stackView.backgroundColor = UIColor.blue
Fornecendo uma extensão para substituir 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
}
}
}