UIStackView की पृष्ठभूमि का रंग कैसे बदलें?


158

मैंने UIStackViewस्टोरीबोर्ड इंस्पेक्टर में स्पष्ट से पृष्ठभूमि को सफेद में बदलने की कोशिश की , लेकिन जब अनुकरण करते हैं, तो स्टैक दृश्य की पृष्ठभूमि का रंग अभी भी एक स्पष्ट रंग है।
मैं पृष्ठभूमि का रंग कैसे बदल सकता हूं UIStackView?


2
यह एसओ पर उन दुर्लभ मामलों में से एक है, जहां उत्तर पूरी तरह से गलत हैं । आप सिर्फ एक ... पृष्ठभूमि दृश्य जोड़ते हैं। यह बहुत सरल है। उदाहरण लेख यह समझाते हुए: useyourloaf.com/blog/stack-view-background-color
Fattie

@ फैटी यह काम किया! क्या आप इसे उत्तर के रूप में भी जोड़ सकते हैं?
अनुपस्थित

hi @AbSin - कुरोदु और मारीनायर्न के उत्तर एकदम सही हैं।
फेटी डे

हाहा, यह महान है, गैर-प्रतिपादन तत्व की पृष्ठभूमि रंग संपत्ति है
ब्रैड थॉमस

जवाबों:


289

आप ऐसा नहीं कर सकते - UIStackViewएक गैर-ड्राइंग दृश्य है, जिसका अर्थ है कि drawRect()इसे कभी नहीं बुलाया जाएगा और इसकी पृष्ठभूमि का रंग अनदेखा किया गया है। यदि आप एक पृष्ठभूमि रंग चाहते हैं, तो स्टैक दृश्य को दूसरे के अंदर रखने UIViewऔर उस दृश्य को एक पृष्ठभूमि रंग देने पर विचार करें।

यहाँ से संदर्भ ।

संपादित करें:

आप यहां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)

12
यह काफी गलत है । यह एक दुर्लभ मामला है जहां HackingWithSwift पर पॉल का लेख पूरी तरह से गलत है । आप बस एक और दृश्य जोड़ते हैं (जो व्यवस्थित विचारों में से एक नहीं है ) और वह उत्तर है।
फेटी

11
यहाँ एक लेख है जो इसे समझाता है, यह तुच्छ है: useyourloaf.com/blog/stack-view-background-color
Fattie

1
तब स्टैकव्यू का उपयोग क्या होता है, क्या हम बस अपने विचारों को दूसरे दृश्य के अंदर नहीं जोड़ सकते हैं और इसे क्षैतिज या लंबवत रूप से संरेखित करने के लिए अड़चनें देते हैं और इस तरह पूरी तरह से स्टैकव्यू से बचते हैं। क्या यह बहुत हास्यास्पद नहीं है कि स्टिव्यू के अंदर के दृश्य हैं और उस स्टिव्यू को यूइवीईवाई के अंदर रखा गया है और फिर हमारे घटक में इस यूविईवी को जोड़ दें।
शिवम पोखरियाल

कम से कम, drawRect()कहा जाता है। आप बस subclassingUIStackView
khcpietro

बहुत बढ़िया जवाब। मैंने इसे थोड़ा विस्तार दिया है, क्योंकि मेरे ऐप में कई थीम हैं इसलिए बैकग्राउंड का रंग बदल सकता है। हर बार रंग बदलने पर सबव्यू जोड़ने से रोकने के लिए, मैं सबव्यू के टैग को 123 में बदल देता हूं, फिर हर बार फ़ंक्शन को I पहली जांच कहा जाता है यदि किसी एक सबव्यू में इस तरह 123 टैग हो if let backgroundView = self.subviews.first(where: {$0.tag == 123}) {। यदि हां, तो मैं उस दृश्य की पृष्ठभूमि का रंग बदलता हूं।
गुइडो

47

मैं इसे इस तरह से करता हूं:

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

एक जादू की तरह काम करता है


स्टोरीबोर्ड में उपयोग किए जाने पर यह मेरे लिए काम नहीं करता है, जिसमें बैकग्राउंड के साथ अपडेटेड उत्तर / सेट विधि शामिल हैं। : - / (IOS 10.2.1, Xcode 8.2.1, iPad पर)
webjprgm

क्षमा याचना, मुझे लगा। इंटरफ़ेस बिल्डर ने क्लास के नीचे "मॉड्यूल" फ़ील्ड को छोड़ दिया ताकि लोड न हो। इसे ठीक करें, फिर बैकग्राउंड को कंट्रोलर के व्यू में सेट करें।
webjprgm

1
अपनी कक्षा को IBDesignable भी बनाएं -> @IBDesignable class StackViewजो आपको स्टोरी बोर्ड पर डिज़ाइन करने की अनुमति देगा। मुझे नहीं रन टाइम पर एक पृष्ठभूमि जोड़ने के लिए ज्यादा परवाह है, लेकिन यह stackview जब यह कहानी बोर्ड पर कोई रंग है डिजाइन करने के लिए बहुत कठिन है
FlowUI। SimpleUITesting.com

@ फैटी केयर यह समझाने के लिए कि यह एक बुरा तरीका क्यों है?
आर्बिटूर

शायद वेरी बैड थोड़ा कठोर है @Arbitur :) :) लेकिन परतों के साथ खेलने की कोई आवश्यकता नहीं है, क्योंकि आप सिर्फ एक और दृश्य जोड़ते हैं (लेकिन एक व्यवस्थित नहीं है)
Fattie

34

UIStackViewएक गैर-रेंडरिंग तत्व है, और इस तरह, यह स्क्रीन पर तैयार नहीं होता है। इसका मतलब यह है कि backgroundColorअनिवार्य रूप से बदलने से कुछ नहीं होता है। यदि आप पृष्ठभूमि का रंग बदलना चाहते हैं UIView, तो नीचे दिए गए की तरह इसे सबव्यू के रूप में जोड़ें (जो व्यवस्थित नहीं है):

extension UIStackView {

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

}

1
यह उत्तर भी सही है। व्यक्तिगत रूप से मैंने सभी चार बाधाओं में डाल दिया (जैसा कि कुरोदु के उत्तर में है)
फेटी

1
मान लें कि आप पृष्ठभूमि का रंग नहीं बदलते हैं तो यह ठीक है। लेकिन अगर आप इस विधि को कई बार कहते हैं तो पिछले समय के विचार अभी भी बने हुए हैं। इसके अलावा इस पद्धति से पृष्ठभूमि रंग को आसानी से हटाने का कोई तरीका नहीं है।
कीजी

11

हो सकता है कि सबसे आसान, अधिक पठनीय और कम hacky रास्ता एम्बेड करने के लिए किया जाएगा UIStackViewएक में UIViewदेखने के लिए पृष्ठभूमि रंग और निर्धारित किया है।

और उन दो विचारों के बीच ऑटो लेआउट की कमी को ठीक से कॉन्फ़िगर करने के लिए मत भूलना ... ;-)


2
हाँ लेकिन इसमें मज़ा कहाँ है? :-)
webjprgm

1
दूर से सबसे अच्छा समाधान - यह अकेले इंटरफ़ेस बिल्डर में काम करता है, कोड की एक पंक्ति के बिना
व्लादिमीर ग्रिगोरोव

10

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)

2
मुझे stackView.insertSubview (bg, belowSubview: stackView.arrangedSubviews [0]) का उपयोग करने की आवश्यकता थी अन्यथा रंगीन दृश्य स्टैक के शीर्ष पर रखा गया था।
14इबरपॉल १

यह उत्तर लगभग सही है, लेकिन गलत है - आप केवल शून्य पर इन्सर्ट का उपयोग करते हैं।
फेटी

1
@iCyberPaul - आप बस शून्य पर इन्सर्ट का उपयोग करते हैं।
फेटी

नोट नमूना कोड को 0 पर डालने के लिए संपादित किया गया है कि दृश्य पदानुक्रम में अंतिम है। (मैंने कहा था कि निम्नलिखित की तरह कुछ करो ...)
माइकल लॉन्ग

8

TL; DR: ऐसा करने का आधिकारिक तरीका addSubview:विधि का उपयोग करके स्टैक दृश्य में एक खाली दृश्य जोड़कर है और इसके बजाय जोड़े गए दृश्य पृष्ठभूमि को सेट करें।

स्पष्टीकरण: UIStackView एक विशेष यूविवि उपवर्ग है जो केवल लेआउट को ड्राइंग नहीं करता है। इसके कई गुण हमेशा की तरह काम नहीं करेंगे। और चूंकि UIStackView अपने व्यवस्थित उप-लेआउटों को ही लेआउट करेगा, इसका मतलब है कि आप बस इसे addSubview:विधि के साथ एक UIView जोड़ सकते हैं , इसकी बाधाओं और पृष्ठभूमि का रंग सेट कर सकते हैं । यह आधिकारिक तरीका है जिसे आप डब्ल्यूडब्ल्यूडीसी सत्र से उद्धृत करना चाहते हैं


3

यह स्विफ्ट 3 और आईओएस 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)

3

IOS10 में, रंग सेट होने के बाद @ Arbitur के उत्तर को setNeedsLayout चाहिए। यह वह परिवर्तन है जिसकी आवश्यकता है:

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

इस बात पर निर्भर करता है कि आप चीजों को कैसे सेट करते हैं, अगर आप backgroundColorइसे जोड़ने से पहले सेट करते हैं कि यह superviewios10 और ios9 पर काम करता है, हालांकि, अगर आपने backgroundColorइसके layoutSubviews()फ़ंक्शन को कॉल करने के बाद इसे अपडेट किया backgroundColorहै तो इसका backgroundLayerमतलब है कि कोई दृश्य अद्यतन नहीं होगा। अब ठीक है, इसे इंगित करने के लिए धन्यवाद।
आर्बिटूर

2

यहां स्टैक व्यू बैकग्राउंड कलर जोड़ने के लिए एक संक्षिप्त अवलोकन दिया गया है।

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

इसे पृष्ठभूमि के रूप में प्रकट करने के लिए हम इसे अनुक्रमणिका 0. पर रूट स्टैक व्यू के सबव्यू सरणी में जोड़ते हैं। यह स्टैक व्यू के व्यवस्थित दृश्यों के पीछे लगाता है।

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

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

से संदर्भ: यहाँ


2

आप एक छोटा सा विस्तार कर सकते हैं 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)

1

ज़मारिन, सी # संस्करण:

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

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

0

उपवर्ग 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

0

आप 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

0

मैं सबक्लासिंग यूआई घटकों में थोड़ा उलझन में हूं। यह मैं इसका उपयोग कैसे कर रहा हूं,

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स्टैक व्यू पर सेट करना होगा ताकि बॉर्डर दिखाई दे।


0

आप स्टैकव्यू के लिए पृष्ठभूमि नहीं जोड़ सकते। लेकिन आप जो कर सकते हैं वह एक दृश्य में स्टैकव्यू जोड़ रहा है और फिर दृश्य की पृष्ठभूमि सेट करें इससे काम पूरा हो जाएगा। * यह स्टैकव्यू के प्रवाह को बाधित नहीं करेगा। आशा है कि यह मदद करेगा।


0

हम 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 = ...। और बैकग्राउंड कलर को कई बार सेट / बदलने से कई सारे इंटरव्यू स्टैक व्यू में डाले जाएंगे।


0

यदि आप खुद को डिजाइनर से नियंत्रित करना चाहते हैं, तो स्टैक दृश्य में इस एक्सटेंशन को जोड़ें

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

-1

आप इसे इस तरह से कर सकते हैं:

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
        }

    }

}

आपको सबव्यू की सही स्थिति निर्धारित करनी होगी, डालने का उपयोग करें
Fattie

-1

BoxView का प्रयास करें । यह UIStackView के समान है, लेकिन यह अधिक लेआउटिंग विकल्पों का प्रतिपादन और समर्थन करता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.