ฉันพยายามเปลี่ยนUIStackView
พื้นหลังจากสีใสเป็นสีขาวในตัวตรวจสอบสตอรีบอร์ด แต่เมื่อทำการจำลองสีพื้นหลังของมุมมองสแต็กยังคงมีสีที่ชัดเจน
ฉันจะเปลี่ยนสีพื้นหลังของ a ได้UIStackView
อย่างไร?
ฉันพยายามเปลี่ยนUIStackView
พื้นหลังจากสีใสเป็นสีขาวในตัวตรวจสอบสตอรีบอร์ด แต่เมื่อทำการจำลองสีพื้นหลังของมุมมองสแต็กยังคงมีสีที่ชัดเจน
ฉันจะเปลี่ยนสีพื้นหลังของ a ได้UIStackView
อย่างไร?
คำตอบ:
คุณทำสิ่งนี้ไม่ได้ -
UIStackView
เป็นมุมมองที่ไม่วาดความหมายที่drawRect()
ไม่เคยถูกเรียกและสีพื้นหลังจะถูกละเว้น หากคุณต้องการสีพื้นหลังอย่างหมดจดพิจารณาวางมุมมองสแต็กภายในอีกUIView
และให้สีพื้นหลังดู
แก้ไข:
คุณสามารถเพิ่ม subView ให้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)
drawRect()
ก็เรียกว่า คุณสามารถทดสอบโดย subclassingUIStackView
if let backgroundView = self.subviews.first(where: {$0.tag == 123}) {
หรือไม่ ถ้าเป็นเช่นนั้นฉันจะเปลี่ยนสีพื้นหลังของมุมมองนั้น
ฉันทำแบบนี้:
@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
ซึ่งจะช่วยให้คุณออกแบบบนกระดานเรื่องราว ฉันไม่สนใจมากสำหรับการเพิ่มพื้นหลังในเวลาทำงาน แต่มันยากมากที่จะออกแบบสแต็ควิวเมื่อไม่มีสีบนกระดานเรื่องราว
UIStackView
เป็นองค์ประกอบที่ไม่เรนเดอร์และดังนั้นจึงไม่ถูกวาดบนหน้าจอ ซึ่งหมายความว่าการเปลี่ยนแปลงbackgroundColor
ไม่ทำอะไรเลย หากคุณต้องการเปลี่ยนสีพื้นหลังเพียงเพิ่ม a UIView
เป็น subview (ที่ไม่ได้จัดเรียง) ดังด้านล่าง:
extension UIStackView {
func addBackground(color: UIColor) {
let subview = UIView(frame: bounds)
subview.backgroundColor = color
subview.autoresizingMask = [.flexibleWidth, .flexibleHeight]
insertSubview(subview, at: 0)
}
}
อาจเป็นวิธีที่ง่ายที่สุดอ่านได้ง่ายกว่าและแฮ็กน้อยกว่าก็คือการฝังUIStackView
ลงในUIView
และตั้งค่าสีพื้นหลังเป็นมุมมอง
และอย่าลืมกำหนดค่าข้อ จำกัด เลย์เอาต์อัตโนมัติระหว่างสองมุมมองเหล่านั้น ... ;-)
ปิติพงษ์ถูกต้องเพื่อให้ได้สแต็ควิวที่มีสีพื้นหลังทำสิ่งต่อไปนี้ ...
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)
TL; DR: วิธีที่เป็นทางการในการทำเช่นนี้คือการเพิ่มมุมมองเปล่าเข้าไปในมุมมองสแต็กโดยใช้addSubview:
วิธีการและตั้งค่าพื้นหลังมุมมองที่เพิ่มไว้แทน
คำอธิบาย: UIStackView เป็นคลาสย่อย UIView พิเศษที่ทำเลย์เอาต์ไม่ได้วาดเท่านั้น คุณสมบัติมากมายของมันจะไม่ทำงานตามปกติ และเนื่องจาก UIStackView จะจัดวางเค้าโครงตัวอย่างย่อยของมันเท่านั้นนั่นหมายความว่าคุณสามารถเพิ่ม UIView ด้วยaddSubview:
วิธีการตั้งค่าข้อ จำกัด และสีพื้นหลัง นี่คือวิธีการอย่างเป็นทางการเพื่อให้บรรลุสิ่งที่คุณต้องการยกมาจากเซสชันของ 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
}()
ในการทำให้มันปรากฏเป็นพื้นหลังเราเพิ่มมันเข้าไปในอาร์เรย์ 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)
}
อ้างอิงจาก: ที่นี่
คุณสามารถขยายขนาดเล็กได้ 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)
Xamarin รุ่น 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];
คลาสย่อย 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
คุณสามารถแทรก sublayer ไปยัง 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 แต่สิ่งที่คุณสามารถทำได้คือการเพิ่ม stackview ในมุมมองจากนั้นตั้งค่าพื้นหลังของมุมมองนี้จะทำให้งานเสร็จ * จะไม่ขัดขวางการไหลของ 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
}
}
}