Tentei alterar o UIStackView
plano 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 UIStackView
plano 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 outraUIView
e dar a ela uma cor de fundo.
Referência AQUI .
EDITAR:
Você pode adicionar um subView UIStackView
como mencionado AQUI ou nesta resposta (abaixo) e atribuir uma cor a ele. Confira abaixo extension
para 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 StackView
O 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 backgroundColor
essencialmente não faz nada. Se você quiser alterar a cor do plano de fundo, basta adicionar um UIView
a 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 UIStackView
ao UIView
e 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()
}
}
backgroundColor
antes de adicioná-lo a um superview
funciona no ios10 e ios9, no entanto, se você atualizou o backgroundColor
após a layoutSubviews()
função ter sido chamada, ele simplesmente não atualizaria backgroundColor
o backgroundLayer
significado 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 pinBackground
deviewDidLoad
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 layoutMargins
no 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 StackView
como 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
}
}
}