ios - objective - uistackview swift 3
¿Cómo cambiar el color de fondo de UIStackView? (16)
Traté de cambiar el fondo
UIStackView
de claro a blanco en el inspector de Storyboard, pero al simular, el color de fondo de la vista de pila todavía tiene un color claro.
¿Cómo puedo cambiar el color de fondo de un
UIStackView
?
No puede hacer esto:
UIStackView
es una vista sin dibujo, lo que significa que nunca se llama adrawRect()
y se ignora su color de fondo. Si desea desesperadamente un color de fondo, considere colocar la vista de pila dentro de otraUIView
y darle a esa vista un color de fondo.
Referencia desde HERE .
EDITAR:
Puede agregar una subvista a
UIStackView
como se menciona
HERE
o en
esta respuesta (a continuación)
y asignarle un color.
Echa un vistazo a la
extension
continuación para eso:
extension UIStackView {
func addBackground(color: UIColor) {
let subView = UIView(frame: bounds)
subView.backgroundColor = color
subView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
insertSubview(subView, at: 0)
}
}
Y puedes usarlo como:
stackView.addBackground(color: .red)
Aquí hay una breve descripción general para agregar una vista de pila Color de fondo.
class RevealViewController: UIViewController {
@IBOutlet private weak var rootStackView: UIStackView!
Crear vista de fondo con esquinas redondeadas
private lazy var backgroundView: UIView = {
let view = UIView()
view.backgroundColor = .purple
view.layer.cornerRadius = 10.0
return view
}()
Para que aparezca como fondo, lo agregamos a la matriz de subvistas de la vista de pila raíz en el índice 0. Eso lo coloca detrás de las vistas organizadas de la vista de pila.
private func pinBackground(_ view: UIView, to stackView: UIStackView) {
view.translatesAutoresizingMaskIntoConstraints = false
stackView.insertSubview(view, at: 0)
view.pin(to: stackView)
}
Agregue restricciones para anclar el backgroundView a los bordes de la vista de la pila, utilizando una pequeña extensión en 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)
])
}
}
llame al
pinBackground
desde
viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
pinBackground(backgroundView, to: rootStackView)
}
Referencia de: useyourloaf.com/blog/stack-view-background-color
En iOS10, la respuesta de @ Arbitur necesita un setNeedsLayout después de configurar el color. Este es el cambio que se necesita:
override var backgroundColor: UIColor? {
get { return color }
set {
color = newValue
setNeedsLayout()
}
}
Esto funciona para mí en Swift 3 y 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)
Lo hago así:
@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 de maravilla
Pitiphong es correcto, para obtener una vista de pila con un color de fondo, haga algo como lo siguiente ...
let bg = UIView(frame: stackView.bounds)
bg.autoresizingMask = [.flexibleWidth, .flexibleHeight]
bg.backgroundColor = UIColor.red
stackView.insertSubview(bg, at: 0)
Esto le dará una vista de pila cuyo contenido se colocará sobre un fondo rojo.
Para agregar relleno a la vista de pila para que los contenidos no estén alineados con los bordes, agregue lo siguiente en el código o en el guión gráfico ...
stackView.isLayoutMarginsRelativeArrangement = true
stackView.layoutMargins = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8)
Podría hacer una pequeña extensión 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)
Podrías hacerlo así:
stackView.backgroundColor = UIColor.blue
Al proporcionar una extensión para anular el
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
}
}
}
Puede insertar una subcapa en StackView, me funciona:
@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
Quizás la forma más fácil, más legible y menos hacky sería incrustar el
UIStackView
en un
UIView
y establecer el color de fondo a la vista.
Y no olvide configurar correctamente las restricciones de diseño automático entre esas dos vistas ... ;-)
Soy un poco escéptico en Subclasificar componentes de la interfaz de usuario. Así es como lo estoy 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
}
}
}
Y este es el 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: con este enfoque, si desea establecer el borde, debe establecer
layoutMargins
en el stackView para que el borde sea visible.
Subclase 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
}
}
Luego en tu clase
yourStackView.backgroundColor = UIColor.lightGray
TL; DR: la forma oficial de hacerlo es agregando una vista vacía a la vista de pila usando el método
addSubview:
y estableciendo el fondo de la vista agregada.
La explicación: UIStackView es una subclase especial de UIView que solo hace que el diseño no se dibuje.
Muchas de sus propiedades no funcionarán como de costumbre.
Y dado que UIStackView diseñará solo sus subvistas organizadas, esto significa que simplemente puede agregarle una UIView con
addSubview:
método, establecer sus restricciones y color de fondo.
Esta es la forma oficial de lograr lo que quiere
citado de la sesión de WWDC
Xamarin, versión 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
es un elemento que no se representa y, como tal, no se dibuja en la pantalla.
Esto significa que cambiar
backgroundColor
esencialmente no hace nada.
Si desea cambiar el color de fondo, simplemente agregue una vista
UIView
como una subvista (que no está organizada) como a continuación:
extension UIStackView {
func addBackground(color: UIColor) {
let subview = UIView(frame: bounds)
subview.backgroundColor = color
subview.autoresizingMask = [.flexibleWidth, .flexibleHeight]
insertSubview(subview, at: 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];