web-dev-qa-db-ja.com

UIStackViewの背景色を変更する方法は?

StoryboardインスペクターでUIStackViewの背景をクリアからホワイトに変更しようとしましたが、シミュレートするとき、スタックビューの背景色はクリアな色のままです。
UIStackViewの背景色を変更するにはどうすればよいですか?

119
Chaz

これはできません。UIStackViewname__は非描画ビューです。つまり、drawRect()は呼び出されず、背景色は無視されます。必死に背景色が必要な場合は、スタックビューを別のUIViewname__内に配置し、そのビューに背景色を与えることを検討してください。

HERE からの参照。

編集:

前述のように、サブビューをUIStackViewname__に追加 ここ または この回答(下) で色を割り当てます。以下のextensionname__をご覧ください。

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)
222
Dharmesh

私はこのようにします:

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

魔法のように働く

43
Arbitur

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

}
27
Marián Černý

TL; DR:これを行う公式の方法は、addSubview:メソッドを使用して空のビューをスタックビューに追加し、代わりに追加したビューの背景を設定することです。

説明:UIStackViewは、描画ではなくレイアウトのみを行う特別なUIViewサブクラスです。そのため、そのプロパティの多くは通常どおり機能しません。また、UIStackViewは配置されたサブビューのみをレイアウトするため、addSubview:メソッドを使用してUIViewを追加し、その制約と背景色を設定するだけです。これはあなたが望むものを達成するための公式な方法です WWDCセッションから引用

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)
7
Michael Long

おそらく、最も簡単で読みやすく、ハッキングの少ない方法は、UIStackViewUIViewに埋め込み、背景色をビューに設定することです。

そして、これらの2つのビュー間の自動レイアウト制約を適切に設定することを忘れないでください; ;-)

7
MonsieurDart

IOS10では、色が設定された後、@ Arbiturの答えにはsetNeedsLayoutが必要です。これは必要な変更です:

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

これは、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)
2
Murray Sagal

スタックビューの背景色を追加するための簡単な概要を次に示します。

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の小さな拡張機能を使用して、スタックビューの端にbackgroundViewを固定する制約を追加します。

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

参照元: HERE

2
kurrodu

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)
2
Nhon Nguyen

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

注:このアプローチでは、境界線を設定する場合、stackViewでlayoutMarginsを設定して、境界線を表示する必要があります。

0
infiniteLoop
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
Xeieshan

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
wlgemini

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